feat(FN-4371): complete Step 4 — triage decision-only heuristic
Fusion-Task-Id: FN-4371 Fusion-Task-Lineage: 4175ba4c-b7cb-4f3a-87c5-75e51f06c0ff
This commit is contained in:
@@ -1513,7 +1513,7 @@ describe("approved triage recovery", () => {
|
||||
await mkdir(join(rootDir, ".fusion", "tasks", "FN-001"), { recursive: true });
|
||||
await writeFile(
|
||||
join(rootDir, ".fusion", "tasks", "FN-001", "PROMPT.md"),
|
||||
"# Task: FN-001\n\n**Size:** M\n\n## Review Level: 2\n\nRecovered specification",
|
||||
"# Task: FN-001\n\n**Size:** M\n\n**No commits expected:** true\n\n## Review Level: 2\n\nRecovered specification",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1558,6 +1558,7 @@ describe("approved triage recovery", () => {
|
||||
dependencies: ["FN-1247"],
|
||||
size: "M",
|
||||
reviewLevel: 2,
|
||||
noCommitsExpected: true,
|
||||
});
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "todo");
|
||||
expect(store.logEntry).toHaveBeenCalledWith(
|
||||
@@ -1644,6 +1645,13 @@ describe("approved triage recovery", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("includes decision-only noCommitsExpected heuristic instructions in system prompts", () => {
|
||||
expect(TRIAGE_SYSTEM_PROMPT).toContain("**No commits expected:** true");
|
||||
expect(TRIAGE_SYSTEM_PROMPT).toContain("Decide whether FN-XYZ needs a fix");
|
||||
expect(TRIAGE_SYSTEM_PROMPT).toContain("Investigate FN-XYZ and fix if needed");
|
||||
expect(FAST_TRIAGE_SYSTEM_PROMPT).toContain("**No commits expected:** true");
|
||||
});
|
||||
|
||||
it("preserves imported GitHub issue titles during planning recovery", async () => {
|
||||
await writeFile(
|
||||
join(rootDir, ".fusion", "tasks", "FN-001", "PROMPT.md"),
|
||||
|
||||
@@ -250,6 +250,21 @@ When the planning conversation produces a structured plan, save it as a document
|
||||
- Testing & Verification must run before Documentation & Delivery
|
||||
- Avoid giant catch-all steps; split outcomes so execution can be verified incrementally
|
||||
|
||||
## Decision-only task flag (noCommitsExpected)
|
||||
When ALL of the following are true, include this metadata line in the header block after Size/Review Level:
|
||||
|
||||
- Add this exact line: **No commits expected:** true
|
||||
|
||||
Set it only when all of these conditions hold:
|
||||
- Title/mission starts with decision verbs like "Decide", "Evaluate", "Verify", "Confirm", "Audit", "Review whether", or "Investigate and report"
|
||||
- Acceptance criteria are strictly observational (record findings, log a decision, update task log/docs) with no required code/config/file mutations
|
||||
- Task description explicitly says things like "no code changes expected" or "the deliverable is the recorded decision"
|
||||
|
||||
Anti-heuristics (bias to false-negative when ambiguous):
|
||||
- SET: Decide whether FN-XYZ needs a fix
|
||||
- LEAVE UNSET: Investigate FN-XYZ
|
||||
- LEAVE UNSET: Investigate FN-XYZ and fix if needed
|
||||
|
||||
## Guidelines
|
||||
- Read the project structure and relevant source files to understand context BEFORE writing
|
||||
- Check package.json/scripts and explicit project commands to align real lint/test/build/typecheck commands
|
||||
@@ -451,6 +466,21 @@ If an existing task already covers the same work, do NOT write a PROMPT.md. Inst
|
||||
When adding a dependency in \`## Dependencies\`, first call \`fn_task_get\` for that task and read its PROMPT.md.
|
||||
Use that context to align file paths, APIs, assumptions, and completion expectations. If the dependency has no PROMPT.md yet, note that explicitly.
|
||||
|
||||
## Decision-only task flag (noCommitsExpected)
|
||||
When ALL of the following are true, include this metadata line in the header block after Size:
|
||||
|
||||
- Add this exact line: **No commits expected:** true
|
||||
|
||||
Set it only when all of these conditions hold:
|
||||
- Title/mission starts with decision verbs like "Decide", "Evaluate", "Verify", "Confirm", "Audit", "Review whether", or "Investigate and report"
|
||||
- Acceptance criteria are strictly observational (record findings, log a decision, update task log/docs) with no required code/config/file mutations
|
||||
- Task description explicitly says things like "no code changes expected" or "the deliverable is the recorded decision"
|
||||
|
||||
Anti-heuristics (bias to false-negative when ambiguous):
|
||||
- SET: Decide whether FN-XYZ needs a fix
|
||||
- LEAVE UNSET: Investigate FN-XYZ
|
||||
- LEAVE UNSET: Investigate FN-XYZ and fix if needed
|
||||
|
||||
## Guidelines
|
||||
- Read relevant source files before writing the spec
|
||||
- Be specific: reference concrete files, modules, and commands from this repo
|
||||
@@ -2085,6 +2115,11 @@ export class TriageProcessor {
|
||||
taskUpdates.reviewLevel = parseInt(reviewMatch[1], 10);
|
||||
}
|
||||
|
||||
const noCommitsExpectedMatch = written.match(/^\*\*No commits expected:\*\*\s*(true|yes)\b/im);
|
||||
if (noCommitsExpectedMatch) {
|
||||
taskUpdates.noCommitsExpected = true;
|
||||
}
|
||||
|
||||
// Apply non-title metadata first. The title is held back and applied AFTER
|
||||
// the column transition (see below) because store.updateTask regenerates
|
||||
// PROMPT.md when title/description change, and the triage-stub regen path
|
||||
|
||||
Reference in New Issue
Block a user