Skip to content

feat(release): add mandatory canary publish gate#812

Merged
rickylabs merged 11 commits into
mainfrom
feat/811-release-canary
Jul 17, 2026
Merged

feat(release): add mandatory canary publish gate#812
rickylabs merged 11 commits into
mainfrom
feat/811-release-canary

Conversation

@rickylabs

@rickylabs rickylabs commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the mandatory canary publish channel and composed publish-readiness gate for NetScript releases. The canary reuses the production OIDC publisher, dispatches and awaits the exact canary-pinned production E2E run, and records a SHA-bound green-pair status that stable publication must verify.

This remains a draft. Do not merge: the supervisor-triggered IMPL-EVAL returned FAIL_FIX; findings F1/F2 are repaired at 64184deb, and a fresh supervisor verdict is pending.

Scope

Slices

  • S1 harness bootstrap and locked design — 1c84e197
  • S2 shared release preparation and canary cut — 4f60ab36
  • S3 composed publish-readiness verdict — 5a41004f
  • S4 canary workflow and green-pair enforcement — ed4573aa
  • S5 mandatory canary-first doctrine and mirror — cce21549
  • S6 initial evidence handoff — ddd4242e
  • S7 supervisor FAIL_FIX repair: merge current main, real detector test, live red proofs — 64184deb

Definition of Done

  • release:canary derives <target>-canary.N from existing JSR versions, uses the shared stable-cut gates, creates no release PR, and retains only its provenance tag after workflow cleanup.
  • release-canary.yml runs readiness, provisioning, the existing real-publish path, and the exact canary-pinned e2e-cli-prod run without marking a release Latest.
  • The green pair is recorded for the content SHA and release:publish fails closed without a matching successful pair.
  • Publish readiness reports structured evidence for new-package, publish-set, lockstep/residue/versionless-specifier, provisioning, and canonical import-attribute preflight checks.
  • Every new readiness check is proven to fail on a seeded violation; the complete release test suite is green.
  • fix(mcp): registry-safe README embedding — JSR rejects text-import attributes #810 integration is documented in both PR bodies and its preflight implementation is reused rather than duplicated.
  • The canonical release skill and generated mirror mandate canary-first publishing, generated-assets preflight, exact-version/min-age handling, same-semver retry, yanking policy, and no ad-hoc publication.
  • Required type/check/lint/fmt, skill-sync, no-suppression, and changed-file quality gates pass.
  • Current origin/main is merged and the three conflicts are resolved.
  • Live seeded text-import, versionless-specifier, and README-standard violations each fail publish:readiness with the required evidence.
  • Fresh supervisor-triggered IMPL-EVAL returns PASS on the repaired head.

Validation

  • PLAN-EVAL — PASS in separate session.
  • Supervisor IMPL-EVAL — FAIL_FIX on pre-merge head ddd4242e: F1 missing real fix(mcp): registry-safe README embedding — JSR rejects text-import attributes #810 detector; F2 conflicts with current main.
  • Repair head — 64184deb, a merge commit with parents ddd4242e and current main aa14e452.
  • Real detector unit — PASS: readiness test spawns the actual preflight-text-imports.ts CLI against a seeded text-import fixture; the mocked detector throw is removed.
  • Live text-import seed — required FAIL, exit 1: import-attribute-preflight reports generated-constant remediation, deno publish rejects ("import attribute type of text is unsupported") even though it is runtime-stable and --dry-run accepts it denoland/deno#35546, and authenticated-canary sunset.
  • Live versionless seed — required FAIL, exit 1: versionless-specifiers reports the required version.
  • Live first-publish README seed — required FAIL, exit 1: first-publish reports missing production H1/install/quick/docs requirements.
  • Seed-free deno task publish:readiness — PASS, exit 0, all eight composed rows green.
  • Full release-tools suite — PASS, 61/61.
  • Release TypeScript check/lint/fmt — PASS on 32 files; check includes --unstable-kv.
  • Repair-file quality scan — PASS, 0 findings / 0 allowances.
  • Skill mirror sync — PASS, 17 skills / 21 mirrored files.

