fix: emit structured JSON from Codex context hooks#87
Open
MoonCaves wants to merge 1 commit into
Open
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.rslooks_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 staticUserPromptSubmitobject.prime.sh: pipe the existing status/warning/guide output throughpython3 json.dumps(reading stdin as bytes and decoding UTF-8 witherrors="replace", so arbitrary guide bytes can't break the JSON) into aSessionStartobject. Existing context andMNEMON_DATA_DIRpath resolution are unchanged.python3is already required by the siblingstop.sh, so no new dependency.stop.shalready 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_DIRoverride, legacy fallback, and invalid-UTF-8 guide). The tests fail on the pre-patch hooks and pass with this change.Closes #86