feat(FN-671): preserve quick entry disclosure and normalize comment migration

- Keep QuickEntryBox disclosure state persisted and covered by updated UI tests
- Add normalized legacy comment migration logic to unify steering comments without duplication
- Update database migration tests to verify schema v5 comment handling behavior
- Carry merged dashboard, engine, and routing changes into the squash commit
This commit is contained in:
gsxdsm
2026-04-01 13:07:26 -07:00
parent 7f47013d13
commit d80a5765cf
14 changed files with 511 additions and 230 deletions

View File

@@ -1587,6 +1587,8 @@ describe("buildExecutionPrompt", () => {
expect(result).toContain("## Project Commands");
expect(result).toContain("- **Build:** `pnpm build`");
expect(result).not.toContain("- **Test:**");
expect(result).toContain("run that exact command in this worktree before calling `task_done()`");
expect(result).toContain("Do not claim success without a real passing run");
});
it("includes both commands when both are set", () => {

View File

@@ -140,7 +140,13 @@ model, read-only access) to independently assess your work.
## Completion
After all steps are done, tests pass, and docs are updated:
\`\`\`bash
Call \`task_done()\` to signal completion.`;
Call \`task_done()\` to signal completion.
\`\`\`
If a project build command is listed in the prompt, it is a hard completion gate:
- Run the exact build command in the current worktree before \`task_done()\`
- Do not claim the build passes unless you actually ran it and got exit code 0
- If the build fails, do NOT call \`task_done()\`; keep working until it passes`;
export interface TaskExecutorOptions {
semaphore?: AgentSemaphore;
@@ -1892,7 +1898,8 @@ Use \`task_create\` if you find out-of-scope work that needs doing.
Commit at step boundaries: \`git commit -m "feat(${task.id}): complete Step N — description"\`
When all steps are complete: call \`task_done()\`
Verify build passes using the configured build command before calling \`task_done()\`.`;
If a build command is configured, run that exact command in this worktree before calling \`task_done()\`.
Treat a non-zero exit code as a blocking failure. Do not claim success without a real passing run.`;
}
/**

View File

@@ -1704,18 +1704,21 @@ describe("aiMergeTask — build verification", () => {
await aiMergeTask(store, "/tmp/root", "FN-050");
expect(capturedSystemPrompt).toContain("## Build verification");
expect(capturedSystemPrompt).toContain("If a build command is configured for this project, you MUST run it");
expect(capturedSystemPrompt).toContain("BUILD FAILED:");
expect(capturedSystemPrompt).toContain("build verification is a hard gate");
expect(capturedSystemPrompt).toContain("Do not assume the build passes");
expect(capturedSystemPrompt).toContain("report_build_failure");
});
it("includes build command in merge prompt when configured", async () => {
let capturedArgs: any;
let capturedPrompt: string | undefined;
mockedCreateHaiAgent.mockImplementation(async (opts: any) => {
capturedArgs = opts;
// Simulate agent committing by returning session that results in clean state
return {
session: {
prompt: vi.fn().mockImplementation(async () => {
prompt: vi.fn().mockImplementation(async (prompt: string) => {
capturedPrompt = prompt;
// Simulate commit happening by making staged check return "0" (clean)
mockedExecSync.mockImplementation((cmd: any) => {
const cmdStr = String(cmd);
@@ -1749,6 +1752,10 @@ describe("aiMergeTask — build verification", () => {
// Verify custom tool was passed
expect(capturedArgs.customTools).toBeDefined();
expect(capturedArgs.customTools.some((t: any) => t.name === "report_build_failure")).toBe(true);
expect(capturedPrompt).toContain("Build command: `pnpm build`");
expect(capturedPrompt).toContain("This command is mandatory before commit.");
expect(capturedPrompt).toContain("Only commit if it exits 0.");
expect(capturedPrompt).toContain("call `report_build_failure`");
});
it("merge succeeds when build passes (agent reports success)", async () => {

View File

@@ -477,13 +477,17 @@ Base the message on the ACTUAL work done in the branch commits.
## Build verification
If a build command is configured for this project, you MUST run it before committing.
If a build command is configured for this project, build verification is a hard gate.
You MUST run the exact configured build command in this worktree before committing.
Do not assume the build passes. Do not describe it as passing unless you actually ran it
and the bash tool returned exit code 0.
1. Run the build command (shown in the prompt context below)
2. If the build succeeds (exit code 0), proceed with the commit
3. If the build fails (non-zero exit code), DO NOT commit. Instead:
- Respond with "BUILD FAILED: <error details>"
- Stop and do not proceed further
- Call the \`report_build_failure\` tool with the real error details
- Stop immediately and do not run \`git commit\`
- Do not claim success in plain text
The merge will only be completed if the build passes or no build command is configured.`;
}
@@ -1254,7 +1258,10 @@ function buildMergePrompt(params: MergePromptParams): string {
"## Build command",
`Build command: \`${buildCommand}\``,
"",
"Run this command via bash tool before committing to verify the build passes.",
"This command is mandatory before commit.",
"Run it with the bash tool in the current worktree and inspect the actual exit code.",
"Only commit if it exits 0.",
"If it exits non-zero, call `report_build_failure` with the concrete error output and stop without committing.",
);
}