feat(FN-1016): add comment-aware triage generation and stale approval invalidation

- Include user comments as context during AI triage spec generation and spec review
- Invalidate stale spec approvals when new user comments are added after approval
- Add lastApprovedAt tracking to task metadata for approval freshness detection
- Add comprehensive tests for comment-aware triage, review, and stale approval logic
- Add changeset for published package and update README with feature documentation
This commit is contained in:
gsxdsm
2026-04-05 23:04:27 -07:00
parent ec33691033
commit 992e525648
8 changed files with 640 additions and 4 deletions

View File

@@ -2134,6 +2134,47 @@ Task with acceptance criteria
const refinement = allTasksAfter.find((t) => t.id !== task.id && t.title?.includes("Refinement"));
expect(refinement).toBeDefined();
});
it("transitions awaiting-approval to needs-respecify when user comments on triage task", async () => {
const task = await store.createTask({ description: "Task in triage" });
// Keep in triage but set awaiting-approval status
await store.updateTask(task.id, { status: "awaiting-approval" });
const result = await store.addComment(task.id, "I want to change the approach", "user");
// Re-read the task to get the Phase 3 status update
const updated = await store.getTask(task.id);
// Task should remain in triage but status should change to needs-respecify
expect(updated.column).toBe("triage");
expect(updated.status).toBe("needs-respecify");
// Comment should still be added
expect(updated.comments).toHaveLength(1);
expect(updated.comments![0].text).toBe("I want to change the approach");
});
it("does NOT transition to needs-respecify when agent comments on awaiting-approval task", async () => {
const task = await store.createTask({ description: "Task in triage" });
await store.updateTask(task.id, { status: "awaiting-approval" });
const updated = await store.addComment(task.id, "Agent system note", "agent");
// Status should remain awaiting-approval for agent comments
expect(updated.status).toBe("awaiting-approval");
// Comment should still be added
expect(updated.comments).toHaveLength(1);
});
it("does NOT transition to needs-respecify when user comments on non-awaiting-approval triage task", async () => {
const task = await store.createTask({ description: "Task in triage" });
// Task is in triage with no status (not awaiting-approval)
expect(task.status).toBeUndefined();
const updated = await store.addComment(task.id, "User feedback", "user");
// Status should remain undefined
expect(updated.status).toBeUndefined();
});
});
describe("task comments and merge details types", () => {

View File

@@ -2388,6 +2388,30 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
}
}
// Phase 3: Invalidate stale spec approval when a user comments on
// a triage task that is awaiting manual approval. The new comment
// means the spec is now stale and must be re-specified/re-reviewed.
// Note: The `task` returned above reflects the state BEFORE this
// transition. Callers that need the post-transition status should
// re-read the task (e.g., via getTask).
if (
task.column === "triage"
&& task.status === "awaiting-approval"
&& author === "user"
) {
try {
await this.updateTask(id, {
status: "needs-respecify",
});
await this.logEntry(
id,
`User comment invalidated spec approval — task needs re-specification`,
);
} catch {
// Best-effort: don't fail the comment if the status update fails
}
}
return task;
}