feat(#683 Cause 2): synthesize impl tasks for core gaps with no implementation home#687
Conversation
…home Gap-fill (#607-step-4) rolls every uncovered outcome onto an existing anchor task's completion_criteria. When that anchor is a DESIGN task (the snake run: collision / game-over / restart all landed on "Design Game Core Mechanics"), the work is never built and its #680 gotchas orphan — the core of #683. _route_gap_fill_to_criteria now decides per gap: - anchor is the integration-verification task (cross-cutting) -> roll onto it. - anchor is already an implementation task -> roll onto it (no new task; the anti-atomization guard). - anchor is a non-implementation (design/testing) task -> SYNTHESIZE one implementation task so the work gets built and #680 gotchas have a host. Capped (GAP_SYNTH_CAP=8) so a pathological gap list cannot re-atomize the graph; excess falls back to the rollup and is logged. Synthesized tasks are wired into the stub->anchor map so signal + #680 gotcha enrichment land on them (verified e2e). Does NOT revert #607-step-4. - Rework _route_gap_fill_to_criteria to return (augmented, synthesized, stub_idx_to_synth_id); wire both callers. - Add _build_impl_task_from_gap + GAP_SYNTH_CAP. - 4 new tests; all 118 prior coverage tests green; mypy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @lwgray's task —— View job Pull Request ReviewI've completed a comprehensive review of this PR addressing issue #683 Cause 2. Here's my detailed analysis: Review Checklist
✅ Code Quality & Best PracticesExcellent implementation quality:
Architecture alignment:
✅ Test CoverageComprehensive test suite (15 new tests):
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa7083e50f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| labels=labels, | ||
| provides=gap.get("provides"), | ||
| requires=gap.get("requires"), | ||
| responsibility=responsibility, |
There was a problem hiding this comment.
Preserve contract metadata for synthesized gap tasks
When a contract-first gap with a responsibility is synthesized here because its anchor is a design/testing task, the new task relies only on Task.responsibility. The kanban conversion path (TaskBuilder.build_task_data) persists source_type/source_context but not this top-level field, and normal contract-first tasks also embed the responsibility in source_context/the description marker for round-tripping. In that production path the synthesized implementation task loses its contract ownership before request_next_task, so agents do not receive the contract-responsibility layer for exactly these generated contract gap tasks.
Useful? React with 👍 / 👎.
…asks Codex P1 on PR #687: a synthesized contract-first gap task set its responsibility only on the SQLite-native top-level Task.responsibility field. TaskBuilder.build_task_data persists source_context and the description, not arbitrary top-level fields, so on the production kanban round-trip the task lost its contract ownership before request_next_task — and the contract-responsibility instruction layer never fired for exactly these tasks. Fix: new _gap_contract_round_trip helper persists responsibility (+ contract_file) into BOTH source_context (JSON-capable providers) AND the <!-- MARCUS_CONTRACT_FIRST: responsibility | contract_file --> description marker (universal fallback, e.g. Planka) — the two non-native sources _parse_contract_metadata reads. Applied to both _build_impl_task_from_gap and _materialize_gap_dicts_as_rescue_tasks (same latent bug). - 3 new tests, incl. a real _parse_contract_metadata round-trip after dropping the native field. 18 gap tests + 456 broader pass; mypy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Good catch — fixed in d2d9f8f3. Confirmed: New Added 3 tests, including one that drops the native field to mimic a non-SQLite round-trip and asserts |
|
Claude finished @lwgray's task —— View job Pull Request ReviewI've completed a comprehensive review of this PR addressing issue #683 Cause 2. Here's my detailed analysis: Review Checklist
✅ Code Quality & Best PracticesExcellent implementation quality:
Architecture alignment:
✅ Test CoverageComprehensive test suite (15 new tests):
|
What is this system, briefly
Marcus turns a plain-English project spec into a graph of small tasks for independent AI agents to build. A user outcome is something the finished product must do ("the snake dies when it hits a wall"). If no task covers an outcome, that's a gap, and gap-fill is supposed to repair it.
Why
Issue #683: on a real Snake run, four required outcomes (wall collision, self collision, game-over screen, restart) ended up with no task to build them — the game would ship unplayable — and their #680 "gotcha" failure-mode checks were dropped.
One of the two causes (this PR): since #607-step-4, gap-fill stopped creating tasks and instead rolls each uncovered outcome onto an existing anchor task's
completion_criteria. The routing often lands on a design task (e.g. "Design Game Core Mechanics") — a planning artifact where no code lives. So the work is never built, and a #680 gotcha (a failure mode in running code) has no valid implementation task to attach to, so it's logged and dropped.What changed
_route_gap_fill_to_criteriainsrc/marcus_mcp/coordinator/outcome_coverage.pynow decides, per gap, using the existing routing precedence + theget_task_typeclassifier:completion_criteriaGAP_SYNTH_CAP = 8); excess gaps fall back to the rollup and are logged, so a pathological gap list can't re-atomize the graph (the concern Decomposition redesign: roll up gap-fill + test-pair atomization into acceptance criteria #607-step-4 was addressing).Glossary
get_task_typeclassification; a gotcha must live on an implementation task (where code is written), not a design task.Bright-line check (MAS invariant)
Deciding that a required outcome gets a buildable task is environment design — Marcus structuring the board. It says nothing about HOW the agent builds collision detection. Passes.
Worked example (real Snake run, after this PR)
The feature filter still dropped collision/game-over/restart (the other #683 cause, tracked separately), but gap-fill now synthesized
Implement Wall Collision Detection,Implement Self Collision Detection,Implement Game-Over Screen Display, andImplement Restart Button— all classified[implementation], each carrying its gotchas. 0 orphan warnings; 20 gotchas, all on implementation tasks (was: 4 orphaned outcomes, gotchas dropped).Test plan
pytest tests/unit/coordinator/test_gap_fill_criteria_rollup.py— 15 pass, incl. 4 new: synthesis on design anchor, no-synthesis on impl anchor (anti-atomization), gotcha-lands-on-synthesized-task end-to-end, cap respectedpytest tests/unit/coordinator/+ outcome/gotcha/integration suites — 453 pass (all prior behavior preserved)mypy src/marcus_mcp/coordinator/outcome_coverage.pycleanscripts/dump_gotcha_criteria.py: previously-orphaned outcomes now synthesized as impl tasks with gotchas; zero decomposition-gap warningspython scripts/dump_gotcha_criteria.py(needsANTHROPIC_API_KEY)Related
acceptance_criteriais not delivered to agents, andcompletion_criteriais delivered unframed — agents miss spec details #664 (acceptance_criteria delivery). Preserves Decomposition redesign: roll up gap-fill + test-pair atomization into acceptance criteria #607-step-4's anti-atomization intent.618f0483, thoughtbc0cc360.🤖 Generated with Claude Code