diff --git a/plugins/brains/.claude-plugin/plugin.json b/plugins/brains/.claude-plugin/plugin.json index 13a9465..194d8ad 100644 --- a/plugins/brains/.claude-plugin/plugin.json +++ b/plugins/brains/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "brains", "description": "Your memory layer: Gmail, Calendar, Drive, and prior Claude conversations as queryable pages, with reflexive recall, hook-driven turn-by-turn capture and inbox delivery, and boards/automations/workflows on top.", - "version": "2.8.1", + "version": "2.8.2", "author": { "name": "brains (ssvlabs)" }, diff --git a/plugins/brains/.codex-plugin/plugin.json b/plugins/brains/.codex-plugin/plugin.json index bf854c3..6398af4 100644 --- a/plugins/brains/.codex-plugin/plugin.json +++ b/plugins/brains/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "brains", - "version": "2.8.1", + "version": "2.8.2", "description": "Your personal memory layer for Codex: query Gmail, Calendar, Drive, and prior conversations, then build boards, automations, and workflows.", "author": { "name": "brains (ssvlabs)", diff --git a/plugins/brains/hooks/claude-hooks.json b/plugins/brains/hooks/claude-hooks.json index d761545..b5b2f8f 100644 --- a/plugins/brains/hooks/claude-hooks.json +++ b/plugins/brains/hooks/claude-hooks.json @@ -2,7 +2,7 @@ "hooks": { "SessionStart": [ { - "matcher": "startup|resume|clear|compact", + "matcher": "startup|resume|clear|compact|fork", "hooks": [ { "type": "command", diff --git a/tests/plugin-contract/run.ts b/tests/plugin-contract/run.ts index 529260d..1670e62 100644 --- a/tests/plugin-contract/run.ts +++ b/tests/plugin-contract/run.ts @@ -117,7 +117,7 @@ type HookGroup = { const CLAUDE_HOOK_EVENTS: Record = { SessionStart: [ { - matcher: "startup|resume|clear|compact", + matcher: "startup|resume|clear|compact|fork", hooks: [ { type: "command", @@ -986,6 +986,15 @@ for (const [label, source, expected] of [ // would reject adding them but would report it as a set mismatch; these say why. assert(!codexEvents.includes("PostToolUseFailure"), "Codex does not support PostToolUseFailure"); assert(!codexEvents.includes("SessionEnd"), "Codex does not support SessionEnd"); +// Not a claim about Codex at runtime — a CONFIGURATION pin recording why the two SessionStart +// matchers above differ, so the asymmetry reads as deliberate rather than as drift. Codex declares +// four SessionStart sources and no `fork` (codex-rs/hooks/src/events/session_start.rs); a forked +// Codex thread arrives as `startup` or `resume` depending on the fork path, and both are already +// matched. `fork` is Claude vocabulary only. +assert( + !(codexHooks.hooks.SessionStart[0].matcher ?? "").split("|").includes("fork"), + "Codex declares no fork SessionStart source — a forked Codex thread arrives as startup or resume, so `fork` here would pin a value Codex never emits", +); for (const command of [...hookScripts(claudeHooks), ...hookScripts(codexHooks)]) { const match = command.match(/hooks\/(brains-[a-z-]+\.sh)/);