Skip to content

feat(test): host-install proof level with real Claude, Codex, and Cursor install proofs (#100 stage 3) - #242

Merged
ScriptedAlchemy merged 2 commits into
mainfrom
wave5/100-s3
Sep 1, 2026
Merged

feat(test): host-install proof level with real Claude, Codex, and Cursor install proofs (#100 stage 3)#242
ScriptedAlchemy merged 2 commits into
mainfrom
wave5/100-s3

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

Closes the stage-3 slice of #100 — real-install proofs per host, binary-gated with honest skips — and carries #108's deferred real-host token proofs. Extends #181's install machinery (#195) with a proof lane.

The host-install proof level (label is load-bearing)

host-install (built bundle installed into an isolated real host home through the public install path, registration observed via the host's own CLI; NOT session-behavior or packed-artifact evidence)

One shared fixture (tests/fixtures/host-install: 1 skill, 1 sessionStart hook, 1 MCP server, all three targets) built ONCE per run with the source-built CLI; every proof spawns node dist/cli.js install <host> — the exact #195 delegation path — into an isolated home. No new pack, no model calls in the default lane.

host gated on what REALLY runs
Claude claude binary (auto-skip otherwise) install claude with isolated CLAUDE_CONFIG_DIR → real claude plugin marketplace add + plugin install --scope user; asserts plugin list --json row (id, version, scope, enabled, installPath in the isolated cache, mcpServers) and plugin details component inventory Skills/Hooks/MCP = 1/1/1; cache physically contains skills/probe/SKILL.md
Codex codex binary (auto-skip otherwise) install codex with isolated CODEX_HOME → real codex plugin marketplace add + plugin add; asserts codex plugin list installed+enabled, cache tree, byte-identical schema-valid agents/openai.yaml skill sidecar, and the manifest interface block
Cursor nothing (no public installer per the pinned contract — runs everywhere) install cursor with isolated HOME → placement at .cursor/plugins/local/<name>, plugin/hooks/mcp documents validated against the pinned schemas, ${CURSOR_PLUGIN_ROOT} kept unresolved in installed hooks/mcp documents, idempotent re-install returns already-installed

#108 token proofs (real session, opt-in)

AGENT_BUNDLE_HOST_INSTALL_CLAUDE_SESSION=1 + claude binary gates one real claude -p turn (sonnet, --plugin-dir inline load, ≤2 attempts hard ceiling) against a Claude-only token fixture. Observed on Claude Code 2.1.257: $ARGUMENTS → the exact invocation arguments, ${CLAUDE_PLUGIN_ROOT} → the loaded bundle root, ${CLAUDE_SKILL_DIR}<bundle>/skills/token-probe. An always-on (model-free) test pins the lowering: canonical tokens → Claude spellings, no canonical/foreign syntax leaks. Two real-host facts recorded honestly:

  • A real turn rewrites Claude's own .claude.json; the session guard pins the settings + installed-plugins surface instead (normalClaudeSettingsAndPluginsUnchanged), and normalClaudeHomeUnchanged is unchanged for its existing caller.
  • Skill targeting is project-wide (frontmatter targets: carries per-host extensions, not host restriction), so a token-bearing skill cannot ship in a project that also targets Codex/Cursor (AB3008) — hence the separate Claude-only fixture. Worth a follow-up issue.
  • Cursor honest ceiling: no non-interactive plugin-loading session surface exists, so runtime var resolution is not provable; recorded in the report as sessionEvidence: unavailable.

Real-binary defect fixed

Claude Code 2.1.257 rejects the emitted claude plugin marketplace add . ("Invalid marketplace source format"); ./ and absolute paths work. Emitted INSTALL.md now uses ./ for Claude and Codex (codex accepts both — verified), with dated capability-evidence notes; installBundle's absolute-path delegation was already correct.

CI

native-host-smoke.yml gains a host-install step per matrix host and a Claude-only session-token step. test:host-install* scripts mirror the packed-native naming. The proof test is classified in the integration pool: cursor lane runs everywhere, claude/codex lanes auto-skip where binaries are absent.

Test plan

  • pnpm typecheck, pnpm lint (874 files, 0 errors/warnings)
  • Scoped suite post-rebase: 65 passed, 1 skipped (the opt-in session without env, skip title carries the exact reason), 0 failed
  • Real host-install proofs 3/3 on this machine: claude 2.1.257, codex-cli 0.147.0, isolated Cursor home
  • Real session token proof 2/2 with the opt-in (one live sonnet turn)
  • Note: packed-native-smoke.test.ts Claude packed proof fails on clean main under npm 12.0.2 (npm pack --json shape change in shared-pack.ts) — pre-existing, unrelated, fix rides the Generate an Agent Bundle framework test harness on top of Rstest #103 s4 lane.

Changeset: minor.

…sor install proofs

Binary-gated real-host installs into isolated homes through the public
install path, observed via each host's own CLI. Fixes emitted
'plugin marketplace add .' to './' (Claude Code 2.1.257 rejects bare '.').
Claude: opt-in real-session proof that $ARGUMENTS, ${CLAUDE_PLUGIN_ROOT},
and ${CLAUDE_SKILL_DIR} resolve in one claude -p turn with the bundle
loaded via --plugin-dir (observed 2.1.257; a real turn rewrites
.claude.json, so the guard pins settings and installed plugins).
Codex: installed cache carries a byte-identical schema-valid
agents/openai.yaml sidecar and the manifest interface block.
Cursor: installed hooks/mcp documents keep ${CURSOR_PLUGIN_ROOT}
unresolved; no non-interactive session surface exists, recorded as the
honest ceiling.
@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 189f129

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 Minor

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 1, 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-01T23:47:34.829812Z 189f129 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 1, 2026

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

commit: 189f129

@ScriptedAlchemy
ScriptedAlchemy merged commit 9928c3e into main Sep 1, 2026
15 of 16 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the wave5/100-s3 branch September 1, 2026 23:58
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.
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