feat(prepack): gate installed dependencies (AB7014/AB7015); host-native INSTALL.md - #547
Conversation
…mitted INSTALL.md host-native A published plugin installs nothing beyond its own files: the build inlines every dependency into dist/bin and the host packs, so package.json dependencies/optionalDependencies/peerDependencies entries only make every consumer's npm install fetch build-time packages — and fail outright under npm 12's default allow-git=none / allow-remote=none when one is a git or remote specifier (cargo-hauler 0.4.7 is uninstallable for exactly this). - AB7014: an installed-dependency field names packages no packed JavaScript imports or requires (evidence read from the packed bytes, one diagnostic per field). - AB7015: an installed-dependency entry resolves through git, a GitHub shorthand, a remote tarball, or a path. - Emitted INSTALL.md states the bundle is self-contained, uses the host's own claude plugin / codex plugin commands for uninstall, and marks every agent-bundle install/uninstall/doctor mention as optional automation. - create-agent-bundle mcp-server and cli-tool templates, and the examples, declare @agent-bundle/runtime, react, and zod under devDependencies.
🦋 Changeset detectedLatest commit: dd51de5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
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 |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ 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. |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b3252614d1
ℹ️ 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".
…ssifier fixes - readModuleImports consults the digest cache itself (a parsed result answers a lexed request); rememberedModuleImports and its three call-site lookups are gone. - pack-dependencies.ts is evidence only (declared entries, imported names, classifiers); AB7014/AB7015 are emitted in pack-inventory.ts beside AB7010-AB7013 through its diagnostic helper and a shared quoteAll. - isRegistrySpecifier catches scp-style git@host:path and Windows drive paths; packageNameOf drops its dead @-guard for one positive shape. - readFile errors other than ENOENT propagate; packed files are read in parallel; AB7015 says optionalDependencies fail to fetch, not install. - Table tests for the classifiers; prepack fixture tests share withPackageDocument and assert codes/names rather than sentences. - Claude/Codex INSTALL.md share the optional-CLI paragraphs.
|
@codex review |
…ts, optional peers, and the packer - ~1.2.3 is a semver range, not a home path (AB7015 false positive). - Packed .d.ts/.d.mts/.d.cts files count as dependency usage: a consumer needs the package that provides referenced types even without a runtime import (AB7014 false positive). - peerDependenciesMeta optional peers are never installed by npm and are not inspected. - workspace:/catalog: are registry specifiers only when pnpm, Yarn, or Bun runs the pack (npm_config_user_agent) and rewrites them; npm publishes them verbatim and consumers fail with EUNSUPPORTEDPROTOCOL.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48165af029
ℹ️ 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".
…classifiers, table-tested scanners - prepack() turns npm_config_user_agent into packerRewritesWorkspaceProtocols; isRegistrySpecifier classifies the string as written and isWorkspaceProtocol lets the emitter apply the policy. RegistrySpecifierOptions is gone. - optionalPeers is one set computed once; declarationSpecifiers is exported and table-tested; requireCall and declarationSpecifier share quotedLiteral. - The JS path keeps the lexer on purpose: bundled library docblocks contain literal 'from "effect"' lines a text scan would count as usage. - pack-inventory uses isErrno and sha256Hex like its sibling; module-imports caches per check level only; AB7015 wording per partition; docs/changeset name declaration references and workspace protocols.
…s; INSTALL.md gates marketplace removal - require.resolve / createRequire(...).resolve / import.meta.resolve with a literal argument count as usage for AB7014. - bundleDependencies (name list or true, either spelling) are embedded in the tarball and never reported by AB7015. - A name under both dependencies and optionalDependencies is judged by its optional entry, as npm does. - Emitted INSTALL.md no longer lists 'plugin marketplace remove' in the uninstall block: it is a separate step gated on 'plugin list' showing no other plugin from the marketplace (any scope or project, for Claude).
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 99e53f8640
ℹ️ 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".
- bundleDependencies never covers peerDependencies (npm packs no node_modules entry for a peer-only name) and 'true' covers dependencies only, so AB7015 still reports a peer's file:/git/workspace specifier. - An npm: alias is a registry specifier only when its target is: npm:bar@file:../bar, npm:bar@workspace:*, and nested npm: are reported.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a2be523b6
ℹ️ 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".
…lds AB7014, Claude marketplace inventory - /// <reference types="x" /> counts for x and @types/x (@types/scope__name when scoped): the declaration cannot say which one the consumer needs. - A computed import(expression) in packed JavaScript may load any declared package, so importedPackageNames reports complete=false and AB7014 is withheld; the recovery text and docs say so. - Claude INSTALL.md: marketplace removal is gated on the cross-project registry plugins/installed_plugins.json, not just 'claude plugin list', and points at the optional uninstaller that performs that inventory. - Docs: externalized runtime packages belong under dependencies; AB7014 permits them.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5e3554d4e8
ℹ️ 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".
…ript bins count as usage - A packed '#subpath' import counts for every package the manifest's imports map targets (conditional targets included). - require(expression) withholds AB7014 like import(expression); bundler runtimes (__webpack_require__) never match. - A dependency a consumer-side preinstall/install/postinstall/prepare script names, or whose bin command it runs (read from node_modules/<name>), is used.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6ca79200fe
ℹ️ 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".
…vable optional deps warn - require.resolve(x), import.meta.resolve(x), and a direct createRequire(...)(x) with a non-literal argument mark the evidence incomplete like require(x); path.resolve/Promise.resolve never match. - AB7015 on optionalDependencies is a warning: npm continues an install without an optional dependency it cannot fetch.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 346da1b08c
ℹ️ 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".
… computed loads withhold AB7014
- prepack() throws only on error-severity diagnostics and returns the
surviving warnings on PrepackResult.diagnostics; the CLI prints them.
- require("driver/" + variant) and the template-literal form count as
computed loads and mark the evidence incomplete.
|
@codex review |
… names
createRequire(new URL("./entry.js", import.meta.url))("driver") is a
load: the factory argument may nest calls two deep. A delegated npm run
"setup" names the script the shell unquotes.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 76b2de6684
ℹ️ 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".
…cript files load optional deps A file: or bare path inside the package whose source directory manifest or tarball file is packed is installable from the consumer's copy, so AB7015 exempts it like a packed bundleDependencies entry. An install script that runs a packed file (node install.cjs) needs every package that file loads, following relative imports through the tarball, so a fetched optional dependency reached that way stays fatal.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0351b9c38
ℹ️ 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".
…test/start delegation, validate packed file: sources installScriptFiles tokenizes the shell command keeping quoted words whole and resolves an extensionless path the way Node does (scripts/install -> scripts/install.js; .cjs/.mjs are never tried). Delegated-run traversal follows npm's direct script commands (test/t/tst/start/stop/restart) with their pre/post hooks. A file: source shipped in the tarball is exempt from AB7015 only when the packed copy is installable: a directory whose package.json parses to an object, or a (gzipped or plain) tar holding <dir>/package.json.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eb2f5fc15e
ℹ️ 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".
…, follow own-file imports targets, allow call-site comments
tarHoldsPackage validates each ustar header checksum and payload bounds and JSON-parses the <dir>/package.json payload before a packed file: tarball exempts AB7015 (npm: TAR_BAD_ARCHIVE / EJSONPARSE). shellWords splits &&, ||, ;, |, & without surrounding whitespace so 'node install.js&&echo done' still follows install.js. Install-script module traversal enqueues relative imports-map targets ('#setup' -> ./setup.js) instead of dropping them. Comments between a CommonJS loader and its parentheses, or around the literal, are trivia for literalLoad and never start a computed argument.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f1711da468
ℹ️ 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".
…rts wildcards, shadowed peers AB7015 escalation of an optional dependency now needs the install script to run it: a bin in command position (after env assignments, options, npx/bunx/cross-env/env wrappers and pnpm/npm/yarn/bun exec|dlx|x), a node_modules/<name>/ file, or a require in an inline node -e program; a bare mention (echo foo) stays keep-only AB7014 evidence. packedModule consults each packed directory manifest's main before index.js, as Node does. Imports-map specifiers resolve to the exact or best wildcard key with * substituted, for install traversal and for AB7014 reachability. declaredDependencies drops a peer that dependencies or optionalDependencies also names, whose selector npm never reads.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b5441c93c
ℹ️ 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".
…command separators
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6a5d214a9
ℹ️ 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".
…r, shell backslash escapes
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a093992d08
ℹ️ 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".
…re aliases mark evidence incomplete
…rograms, unreadable dependency manifests
…led manifests as npm does Second self-review pass on 1e6e5cf (gpt-5.6-sol-medium): - A packed file or inline `node -e` program es-module-lexer rejects now marks its evidence incomplete: its `import()` calls cannot be reported, so AB7014 is withheld for the package and a skipped optional dependency an install script needs escalates to an AB7015 error instead of hiding behind an empty import list. - `node_modules/<dep>/package.json` is parsed with plain `JSON.parse`, as npm parses it, so the last of duplicate keys decides a string-form `bin` name; the strict duplicate-key parser is for our own config, not a third party's manifest (comment says why it is not strict-json.ts). Tests: lexer-rejected packed file withholds AB7014; lexer-rejected inline program escalates AB7015; duplicate-`name` manifest resolves the effective unscoped bin. All three fail on 1e6e5cf. Docs (diagnostics.md, en/zh validation.mdx) and the changeset gain one clause each.
Why
npm install -g cargo-hauler@0.4.7fails for every consumer on npm 12:Nothing shipped in that package imports
@agent-bundle/runtime,effect,bashjsast, or any other third-party module — the build inlines all of them intodist/binand the host packs — butpackage.jsonstill listed the whole build-time stack underdependencies, including a pkg.pr.new tarball and agithub:ref that npm 12 refuses by default (allow-git=none,allow-remote=none). The framework's own templates and examples modelled that shape.What
AB7014(prepack): adependencies/optionalDependencies/peerDependenciesfield names packages that no packed JavaScript imports or requires, one diagnostic per field. Evidence is read from the packed bytes npm would publish (ESM lexer forimport, literalrequire("…")scan, package-name reduction, Node built-ins ignored); a mention in a comment can only keep a dependency, never report one.devDependenciesare never inspected.AB7015(prepack): an installed-dependency entry resolves outside a registry (git /github:& friends /owner/reposhorthand /http(s):tarball /file:/link:/ relative path).npm:aliases andworkspace:protocols count as registry specifiers.INSTALL.mdnow states the bundle is self-contained and nothing requires theagent-bundleCLI; the Claude and Codex uninstall blocks use the host's ownclaude plugin uninstall … --keep-data+marketplace remove/codex plugin remove+marketplace remove(the exact commandsagent-bundle uninstallruns), and every remainingagent-bundle install/uninstall/doctormention is marked optional.create-agent-bundlemcp-serverandcli-tooltemplates, andexamples/{audiobook-curator,host-test,worktree-proximity}, declare@agent-bundle/runtime,react,zodunderdevDependencies.docs/diagnostics.md, en+zhguide/distribution/{validation,installation}.mdx,reference/{index,targets-artifacts}.mdx. Changeset included.Proof
Run against the real published
cargo-hauler@0.4.7tarball (77 files, 138 MB, 1.1 s):Local:
pnpm typecheck,rslinton changed files,pnpm test:unit(3260 pass), integrationprepack/install/uninstall/doctor/adapter suites (427 pass),pnpm docs:site:build(parity OK).Review status
chatgpt-codex-connector.Self-review
Reviewer:
change-risk-reviewersubagent, modelgpt-5.6-sol-medium, run against the diff vsorigin/mainat9ce8c938f. Three findings, all fixed in1e6e5cf76:createRequirefactory calls (pack-dependencies.ts,loadCall) —Module.createRequire(…)("dep")andrequire("node:module").createRequire(…)("dep")reported as unrecognised, giving a false AB7014. Disposition: fixed in1e6e5cf76—factoryQualifier(dotted namespace of any depth, orrequire(…).) now precedes the factory infactoryCall/loadCall(soliteralLoadandcomputedLoad) and inloaderBinding; the direct forms turned out to be matched already through the\bbeforecreateRequire, so the change makes that explicit and closes the one real gap (multi-level namespace bindings,ns.default.createRequire(…)). Sevenit.eachrows pin the behaviour (five direct forms including.resolve, one two-level binding, two computed → incomplete).import()(installScriptCommandDependencies) —node -e "import('optional-driver')"left a fetched optional dependency at warning AB7015. Disposition: fixed in1e6e5cf76—moduleLoads(source)is extracted fromjavaScriptEvidence(lexer imports + literalrequire/createRequire+ completeness) and run over each inline program; a computedimport(x)marks it incomplete and escalates every declared optional. Six-row table: literalimport(),--input-type=module … await import(), computedimport(),require()→ error;import.metaand the name in a string → warning.prepack(executableCommands) —node_modules/<dep>/package.jsonthat is not JSON threw a rawSyntaxError. Disposition: fixed in1e6e5cf76—readManifestparses withcore/strict-json.ts'sparseJsonWithoutDuplicateKeysinside atry, and a parse failure or non-object result takes the existing unreadable-manifest path (unscoped name as the guessed bin,known: false), never a throw. Test writes{ not jsonfor a declaredbroken-deprun bypostinstalland asserts the gate completes withbroken-depnot reported unused.Second pass. Reviewer
change-risk-reviewer, modelgpt-5.6-sol-medium, run against the diff vsorigin/mainat1e6e5cf76. Two warnings, both inpack-dependencies.ts, both fixed in76056b7d1:moduleLoads) — whenreadModuleImports()threw,importsbecame[]withcompletestilltrue, so a packed file or inlinenode -eprogram es-module-lexer rejects could hide a realimport(): a fetched optional dependency the install script needs stayed at warning AB7015, and AB7014 could report a package such a file loads. Disposition: fixed in76056b7d1— a lexer failure now forcescomplete: false, the same conservative path as a computed load. Tests: a packeddist/unlexable.mjswith an unbalancedimport("chosen-at-runtime"withholds AB7014; an inlinenode -e "import('optional-driver'"row escalates AB7015 to error. Both fail on1e6e5cf76(AB7014 reported / severitywarning).binevidence (readManifest) —parseJsonWithoutDuplicateKeysrejected a manifest npm reads fine (last duplicate key wins), so it fell to the guessed-bin path and an alias whose effectivenamedecides a string-formbinran undetected. Disposition: fixed in76056b7d1— third-party manifests are parsed with plainJSON.parseinside the sametryplus the object check, mirroring npm; a comment states why this is deliberately notcore/strict-json.ts(the semantics differ: that parser guards our own config). Test: a git-specifier optional dependency whose installed manifest has"name": "first-name", "name": "@scope/effective"and"bin": "cli.js", withpostinstall: effective --init→ AB7015 error and no AB7014, proving last-key-wins. Fails on1e6e5cf76(severitywarning).Docs (
docs/diagnostics.md, en/zhvalidation.mdx) and the changeset gained one clause each for the two behaviours (lexer-rejected source withholds AB7014; manifests read as npm reads them, unscoped name standing in when not JSON). Gate green locally (typecheck,lint,test:unit, fullprepack.test.ts,docs:site:build); CI green on76056b7d1without reruns.