Skip to content

Local release operations

Consumer access is managed separately from source hosting.

Projects that do not use hosted CI can turn off managed workflow generation while retaining local hooks, WU gates and lifecycle receipts:

pnpm config:set --key software_delivery.agents.lifecycle_enforcement.ci.enabled --value false
pnpm lumenflow:enable
pnpm lumenflow:doctor

When omitted, ci.enabled preserves existing CI generation. Setting it to false removes only the LumenFlow-owned workflow block and regenerates the integrity manifest for local hooks. Content you wrote around the block survives. Repeated init, enable and upgrade operations respect the setting. Other project-owned workflows remain under your control.

Use the repository’s pinned Node and pnpm versions. Complete each work unit through wu:prep and its printed wu:done command. The scoped tests and other required gates still apply.

The release publishes an already-certified tree. Every wu:done starts the post-land sweep, which runs the release source-check plan once at each landed commit, in a detached checkout pinned at that commit, and records a certification: the commit, its status, a digest of the check plan, and each check’s result and log digest. A red check turns the sweep red and names the check. The plan includes strict progress, the documentation and packaging checks, the real-process harnesses, the conformance suites and the full release gate plan, run without replaying any cached lint or typecheck result. Run it by hand with pnpm main:sweep --post-land on the main checkout, or standalone in any checkout with pnpm pre-release:check.

Run the sweep on another machine (offload executor)

Section titled “Run the sweep on another machine (offload executor)”

By default the sweep runs on the machine that landed. You can configure an executor that runs the sweep’s offloadable test files on another machine. Tests that need the local machine, such as confinement, loopback servers and real-process suites, stay local.

Set LUMENFLOW_MAIN_SWEEP_OFFLOAD_EXECUTOR to the executor’s absolute path. The path must be an executable you own that nobody else can write. Otherwise the sweep refuses to run and names the rule. Nothing falls back to a local run.

The executor receives the job name, the commit and the command. It runs a checkout of that exact commit, streams the output back, and exits with the command’s status. Verdicts from the two halves merge: either red is red. An executor with no verdict is recorded as inconclusive, never green, and the next run for that commit retries.

pnpm lumenflow:release and its --dry-run verify that certification instead of re-running the plan. They accept the release commit’s own green certification, or one at an earlier commit when only lifecycle records and documentation changed since. Otherwise they refuse with a typed message that names the remedy:

RefusalMeaning
uncertifiedNo certification yet; let the post-land sweep finish, then release
redThe certification (or the post-land sweep) is red; land the fix first
inconclusiveA check never got a gates or lifecycle admission slot; no test ran. Run pnpm main:sweep --post-land once the host lock frees
stale-digestThe certification was made under another check plan; re-certify
driftSource changed since the last certification; wait for the sweep to certify it
integrityA record or log no longer matches its digest; re-certify

Landings that arrive after certification cannot starve a cut. By default pnpm lumenflow:release builds from the newest certified commit on the first-parent history of origin/main (the tip itself when only lifecycle records and docs follow it), or from --at <sha>. When that commit is not the tip, the version bump commit is pushed to release/v<version> instead of main, the tag points at it, and the bump is re-applied to main as an ordinary commit. The re-apply is written structurally on main’s current files, not replayed as a patch: every publishable package main holds is set to the version (including a package added after the certified commit), and the version-policy and changelog entries are written on main’s own copies, so a previous release’s bump or a new package landed since certification does not block the cut. If a manifest on main cannot be read, the release refuses before release/v<version> is pushed and names the files. If the re-apply itself fails, the release branch this run created is removed (or the exact git push origin --delete release/v<version> is printed). A rerun after a partial cut adopts the release branch and converges.

A cut from a certified ancestor never leaves a landing out silently. Before it starts, the release prints which landed WUs (and how many commits) it will NOT carry, and the tip that would carry them once the post-land sweep certifies it. It also names each newer certified commit it passed over and the rule that rejected it. A post-land sweep that re-reports a failure an ancestor already had does not reject a commit whose wu:prep evidence is green; a failure the landing itself introduced does.

The certificate is checked against the check plan at that certified commit, not the plan of newer tooling, so a later change to the release tooling does not block the cut. A certificate that does not match the plan at its own commit still refuses as stale-digest.

