fix(prompt-gate): pin duplicate prompt dispatches
Keep prompt reservations briefly after successful dispatch so rapid idle/message/error transitions cannot inject the same follow-up twice. Route all production session prompt calls through the shared gate, restore skipped background resume state, release holds after abort/recovery paths, and preserve Ralph/ULW loop state when a dispatch is deferred. Add regression coverage for session routing, static prompt route auditing, team-mode live messaging, model suggestion retries, call-omo-agent reuse, background parent wakes, runtime fallback, compaction recovery, Atlas, and Ralph/ULW loops.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { describe, expect, mock, test } from "bun:test"
|
||||
|
||||
import { unsafeTestValue } from "../../test-support/unsafe-test-value"
|
||||
import { promptAsyncInDirectory } from "./session-route"
|
||||
|
||||
describe("promptAsyncInDirectory", () => {
|
||||
test("#given no session id is present #when routing a promptAsync request #then the helper rejects instead of using an ungated raw prompt", async () => {
|
||||
// given
|
||||
const promptAsync = mock(async () => ({ data: "sent" }))
|
||||
const client = {
|
||||
session: {
|
||||
promptAsync,
|
||||
},
|
||||
}
|
||||
const args = {
|
||||
body: { parts: [{ type: "text", text: "continue" }] },
|
||||
}
|
||||
|
||||
// when, then
|
||||
await expect(
|
||||
promptAsyncInDirectory(
|
||||
unsafeTestValue(client),
|
||||
unsafeTestValue(args),
|
||||
"/workspace/project",
|
||||
),
|
||||
).rejects.toThrow("session id is required for routed promptAsync")
|
||||
expect(promptAsync).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
|
||||
test("#given a routed prompt just dispatched #when the same session is prompted again immediately #then the route keeps the session reserved", async () => {
|
||||
// given
|
||||
const promptAsync = mock(async () => ({ data: "sent" }))
|
||||
const client = {
|
||||
session: {
|
||||
promptAsync,
|
||||
},
|
||||
}
|
||||
const args = {
|
||||
path: { id: "ses_route_hold" },
|
||||
body: { parts: [{ type: "text", text: "continue" }] },
|
||||
}
|
||||
|
||||
// when
|
||||
const first = await promptAsyncInDirectory(
|
||||
unsafeTestValue(client),
|
||||
unsafeTestValue(args),
|
||||
"/workspace/project",
|
||||
)
|
||||
const second = promptAsyncInDirectory(
|
||||
unsafeTestValue(client),
|
||||
unsafeTestValue(args),
|
||||
"/workspace/project",
|
||||
)
|
||||
|
||||
// then
|
||||
expect(first).toEqual({ data: "sent" })
|
||||
await expect(second).rejects.toThrow("promptAsync skipped by gate: reserved")
|
||||
expect(promptAsync).toHaveBeenCalledTimes(1)
|
||||
expect(promptAsync.mock.calls[0]?.[0].query).toEqual({ directory: "/workspace/project" })
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user