feat: reachability-enforced "done" — orphan-module gate (Gate 6)#22
Closed
anombyte93 wants to merge 13 commits into
Closed
feat: reachability-enforced "done" — orphan-module gate (Gate 6)#22anombyte93 wants to merge 13 commits into
anombyte93 wants to merge 13 commits into
Conversation
…+ importer sweep + verdict) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ed tests; anchor TS import match
…fault in enrich + schema hint Adds phaseConfig.tier to every enriched task, derived from the same keyword signals that drive complexity classification. Priority order: live (user-test / user validation checkpoint) > spike (research/investigate/evaluate stems) > wired (integrate/auth/api/deploy/database/cli/mcp/…) > domain-model (safe default). Key design decisions: - _classify_tier() is a standalone helper next to _classify_task(), testable in isolation. It uses two new prefix-stem regexes (_TIER_RESEARCH_RE, _WIRED_KEYWORDS) that drop the trailing \b so "investigate", "evaluate", "integrate" etc. are caught — existing exact-word regexes are not modified. - run_enrich_tasks() is idempotent in two ways: (a) a task with no phaseConfig gets a full phaseConfig including tier; (b) a task with phaseConfig but no tier (pre-feature enrichment) gets tier backfilled; (c) a pre-existing non-empty tier is preserved (honours LLM or manually-set values). - Default is domain-model — existing graphs never suddenly require reachability. - TASKS_SCHEMA_HINT in backend.py gains the tier field and a one-line rule. - 33 new tests in tests/core/test_tier.py; full suite 422 passed, 3 skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…; drop review/assess from spike) - cli: \bcli(?!ent|mat|nic) — excludes client/climate/clinic/clinical; CLI, cli-based, cli entrypoint still fire - auth: \bauthenticat|\bauthoriz|\bauth\b — excludes author/authority/authentic; auth token, authenticate still fire - wire: \bwire(?!frame|less) — excludes wireframe/wireless; wiring/wire X into Y still fire - api: anchored to \bapi\b (word-boundary both sides) — confirmed no collision with rapid/therapist - _TIER_RESEARCH_RE: drop review and assess (high-frequency innocent words); keep audit, spike, investigate, evaluate, etc. - 12 negative regression tests added to tests/core/test_tier.py (each fails against pre-fix code) - All 45 tier tests green; full suite 434 passed 3 skipped Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…DD reachability verdict is ORPHAN/ERROR/missing Adds gate_reachability() to both skel/ship-check.py (stdlib-only, binding) and prd_taskmaster/shipcheck.py (display heuristic), wired into run_all_gates after Gate 5 (oracle). Reads the 'reachability' block from each task's CDD card; fail-closed on missing card, missing block, ORPHAN, ERROR, or unknown verdict for wired/live-tier done tasks. domain-model/spike/untiered and non-done tasks skipped. 31 new tests in tests/core/test_ship_check_reachability.py; full suite 465 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ector + warnings channel - Add warnings channel to run_validate_tasks (alongside problems); hard-block only for wired/live tiers; spike/domain-model get advisory warnings only. - Add reachableVia to TASKS_SCHEMA_HINT, parse prompt, and _task_summaries so it survives expansion; wired/live empty reachableVia is a hard-block, untiered/lower tiers get a warning; bare-word (unscoped) values get an advisory warning. - Add _promise_evidence_mismatch() detector: maps high-altitude claim terms (prisma, cli, client, api, connector/adapter/sync/webhook/integration/endpoint/route) with word-boundary anchored regexes against testStrategy altitude (fixture-only vs live); mismatches are hard-blocked for wired/live, warned for spike/domain-model; includes down-rank suggested_title map. - 27 new tests in tests/core/test_validate_reachability.py; 0 existing tests broken. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… ambiguous(store/route/sync/client/api)=warn-only Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lity gate (wired/live require WIRED/EXEMPT verdict) - run_set_status gains evidence_ref + reachability params (signature backward-compatible: tag/non-done paths unchanged) - wired/live tasks marked done without a WIRED/EXEMPT reachability dict now raise CommandError (fail-closed gate) - ORPHAN/ERROR/unknown/absent verdicts all block; domain-model/spike/untiered tasks keep bare flip - doneEvidence (evidence_ref + timestamp) and reachability dict persisted additively on the task object when provided - set_task_status MCP wrapper passes both new params through - 16 new TDD tests green; full suite 517 passed 3 skipped
…uto-reads it; execute-task sweeps + auto-downgrades orphans - Part A: new `prd-taskmaster reachability-sweep --task <id> --start-commit <sha>` subcommand (prd_taskmaster/reachability_cmd.py + cli.py wiring). Loads task, runs sweep_task(), writes verdict dict into .atlas-ai/cdd/task-<id>.json under "reachability" key (atomic, additive). exit 0 for WIRED/EXEMPT, exit 1 for ORPHAN/ERROR. - Part B: `set-status` gains --evidence-ref and --reachability flags. Auto-read fallback in run_set_status(): when marking done with no explicit reachability, reads the verdict from the CDD card — so Step 9b sweep → Step 10 mark-done works without extra flags. ORPHAN/ERROR from auto-read still blocks (RA5 gate preserved). Untiered/domain-model tasks unchanged. - Part C: execute-task/SKILL.md updated — documents task_start_sha capture, Step 9b reachability sweep (mandatory for wired/live), and Step 10 branching: WIRED/EXEMPT → done, ORPHAN/ERROR → auto-downgrade to scaffold + continue loop. Throughline: "a green test on a module imported by nothing is not done — wire it or it ships as scaffold." - 27 new tests in tests/core/test_reachability_sweep_cmd.py; full suite 544 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t); scaffold blocks ship gate
- Add "scaffold" to VALID_STATUSES in task_state.py so set-status --status scaffold no
longer raises "unknown status" (the auto-downgrade path in execute-task Step 10 now works).
- scaffold is NOT done, NOT deferred — a deliberate incomplete state for orphan modules;
Gate 2 (gate_tasks requires every task done) already blocks any scaffold task from SHIP_CHECK_OK.
- Count scaffold tasks in _count_tasks and surface them in execute_panel with a ⚠ line
("N scaffolded — orphan, blocks ship gate") for honest operator visibility.
- Tests: set-status scaffold succeeds (API + CLI); scaffold task verified to block run_all_gates;
VALID_STATUSES membership assertion; pipeline_state tag_counts dict updated for scaffold key.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s, scaffold honest; orthogonal to oracle Adds 11 genuine end-to-end tests spanning the full reachability lifecycle: real git repo, real reachability-sweep CLI, real ship-check subprocess, fake oracle stub via ATLAS_ORACLE_CMD so Gate 5 passes and Gate 6 is the deciding gate. Scenarios covered: - A: orphan module → sweep writes ORPHAN → ship-check exits 1, stderr names ORPHAN + task id (non-vacuous acceptance criterion) - B: oracle/test orthogonality — task's own test passes (oracle PASS) while reachability is ORPHAN, proving the two axes are independent (the user's exact bug: 10 of 19 'done' tasks were orphan dead code) - C: wire module (edit existing app.py to import Widget) → re-sweep writes WIRED → set-status done auto-reads it → ship-check prints SHIP_CHECK_OK - D: set-status scaffold → Gate 2 blocks honestly (not Gate 6), proving the scaffold path is an honest "not done" exit Bug fixed during e2e development (uncovered by real sweep): gate_reachability in skel/ship-check.py joined modules with ', '.join() but sweep_task writes module dicts, not strings — fixed to extract m["module"] from each dict entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… skel/.npmignore (pyc excluded from pack) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (close JS/TS false-WIRED) Extend _EXCLUDE_NAME_RE to match *.spec.<ext> and *.cy.<ext> for all supported language extensions (py/ts/js/jsx/tsx/go/cjs/mjs). This prevents co-located Jest/Vitest/Angular spec files and Cypress .cy files from being counted as production importers in find_importers, and from being swept as new modules in new_modules_for_task. Without this fix a module imported only by src/bar.spec.ts would return WIRED (false pass). Also aligns the find_importers grep globs to include *.cjs alongside the existing *.mjs so a .cjs-only importer is detected correctly. Five new regression tests added in TestSpecCyImporterIsOrphan confirming: - bar.spec.ts sole importer → ORPHAN (was WIRED pre-fix) - bar.cy.ts sole importer → ORPHAN (was WIRED pre-fix) - bar.cy.js sole importer → ORPHAN (was WIRED pre-fix) - spec + real production importer → still WIRED - new foo.spec.ts excluded from new_modules_for_task Full suite: 568 passed, 3 skipped, 0 failures.
Owner
Author
|
Reachability gate (Gate 6) already merged to main via the 5.3.0 catch-up. Branch fully represented in main (git cherry +0). |
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.
Reachability-enforced "done" — the orphan-module gate
Folds a user's field feedback into the engine: "atlas optimizes 'tasks marked done', a proxy that breaks on orphan modules — tie 'done' back to reachability at every gate." (They shipped 10/19 "done" tasks that were green-tested but imported by nothing.)
Stacked on #21 (the oracle cutover). The two are orthogonal axes:
done = Gate 5 PASS AND Gate 6 WIRED. A green re-executed test on an orphan passes Gate 5 and fails Gate 6 — the exact bug.The 7 recommendations — all implemented & tested
reachableVia(tier-gated required) — every wired/live task must name the route/component/CLI/API it wires into (validation.py+backend.pyschema hint)._promise_evidence_mismatch: a title that outruns its testStrategy ("Prisma connector" with a fixture-only test) is renamed down or blocked. Precise terms (prisma/webhook/connector/endpoint/migration/cli) hard-block; ambiguous (store/route/sync/client/api) warn-only.spike|domain-model|wired|live) — deterministic default in enrich; only wired/live require reachability (tasks.py).reachability.py(git-diff new modules → importer grep →WIRED|ORPHAN|EXEMPT|ERROR, fail-closed) + areachability-sweepCLI that writes the verdict into the CDD card +gate_reachabilityblocks done-orphans in both ship-check copies.run_set_status(tier-gated) refuses orphan→done and persists the verdict (auto-reads from the CDD card), instead of a bare flag flip.run_validate_taskschokepoint covers AI-parsed and hand-authored tasks.Enforcement (per the design decisions)
Hard-block the ship gate + per-task auto-downgrade orphan
done → scaffold(a new first-class non-done status, honestly surfaced as⚠ N scaffolded).reachableViais tier-gated so existing graphs (defaultdomain-model) keep validating and shipping unchanged — no migration break.Exemptions (so the gate isn't noise)
A true orphan is a module with no nameable consumer. CLIs/routes/tools/plugins/dynamic-imports declare themselves via a
reachableViascheme (cli:/route:/tool:/hook:/dynamic:) → EXEMPT. Test/spec/fixture/__main__/migration files are filtered out.Proof
tests/core/test_reachability_e2e.py— real git repo + real ship-check subprocess: an orphan wired task blocks the ship (non-vacuous — wiring it flips to shippable; scaffolding it blocks honestly), and with the oracle stubbed PASS the orphan still blocks — the "green test on dead code" bug, closed.Tests
python3 -m pytest -q→ 568 passing, 0 failures (213 reachability-specific). Two-stage review on every task caught + fixed real defects (fail-open on git/grep error, false-WIRED ×3 incl. nested-tests/TS-substring/.spec, keyword over-matching, thescaffold-status P0).Documented v1 limitation (follow-up)
Python commented-out imports (
# import bar) can still false-WIRED via grep — AST upgrade deferred;find_importers's signature is stable for the swap.🤖 Generated with Claude Code