fix(notepad-guard,start-work): wire dispatch and match .omo paths
notepad-write-guard: - The hook was created by create-tool-guard-hooks but tool-execute-before never invoked it, so the guard was inert. - It also only matched .sisyphus/notepads, missing the current .omo/notepads layout introduced by the workspace migration. - Add the dispatch call alongside writeExistingFileGuard, and extend NOTEPAD_ROOTS to cover both paths via normalize() + sep. New integration test pins the wire and the .omo block; the existing unit test now asserts both paths. start-work session-plan-affinity: - PLAN_PATH_PATTERN only matched .sisyphus/plans, so sessions referring to plans under .omo/plans returned null and start-work missed the current session's own plan. - Extend the regex to .(sisyphus|omo)/plans and add findPrometheusPlans in packages/boulder-state to scan both directories during the transition. New regression test pins .omo/plans matching; legacy .sisyphus/plans coverage preserved.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
|
||||
import { createNotepadWriteGuardHook } from "../hooks/notepad-write-guard"
|
||||
import { unsafeTestValue } from "../../test-support/unsafe-test-value"
|
||||
import { createToolExecuteBeforeHandler } from "./tool-execute-before"
|
||||
import type { CreatedHooks } from "../create-hooks"
|
||||
import type { PluginContext } from "./types"
|
||||
|
||||
const REFUSED_PREFIX = "Refused: Write to"
|
||||
|
||||
function createContext(): PluginContext {
|
||||
return unsafeTestValue<PluginContext>({
|
||||
client: {
|
||||
session: {
|
||||
messages: async () => ({ data: [] }),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function createHooks(): CreatedHooks {
|
||||
return unsafeTestValue<CreatedHooks>({
|
||||
notepadWriteGuard: createNotepadWriteGuardHook(),
|
||||
})
|
||||
}
|
||||
|
||||
async function runTool(args: { readonly tool: string; readonly filePath: string }): Promise<void> {
|
||||
const handler = createToolExecuteBeforeHandler({
|
||||
ctx: createContext(),
|
||||
hooks: createHooks(),
|
||||
})
|
||||
|
||||
await handler(
|
||||
{ tool: args.tool, sessionID: "ses_notepad", callID: "call_notepad" },
|
||||
{ args: { file_path: args.filePath } },
|
||||
)
|
||||
}
|
||||
|
||||
async function expectBlocked(args: { readonly tool: string; readonly filePath: string }): Promise<void> {
|
||||
let caughtMessage = ""
|
||||
try {
|
||||
await runTool(args)
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
caughtMessage = error.message
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
expect(caughtMessage).toContain(REFUSED_PREFIX)
|
||||
}
|
||||
|
||||
describe("tool.execute.before notepad-write-guard dispatch", () => {
|
||||
test("#given guard enabled #when Write targets current .omo notepad #then blocks", async () => {
|
||||
await expectBlocked({
|
||||
tool: "Write",
|
||||
filePath: ".omo/notepads/plan.md",
|
||||
})
|
||||
})
|
||||
|
||||
test("#given guard enabled #when Write targets other .omo path #then allows", async () => {
|
||||
await runTool({
|
||||
tool: "Write",
|
||||
filePath: ".omo/somewhere-else.md",
|
||||
})
|
||||
})
|
||||
|
||||
test("#given guard enabled #when Edit targets current .omo notepad #then allows", async () => {
|
||||
await runTool({
|
||||
tool: "Edit",
|
||||
filePath: ".omo/notepads/plan.md",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -76,6 +76,7 @@ export function createToolExecuteBeforeHandler(args: {
|
||||
}
|
||||
|
||||
await hooks.writeExistingFileGuard?.["tool.execute.before"]?.(input, output)
|
||||
await hooks.notepadWriteGuard?.["tool.execute.before"]?.(input, output)
|
||||
await hooks.questionLabelTruncator?.["tool.execute.before"]?.(input, output)
|
||||
await hooks.claudeCodeHooks?.["tool.execute.before"]?.(input, output)
|
||||
await hooks.nonInteractiveEnv?.["tool.execute.before"]?.(input, output)
|
||||
|
||||
Reference in New Issue
Block a user