mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-10-02 12:54:03 +00:00
openfleet hooks: no member.end for a member that never started
A first prompt refused by the ceiling still lets the session wind down through Stop and SessionEnd; those handlers now write nothing when the ledger holds no member.start for the member, so a refused member is never drawn as done. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RZV4zJ2pDZLNN3kE5jFCmV
This commit is contained in:
parent
ce8fc7c153
commit
85608e5540
2 changed files with 19 additions and 2 deletions
|
|
@ -186,6 +186,17 @@ describe("UserPromptSubmit", () => {
|
|||
expect(runHook("UserPromptSubmit", payload({ permission_mode: "bypassPermissions", prompt: "still" }), fake(home).io).exit).toBe(2);
|
||||
});
|
||||
|
||||
it("writes no end line for a member whose start was refused", () => {
|
||||
append(home, "team-20260913", { event: "fleet.open", by: "sysop", fleet: "team-20260913", sysop: FLEET, ceiling: { depth: 2, hosts: ["dev"] } }, { host: "dev" });
|
||||
writeCurrent(home, "team-20260913");
|
||||
runHook("SessionStart", payload({ source: "startup" }), fake(home).io);
|
||||
expect(runHook("UserPromptSubmit", payload({ permission_mode: "bypassPermissions", prompt: "go" }), fake(home).io).exit).toBe(2);
|
||||
// The session still winds down through Stop and SessionEnd; a member that never started has no end.
|
||||
runHook("Stop", payload({ permission_mode: "bypassPermissions", last_assistant_message: "blocked", background_tasks: [] }), fake(home).io);
|
||||
runHook("SessionEnd", payload({ reason: "other" }), fake(home).io);
|
||||
expect(findEvents(readLedger(home, "team-20260913"), "member.end")).toEqual([]);
|
||||
});
|
||||
|
||||
it("does nothing for a session it never saw, or a subagent", () => {
|
||||
expect(runHook("UserPromptSubmit", payload({ permission_mode: "auto" }), fake(home).io)).toEqual({ exit: 0, stdout: "", stderr: "" });
|
||||
runHook("SessionStart", payload({ source: "startup" }), fake(home).io);
|
||||
|
|
|
|||
|
|
@ -370,8 +370,11 @@ export function handleStop(payload: Payload, io: HookIo): HookResult {
|
|||
if (!jobDir || !session.record) return OK;
|
||||
if (!Array.isArray(payload.background_tasks) || payload.background_tasks.length > 0) return OK;
|
||||
const record = session.record;
|
||||
const lines = readLedger(homeDir, record.fleet);
|
||||
// A member that never started (its first prompt was refused, or none came) has no end line.
|
||||
if (!claimedBy(lines, record.member)) return OK;
|
||||
// A `lost` line a sysop tool wrote is superseded by the engine's own end; anything else stands.
|
||||
const existing = endOf(readLedger(homeDir, record.fleet), record.member);
|
||||
const existing = endOf(lines, record.member);
|
||||
if (existing && existing.state !== "lost") return OK;
|
||||
const state = stateJson(jobDir);
|
||||
endMember(
|
||||
|
|
@ -402,7 +405,10 @@ export function handleSessionEnd(payload: Payload, io: HookIo): HookResult {
|
|||
// clear, resume and logout hand the same work to another session; only a real exit ends the member.
|
||||
if (payload.reason !== undefined && payload.reason !== "other" && payload.reason !== "prompt_input_exit") return OK;
|
||||
const record = session.record;
|
||||
const existing = endOf(readLedger(homeDir, record.fleet), record.member);
|
||||
const lines = readLedger(homeDir, record.fleet);
|
||||
// A member that never started (its first prompt was refused, or none came) has no end line.
|
||||
if (!claimedBy(lines, record.member)) return OK;
|
||||
const existing = endOf(lines, record.member);
|
||||
if (existing && existing.state !== "lost") return OK;
|
||||
const jobDir = ownJobDir(env, sessionId);
|
||||
const state = jobDir ? stateJson(jobDir) : null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue