feat(codex): ship the compaction hook as a plugin-provided hook

The compaction re-injection hook previously required users to hand-merge
an example into user-level ~/.codex/hooks.json — which renders in the
Codex hooks UI as an anonymous, unattributed "Hook 1" and puts the
install burden on every user. Restore the plugin-provided delivery this
repo used before "Remove Codex hooks" (640ce6c0): the Codex manifest
points hooks at hooks/hooks-codex.json, which runs session-start-codex
via ${PLUGIN_ROOT}/hooks/run-hook.cmd with matcher "compact".

Unlike the removed hook, this one never fires at session start — Codex
surfaces skills natively there, which is why the old startup-injecting
hook was removed. The matcher plus the script's own source gate restrict
it to post-compaction re-starts. The explicit manifest pointer also
keeps suppressing Codex's hooks/hooks.json auto-discovery fallback,
which the previous empty-object declaration existed for (7d8d3d4b).

The Codex portal archive now ships hooks/hooks-codex.json,
hooks/run-hook.cmd, and hooks/session-start-codex; other-harness hook
files stay excluded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Drew Ritter
2026-07-23 13:26:01 -07:00
parent 5ab3297ad7
commit 34d4f64f91
9 changed files with 76 additions and 65 deletions

View File

@@ -4,7 +4,7 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
HOOK_UNDER_TEST="$REPO_ROOT/hooks/session-start-codex"
EXAMPLE_UNDER_TEST="$REPO_ROOT/hooks/hooks-codex.json.example"
CONFIG_UNDER_TEST="$REPO_ROOT/hooks/hooks-codex.json"
FAILURES=0
@@ -86,20 +86,25 @@ else
fi
if node -e '
const example = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
const entry = example.hooks.SessionStart[0].hooks[0];
const config = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
const group = config.hooks.SessionStart[0];
if (group.matcher !== "compact") {
console.error(`hook matcher is ${JSON.stringify(group.matcher)}, expected "compact"`);
process.exit(1);
}
const entry = group.hooks[0];
if (entry.type !== "command") {
console.error(`example hook type is ${JSON.stringify(entry.type)}, expected "command"`);
console.error(`hook type is ${JSON.stringify(entry.type)}, expected "command"`);
process.exit(1);
}
if (!/session-start-codex"$/.test(entry.command)) {
console.error(`unexpected example command shape: ${entry.command}`);
if (!entry.command.includes("${PLUGIN_ROOT}") || !/run-hook\.cmd" session-start-codex$/.test(entry.command)) {
console.error(`unexpected command shape: ${entry.command}`);
process.exit(1);
}
' "$EXAMPLE_UNDER_TEST"; then
pass "hooks-codex.json.example parses and invokes session-start-codex"
' "$CONFIG_UNDER_TEST"; then
pass "hooks-codex.json runs session-start-codex via \${PLUGIN_ROOT} on compact"
else
fail "hooks-codex.json.example parses and invokes session-start-codex"
fail "hooks-codex.json runs session-start-codex via \${PLUGIN_ROOT} on compact"
fi
if [[ "$FAILURES" -gt 0 ]]; then