feat(install): make host bundles directly installable - #195
Conversation
🦋 Changeset detectedLatest commit: 14bcd09 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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: c18adf5913
ℹ️ 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".
| hash.update(await readFile(path)); | ||
| hash.update('\0'); | ||
| }; | ||
| for (const name of (await readdir(root)).sort((left, right) => left.localeCompare(right))) { |
There was a problem hiding this comment.
Validate the tree root before traversing it
When an existing Cursor destination is itself a symlink—for example, a previous manual installation linking back to the source bundle—readdir(root) follows the link and only its descendants are checked with lstat. If the linked tree matches the source, installCursor therefore reports already-installed even though Cursor rejects local-plugin symlinks that escape its local directory. Check the root with lstat before traversing it and reject a symlink or non-directory; the generated treeHash in surface.ts has the same omission.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in d5dcf28. treeHash now lstats and validates the root itself before any readdir, so a symlinked Cursor destination fails closed with AB7004 instead of being treated as already installed. The emitted install.mjs uses the same root check, and the regression fixture links the destination to an identical source bundle to cover the false-idempotency case.
a9a1bd1 to
074f12f
Compare
Record the evidence-backed per-host distribution design before adding installer behavior.
Emit exact host install surfaces and add safe native installation so built artifacts can move from distribution to a real host without bespoke setup.
Require an existing Cursor home before direct placement and keep legacy artifact fixtures aligned with the new required install surface.
Clarify that portable bundles use their emitted installer while the native Cursor command consumes Cursor manifests.
Include required install surfaces in manually assembled valid artifacts and pin their emitted host-plan ordering.
Load host installation only for the CLI install action so unrelated packed API consumers keep their existing dependency and startup surface.
074f12f to
14bcd09
Compare
Summary
INSTALL.mdfiles plus safe Cursor-compatibleinstall.mjsfallbacks, and enforce required surfaces in artifact validationagent-bundle install <host> --from <bundle-dir> --scope <scope>with public CLI delegation, typed missing-host failures, and idempotent collision-safe Cursor placementTest plan
pnpm --filter agent-bundle buildpnpm typecheckpnpm lintCloses the real-install proof slice of #100 and reverses #101 stage-0's documentation-only assumption for these bounded host install paths.