18 KiB
Release the exact tested CLI commit
This runbook separates a reviewed fix, a locally packed candidate, a published npm
package and approved production v4 content. Record actual outcomes in the canonical
change's release-handoff.md; a green local suite or an npm version string alone
proves neither production availability nor downloaded-package acceptance.
Human merges remain mandatory. Session A coordinates both repositories' candidate variables and evidence pointers until activation, then the trusted Toolkit coordinator is the sole runtime writer. Production course publication and real email login have separate explicit approval gates. Existing-project migration 3→4 is parked for September 14–15 reconsideration (D15-C); it does not block new 4.0 projects. Keep existing v3 projects bound to v3.
Version preparation and initial merge order
prepare-version.yml calculates the version automatically in the ordinary code
PR, using the last verified stable npm/GitHub tag on master as its baseline.
The operator does not select or separately approve the number. Version-only bot
commits and docs-only churn do not create another bump. Head/base or verified
published-baseline advancement invalidates preparation and triggers reconciliation.
The trusted writer reads PR objects as data, never executes candidate code with
its write token, writes only package.json and refuses forks/stale heads/force-push.
Before this workflow exists on master, Session A uses the same calculation in the initial repair branch. The bootstrap CI artifact records its inputs; after merge the newly trusted master helper verifies that calculation against the original PR Git objects and merged relationship. Numbering provenance does not replace fresh evidence for the merged SHA. The release workflow never creates a version commit on master or calculates a new number from a squash message.
- Finish all implementation/review/version changes. Freeze CLI PR head
Cprand Toolkit PR headTpr. Session A inspects candidate values/timestamps and all nonterminal runs, including queued, waiting, requested and pending. Do not overwrite unexplained newer candidates or disable workflows. - Set Toolkit
CLI_CANDIDATE_SHAto exactCprand obtain complete Toolkit PR Linux/Windows evidence for(Cpr,Tpr). Set CLITOOLKIT_CANDIDATE_SHAandTOOLKIT_COORDINATED_RUN_IDto that exact proof; run CLI ordinary OS and strict receipt checks. Its producer must still be a unique live same-repository Toolkit PR targeting master atTpr. Any new commit, including version, lint or review commits, invalidates proof and requires a fresh complete attempt. - Operator merges CLI first, creating
Cm. The old receipt provesCpr, notCm; publishing waits while post-merge prerequisites are missing. - Reinspect pointers/runs; retest the still-open Toolkit PR against actual CLI
master
Cm. Operator then merges Toolkit, creatingTm. Its successful canonical push/master CI retains a stage for that exact SHA. - Verify scoped runtime credentials and isolated Git-ref contention before
activation. Session A inspects the current flag and lease, activates the
coordinator and requests one reconciliation. No production content changes
are implied. See Toolkit
docs/how-to/release-10xdevs4-cli.mdfor scope table, source-stage selection and promotion.
For future CLI-only PRs, the accepted pre-merge contract still requires a real live Toolkit companion PR. Do not fake a no-op PR, resurrect a merged PR or substitute release dispatch as PR evidence; a different contract needs its own decision.
Exact evidence and runtime ownership
Toolkit release-coordinator.yml wakes after successful Toolkit push/master CI
or after the CLI's ordinary master Linux/Windows checks. It snapshots current
master SHAs, selects a complete source stage and holds an append-only private
Git lease at refs/heads/automation/cli-release-lease throughout evidence and
release. Lease updates use observed-parent commits with non-force fast-forward
updates; no TTL or blind reset can take ownership away from an unresolved child.
The fresh Toolkit ci.yml dispatch runs on master with explicit source/run/
attempt/artifact/release/hash and lease identities. It reuses retained bytes,
reruns Linux/Windows and exports only a bounded sanitized public receipt; no
translation, deployment, npm publish or content promotion occurs in that dispatch.
The original successful push/master producer alone can authorize promotion.
A complete rerun needs every selected-attempt job and artifact; normal retries
use a fresh evidence dispatch. Old artifacts remain retained and cannot be relabeled.
Coordinator registration writes all four CLI pointers:
TOOLKIT_CANDIDATE_SHA, TOOLKIT_COORDINATED_RUN_ID,
TOOLKIT_COORDINATED_RUN_ATTEMPT, TOOLKIT_COORDINATED_ARTIFACT_ID.
Release dispatch carries immutable equivalents plus operation and generation.
Runtime does not rewrite Toolkit CLI_CANDIDATE_SHA.
CLI_RELEASE_AUTOMATION_ENABLED is an admission flag, default inactive.
Missing/not exactly true blocks a new generation under that invocation's
configuration. Acquired generations can finish after disabling. There is no
live kill switch or new Variables-read token. Inspect queued invocations with
older configuration; cancel only explicitly reviewed unstarted coordination.
Never cancel or conceal an in-flight npm publish automatically.
For timeout/cancellation/lost dispatch response, retain owner, generation, source selection, operation token and child run/attempt. Inspect the owner and all children plus external writers. Request Toolkit coordinator reconciliation only after that inspection; it safely adopts the same operation when its owner is terminal. Ambiguous delivery never authorizes another dispatch. A changed master pair makes old evidence obsolete; it cannot be relabeled for the new pair.
Credentials: CLI TOOLKIT_READ_TOKEN has Toolkit Actions read + Pull requests
read for bounded receipts/live PR checks. The private PR permission includes all
PR metadata/diffs, but the verifier emits none. Trusted master jobs alone receive
TOOLKIT_DISPATCH_TOKEN (Toolkit Actions write/read + Contents read) for dispatch,
master and bounded lease reads; never candidate PR jobs. RELEASE_TOKEN has CLI
Contents write + Pull requests read for the same-PR version writer. Toolkit
CLI_RELEASE_CONTROL_TOKEN has CLI Actions write/read + Variables write + Contents
read. Verify actual capabilities; secret names or an operator-token probe do not
prove runtime scopes. No tokens/passwords in chat or public logs.
Publication and evidence to retain
The exact dispatch checkout must equal the selected current CLI master and remain clean. Its committed version must match the verified preparation record, and both ordinary OS checks plus exact private proof precede release preflight. All five standalone binaries build before npm publication from that same SHA.
Pinned npm 11.12.1 packs the frozen directory into an external directory.
The isolated prepack smoke runs before publication. Credential config, tarballs
and binaries stay outside the npm member set; lifecycle scripts are disabled.
npm publish . --ignore-scripts --access public repacks the directory. Therefore
byte identity is checked after publication, by independently downloading npm
and comparing version, registry gitHead, exact source tag and SHA-512 against
the prepack. Tarball package.json need not embed gitHead. A mismatch is an
incomplete immutable publication, never success or permission to overwrite it.
Retain the CLI release run/attempt, exact source/evidence identities and:
release-preflight-<runId>-<attempt>: merged PR/version preparation provenance.release-package-<runId>-<attempt>: candidate.json, prepack tarball and bounded release-manifest.json (source/version/tag/npm version, evidence, binary SHA-256 and original artifact IDs).- Five
binary-<name>-<runId>-<attempt>artifacts, for10x-linux-x64,10x-linux-arm64,10x-darwin-arm64,10x-darwin-x64,10x-windows-x64.exe. published-result-<runId>-<attempt>after successful registry verification.
Select immutable IDs and selected-attempt jobs; never wildcard-merge artifacts from different attempts. Public artifacts contain no Toolkit content, credentials or full private test logs. Record the actual registry integrity separately from expected prepack integrity even when equal.
Manual completion after partial npm success
An existing version is never published again. Do not rerun release jobs hoping
to rebuild missing GitHub assets. Keep the lease in manual-completion while
Session A and the operator account for the original operation.
-
Inspect the original run/attempt, lease owner/generation and every child; require them terminal and no unexplained active writer. Read npm's exact version metadata and tarball; verify the tag points to the recorded CLI SHA.
-
Select the original
release-package-<runId>-<attempt>by immutable ID after checking canonical repository/workflow/source and selected-attempt jobs. The overall run may have failed after npm; all ordinary/evidence/version/ binary jobs and the pre-mutation artifact upload must be accounted for. Reject changed attempt, missing/expired/duplicate artifact or unknown output. Validate manifest schema/bounds and source/run/attempt/version/evidence against the retained preflight and private proof. Verify the original prepack SHA-512. -
Independently validate actual npm against that candidate with the trusted
validateRegistryResultfromscripts/release-identity.mjs; it requires registry gitHead, package version, tag SHA and exact downloaded SHA-512 equality. If npm is absent after an ambiguous request, investigate the original publish before choosing any action. If it conflicts, stop: a new ordinary repair PR and new automatic version are required. Never unpublish or overwrite. -
Download each original binary by its manifest artifact ID into separate empty directories. Verify its exact attempt-specific name/source run, successful
Binary (<name>)job, sole regular filename and SHA-256. Download existing GitHub assets too and compare; a different existing asset is a conflict, not permission to replace it. Reject duplicates, extras or symlinks. -
After this concrete verification, create a missing GitHub release using the existing verified tag, or upload only individually named missing assets. Use the five names above with no wildcard and no
--clobber. For example, where all variables identify the verified original operation:gh release create "v${RELEASE_VERSION}" --repo przeprogramowani/10x-cli \ --verify-tag --target "$CLI_SHA" --generate-notes gh release upload "v${RELEASE_VERSION}" "$VERIFIED_BINARY_FILE" \ --repo przeprogramowani/10x-cliThe first command applies only if the release is absent. Verify every actual GitHub asset after upload; the second is repeated only for verified missing names, never a rebuilt file. No npm publish command belongs in this procedure.
-
Record actual npm/GitHub verification and partial-completion actions in the handoff. The failed original Actions run remains failed; do not relabel it as green. The coordinator deliberately does not automatically clear
manual-completion. Session A may close that exact verified operation with a reviewed conditional lease update using ToolkitreadLease/advanceLease: require the freshly observed ref SHA/generation andmanual-completion, all writers terminal, preserve source/children, and appendphase: completewith updatedAt. Never force/delete/reset the lease. If any precondition changed, stop and reconcile. Missing original artifacts leave this gate blocked.
Verify the actual published npm package against production
Use a new directory and isolated configuration/cache; do not substitute dist,
a local npm pack, a GitHub source build or global CLI. Set RELEASE_VERSION
and CLI_SHA from the verified release manifest. Example POSIX setup:
RELEASE_TEST_ROOT=$(mktemp -d /tmp/10x-cli-published.XXXXXX)
export XDG_CONFIG_HOME="$RELEASE_TEST_ROOT/config"
export npm_config_cache="$RELEASE_TEST_ROOT/npm-cache"
mkdir -p "$RELEASE_TEST_ROOT/install" "$RELEASE_TEST_ROOT/archives"
npm view "@przeprogramowani/10x-cli@${RELEASE_VERSION}" version gitHead dist --json \
> "$RELEASE_TEST_ROOT/registry.json"
npm pack "@przeprogramowani/10x-cli@${RELEASE_VERSION}" --ignore-scripts --json \
--pack-destination "$RELEASE_TEST_ROOT/archives" > "$RELEASE_TEST_ROOT/pack.json"
Compare registry version/gitHead and SHA-512 of the actual downloaded .tgz to
the manifest and source tag before installing. Set DOWNLOADED_TARBALL to that
single verified filename, then:
npm install --prefix "$RELEASE_TEST_ROOT/install" --ignore-scripts --no-audit --no-fund "$DOWNLOADED_TARBALL"
RELEASED_CLI="$RELEASE_TEST_ROOT/install/node_modules/@przeprogramowani/10x-cli/dist/index.mjs"
node "$RELEASED_CLI" --version
node "$RELEASED_CLI" --help
node "$RELEASED_CLI" auth --status --json
Anonymous status must return the documented auth-required result. Use the same isolation on Windows with the downloaded package and Node executable. Record which OS was actually exercised; private CI is separate from a manual OS result.
Coordinate with the operator before sending the real login email. After
approval, run node "$RELEASED_CLI" auth --email marcin@przeprogramowani.pl.
The operator approves the browser link while CLI polling completes. Never request
pasted tokens/passwords. Keep auth files private and remove the session with
node "$RELEASED_CLI" auth --logout afterward. Verify actual refresh without modifying production time
or entitlements; isolated local expiry metadata can exercise real token rotation
as in the prior manual test, without logging credentials.
Run the following in separate fresh project directories, capture a complete
before/after project file inventory (including hidden files), and retain private
results. Confirm the installed package's own --help first:
node "$RELEASED_CLI" auth --status --json
node "$RELEASED_CLI" list --json
node "$RELEASED_CLI" list 1 --course 10xdevs-3 --json
node "$RELEASED_CLI" get m1l1 --course 10xdevs-3 --tool codex --lang en --dry-run --json
node "$RELEASED_CLI" get m1l1 --course 10xdevs-3 --tool codex --lang en --type skills --print --json
node "$RELEASED_CLI" get m1l1 --course 10xdevs-3 --tool codex --lang en --json
node "$RELEASED_CLI" get m1l2 --course 10xdevs-3 --tool codex --lang en --json
node "$RELEASED_CLI" sync --tool codex --lang en --dry-run --json
node "$RELEASED_CLI" sync --tool codex --lang en --json
Check default selection against discovery: the highest available and authorized
edition wins in a fresh unbound project. Existing projects created by npm 1.20.0
and newly v3-bound projects must remain v3 on default get/sync after upgrade.
Require successful preview exit/results before comparing inventories. Dry-run and print leave the entire project unchanged, including binding/ownership
metadata. A locked, unavailable or otherwise failed preflight must create no
binding or project files. Do not use --force to manufacture sync success.
Check complete skill folder keysets and every support file, EN content, separate
PL project with --lang pl and no fallback, missing-file repair, local edit
preservation on ordinary sync, rules/ownership metadata and actual refresh.
For v3 m1l2, both selector and stack-assess include SKILL.md and their six support
documents; compare against the production response, not just a file count.
Auth/session data and paid contents stay out of public evidence.
While v4 is unpublished, discovery available:false and course_unavailable
are correct but do not close v4 acceptance. After the operator's separately
approved promotion, repeat discovery, default fresh selection and the relevant
get/sync/EN/PL/full-skill/preview/preflight checks with --course 10xdevs-4.
Record catalog, signed lesson, installed manifest and production pointer release
ID/hash agreement. Use a genuinely accessible lesson; test locked refusal before
module 1 unlock 2026-09-14T06:00:00Z (08:00 Europe/Warsaw) and actual unlock
afterward with server clock/KV authoritative. Never change production clocks,
overrides, membership or entitlements to make this pass.
Final handoff names package version, expected/actual integrity, gitHead/tag/source pair, all source/evidence/release runs and attempts/artifact IDs, Worker/content identity, actual tests and remaining human/time gates. State whether Session C stage 1 is satisfied; parked migration is not a release dependency. Do not claim v4 readiness while publication or downloaded-package verification is incomplete.
Audit the existing Toolkit internal-package publisher
Before freezing a release pair, compare Toolkit's current internal package
version/tag and the package-affecting paths used by its existing auto-version
script (packages/internal-pkg, packages/ai-artifacts, excluding READMEs).
The release-repair audit found version2.44.1, tagv2.44.1 at
f4be3c5ed59f291f5d42c0b991dd43a8b4321fa5, and zero such changed paths through
the repair branch from master39925ab. No internal version commit is expected for
this pair. Repeat the audit if the branch/base changes.
That existing publisher can still add a master version commit on future payload changes. A new Toolkit master SHA requires its own successful canonical source stage; the coordinator must wait rather than accept the earlier commit's equal tree or transplanted provenance. This repair does not redesign that publisher.