fix(start-work): preserve existing works when starting an explicit new plan
This commit is contained in:
@@ -168,4 +168,52 @@ describe("buildStartWorkContextInfo", () => {
|
|||||||
expect(existsSync(getBoulderFilePath(testDirectory))).toBe(true)
|
expect(existsSync(getBoulderFilePath(testDirectory))).toBe(true)
|
||||||
expect(clearSpy).toHaveBeenCalledTimes(0)
|
expect(clearSpy).toHaveBeenCalledTimes(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("keeps existing works when explicit new plan is started", () => {
|
||||||
|
// given
|
||||||
|
writePlan("work-a", "## TODOs\n- [ ] 1. Work A")
|
||||||
|
const workBPath = writePlan("work-b", "## TODOs\n- [ ] 1. Work B")
|
||||||
|
writePlan("new-plan-c", "## TODOs\n- [ ] 1. Work C")
|
||||||
|
|
||||||
|
const initialState = createBoulderState(
|
||||||
|
join(testDirectory, ".sisyphus", "plans", "work-a.md"),
|
||||||
|
"session-a",
|
||||||
|
"atlas",
|
||||||
|
"/tmp/worktree-a",
|
||||||
|
)
|
||||||
|
writeBoulderState(testDirectory, initialState)
|
||||||
|
|
||||||
|
const workAId = initialState.active_work_id!
|
||||||
|
const withSecondWork = addBoulderWork(testDirectory, {
|
||||||
|
planPath: workBPath,
|
||||||
|
sessionId: "session-b",
|
||||||
|
agent: "atlas",
|
||||||
|
worktreePath: "/tmp/worktree-b",
|
||||||
|
})
|
||||||
|
expect(withSecondWork).not.toBeNull()
|
||||||
|
const workBId = Object.keys(withSecondWork!.works!).find((workId) => workId !== workAId)
|
||||||
|
expect(workBId).toBeDefined()
|
||||||
|
|
||||||
|
// when
|
||||||
|
buildStartWorkContextInfo({
|
||||||
|
ctx: createPluginInput(),
|
||||||
|
explicitPlanName: "new-plan-c",
|
||||||
|
existingState: readExistingState(),
|
||||||
|
sessionId: "session-c",
|
||||||
|
timestamp: "2026-05-11T00:00:00.000Z",
|
||||||
|
activeAgent: "atlas",
|
||||||
|
worktreePath: undefined,
|
||||||
|
worktreeBlock: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
// then
|
||||||
|
const nextState = readBoulderState(testDirectory)
|
||||||
|
const workIds = Object.keys(nextState?.works ?? {})
|
||||||
|
expect(workIds.length).toBe(3)
|
||||||
|
expect(workIds).toContain(workAId)
|
||||||
|
expect(workIds).toContain(workBId!)
|
||||||
|
const workC = getWorkByPlanName(testDirectory, "new-plan-c")
|
||||||
|
expect(workC).not.toBeNull()
|
||||||
|
expect(workIds).toContain(workC!.work_id)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -48,19 +48,14 @@ function findPlanByName(plans: string[], requestedName: string): string | null {
|
|||||||
return normalizedPartialMatch || null
|
return normalizedPartialMatch || null
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildAutoSelectedPlanContext(params: {
|
function buildAutoSelectedPlanContextInfoOnly(params: {
|
||||||
planPath: string
|
planPath: string
|
||||||
sessionId: string
|
sessionId: string
|
||||||
timestamp: string
|
timestamp: string
|
||||||
activeAgent: string
|
|
||||||
worktreePath: string | undefined
|
|
||||||
worktreeBlock: string
|
worktreeBlock: string
|
||||||
directory: string
|
|
||||||
}): string {
|
}): string {
|
||||||
const { planPath, sessionId, timestamp, activeAgent, worktreePath, worktreeBlock, directory } = params
|
const { planPath, sessionId, timestamp, worktreeBlock } = params
|
||||||
const progress = getPlanProgress(planPath)
|
const progress = getPlanProgress(planPath)
|
||||||
const newState = createBoulderState(planPath, sessionId, activeAgent, worktreePath)
|
|
||||||
writeBoulderState(directory, newState)
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
## Auto-Selected Plan
|
## Auto-Selected Plan
|
||||||
@@ -75,6 +70,27 @@ ${worktreeBlock}
|
|||||||
boulder.json has been created. Read the plan and begin execution.`
|
boulder.json has been created. Read the plan and begin execution.`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildAutoSelectedPlanContextWithStateInit(params: {
|
||||||
|
planPath: string
|
||||||
|
sessionId: string
|
||||||
|
timestamp: string
|
||||||
|
activeAgent: string
|
||||||
|
worktreePath: string | undefined
|
||||||
|
worktreeBlock: string
|
||||||
|
directory: string
|
||||||
|
}): string {
|
||||||
|
const { planPath, sessionId, timestamp, activeAgent, worktreePath, worktreeBlock, directory } = params
|
||||||
|
const newState = createBoulderState(planPath, sessionId, activeAgent, worktreePath)
|
||||||
|
writeBoulderState(directory, newState)
|
||||||
|
|
||||||
|
return buildAutoSelectedPlanContextInfoOnly({
|
||||||
|
planPath,
|
||||||
|
sessionId,
|
||||||
|
timestamp,
|
||||||
|
worktreeBlock,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function buildMissingPlanContext(explicitPlanName: string, allPlans: string[]): string {
|
function buildMissingPlanContext(explicitPlanName: string, allPlans: string[]): string {
|
||||||
const incompletePlans = allPlans.filter((p) => !getPlanProgress(p).isComplete)
|
const incompletePlans = allPlans.filter((p) => !getPlanProgress(p).isComplete)
|
||||||
if (incompletePlans.length > 0) {
|
if (incompletePlans.length > 0) {
|
||||||
@@ -218,14 +234,11 @@ function buildExplicitPlanContext(params: {
|
|||||||
worktreePath,
|
worktreePath,
|
||||||
})
|
})
|
||||||
|
|
||||||
return buildAutoSelectedPlanContext({
|
return buildAutoSelectedPlanContextInfoOnly({
|
||||||
planPath: matchedPlan,
|
planPath: matchedPlan,
|
||||||
sessionId,
|
sessionId,
|
||||||
timestamp,
|
timestamp,
|
||||||
activeAgent,
|
|
||||||
worktreePath,
|
|
||||||
worktreeBlock,
|
worktreeBlock,
|
||||||
directory,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +341,7 @@ function buildPlanDiscoveryContext(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (incompletePlans.length === 1) {
|
if (incompletePlans.length === 1) {
|
||||||
return contextInfo + buildAutoSelectedPlanContext({
|
return contextInfo + buildAutoSelectedPlanContextWithStateInit({
|
||||||
planPath: incompletePlans[0],
|
planPath: incompletePlans[0],
|
||||||
sessionId,
|
sessionId,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
|||||||
Reference in New Issue
Block a user