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:
tegwick 2026-07-30 13:16:44 +02:00
parent 37ccee22ab
commit 9566e16a97
6 changed files with 720 additions and 2 deletions

View file

@ -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