fix(orca): publish plugins/genie as a tree-only ref instead of a root manifest - #2844
Conversation
… manifest
Orca 1.4.x installs a plugin from a git URL+ref (or a local folder) whose ROOT
holds orca-plugin.json, and its bundled loader rejects any tree containing a
symlink ("unsafe file path or symlink") and caps an install at 2000 files /
50 MB. The genie repository root can never satisfy that: `docs` is a symlink
into the .docs-vendor submodule, and a dev checkout is ~14k files.
#2843 added a repo-root orca-plugin.json to fix the "manifest must be at the
root" rule, but that rule was only one of three — the root tree is still
un-installable. Remove it, and revert every stamping addition it required:
scripts/version.ts, the version.yml JSON_FILES list (back to nine version
files), release-guard.sh's optional child member, and their tests. The
release-guard.test.ts assertion is kept in its stronger exact-path form.
Publish the plugin as a tree-only ref whose root IS plugins/genie instead:
symlink-free, 132 files, 1.3 MB, manifest at its root.
.github/workflows/orca-plugin-ref.yml force-pushes `git commit-tree
HEAD:plugins/genie` — a parentless, history-free commit — to
refs/heads/orca-plugin on push to main and refs/heads/orca-plugin-dev on push
to dev, skipping when the published ref already carries that tree. contents:
write is scoped to that one job, which runs nothing from the checkout.
orca-marketplace.json stays as the only repo-root Orca file and now points at
ref orca-plugin. scripts/orca-manifest-parity.test.ts is retargeted: it checks
the index against the payload manifest's identity and ref, that no root
orca-plugin.json reappears, and that plugins/genie stays symlink-free and
inside Orca's file cap so the published subtree remains installable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gGxGgKskzyzr1HRUB6cV3
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. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ea254804a2
ℹ️ 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".
| on: | ||
| push: | ||
| branches: [main, dev] | ||
| paths: | ||
| - 'plugins/genie/**' | ||
| - '.github/workflows/orca-plugin-ref.yml' | ||
| # Manual repair path: republish the current branch tip's subtree. | ||
| workflow_dispatch: |
There was a problem hiding this comment.
Republish the auto-version child
On every normal dev release, this workflow publishes the developer-pushed commit, but .github/workflows/version.yml subsequently rewrites the plugins/genie version metadata and pushes a version-only child using github.token; that workflow itself notes that GITHUB_TOKEN-authored pushes do not trigger workflows. Consequently, orca-plugin-dev remains on the pre-bump tree rather than mirroring the resulting dev tip, so pre-release installations receive stale version metadata until an unrelated qualifying push or manual repair occurs. Explicitly dispatch this publisher after the atomic version push or otherwise add a trigger for the version child.
Useful? React with 👍 / 👎.
| gh auth setup-git | ||
| # Force is structural, not a race override: every publish is a fresh | ||
| # root commit, so the ref can only ever be replaced, never advanced. | ||
| git push --force origin "${COMMIT}:refs/heads/${TARGET_REF}" |
There was a problem hiding this comment.
Reject publication from a stale source commit
When a historical successful workflow run is rerun, checkout remains pinned to that run's old push commit, and this unconditional force-push replaces the current orca-plugin or orca-plugin-dev ref with the old subtree. The concurrency group prevents simultaneous publishers but never verifies that SOURCE_SHA is still the source branch tip, so new Orca installations can regress after a rerun; check the current remote main/dev head before publishing and skip stale runs.
Useful? React with 👍 / 👎.
Why the repo root can't be an Orca plugin source
Orca 1.4.x installs a plugin from a git URL+ref, or a local folder, whose root holds
orca-plugin.json. Its bundled loader enforces three things:unsafe file path or symlink. This repo hasdocs -> .docs-vendor/genie.plugins/genie/orca-plugin.json, which a git plugin source never looks at.#2843 added a re-rooted
orca-plugin.jsonat the repo root. That fixes rule 3 only; rules 1 and 2 still make the root tree un-installable, so the root manifest bought nothing and cost a tenth version-stamping target.plugins/genieon its own satisfies all three: symlink-free, 132 files, 1.3 MB, manifest at its root.What changed
Removed the root manifest and every stamping hook #2843 added for it
orca-plugin.jsonscripts/version.ts— path + header comment.github/workflows/version.yml—JSON_FILESentry, and "ten version files" back to nine (both the step name and the delta-guard error)scripts/release-guard.sh— the optional version-only child member and its commentrelease-guard.test.ts,release-payload-version.test.ts,version-ci-staging.test.ts,version-format.test.ts,release-docs.test.tsscripts/version.ts,version.yml, andrelease-guard.share now byte-identical to their pre-#2843 state.release-guard.test.tskeeps one #2843 improvement: thenot.toContain('orca-plugin.json')substring assertion stays in its strongersplit('\n')exact-path form.Publish the subtree as a tree-only ref — new
.github/workflows/orca-plugin-ref.yml:maintouchingplugins/genie(or the workflow itself),git commit-tree $(git rev-parse HEAD:plugins/genie)produces a parentless commit whose root isplugins/genie, force-pushed torefs/heads/orca-plugindevtorefs/heads/orca-plugin-devgh apiand exits without pushing when it already equals the branch's subtree hashcontents: writeis scoped to that one job; top-level iscontents: read. The job runs no package script, dependency installer, hook, or any executable from the checkout.actions/checkoutis SHA-pinned withpersist-credentials: false; credentials are bound withgh auth setup-gitright before the push, mirroringversion.yml.Both refs already exist at the correct trees (
origin/main:plugins/genie=5845229…,origin/dev:plugins/genie=d7dca36…), so the workflow's first real run will be a no-op skip.Retargeted
orca-marketplace.json— singleautomagik.genieentry,source: { kind: git, url: https://github.com/automagik-dev/genie.git, ref: orca-plugin }. It is now the only Orca file at the repo root: source-only, versionless, in no tarball.Retargeted
scripts/orca-manifest-parity.test.ts— marketplaceid==<publisher>.<id>of the payload manifest, description matches,url==<repository>.git,ref==orca-plugin; both JSONs parse; the workflow really is what republishes the ref;plugins/geniehas zero symlinks and ≤ 2000 files (enumerated from the git index, i.e. exactly the bytes that get published); the payloadmainresolves inside the subtree; and no rootorca-plugin.json— nor any stamping of one — comes back.Docs — README "Installing the plugin in Orca",
plugins/genie/references/orca-orchestration.md, and the CLAUDE.md gotcha now all state the three loader constraints, the three install routes, and thatgenie setup --orchestration-mode orcaselects authority only and never registers the plugin with Orca.How to install in Orca
https://github.com/automagik-dev/genie.git, refmain(the index) → resolves the plugin at reforca-pluginhttps://github.com/automagik-dev/genie.git, reforca-plugin(stable) ororca-plugin-dev(pre-release)~/.genie/plugins/genieNever
mainordevas a plugin source — those roots are the un-installable trees described above.Validation
bun run typecheck,lint,dead-code,lint:complexity-budget,lint:hook-content,lint:orca-bundle,lint:plugin-skillsall clean (lint's 3 warnings are pre-existing complexity warnings in untouched files).bun test scripts/→ 439 pass / 5 fail. The 5 failures are all inscripts/reconcile-release-assets.test.tsand reproduce identically on a cleanorigin/devworktree — sandbox timeouts, unrelated to this change.Workflow YAML parses; its
runblock passesbash -n; itsactions/checkoutpin extracts correctly throughscripts/check-action-pins.sh --extract.🤖 Generated with Claude Code
https://claude.ai/code/session_013gGxGgKskzyzr1HRUB6cV3