Implement Development Effort Calculator (WP-0010-T02)
src/target_revenue/effort_calculator.py implements Candidate A (labor-cost-anchored, accepted T01): commit-timestamp session-gap clustering for human interaction time, workplan/task-volume counts via direct workplans/ directory parsing (no state-hub dependency, works uniformly on any repo using this repo's own convention), file/line counts with generated/vendored-path exclusion, and caller-supplied token-cost pricing. estimate_target_basis() combines these and returns a derivation dict (every input shown) plus a warnings list - never a black-box dollar figure. 1-day manual-work floor, as requested: any raw commit-clustered estimate below 1.0 day is floored and flagged with a warning that this is very likely a measurement gap (commit-clustering is a floor estimate by design) that should usually be compensated for by manual override, not trusted at face value. A second, independent sanity-check warning fires when finished-workplan/task volume is substantial but the time estimate is still low, even above the floor - demonstrated live against target-revenue's own history (7 finished workplans, 57 tasks correctly flagged a 2.38-day estimate as under-counted). scripts/effort_calculator_cli.py: CLI wrapper printing JSON, following the same offline-first, no-Phase-declaration pattern as scripts/trf_onboard.py. tests/test_effort_calculator.py (15 deterministic tests, throwaway git repos/tmp_path fixtures) covers commit clustering, workplan/task parsing, size-metric exclusion, token-cost pricing, the floor-and-warning behavior, the sanity-check warning, and an end-to-end smoke test. No new hard dependency.
This commit is contained in:
parent
37ccee22ab
commit
9566e16a97
6 changed files with 720 additions and 2 deletions
|
|
@ -80,7 +80,7 @@ this formula, not Candidate B or a hybrid.
|
|||
|
||||
```task
|
||||
id: TREV-WP-0010-T02
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "b5fb46ea-b737-495f-82b8-5e10f0032cb5"
|
||||
```
|
||||
|
|
@ -107,6 +107,48 @@ black-box dollar figure with no visible derivation would undermine the
|
|||
"transparent, non-gameable" goal (`specs/TargetRevenueLicenseConcept.md`
|
||||
§4.6) this whole framework is built around.
|
||||
|
||||
**Result:** `src/target_revenue/effort_calculator.py` implemented, pure/
|
||||
offline (no network or state-hub dependency — `list_tasks`/`list_workplans`
|
||||
was superseded by direct `workplans/` directory parsing so the module
|
||||
works uniformly on any repo using this repo's own workplan convention,
|
||||
without requiring hub connectivity). `cluster_commit_hours()` does
|
||||
session-gap clustering over `git log --all --format=%at`, with a 15-minute
|
||||
floor for single-commit sessions. `workplan_task_counts()` parses
|
||||
frontmatter `status:` fields and this repo's triple-backtick task-block
|
||||
convention. `repo_size_metrics()`
|
||||
excludes generated/vendored path components
|
||||
(`node_modules`, `.venv`, `__pycache__`, etc.). `token_cost_usd()` takes
|
||||
caller-supplied token counts (e.g. from `get_token_summary`) rather than
|
||||
fetching them itself. `estimate_target_basis()` combines these per
|
||||
Candidate A and returns a `TargetBasisEstimate` with a `derivation` dict
|
||||
(showing every input value) and a `warnings` list.
|
||||
|
||||
**1-day manual-work floor, as requested:** any raw commit-clustered
|
||||
estimate below `MANUAL_EFFORT_FLOOR_DAYS = 1.0` is floored to 1.0 day
|
||||
(never reported smaller) and flagged with an explicit warning explaining
|
||||
this is very likely a measurement gap — commit-clustering is a floor
|
||||
estimate by design — and should usually be compensated for by a manual
|
||||
override rather than trusted at face value. A second, independent
|
||||
sanity-check warning fires when a repo's finished-workplan/task volume is
|
||||
substantial but the raw time estimate is still low, catching the case
|
||||
where the floor itself wasn't triggered but the estimate still looks
|
||||
implausible (demonstrated live: running the calculator against
|
||||
`target-revenue`'s own history — 7 finished workplans, 57 finished
|
||||
tasks — correctly flagged its 2.38-day raw estimate as under-counted,
|
||||
above the 1-day floor but still clearly too low for that much finished
|
||||
work).
|
||||
|
||||
`scripts/effort_calculator_cli.py` — a CLI wrapper printing the estimate
|
||||
as JSON, following the same offline-first, no-Phase-declaration pattern
|
||||
as `scripts/trf_onboard.py`. `tests/test_effort_calculator.py` (15 tests,
|
||||
deterministic — builds throwaway git repos and directory fixtures under
|
||||
`tmp_path` rather than depending on any real repo's changing state)
|
||||
covers commit clustering (empty/single-commit/multi-session), workplan/
|
||||
task parsing, size-metric exclusion, token-cost pricing, the floor-and-
|
||||
warning behavior, the independent sanity-check warning, and an
|
||||
end-to-end smoke test. Full suite: 79 passing offline (64 + 15 new), no
|
||||
new hard dependency (stdlib + existing `pathlib`/`subprocess`/`re` only).
|
||||
|
||||
## Apply calculator to real candidate repos
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue