Skip to content

feat(agent-bundle): add Amp native plugin factory - #729

Merged
ScriptedAlchemy merged 9 commits into
mainfrom
feat/711-amp-native-plugin
Sep 7, 2026
Merged

feat(agent-bundle): add Amp native plugin factory#729
ScriptedAlchemy merged 9 commits into
mainfrom
feat/711-amp-native-plugin

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • add the built-in amp target, emitting one .amp/plugins/<name>/index.js async PluginAPI factory with explicit Skill and inline event registration
  • emit flat skill-scoped MCP with native frontmatter precedence, and reject generated local entries and unexpanded path tokens
  • add receipt-owned project/system install, replace, plan, and uninstall without editing Amp settings, trust, disabled state, or repositories
  • bump the closed artifact contract to manifestVersion 4 for documents.entry and the amp built-in identity
  • document the pinned contract and account-free proof in English and Chinese

Closes #711

Verification

  • pnpm build && pnpm typecheck && pnpm lint && pnpm test:unit && pnpm test:route-unit && pnpm test:projection && pnpm test:integration:run — passed on current origin/main (62e5c3a)
  • pnpm test:packed — passed
  • pnpm docs:site:build — passed, including locale parity, diagnostics coverage, build, and link checks
  • focused generated-factory, Amp install, lifecycle CLI, and event projection regressions — passed
  • disposable @ampcode/plugin@0.0.0-20260907001852-gf348fed typecheck and typed fake PluginAPI import — passed
  • amp --help and amp skill add --help — passed without authentication

Proof matrix

Surface Status Evidence
Generated PluginAPI factory syntax/types verified Disposable consumer typecheck; reserved-binding entries imported successfully
Skill and callback registration/mapping verified Typed fake PluginAPI assertions
Relocation and self-contained output verified Artifact validation and packed deleted-source process tests
Project/user install, replace, plan, uninstall verified Receipt ownership and hostile-filesystem tests
amp plugins list unverified Account-dependent connection error without an Amp account
amp skills list --json unverified Requested login without an Amp account
Live model/tool callback execution and activation unverified Explicitly account-dependent; capability evidence records this state

Deslop

Deslop: GPT-5.6 Sol, 5 edits — removed content-only runtime helpers, reused strict-record/path-token and uninstall-pruning helpers, separated recursive adapter roots from assets, and consolidated Amp MCP validation.

Self-review

