feat(hook): nudge Claude to start watch --block as background bash on session start

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mika Kuns
2026-05-20 16:37:40 +02:00
parent 9f8c1d9e9d
commit efdc752890
3 changed files with 97 additions and 24 deletions

View File

@@ -7,6 +7,7 @@ import {
applyInstall,
applyUninstall,
buildHookCommand,
buildSessionAnnounceLines,
deriveProjectName,
deriveSessionName,
formatActivePeerList,
@@ -359,6 +360,50 @@ describe("formatActivePeerList", () => {
});
});
describe("buildSessionAnnounceLines", () => {
it("includes the identity announcement and tool-call examples", () => {
const out = buildSessionAnnounceLines({
name: "alice-abc12345",
peers: [],
windowMinutes: 60,
maxPeers: 10,
}).join("\n");
expect(out).toContain("alice-abc12345");
expect(out).toContain("mcp__mailbox__send");
});
it("includes the watcher bootstrap instruction when watcherCommand is set", () => {
const out = buildSessionAnnounceLines({
name: "alice-abc12345",
peers: [],
windowMinutes: 60,
maxPeers: 10,
watcherCommand: "claude-mailbox watch --block --name alice-abc12345",
}).join("\n");
expect(out).toContain("watch --block --name alice-abc12345");
expect(out).toContain("run_in_background=true");
expect(out).toMatch(/\[Claude-Mailbox\] Mail from/);
// Strong-directive framing: must be a REQUIRED FIRST ACTION, not a soft tip.
expect(out).toMatch(/REQUIRED FIRST ACTION/);
expect(out).toMatch(/MUST launch/);
// Relaunch protocol must cover every exit code Claude will see.
expect(out).toMatch(/exit code 3/);
expect(out).toMatch(/exit code 2/);
expect(out).toMatch(/renamed to/);
});
it("omits the watcher instruction when watcherCommand is unset", () => {
const out = buildSessionAnnounceLines({
name: "alice-abc12345",
peers: [],
windowMinutes: 60,
maxPeers: 10,
}).join("\n");
expect(out).not.toContain("watch --block");
expect(out).not.toContain("run_in_background");
});
});
describe("readSettings / writeSettings roundtrip", () => {
it("survives an install → write → read cycle", () => {
const dir = mkdtempSync(join(tmpdir(), "claude-mailbox-hook-"));