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:
@@ -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?")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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>`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user