Download prebuilt binaries via pel package manager (Phase A part 2) - #31
Download prebuilt binaries via pel package manager (Phase A part 2)#31JeroenSoeters wants to merge 21 commits into
Conversation
…ged formae by path - start-mcp.sh: read plugin version from .claude-plugin/plugin.json and store it in ~/.formae-ai/opt/.formae-mcp.plugin-version; force-reprovision formae-mcp when the marker is missing or differs from the current version, so a new plugin release replaces the stale binary instead of hitting the existence fast-path. The formae binary is intentionally left on the original fast-path (explicit upgrade only, pinned-CLI policy). - skills/upgrade/SKILL.md: classify the install by checking the managed path (~/.formae-ai/opt/bin/formae) directly before falling back to which formae. The managed binary is exposed via FORMAE_BUNDLED_BIN and is not on PATH, so which formae fails to find it even when the managed tree is active.
… host-key failure)
… startup timeout Codex starts sessions without waiting for MCP servers unless the server is marked required, so on first launch (while the launcher downloads the binaries) the formae tools are silently missing from the session. Make the config.toml block the primary registration path and include required = true plus startup_timeout_sec = 120; codex mcp add cannot set either field.
Each spins a clean container, follows the harness INSTALL doc (clone, skills symlink, register scripts/start-mcp.sh), and proves the harness spawns the launcher and the MCP connects: Codex via a non-interactive exec turn that must complete a search_hub_plugins tool call (agentless, hub-backed), and OpenCode via 'opencode mcp list' showing the server connected plus a direct JSON-RPC tools/list through the launcher. Both assert the binaries were downloaded, not built (no Go toolchain in the image).
|
Codex + OpenCode install docs are now verified in clean containers (dev channel), via the two new test scripts:
Both tests assert the binaries were downloaded, not built (no Go toolchain in the image). Still open: the agent-backed |
Codex CLI >=0.148 installs plugins from Claude-format marketplaces:
`codex plugin marketplace add` reads .claude-plugin/marketplace.json, and
plugin manifests are discovered at .codex-plugin/plugin.json (falling back to
.claude-plugin/plugin.json).
Add .codex-plugin/plugin.json declaring the skills dir and pointing at
.codex-plugin/mcp.json for the MCP server config. The command is a relative
path with an explicit cwd rather than ${CLAUDE_PLUGIN_ROOT}/${PLUGIN_ROOT}
interpolation, which is currently broken upstream — a relative command
resolves fine once cwd is set to the plugin's own root. required=true plus a
120s startup_timeout_sec make the first session wait for the one-time prebuilt
binary download instead of silently starting without the formae tools.
The MCP config lives inside .codex-plugin/ (not a root .mcp.json) so Claude
Code never auto-loads it as its own server.
Codex CLI >=0.148 can install the formae plugin the same way it installs
any Claude-format marketplace plugin:
codex plugin marketplace add platform-engineering-labs/formae-marketplace
codex plugin add formae@formae-marketplace
No clone, no symlink, no config.toml editing, nothing on PATH. The plugin
manifest carries required=true and a 120s startup_timeout_sec, so the first
session waits for the one-time prebuilt-binary download instead of silently
starting without formae tools; later sessions start instantly.
Keep the old clone + symlink + config.toml flow as a documented fallback for
Codex versions that predate plugin marketplace support.
Rewrite the clean-container Codex test to install the plugin the way an end user now does: build a local marketplace naming the plugin "formae" sourced from a clone of this repo, then run the same two commands documented in .codex/INSTALL.md (marketplace add + plugin add). Pin the test channel by injecting FORMAE_MCP_CHANNEL into the cloned plugin's .codex-plugin/mcp.json before installing, mirroring how the other clean-install scripts avoid touching stable. Proves the install end to end: no Go toolchain in the image, codex plugin list shows formae installed, a cold codex exec turn drives a real search_hub_plugins tool call through the spawned MCP server, and the downloaded formae-mcp/formae binaries are executable in ~/.formae-ai/opt. Also exercises marketplace upgrade + remove/add as a non-fatal probe of the update flow, to decide whether INSTALL.md can document it as working.
Codex plugin install now works end to endCodex CLI >=0.148 reads Claude-format marketplaces ( codex plugin marketplace add platform-engineering-labs/formae-marketplace
codex plugin add formae@formae-marketplaceWhat changed and why
Test evidence (clean container, cold)Also exercised the update flow in the same run ( |
What
Phase A part 2 — the "download, don't build" provisioning layer. The plugin now downloads a prebuilt
formae-mcpand a matchedformaevia the pel package manager into a dedicated user tree~/.formae-ai/opt(sudo-free) instead of compiling on the user's machine, publishes theformae-mcpopkg on a version tag, and makes/formae:upgradepull the newer binary on version skew.Stacked on #30 (
mcp-prebuilt-distribution, the Go execution-context/formaebin/skew foundation). Base is that branch so this diff shows only the part-2 work; retarget tomainonce #30 merges. Neither merges tomainuntil Phase A's definition-of-done — including the real install test below — is met, somainstays releasable.Changes
scripts/provision.sh—provision_pkg <pkg> <channel>: installs a pel package into~/.formae-ai/optwith no sudo. Pre-creates~/.formae-ai(works around orbital's one-level privilege walk), never passes a leading--to pelmgr, idempotent fast-path.justfile+Makefile— opkg build/publish targets mirroring theformaerepo (ops opkg build→ops publish --repo pel --channel {dev|stable}; channel routed by tag shape).Opkgfile— package manifest (name = formae-mcp, version from the CIVERSIONenv)..github/workflows/release.yml+package.yml— publish the opkg on a[0-9]*tag, 4-platform matrix, OIDC assume-rolegithub-pel.scripts/start-mcp.sh— rewritten to provision + exec;go buildsurvives only underFORMAE_MCP_DEV=1. Retires compile-on-first-launch.skills/upgrade/SKILL.md—/formae:upgradedoes a channel-aware, non-silent pull (managed tree viaprovision_pkg; classic/opt/pelhanded back to the user).Target layout
Testing
make testgreen; workflows YAML-validated;provision.sh/start-mcp.shsh -n+ dry-run verified (mkdir mitigation, no---rule, idempotent fast-path, dev/normal branches). Reviewed task-by-task plus a whole-branch pass (one Critical caught and fixed: the missingOpkgfile).Remaining (human-gated, before this can be considered done)
End-to-end verification that can't run without touching the prod hub / a dev agent:
-dev.Ntag → confirm theformae-mcpopkg publishes to the peldevchannel (real check ofOpkgfile+ workflow + role).~/.formae-ai/opt/bin,check_healthworks against a dev agent, and skew →/formae:upgradepulls the newer binary.Follow-ups (tracked)
Client identity
Commands issued through the MCP now send the CLI's client ID (
~/.pel/formae/cli_client_id) as theClient-IDheader instead of a fixedformae-mcpvalue, so the agent attributes them to the same client as the user's ownformaeruns. When the file does not exist yet (fresh install via the prebuilt download, formae never executed), the MCP runsformae --versiononce so formae creates it, and falls back to the oldformae-mcpidentity if it still cannot be read. Note: this is a one-time attribution shift; commands submitted before the upgrade remain recorded underformae-mcp.