diff --git a/.changeset/proud-geese-caper.md b/.changeset/proud-geese-caper.md new file mode 100644 index 000000000..d925cf412 --- /dev/null +++ b/.changeset/proud-geese-caper.md @@ -0,0 +1,5 @@ +--- +type: Fixed +pr: 2227 +--- +**`/gsd-debug` no longer stalls on a phantom background handoff** — the orchestrator treated the foreground session-manager spawn as a background task and queried its agent ID via TaskOutput (which needs a task ID), then waited on a handoff that was never queryable. The workflow now states the spawn is foreground/blocking, forbids passing an agent ID to TaskOutput, and gives a lost-handoff recovery path. (#2196) diff --git a/gsd-core/workflows/debug.md b/gsd-core/workflows/debug.md index f3ae29109..7bd7a78d4 100644 --- a/gsd-core/workflows/debug.md +++ b/gsd-core/workflows/debug.md @@ -190,6 +190,8 @@ Create `.planning/debug/{slug}.md` with initial state using the Write tool (neve After initial context setup, spawn the session manager to handle the full checkpoint/continuation loop. The session manager handles specialist_hint dispatch internally: when gsd-debugger returns ROOT CAUSE FOUND it extracts the specialist_hint field and invokes the matching skill (e.g. typescript-expert, swift-concurrency) before offering fix options. +> **Foreground, blocking spawn — #2196.** The `Agent(subagent_type="gsd-debug-session-manager", …)` call below is FOREGROUND and BLOCKING — it returns the compact session summary directly. Wait for it; do not background it, and do not poll for it. Never pass an agent or session identifier to `TaskOutput` — an agent ID is NOT a task ID, so `TaskOutput ` always returns `No task found with ID`. If the spawn returns no usable result (the handoff is lost), do NOT claim the session is still running: preserve the checkpoint at `.planning/debug/{slug}.md`, report the failed handoff plainly, and resume by re-spawning the session manager or via `/gsd:debug continue {slug}`. + Print before spawning (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze): ``` [debug] Delegating loop to session manager... diff --git a/tests/fix-2196-debug-agent-handoff.test.cjs b/tests/fix-2196-debug-agent-handoff.test.cjs new file mode 100644 index 000000000..623533aaf --- /dev/null +++ b/tests/fix-2196-debug-agent-handoff.test.cjs @@ -0,0 +1,52 @@ +'use strict'; + +/** + * #2194… no — #2196: the /gsd-debug orchestrator misused the foreground + * session-manager Agent() spawn as a background task, then queried the returned + * agent ID via TaskOutput (which expects a task ID) — yielding "No task found + * with ID" and leaving the workflow waiting on a handoff that was never + * queryable, with no recovery. + * + * The fix makes debug.md state explicitly that the spawn is foreground/blocking, + * that an agent ID must never be passed to TaskOutput, and that a lost handoff + * must be recovered (preserve checkpoint + resume). debug.md IS the product the + * runtime loads, so this asserts the deployed text carries that contract. + */ + +const { describe, test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); + +const DEBUG_MD = path.join(__dirname, '..', 'gsd-core', 'workflows', 'debug.md'); + +describe('#2196 debug.md session-manager spawn contract', () => { + const content = fs.readFileSync(DEBUG_MD, 'utf-8'); + const sectionStart = content.indexOf('Session Management'); + const section = sectionStart !== -1 ? content.slice(sectionStart) : ''; + + test('debug.md has the Session Management section', () => { + assert.notEqual(sectionStart, -1, 'debug.md must contain the Session Management section'); + }); + + test('the session-manager spawn is declared foreground/blocking (not backgrounded)', () => { + assert.ok(/foreground/i.test(section) && /blocking/i.test(section), + 'the Agent() spawn must be declared foreground and blocking so it is not polled'); + }); + + test('an agent ID must not be passed to TaskOutput', () => { + assert.ok(/TaskOutput/.test(section), + 'the contract must mention TaskOutput by name'); + assert.ok(/agent ID is NOT a task ID|agent ID is not a task ID/i.test(section), + 'the contract must state an agent ID is not a task ID'); + }); + + test('a lost handoff has a recovery path (preserve checkpoint + resume)', () => { + // Pin the CANONICAL colon form — the retired /gsd-debug hyphen syntax is + // rejected by the slash-command-namespace guard, so this must be /gsd:debug. + assert.ok(/\/gsd:debug continue \{slug\}/.test(section), + 'the contract must point to /gsd:debug continue {slug} (canonical colon form) as the resume path'); + assert.ok(/do not claim|do NOT claim/i.test(section), + 'the contract must forbid claiming a lost-handoff session is still running'); + }); +}); diff --git a/tests/fixtures/golden-install-parity/antigravity.json b/tests/fixtures/golden-install-parity/antigravity.json index 2529f592e..c81c1c0ee 100644 --- a/tests/fixtures/golden-install-parity/antigravity.json +++ b/tests/fixtures/golden-install-parity/antigravity.json @@ -211,7 +211,7 @@ "gsd-core/workflows/code-review-fix.md": "60640e633b0a124b", "gsd-core/workflows/code-review.md": "5c40505c01871153", "gsd-core/workflows/complete-milestone.md": "aaf272074acec69d", - "gsd-core/workflows/debug.md": "68f1ddc74886ebe5", + "gsd-core/workflows/debug.md": "af2d1ae03b24fc71", "gsd-core/workflows/diagnose-issues.md": "c8c41993c277363c", "gsd-core/workflows/discovery-phase.md": "3de990caffdde4f8", "gsd-core/workflows/discuss-phase-assumptions.md": "8581fd77def7ce84", diff --git a/tests/fixtures/golden-install-parity/augment.json b/tests/fixtures/golden-install-parity/augment.json index 9715eb856..8b4b9e282 100644 --- a/tests/fixtures/golden-install-parity/augment.json +++ b/tests/fixtures/golden-install-parity/augment.json @@ -282,7 +282,7 @@ "gsd-core/workflows/code-review-fix.md": "2e113d1f4350a075", "gsd-core/workflows/code-review.md": "334c90c401f291f8", "gsd-core/workflows/complete-milestone.md": "c1f91b77f4ace7f2", - "gsd-core/workflows/debug.md": "849d7e5b9c12dcae", + "gsd-core/workflows/debug.md": "c581e89aa9d9d71e", "gsd-core/workflows/diagnose-issues.md": "6cc3900891dfb927", "gsd-core/workflows/discovery-phase.md": "3ba7cfb89fb1e761", "gsd-core/workflows/discuss-phase-assumptions.md": "f5b765d33eba4f88", diff --git a/tests/fixtures/golden-install-parity/claude-local.json b/tests/fixtures/golden-install-parity/claude-local.json index e825323e6..ec1bd721d 100644 --- a/tests/fixtures/golden-install-parity/claude-local.json +++ b/tests/fixtures/golden-install-parity/claude-local.json @@ -281,7 +281,7 @@ "gsd-core/workflows/code-review-fix.md": "78c716068ccdf820", "gsd-core/workflows/code-review.md": "2d21452eb0449fdd", "gsd-core/workflows/complete-milestone.md": "9962377cddee50d7", - "gsd-core/workflows/debug.md": "3354c726abbfd75b", + "gsd-core/workflows/debug.md": "18c97b804f2dd5dd", "gsd-core/workflows/diagnose-issues.md": "db6a599674efbc4d", "gsd-core/workflows/discovery-phase.md": "a20dfb32adec51de", "gsd-core/workflows/discuss-phase-assumptions.md": "35a3b2d1285565d8", diff --git a/tests/fixtures/golden-install-parity/claude.json b/tests/fixtures/golden-install-parity/claude.json index 89a1f3e6f..c2f7e3af9 100644 --- a/tests/fixtures/golden-install-parity/claude.json +++ b/tests/fixtures/golden-install-parity/claude.json @@ -210,7 +210,7 @@ "gsd-core/workflows/code-review-fix.md": "722416b71b31c5fc", "gsd-core/workflows/code-review.md": "506412604f767adc", "gsd-core/workflows/complete-milestone.md": "dcf1182398efb1ca", - "gsd-core/workflows/debug.md": "a9397fd35cca2240", + "gsd-core/workflows/debug.md": "7183935f8e145a01", "gsd-core/workflows/diagnose-issues.md": "75ffc381ac3059ff", "gsd-core/workflows/discovery-phase.md": "6161c60d752d0058", "gsd-core/workflows/discuss-phase-assumptions.md": "a8cd1db094fefd35", diff --git a/tests/fixtures/golden-install-parity/cline.json b/tests/fixtures/golden-install-parity/cline.json index d7f323bbc..2a41dd607 100644 --- a/tests/fixtures/golden-install-parity/cline.json +++ b/tests/fixtures/golden-install-parity/cline.json @@ -214,7 +214,7 @@ "gsd-core/workflows/code-review-fix.md": "e4549af672e74e6f", "gsd-core/workflows/code-review.md": "a65e3e869508f89e", "gsd-core/workflows/complete-milestone.md": "c0808127038a8f86", - "gsd-core/workflows/debug.md": "f42e8e3cbc298694", + "gsd-core/workflows/debug.md": "337fc2076e7fc449", "gsd-core/workflows/diagnose-issues.md": "e616d0d730328d68", "gsd-core/workflows/discovery-phase.md": "3ba7cfb89fb1e761", "gsd-core/workflows/discuss-phase-assumptions.md": "9efcb2ef6a9245b3", diff --git a/tests/fixtures/golden-install-parity/codebuddy.json b/tests/fixtures/golden-install-parity/codebuddy.json index 3ef9ae7aa..ebccb820a 100644 --- a/tests/fixtures/golden-install-parity/codebuddy.json +++ b/tests/fixtures/golden-install-parity/codebuddy.json @@ -282,7 +282,7 @@ "gsd-core/workflows/code-review-fix.md": "2e113d1f4350a075", "gsd-core/workflows/code-review.md": "334c90c401f291f8", "gsd-core/workflows/complete-milestone.md": "c1f91b77f4ace7f2", - "gsd-core/workflows/debug.md": "849d7e5b9c12dcae", + "gsd-core/workflows/debug.md": "c581e89aa9d9d71e", "gsd-core/workflows/diagnose-issues.md": "77d98ac07c4a26ff", "gsd-core/workflows/discovery-phase.md": "3ba7cfb89fb1e761", "gsd-core/workflows/discuss-phase-assumptions.md": "f5b765d33eba4f88", diff --git a/tests/fixtures/golden-install-parity/codex.json b/tests/fixtures/golden-install-parity/codex.json index 15d7132dd..cd6c6ccf2 100644 --- a/tests/fixtures/golden-install-parity/codex.json +++ b/tests/fixtures/golden-install-parity/codex.json @@ -317,7 +317,7 @@ "gsd-core/workflows/code-review-fix.md": "ae7f9c6b39a23c12", "gsd-core/workflows/code-review.md": "eadada9e0a89adf2", "gsd-core/workflows/complete-milestone.md": "017df7443bd08da5", - "gsd-core/workflows/debug.md": "cc7b2d2fd4307a78", + "gsd-core/workflows/debug.md": "7c3b407470762585", "gsd-core/workflows/diagnose-issues.md": "e38bb21d06dff077", "gsd-core/workflows/discovery-phase.md": "71a4b78ff876a854", "gsd-core/workflows/discuss-phase-assumptions.md": "0d936ec25299917c", diff --git a/tests/fixtures/golden-install-parity/copilot.json b/tests/fixtures/golden-install-parity/copilot.json index 813333959..d24e717ad 100644 --- a/tests/fixtures/golden-install-parity/copilot.json +++ b/tests/fixtures/golden-install-parity/copilot.json @@ -212,7 +212,7 @@ "gsd-core/workflows/code-review-fix.md": "fda53892ae4b17fc", "gsd-core/workflows/code-review.md": "f1c045ec4d33abc8", "gsd-core/workflows/complete-milestone.md": "470cf39261400ee2", - "gsd-core/workflows/debug.md": "36cb536be452d79e", + "gsd-core/workflows/debug.md": "505ed67d48b1fa9d", "gsd-core/workflows/diagnose-issues.md": "42acbe2a43fc886e", "gsd-core/workflows/discovery-phase.md": "8e99da61fb2b7074", "gsd-core/workflows/discuss-phase-assumptions.md": "ab0c432b84038681", diff --git a/tests/fixtures/golden-install-parity/cursor.json b/tests/fixtures/golden-install-parity/cursor.json index f16b51a78..dd01c479c 100644 --- a/tests/fixtures/golden-install-parity/cursor.json +++ b/tests/fixtures/golden-install-parity/cursor.json @@ -282,7 +282,7 @@ "gsd-core/workflows/code-review-fix.md": "c57af378033b1b58", "gsd-core/workflows/code-review.md": "32c37bcbec8b8698", "gsd-core/workflows/complete-milestone.md": "1400a4856f592f3e", - "gsd-core/workflows/debug.md": "a73d8018986131ba", + "gsd-core/workflows/debug.md": "c02dec84c8a346b9", "gsd-core/workflows/diagnose-issues.md": "cd582747131726e3", "gsd-core/workflows/discovery-phase.md": "7dcf150998559c11", "gsd-core/workflows/discuss-phase-assumptions.md": "c25c6a6c633d71b6", diff --git a/tests/fixtures/golden-install-parity/hermes.json b/tests/fixtures/golden-install-parity/hermes.json index 7a187e3b0..57f4fee5d 100644 --- a/tests/fixtures/golden-install-parity/hermes.json +++ b/tests/fixtures/golden-install-parity/hermes.json @@ -211,7 +211,7 @@ "gsd-core/workflows/code-review-fix.md": "e829d3baf9901b54", "gsd-core/workflows/code-review.md": "50a05ab8957bd05f", "gsd-core/workflows/complete-milestone.md": "f1866541148dc291", - "gsd-core/workflows/debug.md": "15cf6999e85dcc8c", + "gsd-core/workflows/debug.md": "639348c8657e7147", "gsd-core/workflows/diagnose-issues.md": "16f2d2a85335641f", "gsd-core/workflows/discovery-phase.md": "6161c60d752d0058", "gsd-core/workflows/discuss-phase-assumptions.md": "3a1e215890d2b3f4", diff --git a/tests/fixtures/golden-install-parity/kilo.json b/tests/fixtures/golden-install-parity/kilo.json index c363502d4..a2cc18051 100644 --- a/tests/fixtures/golden-install-parity/kilo.json +++ b/tests/fixtures/golden-install-parity/kilo.json @@ -282,7 +282,7 @@ "gsd-core/workflows/code-review-fix.md": "722416b71b31c5fc", "gsd-core/workflows/code-review.md": "506412604f767adc", "gsd-core/workflows/complete-milestone.md": "59753bf44d4300da", - "gsd-core/workflows/debug.md": "a72d830ac3df74aa", + "gsd-core/workflows/debug.md": "28c964bceb6f03af", "gsd-core/workflows/diagnose-issues.md": "210b5b313e8a559a", "gsd-core/workflows/discovery-phase.md": "ca7b2be46e59e862", "gsd-core/workflows/discuss-phase-assumptions.md": "3ef1df313e715387", diff --git a/tests/fixtures/golden-install-parity/kimi.json b/tests/fixtures/golden-install-parity/kimi.json index 43ff9373a..eef41d3cd 100644 --- a/tests/fixtures/golden-install-parity/kimi.json +++ b/tests/fixtures/golden-install-parity/kimi.json @@ -275,7 +275,7 @@ "gsd-core/workflows/code-review-fix.md": "2e113d1f4350a075", "gsd-core/workflows/code-review.md": "334c90c401f291f8", "gsd-core/workflows/complete-milestone.md": "c1f91b77f4ace7f2", - "gsd-core/workflows/debug.md": "849d7e5b9c12dcae", + "gsd-core/workflows/debug.md": "c581e89aa9d9d71e", "gsd-core/workflows/diagnose-issues.md": "67c058fc7ae6026b", "gsd-core/workflows/discovery-phase.md": "3ba7cfb89fb1e761", "gsd-core/workflows/discuss-phase-assumptions.md": "f5b765d33eba4f88", diff --git a/tests/fixtures/golden-install-parity/opencode.json b/tests/fixtures/golden-install-parity/opencode.json index 8cbf839b3..7c19f52c7 100644 --- a/tests/fixtures/golden-install-parity/opencode.json +++ b/tests/fixtures/golden-install-parity/opencode.json @@ -282,7 +282,7 @@ "gsd-core/workflows/code-review-fix.md": "adb9388bb157610c", "gsd-core/workflows/code-review.md": "ae6bcbd1575aeec4", "gsd-core/workflows/complete-milestone.md": "614299b2c08e66c3", - "gsd-core/workflows/debug.md": "9d4a8afc8d36be93", + "gsd-core/workflows/debug.md": "437b47e14eba8786", "gsd-core/workflows/diagnose-issues.md": "2971c699d52f1b85", "gsd-core/workflows/discovery-phase.md": "724408336596c50c", "gsd-core/workflows/discuss-phase-assumptions.md": "92e43cd12200c610", diff --git a/tests/fixtures/golden-install-parity/pi.json b/tests/fixtures/golden-install-parity/pi.json index ece2925e8..bcf46ba88 100644 --- a/tests/fixtures/golden-install-parity/pi.json +++ b/tests/fixtures/golden-install-parity/pi.json @@ -178,7 +178,7 @@ "gsd-core/workflows/code-review-fix.md": "2e113d1f4350a075", "gsd-core/workflows/code-review.md": "334c90c401f291f8", "gsd-core/workflows/complete-milestone.md": "c1f91b77f4ace7f2", - "gsd-core/workflows/debug.md": "849d7e5b9c12dcae", + "gsd-core/workflows/debug.md": "c581e89aa9d9d71e", "gsd-core/workflows/diagnose-issues.md": "d6d978fddfd5da8d", "gsd-core/workflows/discovery-phase.md": "3ba7cfb89fb1e761", "gsd-core/workflows/discuss-phase-assumptions.md": "f5b765d33eba4f88", diff --git a/tests/fixtures/golden-install-parity/qwen.json b/tests/fixtures/golden-install-parity/qwen.json index f1213ed48..81c60c85f 100644 --- a/tests/fixtures/golden-install-parity/qwen.json +++ b/tests/fixtures/golden-install-parity/qwen.json @@ -211,7 +211,7 @@ "gsd-core/workflows/code-review-fix.md": "f3725ae9d685bed2", "gsd-core/workflows/code-review.md": "29125604bed2c467", "gsd-core/workflows/complete-milestone.md": "40085d32b15805c8", - "gsd-core/workflows/debug.md": "c23d067580b09f63", + "gsd-core/workflows/debug.md": "a4e4c2f6d004460e", "gsd-core/workflows/diagnose-issues.md": "652ae26975f82242", "gsd-core/workflows/discovery-phase.md": "6161c60d752d0058", "gsd-core/workflows/discuss-phase-assumptions.md": "18712f78bb960ec8", diff --git a/tests/fixtures/golden-install-parity/trae.json b/tests/fixtures/golden-install-parity/trae.json index aa3551cf0..027a8b0ac 100644 --- a/tests/fixtures/golden-install-parity/trae.json +++ b/tests/fixtures/golden-install-parity/trae.json @@ -211,7 +211,7 @@ "gsd-core/workflows/code-review-fix.md": "f2761f7f8c4a5674", "gsd-core/workflows/code-review.md": "47663a2922756c5e", "gsd-core/workflows/complete-milestone.md": "6e918b72bd885426", - "gsd-core/workflows/debug.md": "197d3642a6704de5", + "gsd-core/workflows/debug.md": "7783c3cb81fef70d", "gsd-core/workflows/diagnose-issues.md": "9274b11a3db98c65", "gsd-core/workflows/discovery-phase.md": "b32b6197b66c9a13", "gsd-core/workflows/discuss-phase-assumptions.md": "e376b1cf29379df4", diff --git a/tests/fixtures/golden-install-parity/windsurf.json b/tests/fixtures/golden-install-parity/windsurf.json index 7bec92ba7..76b19cb99 100644 --- a/tests/fixtures/golden-install-parity/windsurf.json +++ b/tests/fixtures/golden-install-parity/windsurf.json @@ -211,7 +211,7 @@ "gsd-core/workflows/code-review-fix.md": "b99b1f20bb27c291", "gsd-core/workflows/code-review.md": "faa87faf07ae765a", "gsd-core/workflows/complete-milestone.md": "f463bf4e86ac26f6", - "gsd-core/workflows/debug.md": "52243eb936a43150", + "gsd-core/workflows/debug.md": "d0ee63e547f4d997", "gsd-core/workflows/diagnose-issues.md": "447072aa72385271", "gsd-core/workflows/discovery-phase.md": "7dcf150998559c11", "gsd-core/workflows/discuss-phase-assumptions.md": "b091b3d3e580dd29", diff --git a/tests/fixtures/golden-install-parity/zcode.json b/tests/fixtures/golden-install-parity/zcode.json index f9aa16f65..7c3ef7577 100644 --- a/tests/fixtures/golden-install-parity/zcode.json +++ b/tests/fixtures/golden-install-parity/zcode.json @@ -282,7 +282,7 @@ "gsd-core/workflows/code-review-fix.md": "2e113d1f4350a075", "gsd-core/workflows/code-review.md": "334c90c401f291f8", "gsd-core/workflows/complete-milestone.md": "c1f91b77f4ace7f2", - "gsd-core/workflows/debug.md": "849d7e5b9c12dcae", + "gsd-core/workflows/debug.md": "c581e89aa9d9d71e", "gsd-core/workflows/diagnose-issues.md": "aa8d787db8f3c46c", "gsd-core/workflows/discovery-phase.md": "3ba7cfb89fb1e761", "gsd-core/workflows/discuss-phase-assumptions.md": "f5b765d33eba4f88", diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index 9e7b9fc87..7ba2a99d9 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -14,7 +14,7 @@ "code-review-fix.md": 24320, "code-review.md": 31916, "complete-milestone.md": 31071, - "debug.md": 13549, + "debug.md": 14241, "diagnose-issues.md": 12864, "discovery-phase.md": 8651, "discuss-phase-assumptions.md": 27302,