P10Y variance per implementation-plan phase instead of commit component - #56
Merged
Merged
Conversation
Commit-message component prefixes (backend_/frontend_/...) were freely chosen per agent, so only ~20% of buckets were shared across parallel generation variants and the reported "variance" was mostly noise from mismatched buckets rather than real signal. Every variant executes the same implementation plan, so a prepare-commit-msg git hook now stamps each commit with the active plan phase (pNN_) deterministically, and P10Y groups/compares hours by phase instead of by freeform component name. Also: fixes the TUI buffer display (was rendering a fraction as a raw percent, e.g. "+1%" instead of "+83%"), and splits P10Y commit coverage into a P10Y service-gap cause vs a non-code (docs/config) filtered cause instead of one conflated number.
execute_all_phases calls raise_if_cancelled(db_adapter, ...) on every phase iteration; the test's bare Mock() for generation_session_service.db_adapter isn't awaitable, so the test failed before ever reaching the connection-error behavior it's meant to check. Set db_adapter=None to match the documented no-op path for tests without a DB adapter.
Conflict in test/test_execute_all_phases_connection_error.py: both sides fixed the same non-awaitable-Mock bug (ours in 9c6aa68, main in #52) by setting svc.db_adapter = None, differing only in the explanatory comment. Kept main's single assignment and comment, and dropped the duplicate assignment #53 left behind on top of #52.
The breakdown rendered "Phase 1"/"Phase 2", which says nothing the Phase # column doesn't already say. Root cause: _load_phase_names read a top-level planning_data, but the plan is persisted per workspace under workspace_phases[ws_id].planning_data (save_generation_plan writes it there, and get_current_phase_name reads it there). The lookup therefore always came back empty and every row fell back to a label derived from the number. Reads the plan from workspace_phases now, taking the first entry that carries phases since all workspaces share one plan, and logs when none is found. When a phase has no name the label is an em dash rather than "Phase N" — the number has its own column. Renames the description column accordingly across the TUI, markdown and HTML reports.
akozak-gd
approved these changes
Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Per-component variance was mostly noise. The bucket name came from the commit subject prefix, freely chosen by each agent, so parallel variants of the same plan produced different axes — in run
ws-03onlybackendandfrontendwere common to all three variants (report said "Only 22% of components are common"), andinfrastructure 130%was really 90h vs absent vs 4h. Every variant executes the same implementation plan, so phases are a genuinely comparable axis.Key design decisions
prepare-commit-msgstampspNN_usinggit config specflow.phase, which the codegen loop sets before each phase. Attribution no longer depends on agent commit hygiene, and--no-verifydoes not bypass this hook. Agents now write a plain<action> <subject>.SKIP_*commits. Otherwise the seed/janitor commits would becomep24_SKIP_janitor_finalizeand silently enter P10Y — this keeps_subject_excluded_from_estimationthe single source of truth for exclusion.planning_data, so every variant labels a phase identically.unphasedbucket (initial seed, deploy/E2E loop, strays) — never silently folded into a real phase. The marker is set only in the codegen loop and cleared for deploy.component_*→phase_*across schemas, reports and TUI;KNOWN_COMPONENTSdeleted). Pre-release, no consumers of the old shape.Folded in along the way: the TUI rendered the risk buffer fraction as a raw percent (
+1%instead of+83%), and P10Y commit coverage conflated two causes — now reported separately as a P10Y service gap vs non-code (docs/config) commits filtered by technology, which are not expected to score.Verification
make unit-tests— backend 2109 passed, mcp_server 137 passed.make check-complexity-diff METRIC=cc: 3.61 → 3.62 (+0.01).Note: 3
TestStartupGatefailures inmcp_server/tests/test_tui_app.pyare pre-existing onmain(verified on a cleanmainworktree) and unrelated to this branch.