release: cut v0.3.0, and make the package prove it contains what the notes claim - #96
Conversation
|
CI closes the one thing the local candidate reported as All four required checks green on
Those Test jobs run the full
|
…notes claim On 2026-08-20 this repository described five different releases at once. package.json said 0.2.0. package-lock.json still said 0.1.0 — the #81 bump never touched it. RELEASE_NOTES.md's top entry described a 0.2.0 whose feature list was written at 477f0fc, before #72 added `aether skills`, `aether capabilities` and `aether support-bundle`. The npm registry served 0.1.0 and nothing else. And a packed aether-agents-0.2.0.tgz sat in the repo root from #83 until #90 deleted it, containing a build with no skills runtime in it at all. Nothing was lying on purpose. The four statements drifted apart because nothing compared them. 0.2.0 -> 0.3.0, not 0.2.1 ------------------------- #72 is a backwards-compatible feature addition — a skills runtime, three new CLI commands, six built-in skills shipped inside the package — that the v0.2.0 notes never mentioned. Semver makes that a minor bump. Reusing 0.2.0 was rejected on identity grounds. 0.2.0 already names a specific dated artifact: the August 19 notes entry, the README availability paragraph, install.sh's pin example, and that committed tarball. Publishing different contents under the same version would make two materially different artifacts answer to one name, which is the defect this release exists to close. 0.2.0 is retired unused; it will never be published. Reconciled ---------- - package.json, package-lock.json (both version fields) and src/version.ts all say 0.3.0. - RELEASE_NOTES.md leads with v0.3.0 covering 477f0fc..ed094dc: one feature, nine user-visible fixes, three test-only commits, one unwired module (#86 ship rail, which no command invokes), one docs commit. The v0.2.0 entry is marked superseded rather than rewritten — it is the record of what was written that day, not an install instruction. - README and the release log name 0.3.0, and both still say plainly that `npm i -g aether-agents` gives you 0.1.0, because it does. New gate: test/release_coherence.test.ts ---------------------------------------- Gate A asserts every place that names the release names the same one — including both package-lock version fields, which is the drift nothing was watching. Gate B is the load-bearing one: for every feature the release notes claim, the code behind it must be present in the file list `npm pack` would actually ship, and the command exposing it must be in the CLI registry. The source checkout's dist/ is NOT the package — the allowlist is dist/src plus four docs. Mutation-checked. Adding "!dist/src/commands/skills.js" to the files allowlist silently drops `aether skills` from the tarball: verify:production -> {"ok":true, ... "packedFiles":523} MISSED IT release_coherence -> FAIL: dist/src/commands/skills.js (agent skills runtime — `aether skills`) Restored: 7/7 pass, 524 packed files. New: npm run release:candidate ------------------------------ release.yml only runs after a founder has already tagged and published, so everything it checks is checked too late to change the decision. This runs the same sequence, in the same order, before the tag exists — against a detached git worktree of a specific commit, never the dirty checkout. A dirty tree is refused unless --allow-dirty, which marks the report commitBound:false rather than pretending. Every CLI proof runs the binary npm installed from the packed tarball into a clean prefix: --version, --help, `skills list`, `capabilities`, and the handoff demo (the demo harness is not shipped, so it is placed beside the installed package and resolves the CLI and its imports from the tarball's own dist/src). Skipped steps are recorded as "not-run" with a reason and can never read as a green tick — the full npm test suite is release.yml's gate and says so in the report. No string is handed to a shell: npm is reached through its own JS entrypoint under node, so every argument stays an argument. Also ---- - scripts/verify-production.ts exports createPackReport, so a gate reasoning about what a user receives asks npm instead of reading the build directory. - test/release_canaries.test.ts's coverage map said canaries 5 and 7 were unwritable. #86 and #87 wrote them two commits later; the excuse outlived the condition. The map is now enforced by a test that reads the delegated files. - docs/releases/OPERATOR-PACKET-v0.3.0.md: the founder-owned publish sequence, with what is proven and what is explicitly not. Gates at this commit: npm run typecheck exit 0 release + production test files 21 pass / 0 fail npm run verify:production --tag v0.3.0 ok Full npm test NOT run locally (a tool_executor test does not return on this Windows box); CI is the authority. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…te evidence Run against a63e1c6 in a detached worktree: commitBound true, ok true, exit 0. Tarball aether-agents-0.3.0.tgz, 524 entries, 589,829 bytes packed / 2,435,029 unpacked, sha256 25f33524bd866275674eccbf8cfe5706f14e925cb0ba35861dc6bc21a9245a2d. The digest came out identical from an uncommitted tree and from the detached worktree, which is recorded as content stability across a docs-only commit and explicitly NOT as a cross-machine reproducibility claim. Also records the mutation check: dropping dist/src/commands/skills.js from the files allowlist leaves verify:production reporting ok:true at 523 files, and fails release_coherence by name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ional The ground moved while PR #96 was open. #98 squash-merged to main, main became 426b124, and the v0.3.0 notes said nothing about it — which is this lane's own defect arriving from the direction the lane did not gate. WORK A: the notes now cover #98 ------------------------------- Its user-visible half is three fixes, and the first is the exact failure class this codebase forbids: - `aether doctor --live` never received --live. main.ts parses non-strictly, so a flag the command had not declared was captured globally and stripped from what the command was handed. --live ran the fast configured-only report and EXITED 0, presenting a live end-to-end verification that was never performed. Unknown rendered as verified. --deep, --dry-run, --no-ui and --only were lost the same way, and the whole --fix repair path was unreachable. - `aether doctor --fix --yes` answered "re-run with --yes" to someone who had just passed it, because the global --yes never arrived either. - Command lookup lowercased the token while dispatch was case-sensitive, so `aether Vault` fell past the typo guard into a chat turn and billed a paid model call. The seam itself is announced too: a command now carries its own help metadata, flag table and loader in one entry, flag collisions are load-time errors, and reachability is structural rather than a regex over main.ts's source. Range moves 477f0fc..ed094dc -> 477f0fc..426b124, 16 commits -> 17, across RELEASE_NOTES.md, docs/releases/2026-08-22.md and the operator packet. Fixed a miscount while re-deriving: the packet said "9 user-visible fixes" over a list of ten. WORK B: the gate now runs both directions ----------------------------------------- Gate B ran notes -> package: a claim with no code behind it fails. It could not see the inverse — a user-visible command that ships with NO claim anywhere — and the inverse is what actually keeps happening, once per lane that lands between the note being written and the tag being cut. Gate C: every non-hidden command in the CLI registry must be announced by some release note, or named in SHIPPED_WITHOUT_A_NOTE with a reason. An explicit list is fine; silence is not. It is enforced in both directions — a stale entry fails, and an entry that IS announced fails — so it cannot rot into a permanent bypass that quietly absorbs the next unannounced command. Every entry must also appear in the operator packet, because the founder cutting the tag is the person who needs to know what goes out unannounced. 15 commands are on it today; all predate the release log or were announced by capability in the June 2026 entry, and none is new in this release. Mutation-checked, per the controller's instruction. Added to the registry: { name: "teleport", args: "<dest>", summary: "beam the working tree somewhere", section: "System" } verify:production -> {"ok":true, ... "packedFiles":527} MISSED IT release_coherence -> FAIL: no user-visible command ships without either a release note or a named exemption + [ 'teleport — beam the working tree somewhere' ] - [] Registry restored byte-identical (md5 37b3f944…, `git status src/` empty), 10/10 pass. cli_registry.ts is read-only for this lane: it was mutated only in the working tree, never committed, and the restore is verified by digest. Also: Gate B now reads the registry by IMPORTING it instead of by regex over its source. #98 replaced "reachability asserted by a regex over main.ts" for exactly this reason, and it immediately split the commands across CLI_COMMANDS and DISPATCH_COMMANDS — a source regex keyed on one array would have silently stopped covering the other. doctor is in the second one. Gates at this commit: npm run typecheck exit 0 release_coherence 10 pass / 0 fail Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…igest change The base moved to 426b124 (#98), so every number in the packet was taken against a tree that no longer exists. Re-run, commit-bound, at 22aa021: commitBound true, ok true, exit 0 aether-agents-0.3.0.tgz sha256 8c5c119d93cabf49af0c49c97addb055308d508af93f8675a26b6f5c8ecba307 527 entries, 597,400 packed / 2,459,474 unpacked The digest CHANGED from the a63e1c6 run (25f33524…, 524 entries), and the packet now says why that is the correct outcome rather than a discrepancy: #98 added dist/src/core/command_dispatch.* and rewrote main.js, so the packed content is genuinely different. A digest that had survived that change would have meant the pack was not reading the tree. Both mutation checks were re-measured against this base rather than carried forward: skills drop verify:production {"ok":true, ... "packedFiles":526} MISSED IT release_coherence FAIL: dist/src/commands/skills.js restored -> 527 files, 10/10 pass teleport verify:production {"ok":true, ... "packedFiles":527} MISSED IT release_coherence FAIL: 'teleport — beam the working tree somewhere' restored -> registry byte-identical, 10/10 pass I had initially edited the skills figure from 523 to 526 by inference. That is a number nobody measured, so it was re-run before being written down. Release-owned suite at this commit: 24 pass / 0 fail. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
02a8aa8 to
e0f9458
Compare
|
Rebased onto All five checks green at
Two things worth flagging to a reviewer: The digest changed and that is correct. Gate C is the new direction. Gate B caught a note promising something the package lacks. It could not see a command shipping with no note at all — which is what #98 just did to this very PR. Both directions are now enforced, both mutation-proven at this base, and Still not merging. Tag and publish remain founder-owned, and #93/#94/#95/#97/#99/#100/#101/#102 are all expected to land first — each one moves the range and the digest again, which is why step 2 of the packet re-runs the candidate on the merge commit instead of trusting this PR's number. |
|
MERGE-TRAIN STATE — HELD (2026-08-22T15:56Z) Head: Evidence: required Ubuntu, Windows, supply-chain, and CodeQL checks passed on this exact head. Independent release review found the recorded Owner: release PR branch writer. Next legal action: run |
# Conflicts: # test/release_canaries.test.ts
Regenerates the packet against a845479 (origin/main after #105): base SHA, evidence commit, tarball digest, packed entry count, the recorded release-candidate run, and the coverage breakdown. Two corrections rather than refreshes: - Section 5 no longer lists the full test suite as unproven. It was run at the evidence commit (1464 tests, 1460 pass, 0 fail, 4 skipped); what is genuinely unproven is the suite INSIDE the candidate run, which reports npm-test as not-run by design. - Two new unproven entries name the deployed API. The notes' Authentication claims are about a server this repository cannot test, and #105 exists precisely because `aether agent` does not work end to end against production today. Both are marked rather than implied.
The packed size in the packet header was written from npm's rounded "740.0 kB" notice rather than measured. The tarball is 739,977 bytes. A digest and a byte count that disagree are the same class of defect this packet exists to close.
Contract
Cut v0.3.0, and make the package prove it contains what the notes claim.
Two things, and only these two:
package.json, bothpackage-lock.jsonversion fields,
src/version.ts,RELEASE_NOTES.md,docs/releases/and theoperator packet all name v0.3.0 and describe the same build.
test/release_coherence.test.tsmaps every headline claim in the notes to (a) a command in the CLI registry and
(b) files that
npm packactually ships, and fails the build in bothdirections — a claim with no code behind it, and a user-visible command that
ships with no claim.
No feature code is touched. Every file below is release-owned.
Regenerated against the merged
mainThe notes were originally written at
426b124. Eleven commits have landed since,so the release truth was regenerated rather than tagged stale.
origin/mainwasmerged into this branch twice (no rebase, no force):
2769778— feat(review): structured repository state, and a verification that knows what it verified #93/feat(review): select, stage, unstage, revert and commit exactly what was chosen #94/feat(ship): publish HEAD and only HEAD, and bind the work to what carries it #95/feat(review): the one writer for a verification record, and the one condition it writes under #97/feat(review): line counts beside the state, not inside it #101/feat(review): the review to commit to pull request rail, reachable as a command #102 (review → commit → PR rail), feat(sessions): project continuity and the session library (AA-CONT-04) #99(
aether sessions), feat(skills): put skills and AGENTS.md inside real runs, and enforce their policy #100 (skills enforced in real runs), fix(opener): route win32 URLs through rundll32, not explorer.exe #103 (win32 URLopener), fix(auth): stop following planted links and tearing the token file #104 (token store hardening).
a845479— fix(cloud): refuse the silent dev-session to chat-stream downgrade (ROUTING_DRIFT, exit 3) #105 (CloudBrainROUTING_DRIFT, fail-closed exit 3).One conflict, in
test/release_canaries.test.tsagainst #102, resolved keepingboth sides' canaries:
main's canary-5 prose (which correctly names the twofiles that now cover it) and this lane's test that enforces the coverage map.
main's closing note still called canary 7 unwritable after #87 had landed theparity seam; enforcing the map is what stops that from surviving another merge.
Claims added, each pointing at code on
mainaether review/aether shiprail;--approve <action>as the authority boundaryaether sessionsproject session library, six distinct continuity statesAGENTS.mdcomposed into real runs, tool policy enforced, skills only subtractaether auth loginopens the approval page on win32 (rundll32, notexplorer.exe)ROUTING_DRIFTbanner; a coding run no longer silently becomes a chatBehaviour changes are called out under their own heading in the notes — three
of them, from two PRs:
breaks a deliberate
~/.config/aethersymlink;An Authentication section states the auth reality with its provenance, because
half of it lives in a server this repository cannot test. See "What is skipped".
Evidence
a845479082e5e1b07337aae95833767d9f8ab4e585248956e660bc10de80080c805235756ca21e10e0f94587dfae6876ba7cf7b92799956a9f36a537(unmoved)Gates, from a clean
npm cinpm cinpm run typechecktsc --noEmitexit 0npm testnpm run verify:production{"ok":true,"version":"0.3.0","packedFiles":575,"packedBytes":3022168,"workflows":3}npm pack --dry-runnpm run release:candidateRELEASE CANDIDATE OK,ok:true,commitBound:true, exit 0npm run smokenpm run smokefails onlocal turn:Ollama model 'qwen2.5-coder:7b' not found (404)— the model is not pulled on this machine. Everything it can reach passes,including
auth(signed in againstapi.aethersystems.net/cloud) and a livecloud turn. This is a machine state, not a defect in the release.Mutation evidence
The load-bearing gate was mutated in both directions and restored (
git statusclean after each; the tree was committed first so the restore could not lose work).
1 — a fabricated feature claim in the notes. Added
- **aether teleport** — move the working tree to another machine mid-run.toRELEASE_NOTES.md, with theFEATURE_MANIFESTrow the file itself calls thecontract. 2 of 11 gates failed:
2 — a false availability claim. Added
A plainnpm i -g aether-agents --ignore-scriptsnow installs 0.3.0.toREADME.md. 1 gate failed:Restored, all 11 coherence gates pass.
One gate was vacuous, and is fixed here
Worth reading, because it changed what the release reports. The
announced-command matcher counted a command as announced if the notes contained
its name in bare backticks anywhere. When #102 landed
aether reviewandaether ship, the gate passed both immediately — not because they wereannounced, but because the notes mention the built-in skills named
review-prand
ship. The gate built to catch an unannounced command would have let thisrelease's two headline commands through in silence.
It now requires the form a user actually types,
aether <name>, and a new testasserts it rejects
review-pras an announcement ofreview. Two consequences,both made by the gate rather than by hand:
aether authleft the exemption list — the new Authentication sectiongenuinely announces it, and the list refuses to hold an exemption for a command
that is announced.
aether outputjoined it — never announced by command token, only evercovered as "durable media output history" in the 2026-08-14 entry.
Files changed (12, all release-owned)
README.md·RELEASE_NOTES.md·docs/releases/2026-08-22.md·docs/releases/OPERATOR-PACKET-v0.3.0.md·docs/releases/README.md·package.json·package-lock.json·src/version.ts·scripts/release-candidate.ts·scripts/verify-production.ts·test/release_canaries.test.ts·test/release_coherence.test.tsNo file under
src/other thanversion.ts. No feature code.Release candidate
aether-agents-0.3.0.tgz70a48aca8baa8b63f551980256eafa42531cd22fc5ca1146829d31f8b4bd2e4dCross-checked with
certutil -hashfileand Node'scryptoindependently; bothagree. The digest is identical at the evidence commit
fb96ee44and at thepushed head
8524895, which is the expected result:docs/is not in thefilesallowlist, so writing the digest into the operator packet cannot move it.
What is skipped
release, no registry contact.
npm i -g aether-agentsstill installs0.1.0,and the notes say so. Publishing is founder-owned; the sequence is §6 of the
operator packet.
release:candidatereportsnpm-testasnot-runby design and runs the release-owned files only(25 tests). The full 1464 were run separately, at the evidence commit; CI is the
authority.
accepts long-lived
aek_tokens and thataether auth logoutends the sessionserver-side. Neither is provable here — no live credential in CI, no test
asserts either — so both are marked in the notes as operator-verified rather
than stated flat. The client's
/auth/logoutcall is also not new in thisrange (it predates Fix: terminal auth 401 on model-select + UX/UI cleanup #47/Meta-loop: further harden the auth flow + UX beyond PR #47 #53); what changed is on the server. What this lane can
say is narrower:
npm run smokegot an authenticated cloud turn back fromapi.aethersystems.net.aether agentagainst production. fix(cloud): refuse the silent dev-session to chat-stream downgrade (ROUTING_DRIFT, exit 3) #105 exists because it does not workend to end:
AETHER_AGENT_DEV_ENABLEDis unset onapi.aethersystems.net, sothe run now exits 3 rather than silently degrading. Correct behaviour, still
a broken path — a server configuration gap this tag does not fix.
produced, recorded so CI's tarball can be compared against it.
Inclusion status
fix/cloud-brain-silent-degradeis included: it merged as #105(
a845479082e5e1b07337aae95833767d9f8ab4e5) while this lane was open, was mergedinto this branch, and is covered in the notes, the dated entry, the operator
packet and the Behaviour changes section. There is now no open PR in this
repository other than #96, so the notes describe all of
mainas ofa845479. If anything lands before the tag is cut, the release must beregenerated — the coherence gate fails the build if a new user-visible command
arrives unannounced, which is what makes that detectable rather than silent.
Author model: claude-opus (requested gpt56_luna)