Before each push that establishes the release source, the cut verifies the exact version-bump commit again. If origin moved and the retry rebased the bump onto uncertified source, it refuses before pushing the bump. The refusal names the uncertified source SHA, its landings and changed paths: wait for that SHA’s post-land sweep or the next certified landing, then retry. Lifecycle and documentation advances remain allowed; any other advance still needs valid certification, including an earlier version-bump commit. The separate structural re-apply to main for a cut from a certified ancestor is not the release source and keeps its existing behavior.

Each work unit that changes released behaviour adds a .changeset/*.md entry. The version bump commit consumes every pending entry: it writes a ## [<version>] - <date> section in the root CHANGELOG.md (entries that start with “Behaviour change” or “Breaking” are listed first, under their own heading, then the rest in file order, each naming its packages), moves the old ## [Unreleased] body under that version, and deletes the consumed files in the same commit. The PUBLISHED signal links the notes. A pending entry that cannot be parsed (bad frontmatter, an unknown bump type, an empty summary) refuses the release with that file named, before any version commit. pnpm lumenflow:release --dry-run prints the notes it would write and changes nothing. Every package moves to one version on a cut, so the per-package bump types are listed, not applied.

The release-time packed-consumer smoke runs the tools of the commit being released, so newer test legs never judge older artifacts. Archives upload concurrently (default 4 at a time; set LUMENFLOW_RELEASE_UPLOAD_CONCURRENCY, at most 8), each package keeps its receipt, and a failed upload stops further uploads. wu:done certifies a landing by its prep evidence whenever the landed tree is the tree prep gated and no gate was skipped; it logs the outcome either way. When wu:done re-runs the gates itself (after an in-run rebase onto a sibling landing, or because the lane changed since prep), it records a fresh gate checkpoint for the tree it gated, so the landing is certified against that re-gated tree and not the older prep commit.

A landing that rebased over other certified landings is also certified when its own prep-gated diff touches nothing that changed since its prep base and no uncertified landing sits in between; the certificate records the certified parent and the composition. Otherwise wu:done logs why and the post-land sweep certifies it.

Release incidents and minor/major releases

Section titled “Release incidents and minor/major releases”

If a post-land sweep goes red at a commit that a published release tag contains, one urgent release-incident signal names the version, the failing checks, the sweep run and the hotfix route (once per version and run). A minor or major release refuses a certificate backed only by wu:prep evidence (sweep-required) and waits for the sweep; patches and hotfixes are not slowed.

pnpm lumenflow:release --release-now --owner-decision "<the reason, in your words>" cuts a patch or hotfix immediately from the latest certified commit: no sweep runs, and the consumer smoke test is the only test step. The decision is recorded verbatim in the certification reuse ledger. The throughput comparison is printed and recorded as advisory for every patch or hotfix, never a refusal: the pre-check line reads WARN with the advisory reason, and FAIL is printed only for an outcome that refuses. Minor and major releases keep it as a refusal and refuse --release-now. A change to the throughput baseline file never makes certification refuse.

A landing whose tree is exactly the tree wu:prep gated is certified by its own prep evidence when wu:done lands it, so a release from it waits for no sweep. A landing that merged with other source changes gets no such certificate and is certified by the post-land sweep instead. The cut itself runs no sweep: the packed-consumer smoke is its only test step, and a genuine red sweep record at the target commit still refuses it.

A verified green certification supersedes a red sweep record at a strict first-parent ancestor of its certified commit, however many commits behind it; the release report names the superseded marker. If newer source is uncertified, the refusal names that source and its landing; the old red marker does not replace the real cause. An applicable red marker is named alongside any source or certificate failure. A red record at the certified commit itself, or at any other commit, still refuses. An unverified or tampered green record cannot supersede a marker.

A full cut can outlast a foreground tool timeout, so run it detached and read its log. Rerunning the same command resumes from the retained pin and artifacts.

Right after verifying the certification, and before any version commit, the release runs the throughput regression check, so a refused attempt costs seconds and pushes nothing. It then runs only the work that depends on the version, the build or the registry: version and channel checks, the version bump, the minified build, self-consistency, the exact-archive and pack-root guards, the packed-consumer smoke, pack-registry parity, upload and read-back, and the tag. Review pnpm release --help and rehearse with --dry-run; a tag or --skip-publish result alone does not prove that packages are available to consumers. Configure and verify the intended delivery service before publishing a package.

The release log names every check it ran. Each check prints one line, [pre-release-checks] PASS <name> (<seconds>s) or FAIL, and the certification line names the certified commit and the run it reused, so a green release is proof of what ran and how long it took. The packed-consumer smoke is timed as one lane.

Keep release credentials and consumer license configuration outside the source checkout.