Skip to content

fix: emit structured JSON from Codex context hooks#87

Open
MoonCaves wants to merge 1 commit into
mnemon-dev:masterfrom
MoonCaves:fix/codex-hooks-structured-json
Open

fix: emit structured JSON from Codex context hooks#87
MoonCaves wants to merge 1 commit into
mnemon-dev:masterfrom
MoonCaves:fix/codex-hooks-structured-json

Conversation

@MoonCaves

Copy link
Copy Markdown
Contributor

Codex's hook-output parser treats any hook stdout beginning with [ or { as an attempted JSON object and rejects it if it isn't valid hook JSON (codex-rs/hooks/src/engine/output_parser.rs looks_like_json + session_start.rs). Mnemon's Codex SessionStart (prime) and UserPromptSubmit hooks print context beginning with [mnemon] …, so Codex fails to parse them on every session start and prompt, and the memory context can be dropped.

This aligns those two hooks with Codex's documented hook-output contract by wrapping their existing output in hookSpecificOutput.additionalContext — the context text is unchanged:

  • user_prompt.sh: emit the reminder as a static UserPromptSubmit object.
  • prime.sh: pipe the existing status/warning/guide output through python3 json.dumps (reading stdin as bytes and decoding UTF-8 with errors="replace", so arbitrary guide bytes can't break the JSON) into a SessionStart object. Existing context and MNEMON_DATA_DIR path resolution are unchanged. python3 is already required by the sibling stop.sh, so no new dependency.
  • stop.sh already emits a valid JSON object, so it never triggered this parse failure — left untouched.

Adds internal/setup/assets/codex_hooks_test.go, which executes the embedded hook byte slices and asserts their external JSON contract (missing-binary, stats, empty-status, MNEMON_DATA_DIR override, legacy fallback, and invalid-UTF-8 guide). The tests fail on the pre-patch hooks and pass with this change.

Closes #86

Codex classifies hook stdout beginning with `[` or `{` as attempted JSON and
parses it. Mnemon's SessionStart (prime) and UserPromptSubmit hooks emit context
beginning with `[mnemon]`, so Codex tries to parse it, fails, and reports
`hook returned invalid ... JSON output` on every session start and prompt.

Move the existing context into Codex's documented
`hookSpecificOutput.additionalContext` envelope:

- user_prompt.sh: emit the reminder as a static UserPromptSubmit object.
- prime.sh: pipe the existing status/warning/guide output through
  `python3 json.dumps` into a SessionStart object (python3 is already required by
  the sibling stop.sh). Existing context and MNEMON_DATA_DIR path resolution are
  unchanged. Guide bytes are read via sys.stdin.buffer and decoded with
  errors="replace", so invalid UTF-8 in the guide can never crash the hook or
  emit lone surrogates that strict JSON parsers reject.

stop.sh already emitted valid JSON and is untouched.

Add internal/setup/assets/codex_hooks_test.go, which executes the embedded hook
byte slices and asserts their external JSON contract: exact additionalContext
equality across the missing-binary, stats, empty-status, MNEMON_DATA_DIR
override, and legacy-fallback cases, plus an invalid-UTF-8 case asserting the
hook exits zero and emits no lone-surrogate escapes. The tests fail on the
pre-patch hooks and pass with this change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex hooks emit [mnemon] … and Codex rejects them as invalid JSON

1 participant