Harness

  • Run dir: .llm/runs/feat-811-release-canary--canary-readiness/
  • Repair evidence: .llm/runs/feat-811-release-canary--canary-readiness/repair-evidence.md
  • Phase: FAIL_FIX repair complete; fresh supervisor IMPL-EVAL pending.
  • The earlier generator-arranged Qwen PASS artifact is retained as history but is non-authorizing for this supervisor repair cycle. No self-evaluation is claimed.

Integration with #810

Merged PR #810 owns the import-attribute scanner and its conditional sunset. Current main is now merged into this branch, so publish:readiness delegates to the real canonical detector. The real-fixture test and live seed prove that boundary. Lift the ban only after denoland/deno#35546 is fixed, merged, and released in the pinned Deno version and an authenticated canary text-import probe is green.

OWNER actions after merge

  • Confirm repository workflow permissions allow actions: write, statuses: write, and contents: write for the canary workflow.
  • Confirm JSR_API_TOKEN has package-edit permission for first-publish provisioning and that every new @netscript/* package is linked to rickylabs/netscript; OIDC remains the publish credential.
  • Run the first live canary pair and yank obsolete/failed canary versions when appropriate; JSR versions are immutable and are never deleted.

Drift / Debt

@rickylabs rickylabs added this to the 0.0.1-beta.11 milestone Jul 17, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Owner Author

[PHASE: RESEARCH]

Re-baselined issue #811, PR #810, and the complete release toolbelt against origin/main@a5adb706.

Findings

  1. Stable cut and canary cut can share the existing coordinated bump/residue/gate machinery.
  2. Canary numbering must scan JSR metadata across the full publish set to survive partial publishes.
  3. The green pair can be represented as a SHA-bound commit status only after the exact dispatched e2e-cli-prod run is green.
  4. fix(mcp): registry-safe README embedding — JSR rejects text-import attributes #810 remains the sole owner of import-attribute detection; this PR calls release:preflight.
  5. Baseline release suite: 29 passed / 0 failed.

Next

  • Separate OpenRouter/Qwen PLAN-EVAL; no implementation before PASS.

Artifact: .llm/runs/feat-811-release-canary--canary-readiness/research.md

Copy link
Copy Markdown
Owner Author

[PHASE: PLAN]

Locked a six-slice contract-first design for shared cut preparation, composed readiness, the canary workflow, SHA-bound green-pair enforcement, and mandatory release doctrine.

Commit

  • 1c84e197 — harness bootstrap, research, design checkpoint, evaluator brief, and resumable context.

Gate

  • Existing release tests: 29/29 PASS.
  • Implementation remains blocked until separate-session PLAN-EVAL returns PASS.

Artifact: .llm/runs/feat-811-release-canary--canary-readiness/plan.md

Copy link
Copy Markdown
Owner Author

PLAN-EVAL — PASS

Separate evaluator: Claude Code + OpenRouter/Qwen 3.7 Max (high), direct-only session 55159172-5792-49dc-a7aa-be92f8dc80a6.

All 8 Plan-Gate items passed. The evaluator spot-checked the current release toolbelt and PR #810 boundary, confirmed the six implementation slices and negative-proof gates, and found no open decision that forces rework. Implementation is unblocked at commit 6353ec49.

Evidence: .llm/runs/feat-811-release-canary--canary-readiness/plan-eval.md.

@rickylabs rickylabs added status:impl and removed status:plan-eval Awaiting plan evaluation labels Jul 17, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Owner Author

Implementation — slice 2/6: shared preparation + canary cut

Commit: 4f60ab36

  • Factored the existing stable-cut bump → residue → release-set/preflight → release:preflightpublish:dry-rundeno ci --prod sequence into prepare-release.ts; release:cut now consumes it.
  • Added release:canary and canary.ts: strict stable target input, <target>-canary.N, N=max across every effective member’s JSR metadata (including yanked keys) plus tag collision guard, ephemeral release/canary-* branch, immutable tag, and no PR path.
  • JSR absence is 404-only; other HTTP or malformed metadata fails closed.

Evidence:

  • targeted deno check --unstable-kv: PASS
  • focused stable/canary/preparation tests: 15 passed, 0 failed
  • separate opposite-family review: SLICE_REVIEW_PASS (Claude Opus 4.8 medium fallback; Fable 5 route returned model_not_found, logged in drift)

Next: composed publish-readiness evidence and seeded negative checks.

Copy link
Copy Markdown
Owner Author

Implementation — slice 3: composed publish readiness

Commit: 5a41004f

  • Added publish:readiness with ordered structured evidence for publish-set completeness, Markdown pins, lockstep/residue, versionless specifiers, new packages, first-publish standards, provisioning dry-check, and the canonical release preflight.
  • Reused the fix(mcp): registry-safe README embedding — JSR rejects text-import attributes #810 task boundary and preserved its denoland/deno#35546 plus authenticated-canary sunset criterion; no scanner logic was duplicated.
  • First-publish checks apply only to JSR-absent effective publish members. Registry failures fail closed and dependent checks skip instead of consuming partial evidence.
  • The shared stable/canary preparation path now requires readiness before dry-run and production install.

Evidence:

  • full .llm/tools/release/ suite: 51 passed, 0 failed
  • touched slice TypeScript: deno check --unstable-kv PASS
  • live repository deno task publish:readiness: PASS, all 8 checks
  • every readiness row has a seeded negative proof
  • independent opposite-family review: initial FAIL on an orphaned Markdown audit; repaired and re-reviewed SLICE_REVIEW_PASS

This slice is pushed with the explicit refspec to feat/811-release-canary.

Copy link
Copy Markdown
Owner Author

Implementation — slice 4: canary workflow + green-pair enforcement

Commit: ed4573aa

  • Added release-canary.yml: composed readiness → provisioning → the canonical dry-run/preflight/real-publish path, then exact workflow-dispatch correlation and awaited canary-pinned e2e-cli-prod.
  • Records release/canary-pair on the pre-bump content SHA only after both live stages pass; cleanup is best-effort and reported.
  • Stable publishing and github-release.ts now fail closed unless the same content (or its exact coordinated version-only child) has a green pair.
  • Added durable ~/.config/gh/hosts.yml token fallback through resolveGithubToken; Actions installation tokens use the repository-scoped status request as their validation boundary.
  • Independent opposite-family re-review: SLICE_REVIEW_PASS (session f0845c4d-4498-45e5-ba0f-74ab8f92ca19).

Evidence: full release suite 59/59, focused slice suite 81/81, touched TypeScript check/format clean, and all three touched workflows parse under @std/yaml.

Copy link
Copy Markdown
Owner Author

Implementation — slice 5: mandatory canary-first doctrine

Commit: cce21549

rickylabs commented Jul 17, 2026

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL] [VERDICT: PASS]

Separate direct OpenRouter/Qwen IMPL-EVAL completed against implementation/handoff head fbabeb6b; final head ddd4242e adds only the evaluator artifact and closing harness records.

The PR remains draft and is now labeled status:impl-eval. It has not been merged.

OWNER actions remain as documented in the PR body: confirm workflow permissions and JSR grants/linkage, then run the first live canary publish + canary-pinned production E2E pair and yank failed/obsolete immutable canaries as needed.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL REPAIR] [STATUS: F1/F2 FIXED — RE-EVAL PENDING]

Supervisor FAIL_FIX findings repaired at merge commit 64184deb:

Live merged-head proofs:

Repair gates:

  • release tools: 61/61 PASS;
  • release check/lint/fmt: 32 files, 0 findings (--unstable-kv on check);
  • skill sync: 17 skills / 21 mirrors PASS;
  • repair-file quality: 0 findings / 0 allowances;
  • local/remote head: 64184deb20fd2ecd6572897505078dfaa08a7351.

Evidence: .llm/runs/feat-811-release-canary--canary-readiness/repair-evidence.md.

PR remains draft at status:impl-eval. This is implementation evidence only, not a self-evaluation; a fresh supervisor-triggered IMPL-EVAL is still required. No merge performed.

rickylabs added a commit that referenced this pull request Jul 17, 2026
…VAL FAIL_FIX

Proves: preflight-vs-publish outcomes are no longer conflated (33
published / mcp failed / cli skipped, separate from the unauthenticated
10-failed/25-skipped graph preflight); byte-identity of already-published
members is now a MANDATORY precondition for any tag move, with beta.10
recast honestly as a non-byte-identical move (6 plugins changed) that
JSR's skip-existing/fill-unpublished behavior papered over, not a safe
precedent; first-publish live-validation wording now matches #808/#809
(in-tree maintainer CLI against a real scaffolded app) with an explicit
note that #812's canary channel changes this to canary-published surface
+ pinned prod E2E verdict.

Cures findings 1-3 of .llm/runs/beta10-cli--orchestrator/slices/819-relskill-eval/evaluate.md.
Finding 4 (non-blocking, #812 merge-conflict guidance) is untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017LHrkXyMzsQwb9bqr82EFK
@rickylabs
rickylabs marked this pull request as ready for review July 17, 2026 08:51
@rickylabs
rickylabs merged commit 47cc2fa into main Jul 17, 2026
17 of 18 checks passed
rickylabs added a commit that referenced this pull request Jul 17, 2026
…very doctrine

Proves both streams coexist in netscript-release: #812's canary-first
mandatory flow (canary pair precondition, publish:readiness, exact-version
resolution bullets) AND the FAIL_FIX-corrected recovery doctrine
(preflight/publish outcome separation, MANDATORY byte-identity tag-move
precondition with beta.10 recast as non-compliant, min-dependency-age
forensics, first-publish checklist). First-publish canary wording is now
present-tense since #812 is merged. .claude mirror regenerated via
agentic:sync-claude, not hand-resolved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017LHrkXyMzsQwb9bqr82EFK
rickylabs added a commit that referenced this pull request Jul 17, 2026
…, first-publish checklist (#819)

* docs(release): codify same-semver republish recovery + min-dependency-age handling + first-publish checklist

Owner directive after the v0.0.1-beta.10 cut (2026-07-17): two release patterns were proven live
and need to be reachable before an agent defaults to an unwanted stable-channel semver bump.

- Same-semver republish (partial-publish recovery): JSR version immutability binds only published
  members; a failed/skipped member can still publish at the same semver via fix-forward + tag
  fast-forward + publish.yml re-dispatch. Cites the beta.10 precedent (33/70 members published,
  mcp/cli recovered without a version bump — runs 29558968037 -> 29562537123).
- Minimum-dependency-age at release time: Deno 2.9's ~24h default rejects same-day publishes; the
  harness pins --minimum-dependency-age=0 and keeps fresh-plugin resolution in one Deno process
  (child deno x re-exec drops the flag) — #813 + #817. User-facing 24h window tracked in #818.
- First-publish checklist: manual README/tagline/license/exports/docs-site/live-validation checks
  until #811/#812's publish-readiness automation lands.

Regenerated the .claude mirror via agentic:sync-claude; docs:links, sync-claude:check, and fmt all
green on touched files.

* fix(docs): correct beta.10 same-semver recovery accounting per IMPL-EVAL FAIL_FIX

Proves: preflight-vs-publish outcomes are no longer conflated (33
published / mcp failed / cli skipped, separate from the unauthenticated
10-failed/25-skipped graph preflight); byte-identity of already-published
members is now a MANDATORY precondition for any tag move, with beta.10
recast honestly as a non-byte-identical move (6 plugins changed) that
JSR's skip-existing/fill-unpublished behavior papered over, not a safe
precedent; first-publish live-validation wording now matches #808/#809
(in-tree maintainer CLI against a real scaffolded app) with an explicit
note that #812's canary channel changes this to canary-published surface
+ pinned prod E2E verdict.

Cures findings 1-3 of .llm/runs/beta10-cli--orchestrator/slices/819-relskill-eval/evaluate.md.
Finding 4 (non-blocking, #812 merge-conflict guidance) is untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017LHrkXyMzsQwb9bqr82EFK

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

release: canary publish channel — mandatory authenticated pre-publish gate with post-canary live production CI, + publish-readiness automation

1 participant