Add autonomous execution guard to plan-slice, execute-task, and complete-slice prompts prohibiting ask_user_questions and secure_env_collect in auto-mode. When the LLM called these interactive tools mid-unit, the queued user response caused the subsequent gsd_plan_slice/gsd_complete_task call to fail with "Skipped due to queued user message", leading to artifact verification failure and stuck-loop re-dispatch 2-4x. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
493bf3cd6b
commit
aa6cde32d9
4 changed files with 77 additions and 0 deletions
|
|
@ -33,6 +33,8 @@ Then:
|
|||
12. Do not run git commands — the system commits your changes and handles any merge after this unit succeeds.
|
||||
13. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed.
|
||||
|
||||
**Autonomous execution:** Do not call `ask_user_questions` or `secure_env_collect`. You are running in auto-mode — there is no human available to answer questions. Make reasonable assumptions and document them in the slice summary. If a decision genuinely requires human input, note it in the summary and proceed with the best available option.
|
||||
|
||||
**You MUST call `gsd_complete_slice` with the slice summary and UAT content before finishing. The tool persists to both DB and disk and renders `{{sliceSummaryPath}}` and `{{sliceUatPath}}` automatically.**
|
||||
|
||||
When done, say: "Slice {{sliceId}} complete."
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ Then:
|
|||
|
||||
All work stays in your working directory: `{{workingDirectory}}`.
|
||||
|
||||
**Autonomous execution:** Do not call `ask_user_questions` or `secure_env_collect`. You are running in auto-mode — there is no human available to answer questions. Make reasonable assumptions and document them in the task summary. If a decision genuinely requires human input, note it in the summary and proceed with the best available option.
|
||||
|
||||
**You MUST call `gsd_complete_task` AND write `{{taskSummaryPath}}` before finishing.**
|
||||
|
||||
When done, say: "Task {{taskId}} complete."
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ Then:
|
|||
|
||||
The slice directory and tasks/ subdirectory already exist. Do NOT mkdir. All work stays in your working directory: `{{workingDirectory}}`.
|
||||
|
||||
**Autonomous execution:** Do not call `ask_user_questions` or `secure_env_collect`. You are running in auto-mode — there is no human available to answer questions. Make reasonable assumptions and document them in the plan. If a decision genuinely requires human input, write a note in the relevant task's description and call `gsd_plan_slice` with what you have.
|
||||
|
||||
**You MUST call `gsd_plan_slice` to persist the planning state before finishing.**
|
||||
|
||||
When done, say: "Slice {{sliceId}} planned."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Test: auto-mode prompts must prohibit ask_user_questions / secure_env_collect
|
||||
*
|
||||
* Bug #2936: When the LLM calls ask_user_questions during auto-mode units
|
||||
* (plan-slice, execute-task, complete-slice), the interactive tool queues a
|
||||
* user response which causes the subsequent gsd_plan_slice / gsd_complete_task
|
||||
* call to fail with "Skipped due to queued user message." The canonical GSD
|
||||
* tool call is never recorded, verifyExpectedArtifact finds no artifact, and
|
||||
* the dispatch loop re-dispatches the same unit 2-4x.
|
||||
*
|
||||
* Fix: Each auto-mode prompt must contain an "Autonomous execution" guard
|
||||
* that explicitly prohibits ask_user_questions and secure_env_collect.
|
||||
*/
|
||||
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const promptsDir = join(__dirname, "..", "prompts");
|
||||
|
||||
function loadPromptRaw(name: string): string {
|
||||
return readFileSync(join(promptsDir, `${name}.md`), "utf-8");
|
||||
}
|
||||
|
||||
const AUTO_MODE_PROMPTS = ["plan-slice", "execute-task", "complete-slice"];
|
||||
|
||||
for (const promptName of AUTO_MODE_PROMPTS) {
|
||||
test(`${promptName} prompt prohibits ask_user_questions in auto-mode`, () => {
|
||||
const content = loadPromptRaw(promptName);
|
||||
|
||||
assert.ok(
|
||||
content.includes("ask_user_questions"),
|
||||
`${promptName}.md must mention ask_user_questions (to prohibit it)`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
content.includes("secure_env_collect"),
|
||||
`${promptName}.md must mention secure_env_collect (to prohibit it)`,
|
||||
);
|
||||
|
||||
// The guard must clearly state this is autonomous / auto-mode
|
||||
assert.ok(
|
||||
content.toLowerCase().includes("auto-mode") || content.toLowerCase().includes("autonomous"),
|
||||
`${promptName}.md must reference auto-mode or autonomous execution`,
|
||||
);
|
||||
|
||||
// The guard must indicate no human is available
|
||||
assert.ok(
|
||||
content.includes("no human") || content.includes("no user"),
|
||||
`${promptName}.md must state that no human/user is available to answer`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
test("auto-mode prompts contain autonomous guard before final tool call reminder", () => {
|
||||
for (const promptName of AUTO_MODE_PROMPTS) {
|
||||
const content = loadPromptRaw(promptName);
|
||||
|
||||
// The guard should appear before the final "MUST call" line
|
||||
const guardIndex = content.indexOf("ask_user_questions");
|
||||
const mustCallIndex = content.lastIndexOf("MUST call");
|
||||
|
||||
assert.ok(
|
||||
guardIndex !== -1 && mustCallIndex !== -1 && guardIndex < mustCallIndex,
|
||||
`${promptName}.md: autonomous guard (ask_user_questions prohibition) must appear before the final MUST call reminder`,
|
||||
);
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue