Skip to content

fix(release): lockstep all 9 version surfaces + enforce in CI#35

Merged
FerroxLabs merged 1 commit into
mainfrom
feat/gemini-version-lockstep
Jul 11, 2026
Merged

fix(release): lockstep all 9 version surfaces + enforce in CI#35
FerroxLabs merged 1 commit into
mainfrom
feat/gemini-version-lockstep

Conversation

@FerroxLabs

@FerroxLabs FerroxLabs commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Lockstep all 9 release-versioned surfaces to 1.6.4 and enforce it in CI (wired check-version-lockstep.sh into check-all.sh). Fixes the silent drift: gemini + both marketplaces were at 1.5.6, hermes + wayland plugin.yaml at 1.5.1. Two adversarial review rounds (round 1 REJECT caught the hermes/wayland YAML surfaces a JSON-only gate could never see; round 2 APPROVE). Suite 3614/0 Node 22, preflight 11/11, per-surface negative control green on all 9. Overwatch: Sean confirmed gemini locksteps; I included the 4 other same-class drifted surfaces — narrow if any has independent cadence.

The version-lockstep gate ran ONLY in the manual scripts/e2e-smoke.sh --
never check-all.sh or publish.yml -- and checked only 3 JSON surfaces
(installer / mcp-server / codex plugin.json). So five RELEASE-facing
manifests silently drifted while the code shipped 1.6.4:
  - gemini/extensions/ijfw/gemini-extension.json  1.5.6 (Sean-confirmed lockstep)
  - claude/.claude-plugin/marketplace.json         1.5.6 (marketplace listing)
  - codex/.agents/plugins/marketplace.json         1.5.6 (marketplace listing;
    its plugin_manifest already pointed at plugin.json@1.6.4 -- internally
    inconsistent, proving a missed bump not an independent cadence)
  - hermes/plugins/ijfw/plugin.yaml                1.5.1 (SHIPS verbatim to
    ~/.hermes/plugins/ijfw via the installer -- a 1.6.4 user got a 1.5.1 manifest)
  - wayland/plugins/ijfw/plugin.yaml               1.5.1 (in-repo source manifest;
    Wayland's SHIPPED toml is rendered from installer/package.json, so this one
    is source-only, but kept in lockstep for coherence)

Fix:
- bump all five to 1.6.4;
- rewrite check-version-lockstep.sh from 3 JSON surfaces to all 9 release
  surfaces (7 JSON incl. claude plugin.json + both marketplaces + gemini, plus
  2 YAML via a zero-dep version-line reader). Root package.json stays EXCLUDED
  -- private ijfw-workspace stub at 1.0.0, not a release surface. Manifest path
  passed via argv (not string-interpolated) so a checkout path with a quote
  can't break require();
- WIRE check-version-lockstep.sh into check-all.sh (fail-fast, before the
  ~5min suite) so CI (ci.yml + publish.yml) enforces lockstep every run;
- update e2e-smoke.sh's stale "installer/mcp-server/codex" message.

Verified: script passes (all 9 at 1.6.4), shellcheck clean, per-surface
negative control catches drift on EACH of the 9 independently; full
check-all.sh green (suite 3614/0) + preflight 11/11.

Adversarial review round 1 REJECTED the initial 7-surface version: it found
hermes+wayland plugin.yaml at 1.5.1 that a JSON-only gate could never catch
(Hermes ships its manifest verbatim). This round adds YAML coverage + the
two bumps. Scope note for review: Overwatch confirmed the GEMINI surface
locksteps; I included the other four drifted surfaces (same class) so the
gate is not hollow. Narrow if any has an independent cadence.
@FerroxLabs FerroxLabs enabled auto-merge (squash) July 11, 2026 02:01
@FerroxLabs FerroxLabs merged commit 4d988e8 into main Jul 11, 2026
7 checks passed
FerroxLabs added a commit that referenced this pull request Jul 11, 2026
…ix (#36)

Supply-chain hardening for the publish pipeline (v1.6.4 cross-audit
dimension d + Overwatch card). Token blast-radius is already closed (Sean
made NPM_TOKEN granular, 2-package scope); this PR is the WHO-can-trigger +
what-can-ship half. WORKFLOW-only + a runbook note -- no live admin edits.

publish.yml:
- gate the publish job on the protected `release` environment (required
  reviewer): a v* tag, regardless of who pushes it, now pauses for human
  approval before any npm publish runs. Overwatch/Sean configure the env
  protection + the tag-creation ruleset (only the release actor may create
  v*) outside the workflow.
- assert the pushed tag matches installer/package.json AND mcp-server/
  package.json version before publishing. Without it, `git tag v9.9.9` on a
  1.6.5 commit would publish 1.6.5 under a v9.9.9 Release. check-all's
  9-surface version-lockstep gate (rebased in from #35) proves all in-repo
  surfaces agree, so tag == installer+mcp + lockstep == tag == every
  published + manifest version.
- fix the dist-tag rule: the old check matched ONLY `-rc.`, so a
  `-beta`/`-alpha` tag silently shipped to `latest`. Now a strict anchored
  regex validates the tag shape FIRST (adversarial review: the old `case`
  globs would have let `v1.2.3.4`/`v1.2.3extra` fall through to `latest`),
  then stable -> latest, ANY prerelease -> next, malformed -> refused.
- injection-safe: tag values flow via env (TAG_REF), never inlined into
  run: scripts (verified an injected `; rm -rf` tag is neutralized).

docs/CI-PUBLISH.md: 'current pipeline' callout overriding the stale legacy
'no NPM_TOKEN / nothing to rotate' line -- documents the granular token +
its ~2026-10-08 (90-day) ROTATION deadline, the release-env gate, the
tag<->version assert, and the dist-tag rule. Plus a settings-audit block
(gh api one-liners) so an operator can VERIFY the release-env required-
reviewer + tag-creation ruleset are actually applied -- the workflow can't
enforce them and an unconfigured environment auto-creates UNPROTECTED.

Verified: publish.yml valid YAML, environment key present on publish job,
banned-char clean; dist-tag + assert logic unit-tested across stable/rc/
beta/alpha/malformed/injection tags + matching/mismatching versions.

Out of scope (per Overwatch): token/OIDC migration (granular suffices),
account classic-token cleanup (Sean owns), the tag-creation ruleset +
release-env protection SETTINGS (admin, not workflow). Overwatch reviews
this as release-infra.

Co-authored-by: ci <sean@seandonahoe.com>
@FerroxLabs FerroxLabs mentioned this pull request Jul 11, 2026
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.

2 participants