fix(stop-continuation): clear stop state for native work-starting commands
This commit is contained in:
@@ -0,0 +1,114 @@
|
|||||||
|
import { describe, expect, mock, test } from "bun:test"
|
||||||
|
|
||||||
|
import { createCommandExecuteBeforeHandler } from "./command-execute-before"
|
||||||
|
|
||||||
|
describe("createCommandExecuteBeforeHandler", () => {
|
||||||
|
test("#given stopped session and /ulw-loop #when command.execute.before runs #then clear is called", async () => {
|
||||||
|
// given
|
||||||
|
const clear = mock(() => {})
|
||||||
|
const isStopped = mock(() => true)
|
||||||
|
const startLoop = mock(() => true)
|
||||||
|
const handler = createCommandExecuteBeforeHandler({
|
||||||
|
hooks: {
|
||||||
|
ralphLoop: {
|
||||||
|
startLoop,
|
||||||
|
cancelLoop: mock(() => true),
|
||||||
|
},
|
||||||
|
stopContinuationGuard: {
|
||||||
|
isStopped,
|
||||||
|
clear,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// when
|
||||||
|
await handler(
|
||||||
|
{
|
||||||
|
command: "ulw-loop",
|
||||||
|
sessionID: "ses-stopped",
|
||||||
|
arguments: "Ship feature",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parts: [],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(startLoop).toHaveBeenCalledTimes(1)
|
||||||
|
expect(isStopped).toHaveBeenCalledWith("ses-stopped")
|
||||||
|
expect(clear).toHaveBeenCalledTimes(1)
|
||||||
|
expect(clear).toHaveBeenCalledWith("ses-stopped")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("#given stopped session and /start-work #when command.execute.before runs #then clear is called", async () => {
|
||||||
|
// given
|
||||||
|
const clear = mock(() => {})
|
||||||
|
const isStopped = mock(() => true)
|
||||||
|
const startWorkHook = mock(async () => {})
|
||||||
|
const handler = createCommandExecuteBeforeHandler({
|
||||||
|
hooks: {
|
||||||
|
startWork: {
|
||||||
|
"command.execute.before": startWorkHook,
|
||||||
|
},
|
||||||
|
stopContinuationGuard: {
|
||||||
|
isStopped,
|
||||||
|
clear,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// when
|
||||||
|
await handler(
|
||||||
|
{
|
||||||
|
command: "start-work",
|
||||||
|
sessionID: "ses-stopped",
|
||||||
|
arguments: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parts: [],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(startWorkHook).toHaveBeenCalledTimes(1)
|
||||||
|
expect(isStopped).toHaveBeenCalledWith("ses-stopped")
|
||||||
|
expect(clear).toHaveBeenCalledTimes(1)
|
||||||
|
expect(clear).toHaveBeenCalledWith("ses-stopped")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("#given non-stopped session and /ulw-loop #when command.execute.before runs #then clear is not called", async () => {
|
||||||
|
// given
|
||||||
|
const clear = mock(() => {})
|
||||||
|
const isStopped = mock(() => false)
|
||||||
|
const startLoop = mock(() => true)
|
||||||
|
const handler = createCommandExecuteBeforeHandler({
|
||||||
|
hooks: {
|
||||||
|
ralphLoop: {
|
||||||
|
startLoop,
|
||||||
|
cancelLoop: mock(() => true),
|
||||||
|
},
|
||||||
|
stopContinuationGuard: {
|
||||||
|
isStopped,
|
||||||
|
clear,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// when
|
||||||
|
await handler(
|
||||||
|
{
|
||||||
|
command: "ulw-loop",
|
||||||
|
sessionID: "ses-running",
|
||||||
|
arguments: "Ship feature",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parts: [],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(startLoop).toHaveBeenCalledTimes(1)
|
||||||
|
expect(isStopped).toHaveBeenCalledWith("ses-running")
|
||||||
|
expect(clear).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { CreatedHooks } from "../create-hooks"
|
import type { CreatedHooks } from "../create-hooks"
|
||||||
import { parseRalphLoopArguments } from "../hooks/ralph-loop/command-arguments"
|
import { parseRalphLoopArguments } from "../hooks/ralph-loop/command-arguments"
|
||||||
|
import { log } from "../shared/logger"
|
||||||
|
|
||||||
type CommandExecuteBeforeInput = {
|
type CommandExecuteBeforeInput = {
|
||||||
command: string
|
command: string
|
||||||
@@ -45,6 +46,13 @@ export function createCommandExecuteBeforeHandler(args: {
|
|||||||
})
|
})
|
||||||
output.message ??= {}
|
output.message ??= {}
|
||||||
output.message[NATIVE_LOOP_TRIGGERED_FLAG] = true
|
output.message[NATIVE_LOOP_TRIGGERED_FLAG] = true
|
||||||
|
if (hooks.stopContinuationGuard?.isStopped(sessionID)) {
|
||||||
|
hooks.stopContinuationGuard.clear(sessionID)
|
||||||
|
log("[stop-continuation] Stop state cleared by native command", {
|
||||||
|
sessionID,
|
||||||
|
command: normalizedCommand,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if (normalizedCommand === "cancel-ralph") {
|
} else if (normalizedCommand === "cancel-ralph") {
|
||||||
hooks.ralphLoop.cancelLoop(sessionID)
|
hooks.ralphLoop.cancelLoop(sessionID)
|
||||||
output.message ??= {}
|
output.message ??= {}
|
||||||
@@ -58,6 +66,13 @@ export function createCommandExecuteBeforeHandler(args: {
|
|||||||
&& hasPartsOutput(output)
|
&& hasPartsOutput(output)
|
||||||
) {
|
) {
|
||||||
await hooks.startWork["command.execute.before"]?.(input, output)
|
await hooks.startWork["command.execute.before"]?.(input, output)
|
||||||
|
if (hooks.stopContinuationGuard?.isStopped(sessionID)) {
|
||||||
|
hooks.stopContinuationGuard.clear(sessionID)
|
||||||
|
log("[stop-continuation] Stop state cleared by native command", {
|
||||||
|
sessionID,
|
||||||
|
command: normalizedCommand,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user