Skip to content

v4.3.1: fix /code:plan → /code:ship handoff (schema trap, silent rejection, stale-task pollution) - #65

Merged
NOGIT007 merged 1 commit into
mainfrom
fix/plan-ship-metadata-trap-and-empty-queue
May 16, 2026
Merged

NOGIT007 merged 1 commit into
mainfrom
fix/plan-ship-metadata-trap-and-empty-queue

Conversation

@NOGIT007

Copy link
Copy Markdown
Contributor

Summary

A live /code:plan/clear/code:ship session reproduced three compounding bugs that landed the orchestrator on phantom task ids and the dispatcher on an empty queue. Root cause traced via the hook's rejection dump at ${TMPDIR}/code-et-task-hook/last-rejected.json:

  • Bug 1 (trigger) — schema trap in commands/plan.md. The metadata example showed "user_story": "US-N | AC-N.M | chore:<reason>" with pipe-alternation in value position. The planner read the | as composition, emitted "US-1 | AC-1.1, AC-1.2", and the PreToolUse hook regex (correctly) rejected. Fixed by replacing the example values with concrete singular tags ("US-1", "interface") and moving the allowed-forms enumeration into adjacent prose.

  • Bug 2 (what made it invisible) — no recovery from rejection (commands/plan.md §"On TaskCreate rejection"). Phase 3 had no instruction for hook exit-2, so the orchestrator narrated "Now wiring task dependencies…" on task ids that didn't exist. Added explicit recovery: read the rejection dump, identify the field, re-issue the same TaskCreate; never TaskUpdate(addBlockedBy) on phantom ids. Three retries on the same field escalates to the user.

  • Bug 3 (what made the symptom hard to diagnose) — silent empty queue + stale-task pollution in /code:ship (commands/ship.md §"Pre-dispatch"). TaskList is project-global, not branch-scoped — pending tasks from a merged PRD persist forever, and /code:ship was both dispatching them blindly and (when the current branch had no tasks) reporting "no queue" with no diagnostic. Added Pre-dispatch step that resolves the active PRD, parses its ## Story Checklist for US tags, and scopes the queue to matching US-N / AC-N.M / chore:* tasks. Empty-queue branch now distinguishes three cases with specific next-step messages.

Also catches up marketplace.json (was stale at 4.2.3; missed in #64).

Known follow-up

This release prevents dispatch of stale tasks but does not clear them. A v4.3.2 task-completion-on-PR-merge hook is the proper fix; tracked in the CHANGELOG entry.

Test plan

  • Re-run the failing flow: /code:plan an idea → verify TaskCreate calls use singular user_story values, no rejections in ${TMPDIR}/code-et-task-hook/last-rejected.json.
  • Simulate a rejection (intentionally emit "US-1 | AC-1.1") → orchestrator stops on that call, reads the dump, retries with corrected value.
  • /code:ship on a branch with PRD on disk + 0 tasks → expect "Active PRD: …, 0 tasks tied to its user stories. Run /code:plan to decompose."
  • /code:ship on a branch with PRD + only stale-from-other-PRD pending tasks → expect "Pending tasks (N) belong to a different PRD."
  • /code:ship on a branch with PRD + matching tasks + one chore:* task → both dispatch.

🤖 Generated with Claude Code

…ction, stale-task pollution)

Live session hit three compounding bugs: (1) the TaskCreate metadata example
in commands/plan.md used pipe-alternation in value position
("user_story": "US-N | AC-N.M | chore:<reason>"), which the planner copied
verbatim as "US-1 | AC-1.1, AC-1.2" — correctly rejected by the PreToolUse
hook regex, but (2) Phase 3 had no recovery path so the orchestrator
narrated forward on phantom task ids; (3) /code:ship then read project-global
TaskList which still contained pending tasks from the prior merged PRD and
none for the current branch, and exited with "no queue" instead of diagnosing.

Fix 1: replace alternation-as-value with concrete singular examples
("US-1", "interface") and lift the allowed-forms enumeration into adjacent
prose so the schema can't be copied wrong.

Fix 2: §"On TaskCreate rejection" — read the rejection dump, identify the
bad field, re-issue the same TaskCreate; never call TaskUpdate on phantom
ids. Three retries on the same field escalates to the user.

Fix 3: §"Pre-dispatch" scopes the queue to tasks whose user_story matches
the active PRD's US/AC tags or starts with "chore:" (chores during a
feature are this-branch work, never stale). Empty-queue branch now
distinguishes three cases (PRD/no tasks; PRD/different-PRD tasks;
no PRD/no tasks) with specific next-step messages.

Also bumps marketplace.json 4.2.3 → 4.3.1, catching up the 4.3.0 release
that missed the marketplace metadata.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NOGIT007
NOGIT007 merged commit c5bad00 into main May 16, 2026
1 check passed
@NOGIT007
NOGIT007 deleted the fix/plan-ship-metadata-trap-and-empty-queue branch May 16, 2026 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant