Skip to content

fix(docs,test): closed-issue audit G4 — stale Claude cwd/preview-peer docs, restore rendered-skill docs, pin the #23 handshake queue - #368

Merged
ScriptedAlchemy merged 1 commit into
mainfrom
fix/closed-audit-g4
Sep 3, 2026
Merged

fix(docs,test): closed-issue audit G4 — stale Claude cwd/preview-peer docs, restore rendered-skill docs, pin the #23 handshake queue#368
ScriptedAlchemy merged 1 commit into
mainfrom
fix/closed-audit-g4

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

Closed-issue verification lane G4 re-audited #73, #72, #63, #59, #58, #53, #50, #47, #45, #44, #43, #42, #38, #23 against origin/main. Everything is implemented and tested on main; four small gaps were found and fixed here (docs + one unit test, no runtime code):

Changeset: agent-bundle patch (docs-only; README ships in the package).

Evidence

Test plan

  • pnpm exec rstest --config rstest.unit.config.ts packages/agent-bundle/tests/runtime-client-surface-proxy.test.ts
  • pnpm typecheck && pnpm lint
  • CI Verify matrix green

…the handshake queue

- packages/agent-bundle/README.md: the Claude adapter no longer emits
  cwd for plugin-root stdio servers (#347 removed it because Claude's
  placeholder table excludes cwd); the README still claimed it did (#47).
- docs/preview-packages.md: the --peerDeps rewrite now applies to the
  optional @agent-bundle/runtime peer declared by agent-bundle, not an
  agent-bundle peer inside the (renamed) runtime package (#45).
- docs/framework-mode.md: restore the rendered-skills (SKILL.tsx) power
  tier and the skills precedence rule (AB4734/AB4735/AB4736, AB3003-AB3005)
  that #150's rewrite dropped from the RFC #63 newcomer doc.
- runtime-client-surface-proxy.test.ts: unit-pin the #23 fix — host
  requests relayed during the App handshake are queued (bounded at 32)
  and flushed on ui/notifications/initialized instead of dropped; only
  the mcp-app-real e2e covered it before.
@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c7ab56c

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-03T05:17:18.216094Z c7ab56c 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@368
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@368
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@368

commit: c7ab56c

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7ab56ce64

ℹ️ 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".

launches stdio servers from the host's own working directory and ignores stdio `cwd` at runtime,
and its placeholder-substitution table excludes `cwd`, so the Claude adapter emits no `cwd` for a
plugin-root working directory (the absolute `${CLAUDE_PLUGIN_ROOT}/mcp/...` entry path plus this
env anchor carry the guarantee) and rejects token-bearing `cwd` values outright. A server's own

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document the accepted plugin-root cwd exception

When a server uses the canonical pathTokens.pluginRoot cwd—as source-built entries do—planMcpServer explicitly accepts it, uses it to prefix the entry argument, and merely omits cwd from Claude’s emitted manifest; only other token-bearing cwd values are rejected. Saying such values are rejected “outright” therefore misleads users into avoiding a valid cross-target configuration, so this sentence should describe the canonical exception.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed on main in #408 (a00273b): the README now states that the canonical plugin-root cwd is the one accepted token-bearing value on Claude (emitted as the ${CLAUDE_PLUGIN_ROOT}/... entry path plus the env anchor, with cwd omitted) and that any other token-bearing cwd is rejected.

@ScriptedAlchemy
ScriptedAlchemy merged commit c94df11 into main Sep 3, 2026
9 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the fix/closed-audit-g4 branch September 3, 2026 05:24
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
…st-install proof

#364 made the Codex adapter honor plugin.logo (interface.logo + shipped image). The
host-install fixture declares plugin.logo, so the binary-gated Codex host-install proofs
started failing on the interfaceFields key list. #368 fixed the built-bundle proof;
this brings the packed-tarball proof (packed-host-install-proof.test.ts) in line.
Test-expectation-only; product behavior is unchanged.

Found by the #181/#242 closed-issue re-verification.
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
…st-install proof (#367)

#364 made the Codex adapter honor plugin.logo (interface.logo + shipped image). The
host-install fixture declares plugin.logo, so the binary-gated Codex host-install proofs
started failing on the interfaceFields key list. #368 fixed the built-bundle proof;
this brings the packed-tarball proof (packed-host-install-proof.test.ts) in line.
Test-expectation-only; product behavior is unchanged.

Found by the #181/#242 closed-issue re-verification.
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
…ry PR with pinned CLIs

The host-install, packed host-install, and packed Claude plugin-validation
proofs skip their Claude/Codex legs when the CLIs are absent, which let #364
break both proofs on main unnoticed (#367/#368 repaired them from local runs).

- Pin @anthropic-ai/claude-code@2.1.250 and @openai/codex@0.147.0 as `hostCli`
  in each adapter's schema PROVENANCE.json; scripts/host-cli-pins.mjs reads
  the pins, refuses a pin that differs from observedCliVersion, installs them
  (re-running Claude's postinstall when npm blocks it), and fails closed with
  one diagnostic line when the CLI on PATH is not the pin.
- Add the host-install-proofs CI job (cached CLI prefix, version gate, build,
  test:host-install, test:host-install:packed, test:packed:native) honoring
  the docs-only skip. No secrets or login are needed.
- Harden the Codex interface proof: one shared pinned snapshot for both proof
  suites, installed manifest must equal the built artifact, validate against
  the pinned plugin schema, and reject fields outside the adapter's exported
  codexInterfaceFields.
- Document the job and the local commands in docs/local-ci.md and README.
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
…ry PR with pinned CLIs (#395)

* ci(host-proofs): run the binary-gated real-host install proofs on every PR with pinned CLIs

The host-install, packed host-install, and packed Claude plugin-validation
proofs skip their Claude/Codex legs when the CLIs are absent, which let #364
break both proofs on main unnoticed (#367/#368 repaired them from local runs).

- Pin @anthropic-ai/claude-code@2.1.250 and @openai/codex@0.147.0 as `hostCli`
  in each adapter's schema PROVENANCE.json; scripts/host-cli-pins.mjs reads
  the pins, refuses a pin that differs from observedCliVersion, installs them
  (re-running Claude's postinstall when npm blocks it), and fails closed with
  one diagnostic line when the CLI on PATH is not the pin.
- Add the host-install-proofs CI job (cached CLI prefix, version gate, build,
  test:host-install, test:host-install:packed, test:packed:native) honoring
  the docs-only skip. No secrets or login are needed.
- Harden the Codex interface proof: one shared pinned snapshot for both proof
  suites, installed manifest must equal the built artifact, validate against
  the pinned plugin schema, and reject fields outside the adapter's exported
  codexInterfaceFields.
- Document the job and the local commands in docs/local-ci.md and README.

* docs(local-ci): list dev-live-host among the CI-run host proofs

* fix(ci): key host CLI cache on package names and resolve npm global bin via prefix

Address the automated review on #395: the actions/cache key now includes each
pinned hostCli.package as well as its version, so a re-pin to a different
package with the same version misses the cache instead of reusing stale
binaries; and the installer derives npm's global bin directory from
`npm prefix -g` (<prefix>/bin on POSIX, the prefix itself on Windows)
instead of walking up from `npm root -g`.

* fix(ci): hash exact host CLI pins into the cache key

Sanitising package names for the actions/cache key can map distinct
packages (`@foo/bar`, `foo-bar`) to the same text; append a 16-hex SHA-256
of the exact `package@version` pairs so any re-pin misses the cache.

* fix(ci): probe installed host CLIs from the prefix only and reject bare --prefix

The post-install probe now runs with PATH limited to the prefix bin
directory plus the running Node, so a pre-existing claude/codex elsewhere
on the inherited PATH cannot mask an incomplete prefix. `install --prefix`
without a directory operand is rejected instead of silently installing
into the default global npm prefix.
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
#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)
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