Repository navigation
Conversation
Stop-only uploads hide long-running activity, and rejected automatic exports can be mistaken for successful delivery. Upload changed observations from all 12 hooks with durable queues, stable IDs, small sequential batches, and bounded async execution. Preserve child parenting and acknowledge only accepted observations. SessionEnd stays synchronous within Codex's three-second limit; other hooks run async. Ship the standalone fork bundle for Git marketplace installation and verify source/bundle parity in CI. Linux flock is required. Streamed model tokens have no Codex hook. Signed-off-by: Bernardo Donadio <bcdonadio@bcdonadio.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (1)ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d6b7c347f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "type": "command", | ||
| "command": "node \"${PLUGIN_ROOT}/dist/index.mjs\"", | ||
| "timeout": 30, | ||
| "async": true, |
There was a problem hiding this comment.
Make async handlers exit after durable enqueue
When Langfuse is slow or unavailable and more than eight hook events arrive, these 30-second async invocations occupy Codex's entire background-hook pool while waiting for upload/locking; later events remain only in Codex's in-memory queue and never reach enqueueHook. Codex 0.162.1 limits this pool to eight tasks and aborts all queued tasks during shutdown (command runtime, shutdown path), so a final SessionEnd cannot recover payloads whose processes never started. Have the async command persist its payload and exit promptly, with delivery performed separately, to preserve the stated durable-queue guarantee.
Useful? React with 👍 / 👎.
| const turn = hook.input.turn_id | ||
| ? turns.find((t) => t.turnId === hook.input.turn_id) | ||
| : turns.filter((candidate) => candidate.startTime <= hook.timestamp).at(-1); |
There was a problem hiding this comment.
Do not attach SessionStart to the previous turn
On a resumed or post-compaction session, SessionStart has no turn_id in the Codex hook contract (0.162.1 schema), while the transcript already contains completed turns. This fallback therefore selects the most recent old turn, mutates the event with that turn's ID, and permanently emits the start event as a child of the wrong trace; it should remain session-level or be retained for the upcoming turn instead. The timestamp fallback is appropriate for terminal events such as SessionEnd, but not for SessionStart.
Useful? React with 👍 / 👎.
The committed standalone bundle embeds unchanged dependency code. Scan the\nTypeScript sources and tests while CI verifies byte-for-byte bundle parity.\nUse advanced CodeQL setup for this fork with the default query suite. Signed-off-by: Bernardo Donadio <bcdonadio@bcdonadio.com>
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: f1acda1a3a
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
| ] | ||
| } | ||
| ], | ||
| "SessionStart": [ |
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Security: Reject project endpoints that inherit global credentials
When the plugin is globally enabled/trusted with credentials, starting Codex in an untrusted checkout whose .codex/langfuse.json overrides only base_url runs this new hook. getConfig() inherits public_key/secret_key from ~/.codex but accepts the checkout's endpoint, and the standalone path immediately sends those inherited values in Basic auth. I reproduced credential capture without a transcript. Previously only Stop was registered, so this makes starting the session sufficient rather than requiring a completed turn. Bind the endpoint and credentials to the same trusted source or reject mixed-provenance config.
Useful? React with 👍 / 👎.
Native Codex cancels async hooks before SessionEnd. A real CLI probe confirmed that an async Stop could disappear before enqueueing its payload. Keep activity hooks async, but flush Stop, SubagentStop, Interrupt, and SessionEnd synchronously. The hook deadlines and durable retries remain bounded. Increment the fork prerelease for cache and hook review identity. Signed-off-by: Bernardo Donadio <bcdonadio@bcdonadio.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30284e0279
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const instrumentation = setupInstrumentation(config, { | ||
| acknowledged: await loadObservationCheckpoint(file), | ||
| }); |
There was a problem hiding this comment.
Namespace delivery checkpoints by Langfuse destination
When base_url, public_key, or secret_key is changed for an existing session, this reloads acknowledgements created for the previous destination. The stored fingerprints cover only serialized span contents, while the destination and credentials exist only in the HTTP URL/headers, so unchanged observations are skipped against the new backend; newly uploaded hook spans can consequently reference parent observations that exist only in the old Langfuse project. Include a destination identity in the checkpoint or discard acknowledgements when it changes.
Useful? React with 👍 / 👎.
Long-running Codex turns stay invisible when uploads run only at Stop. Large automatic exports can also fail while the uploader later records successful delivery.
This fork uploads changed observations across all 12 native hooks. Eight live activity hooks run asynchronously. Stop, SubagentStop, Interrupt, and SessionEnd flush synchronously because native Codex cancels outstanding async work during shutdown; the latter two retain the native three-second limit. Private durable inboxes, bounded kernel locks, stable observation IDs, and acknowledged checkpoints preserve retries and late child activity.
Requests contain at most 16 observations or 8 MiB of encoded JSON, with a one-second flush interval and sequential delivery. Larger individual observations remain untruncated up to 256 MiB. Semantic turn and step caches avoid reconstructing acknowledged history.
Validation
Review
Start with
plugins/tracing/src/index.ts,trace.ts,sidecar.ts, andinstrumentation.ts, then their regressions.dist/index.mjsis generated and committed so the Git marketplace installs a standalone hook without a build step. Linuxflockis required. Codex has no hook for streamed model tokens; shutdown timeouts retain pending work for retry.