feat(capacity): capacity:backfill tool + cold-start discoverability (#1606)#1611
Conversation
…1606) - scripts/capacity_backfill.py: one-time classifier for completed vBRIEFs -- infers capacityBucket from origin-issue labels via the configured bucket match rules, stamps completedAt from git landing time. Dry-run by default, idempotent, never touches cost. Offline cache-first with an opt-in --fetch (REST shim) for closed issues absent from the open-issue triage cache, and --window-only to restrict to the activation-critical trailing window. - tasks/capacity.yml: task capacity:backfill surface. - capacity:show: actionable advisory hint when buckets are configured but history is unclassified; exposes unclassified_completions on the report. - _lifecycle_hygiene: Tier-3 capacity cold-start session-start nudge. - tests: classification, dry-run/apply/idempotency, cost-preservation, window-only, config-error, fetch fallback, cold-start nudge fire/suppress. Refs #1419. Closes #1606. Co-authored-by: Cursor <cursoragent@cursor.com>
…tory (#1606) Mechanical one-time run of `task capacity:backfill --window-only --fetch --apply` over the trailing 30d window: stamps capacityBucket (152 inferred from origin-issue labels, 31 defaulted) + git-derived completedAt (132) on 183 completed vBRIEFs. Crosses minSampleSize (183 >= 20), lifting capacity accounting out of advisory mode. Data-only; no logic changes. Refs #1606 #1419. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
| Filename | Overview |
|---|---|
| scripts/capacity_backfill.py | New one-time backfill script; write-then-count ordering correct; skipped_unreadable counter added; one silent-skip path remains (valid JSON, non-dict plan). |
| scripts/capacity_show.py | Added unclassified_completions (window-aware, excludes out-of-window explicit dates), discoverability hint, and completed_at_present field; logic is correct. |
| scripts/_lifecycle_hygiene.py | Adds Tier-3 capacity cold-start nudge that lazily imports capacity_show and fires/suppresses correctly; suppression for unconfigured and fully-classified cases is tested. |
| tasks/capacity.yml | New backfill task wired correctly; --fetch flag absent from desc example usage. |
| tests/cli/test_capacity_backfill.py | 16 tests covering classification, dry-run/apply/idempotency, cost preservation, window-only, config errors, fetch fallback, and cold-start nudge fire/suppress. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[task capacity:backfill] --> B{--apply?}
B -- dry-run --> C[Scan completed/ vBRIEFs]
B -- apply --> C
C --> D{Read JSON OK?}
D -- OSError/ValueError --> E[skipped_unreadable++]
D -- valid JSON --> F{plan dict present?}
F -- No --> G[silent skip\nnot counted]
F -- Yes --> H[scanned++]
H --> I{--window-only?}
I -- Yes --> J{in window?}
J -- No --> K[skipped_out_of_window++]
J -- Yes --> L{has capacityBucket?}
I -- No --> L
L -- Yes --> M[already_classified++]
L -- No --> N[Resolve labels\ncache / --fetch]
N --> O[classify_bucket\nmatch or default]
O --> P{dry-run?}
P -- dry-run --> Q[tally only]
P -- apply --> R[_write_metadata]
R --> S{OSError?}
S -- Yes --> T[exit_code=1, return]
S -- No --> U[stamped_bucket++ / stamped_completed_at++]
Q --> U
U --> V[BackfillResult.summary]
Reviews (2): Last reviewed commit: "fix: address Greptile review findings (b..." | Re-trigger Greptile
- capacity_show: make unclassified_completions backfill-actionable (window-aware) -- exclude unclassified completions with an explicit out-of-window completedAt so the advisory hint + Tier-3 cold-start nudge no longer promise a no-op migration (P1). - capacity_backfill: tally stamped_bucket/completed_at after a successful write so an OSError mid-run no longer overstates the summary (P2). - capacity_backfill: count unreadable/malformed completed vBRIEF files via skipped_unreadable (summary + --json) so scanned is not silently short (P2). - tests: out-of-window suppression, undated fires, direct compute_report count, write-failure accounting, unreadable-file accounting. MCP unavailable in this session -- used gh api fallback for review comments. Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Ships the deferred
task capacity:backfilltool (#1419 "Brownfield Backfill") and closes the discoverability gap that left capacity accounting silently dormant on pre-adoption trees.scripts/capacity_backfill.py— one-time classifier forcompleted/vBRIEFs. InferscapacityBucketfrom each item's origin-issue labels via the configuredcapacityAllocation.buckets[].match.labelsrules (declaration-order match wins; no match falls todefaultBucketand is surfaced in a low-confidence batch), and stampscompletedAtfrom git landing time. Dry-run by default, idempotent (explicit values preserved), and never touchescost. Offline cache-first with an opt-in--fetch(REST shim, never GraphQL) for closed issues absent from the open-issue-scoped triage cache, plus--window-onlyto restrict to the activation-critical trailing window.task capacity:backfillTaskfile surface.capacity:shownow emits an actionable hint when buckets are configured but history is unclassified, and a Tier-3 session-start cold-start nudge points the operator at the one-time backfill. Both self-suppress onceminSampleSizeis crossed.completedAt. Capacity is now out of advisory mode (183 ≥ minSampleSize 20) with a real 4-bucket mix and actionable deficits.Commits are split: logic + tests (reviewable) / data migration (mechanical) / lifecycle completion.
Test plan
task checkgreen (7681 passed)tests/cli/test_capacity_backfill.py(16 tests): classification, dry-run/apply/idempotency, cost-preservation,--window-only, config-error exit 2,--fetchfallback, cold-start nudge fire/suppresscapacity:showpost-backfill reports 183 classified completions, advisory mode clearedRefs #1419. Closes #1606.