fix(start-work): honor explicit plan name and strip ultrawork keywords

When user types '/start-work my-plan ultrawork', the hook now:

1. Extracts plan name from <user-request> section
2. Strips ultrawork/ulw keywords from the plan name
3. Searches for matching plan (exact then partial match)
4. Uses the matched plan instead of resuming stale boulder state

This fixes the bug where '/start-work [PLAN] ultrawork' would:
- Include 'ultrawork' as part of the plan name argument
- Ignore the explicit plan and resume an old stale plan from boulder.json

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Nguyen Khac Trung Kien
2026-01-15 16:55:44 +07:00
parent be5f20f4cc
commit 62448c1148
2 changed files with 231 additions and 2 deletions
+88 -2
View File
@@ -7,11 +7,14 @@ import {
getPlanProgress,
createBoulderState,
getPlanName,
clearBoulderState,
} from "../../features/boulder-state"
import { log } from "../../shared/logger"
export const HOOK_NAME = "start-work"
const KEYWORD_PATTERN = /\b(ultrawork|ulw)\b/gi
interface StartWorkHookInput {
sessionID: string
messageID?: string
@@ -21,6 +24,27 @@ interface StartWorkHookOutput {
parts: Array<{ type: string; text?: string }>
}
function extractUserRequestPlanName(promptText: string): string | null {
const userRequestMatch = promptText.match(/<user-request>\s*([\s\S]*?)\s*<\/user-request>/i)
if (!userRequestMatch) return null
const rawArg = userRequestMatch[1].trim()
if (!rawArg) return null
const cleanedArg = rawArg.replace(KEYWORD_PATTERN, "").trim()
return cleanedArg || null
}
function findPlanByName(plans: string[], requestedName: string): string | null {
const lowerName = requestedName.toLowerCase()
const exactMatch = plans.find(p => getPlanName(p).toLowerCase() === lowerName)
if (exactMatch) return exactMatch
const partialMatch = plans.find(p => getPlanName(p).toLowerCase().includes(lowerName))
return partialMatch || null
}
export function createStartWorkHook(ctx: PluginInput) {
return {
"chat.message": async (
@@ -51,8 +75,70 @@ export function createStartWorkHook(ctx: PluginInput) {
const timestamp = new Date().toISOString()
let contextInfo = ""
const explicitPlanName = extractUserRequestPlanName(promptText)
if (explicitPlanName) {
log(`[${HOOK_NAME}] Explicit plan name requested: ${explicitPlanName}`, {
sessionID: input.sessionID,
})
const allPlans = findPrometheusPlans(ctx.directory)
const matchedPlan = findPlanByName(allPlans, explicitPlanName)
if (matchedPlan) {
const progress = getPlanProgress(matchedPlan)
if (progress.isComplete) {
contextInfo = `
## Plan Already Complete
if (existingState) {
The requested plan "${getPlanName(matchedPlan)}" has been completed.
All ${progress.total} tasks are done. Create a new plan with: /plan "your task"`
} else {
if (existingState) {
clearBoulderState(ctx.directory)
}
const newState = createBoulderState(matchedPlan, sessionId)
writeBoulderState(ctx.directory, newState)
contextInfo = `
## Auto-Selected Plan
**Plan**: ${getPlanName(matchedPlan)}
**Path**: ${matchedPlan}
**Progress**: ${progress.completed}/${progress.total} tasks
**Session ID**: ${sessionId}
**Started**: ${timestamp}
boulder.json has been created. Read the plan and begin execution.`
}
} else {
const incompletePlans = allPlans.filter(p => !getPlanProgress(p).isComplete)
if (incompletePlans.length > 0) {
const planList = incompletePlans.map((p, i) => {
const prog = getPlanProgress(p)
return `${i + 1}. [${getPlanName(p)}] - Progress: ${prog.completed}/${prog.total}`
}).join("\n")
contextInfo = `
## Plan Not Found
Could not find a plan matching "${explicitPlanName}".
Available incomplete plans:
${planList}
Ask the user which plan to work on.`
} else {
contextInfo = `
## Plan Not Found
Could not find a plan matching "${explicitPlanName}".
No incomplete plans available. Create a new plan with: /plan "your task"`
}
}
} else if (existingState) {
const progress = getPlanProgress(existingState.active_plan)
if (!progress.isComplete) {
@@ -78,7 +164,7 @@ Looking for new plans...`
}
}
if (!existingState || getPlanProgress(existingState.active_plan).isComplete) {
if ((!existingState && !explicitPlanName) || (existingState && !explicitPlanName && getPlanProgress(existingState.active_plan).isComplete)) {
const plans = findPrometheusPlans(ctx.directory)
const incompletePlans = plans.filter(p => !getPlanProgress(p).isComplete)