Skip to content

fix(codex): accept any JSON tool_input/tool_response on Codex tool hooks (#188 follow-up) - #404

Merged
ScriptedAlchemy merged 1 commit into
mainfrom
fix/188-codex-tool-payload-any
Sep 3, 2026
Merged

fix(codex): accept any JSON tool_input/tool_response on Codex tool hooks (#188 follow-up)#404
ScriptedAlchemy merged 1 commit into
mainfrom
fix/188-codex-tool-payload-any

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

  • Follow-up to feat(codex): pin the release hook contract, handler types, and generated wire schemas (#188 S2) #378 addressing the Codex review thread on post-tool-use.command.input.schema.json: the pinned rust-v0.147.0 pre-tool-use/post-tool-use input schemas declare "tool_input": true and "tool_response": true (any JSON value), but the generated Codex hook wrapper and the event-route envelope validator still required objects, so a valid scalar/null tool_response (or tool_input) failed before reaching the handler.
  • For Codex, validateNativeInput (generated wrapper) and validateNativeEventEnvelope (events/projection.ts) now require presence only (tool_input is required / tool_response is required), matching the existing PermissionRequest tool_input handling. Claude keeps its documented object requirement and error text.
  • Tests: hooks.test.ts runs the built Codex PostToolUse wrapper with string/number/boolean/null tool_response and a string tool_input (handler receives them, exit 0); the malformed-input matrix now asserts the Codex presence error vs. the Claude object error per target. event-project.test.ts covers the envelope validator for every JSON kind on tool/before and tool/after.

Refs #188.

Test plan

  • pnpm build, pnpm typecheck, pnpm lint
  • rstest unit: event-project, codex-hook-contract, lifecycle-replay-service, lifecycle-replay-routes
  • rstest integration: hooks.test.ts (26/26)
  • CI green + Codex review threads addressed

…oks (#188 follow-up)

The pinned rust-v0.147.0 pre-tool-use/post-tool-use input schemas declare
`"tool_input": true` and `"tool_response": true`, so Codex may deliver
scalar or null payloads. The generated Codex hook wrapper and the
event-route envelope validator now require presence only for Codex and
keep the documented object requirement for Claude.

Addresses the PR #378 Codex review thread.
@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8eb073e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-03T06:50:35.612303Z 8eb073e PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@404
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@404
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@404

commit: 8eb073e

@ScriptedAlchemy
ScriptedAlchemy merged commit c95091d into main Sep 3, 2026
9 checks passed
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
/#379/#385/#390) (#408)

* fix: address late review threads on merged PRs #368/#373/#374/#377/#378/#379/#385/#390

- dev: lease the adopted epoch in EpochAdoptionPolicy until replaced or closed;
  select the contract-matrix target from the server's own target list; apply the
  session timeout per matrix request; observe lifecycle progress through the
  session trace via a new ContractMatrixClient.observeProgress seam (#385)
- playground: wait for a hard-link catalog publisher to release its staging link
  before adopting the sidecar; return to discovery when the publication is
  rolled back (#377)
- build: run the Agent Plugins byte lane over portable/ during ordinary artifact
  validation; reject every forbidden control character in header values (#373)
- events/hooks: Codex PostToolUse accepts any present JSON tool_response (#378)
- api: project only contract fields of adapter capability rows in inspect (#390)
- tests/support: digest the real Claude home in the live session guard; isolate
  USERPROFILE alongside HOME (#374)
- docs: Claude plugin-root cwd exception, parked-pin trigger independence,
  provider typing contract, portable validation moments (#368/#379/#382/#373)

* fix(dev): lease before publishing contract status; align fixtures with the portable byte lane

- EpochAdoptionPolicy acquires the epoch lease before publishing a passed
  dev.contract.status and announces adoption synchronously with it, so a
  status reader never sees "passed" for an epoch that is not yet adopted
- hooks.test: Codex PostToolUse accepts a string tool_response and rejects a
  missing one; Claude keeps the object check
- mcp-session-service/public-api-packed fixtures: Agent Plugins forbids
  placeholders in headers and non-bare/non-./ commands, and ordinary artifact
  validation now enforces the standard, so the fixtures carry a literal header
  and a bare `node` command

* chore(changeset): drop the Codex tool_response bullet already released by #404

* fix(playground,test): withdraw a failed catalog publication before releasing its staging link; bind custom observeProgress

- #persistSnapshot rolls the sidecar back while the staging link still exists
  when the post-link directory fsync fails, so a concurrent reader keeps seeing
  an in-progress publication until the path is withdrawn instead of adopting a
  briefly singly linked file
- contractProgressObserver invokes a client's observeProgress method with the
  client as receiver

* chore(changeset): one-paragraph summary ending with the PR reference

* fix(playground): recover a catalog staging link abandoned by an exited publisher

After the settle deadline, a matching .stage-<pid>-* link whose publisher pid
no longer exists is an abandoned publication of an already fsynced sidecar:
withdraw the orphan and adopt the sidecar instead of rejecting the epoch
forever. A live publisher's staging link is still never yanked. Adds the
@internal catalogStagingSettleDeadlineMs seam for deterministic tests.

* fix(playground): fsync the catalog directory after withdrawing an abandoned staging link

* fix(dev): forward request _meta (progress token) through McpSession and the dev matrix client

Lifecycle fixtures pass their generated progressToken as params._meta; the
session adapter and McpSession.callTool dropped it, so generated routes never
enabled sendProgress and every progress-gated lifecycle fixture failed the dev
matrix. McpSessionToolCallOptions and McpClient.callTool now carry _meta.

* fix(dev,playground): restart the adoption drain after a handoff race; keep the staging link when a sidecar rollback fails

- EpochAdoptionPolicy reschedules its drain from the completion handler when a
  candidate arrived between the loop's last empty check and #processing being
  cleared, and settled() waits through restarts
- #persistSnapshot releases the staging link after a failed publication only
  once the owned sidecar is confirmed withdrawn, so a rollback failure never
  leaves a singly linked sidecar for readers to adopt

* ci: retrigger checks for the rebased head

* chore: drop the portable byte-lane changes superseded by #406; keep the _meta assertions

* fix(playground): restore the staging guard when a recovery fsync fails

* fix(playground): accept a concurrently restored staging guard (EEXIST aliasing the sidecar) during recovery

* fix(dev): recheck supersession after the adoption lease settles

* fix(playground): keep a fresh pid-owned guard when recovery can neither re-link nor withdraw the sidecar

* fix(playground): fsync every compensating recovery guard before trusting it
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.

1 participant