feat(start-work): auto-select single incomplete plan and use system-reminder format

- Auto-select when only one incomplete plan exists among multiple
- Wrap multiple plans message in <system-reminder> tag
- Change prompt to 'ask user' style for agent guidance
- Add 'All Plans Complete' state handling
This commit is contained in:
YeonGyu-Kim
2026-01-08 14:20:04 +09:00
parent 57fb5e0c71
commit 64b9b4d36a
2 changed files with 98 additions and 4 deletions

View File

@@ -151,5 +151,90 @@ describe("start-work hook", () => {
expect(output.parts[0].text).not.toContain("$TIMESTAMP")
expect(output.parts[0].text).toMatch(/\d{4}-\d{2}-\d{2}T/)
})
test("should auto-select when only one incomplete plan among multiple plans", async () => {
// #given - multiple plans but only one incomplete
const plansDir = join(TEST_DIR, ".sisyphus", "plans")
mkdirSync(plansDir, { recursive: true })
// Plan 1: complete (all checked)
const plan1Path = join(plansDir, "plan-complete.md")
writeFileSync(plan1Path, "# Plan Complete\n- [x] Task 1\n- [x] Task 2")
// Plan 2: incomplete (has unchecked)
const plan2Path = join(plansDir, "plan-incomplete.md")
writeFileSync(plan2Path, "# Plan Incomplete\n- [ ] Task 1\n- [x] Task 2")
const hook = createStartWorkHook(createMockPluginInput())
const output = {
parts: [{ type: "text", text: "Start Sisyphus work session" }],
}
// #when
await hook["chat.message"](
{ sessionID: "session-123" },
output
)
// #then - should auto-select the incomplete plan, not ask user
expect(output.parts[0].text).toContain("Auto-Selected Plan")
expect(output.parts[0].text).toContain("plan-incomplete")
expect(output.parts[0].text).not.toContain("Multiple Plans Found")
})
test("should wrap multiple plans message in system-reminder tag", async () => {
// #given - multiple incomplete plans
const plansDir = join(TEST_DIR, ".sisyphus", "plans")
mkdirSync(plansDir, { recursive: true })
const plan1Path = join(plansDir, "plan-a.md")
writeFileSync(plan1Path, "# Plan A\n- [ ] Task 1")
const plan2Path = join(plansDir, "plan-b.md")
writeFileSync(plan2Path, "# Plan B\n- [ ] Task 2")
const hook = createStartWorkHook(createMockPluginInput())
const output = {
parts: [{ type: "text", text: "Start Sisyphus work session" }],
}
// #when
await hook["chat.message"](
{ sessionID: "session-123" },
output
)
// #then - should use system-reminder tag format
expect(output.parts[0].text).toContain("<system-reminder>")
expect(output.parts[0].text).toContain("</system-reminder>")
expect(output.parts[0].text).toContain("Multiple Plans Found")
})
test("should use 'ask user' prompt style for multiple plans", async () => {
// #given - multiple incomplete plans
const plansDir = join(TEST_DIR, ".sisyphus", "plans")
mkdirSync(plansDir, { recursive: true })
const plan1Path = join(plansDir, "plan-x.md")
writeFileSync(plan1Path, "# Plan X\n- [ ] Task 1")
const plan2Path = join(plansDir, "plan-y.md")
writeFileSync(plan2Path, "# Plan Y\n- [ ] Task 2")
const hook = createStartWorkHook(createMockPluginInput())
const output = {
parts: [{ type: "text", text: "Start Sisyphus work session" }],
}
// #when
await hook["chat.message"](
{ sessionID: "session-123" },
output
)
// #then - should prompt agent to ask user, not ask directly
expect(output.parts[0].text).toContain("Ask the user")
expect(output.parts[0].text).not.toContain("Which plan would you like to work on?")
})
})
})

View File

@@ -80,6 +80,7 @@ Looking for new plans...`
if (!existingState || getPlanProgress(existingState.active_plan).isComplete) {
const plans = findPrometheusPlans(ctx.directory)
const incompletePlans = plans.filter(p => !getPlanProgress(p).isComplete)
if (plans.length === 0) {
contextInfo += `
@@ -88,8 +89,14 @@ Looking for new plans...`
No Prometheus plan files found at .sisyphus/plans/
Use Prometheus to create a work plan first: /plan "your task"`
} else if (plans.length === 1) {
const planPath = plans[0]
} else if (incompletePlans.length === 0) {
contextInfo += `
## All Plans Complete
All ${plans.length} plan(s) are complete. Create a new plan with: /plan "your task"`
} else if (incompletePlans.length === 1) {
const planPath = incompletePlans[0]
const progress = getPlanProgress(planPath)
const newState = createBoulderState(planPath, sessionId)
writeBoulderState(ctx.directory, newState)
@@ -106,7 +113,7 @@ Use Prometheus to create a work plan first: /plan "your task"`
boulder.json has been created. Read the plan and begin execution.`
} else {
const planList = plans.map((p, i) => {
const planList = incompletePlans.map((p, i) => {
const progress = getPlanProgress(p)
const stat = require("node:fs").statSync(p)
const modified = new Date(stat.mtimeMs).toISOString()
@@ -115,6 +122,7 @@ boulder.json has been created. Read the plan and begin execution.`
contextInfo += `
<system-reminder>
## Multiple Plans Found
Current Time: ${timestamp}
@@ -122,7 +130,8 @@ Session ID: ${sessionId}
${planList}
Which plan would you like to work on? Reply with the number or plan name.`
Ask the user which plan to work on. Present the options above and wait for their response.
</system-reminder>`
}
}