Reviewer: Claude Fable 5.1 Thinking High (change-risk-reviewer), run twice after fixes and once after rebasing over #730/#732.

  • Generated hooks launched the Amp standalone executable as a script runtime: fixed by setting BUN_BE_BUN=1, with launch assertions.
  • The shared portable-segment predicate allowed separators: fixed at the shared predicate; planner and installer now reject traversal/multi-segment names and accept My_Plugin.
  • Programmatic project uninstall omitted projectRoot: fixed with a round-trip regression.
  • Changeset and manifest reference omitted version 4 details: fixed in the changeset and both locales.
  • Non-Amp result-field error named an undefined outcome: fixed with an explicit Amp-only-field diagnostic.
  • Package-bound Amp user install consulted cwd unnecessarily: fixed so only project scope resolves cwd.
  • Rebase conflict with feat(install): add the agent-bundle/install package-bound lifecycle entry (#724) #730 lifecycle command extraction: preserved registerLifecycleCommands, added Amp only to install/uninstall, and kept development installs narrowed to DevInstallHost.

Final review: no merge blockers. Residual live activation and callback execution remain deliberately unverified because no Amp account is available; they are not represented as unsupported.

@changeset-bot

changeset-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d1f6dcf

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 7, 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-07T03:20:09.258382Z 2df178f 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.

@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: 2df178f533

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

Comment thread packages/agent-bundle/src/adapters/amp.ts Outdated
Comment thread packages/agent-bundle/src/adapters/amp.ts
Comment thread packages/agent-bundle/src/install/identity.ts Outdated
Comment thread website/docs/en/guide/concepts/architecture.mdx

@ScriptedAlchemy ScriptedAlchemy left a comment

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.

Current-head review — 894c7321f09bc2df66f052ac2034044b90f2e042

Hold for the lifecycle/location corrections below and a rebased integration gate. The no-account decision on #711 remains accepted: authenticated Amp model execution is unverified, not a new merge prerequisite. These findings concern framework-owned behavior that can be tested without an account.

Reviewed the complete changed-path inventory and traced the adapter/factory, event lowering, registry/manifest integration, installer/uninstaller, focused tests, and documented proof. Repository/native-host tests were not run by this reviewer. A standalone Node calculation reproduced the path expressions below; that was not an installation or filesystem-mutation test.

P2 — The generated callback factory never disposes the child processes it starts

File: src/adapters/amp.ts, factorySource / generated runHook.

runHook starts Bun.spawn, collects stdout/stderr with unbounded Response(...).text(), and waits on Promise.all([child.exited, stdout, stderr]). There is no tracked child ownership, disposal registration, or finally-path termination. Reload/unload can therefore abandon a still-running plain hook or fail to settle pending work; a hung child/stream has no cleanup path in this factory. This is a source-derived lifecycle gap, not a reproduced orphan-process incident.

Amp's official PluginAPI onDispose specifically provides bounded cleanup on unload/reload/graceful host shutdown for resources including children. Wire the generated process owner to that lifecycle, stop admitting work during disposal, and settle/terminate owned children within the host's documented budget. Cover spawn/stdin/read failure paths and bound protocol capture rather than collecting arbitrary output forever. Reuse existing process/stream handling where viable instead of introducing a parallel lifecycle framework.

Do not invent an event ctx.signal or a session.end callback: those are not established by the pinned event contract. Do not claim crash/SIGKILL cleanup that onDispose cannot provide.

Acceptance gap: amp-adapter.test.ts replaces Bun.spawn with a fake that ignores executable arguments; the compiled wrapper test launches the wrapper directly through Node. Neither proves the actual generated factory → real child → compiled wrapper path or disposal. Add an account-free generated-factory test with a deliberately blocked real child; invoke the registered dispose callback and assert the invocation settles and the owned process is gone. Verify the actual interpreter/argv used by that path and normal/error outputs as well. This does not require an authenticated Amp turn.

P2 — Project installation has an explicit root; typed uninstall cannot target the same root

Files: src/install/install.ts, InstallBundleOptions.projectRoot / ampInstallLocation; src/install/uninstall.ts, UninstallBundleOptions / uninstallAmp.

Install supports { scope: 'project', projectRoot: '/projects/A' } from a caller elsewhere. UninstallBundleOptions has no projectRoot, yet uninstallAmp delegates to the same location function, which then falls back to process.cwd(). The supported typed round trip cannot address A without changing global cwd; it may report not installed or address another project containing the same plugin.

Share the explicit location option across install, uninstall and uninstall plan. Extend amp-install.test.ts: call both operations from outside A, give A explicitly, and retain a separate sentinel/installation in caller project B. Existing project coverage only verifies installation. Do not solve this with process-global chdir or ambient-root guessing.

P2 — Empty or relative XDG_CONFIG_HOME makes user installation cwd-dependent

File: the same ampInstallLocation implementation.

join(environment['XDG_CONFIG_HOME'] ?? join(home, '.config'), 'amp') only defaults null/undefined. Reproducing that expression yields:

XDG_CONFIG_HOME unset       -> /tmp/amp-review/home/.config/amp/plugins/probe
XDG_CONFIG_HOME=""          -> amp/plugins/probe
XDG_CONFIG_HOME="relative"  -> relative/amp/plugins/probe

The XDG specification requires an empty configuration variable to use the home default and treats relative values as invalid. Apply the existing/shared absolute-XDG fallback policy before deriving both install and uninstall locations. Add unset, empty, relative and valid absolute cases; assert no cwd-relative plugin directory is created or selected. Do not normalize a relative XDG value against cwd and call it a user-config root.

Previous review findings visibly fixed

The reserved/strict-mode factory identifiers, remote MCP URL/header path-token validation, and mixed-case Amp installation-name mismatch now have implementation changes and focused regression tests. I am not reposting those old inline findings as current defects. Answer/resolve their existing threads with the fixing evidence rather than duplicating them.

The selected-skill MCP constraint, refusal to invent relocation semantics, content-only runtime absence, explicit registration, and preservation of foreign files/settings are appropriate scoped decisions. Final API-required allow is not being confused here with the old Claude implicit-permission defect.

Integration and evidence gate

GitHub currently reports this branch conflicting with main (596d3371e9a9efbd2e84561826f5f390fefb2c3d). It changes the closed manifest to v4, public types, emitted roots and lifecycle consumers; the PR body currently records 81 focused tests and disposable type/fake-host proof, not the complete integrated gate.

After resolving conflicts, record the repository's allowed local build/typecheck/lint/unit gate, the full integration coverage implicated by the output/manifest changes, affected packed tests, and the English/Chinese docsite gate on the exact resulting head. Preserve existing Claude/Codex/Cursor/portable, installed-artifact, Workbench and npm-root behavior. The exact-head PR-workflow query returned no runs; that is not a failed CI result and does not replace or invalidate a properly recorded local gate. No approval, source modification or merge is performed by this review.

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.

Host support: Amp — native plugin factory, explicit skill registration, and skill-scoped MCP

1 participant