Skip to content

release: cut v0.3.0, and make the package prove it contains what the notes claim - #96

Merged
AetherAI3 merged 10 commits into
mainfrom
lane/aa-rel-01-release
Aug 23, 2026
Merged

release: cut v0.3.0, and make the package prove it contains what the notes claim#96
AetherAI3 merged 10 commits into
mainfrom
lane/aa-rel-01-release

Conversation

@AetherAI3

@AetherAI3 AetherAI3 commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Contract

Cut v0.3.0, and make the package prove it contains what the notes claim.

Two things, and only these two:

  1. One release, described once. package.json, both package-lock.json
    version fields, src/version.ts, RELEASE_NOTES.md, docs/releases/ and the
    operator packet all name v0.3.0 and describe the same build.
  2. The description is enforced, not asserted. test/release_coherence.test.ts
    maps every headline claim in the notes to (a) a command in the CLI registry and
    (b) files that npm pack actually ships, and fails the build in both
    directions — 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 main

The notes were originally written at 426b124. Eleven commits have landed since,
so the release truth was regenerated rather than tagged stale. origin/main was
merged into this branch twice (no rebase, no force):

One conflict, in test/release_canaries.test.ts against #102, resolved keeping
both sides' canaries: main's canary-5 prose (which correctly names the two
files 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 the
parity seam; enforcing the map is what stops that from surviving another merge.

Claims added, each pointing at code on main

Claim PR
aether review / aether ship rail; --approve <action> as the authority boundary #93 #94 #95 #97 #101 #102
aether sessions project session library, six distinct continuity states #99
Skills + AGENTS.md composed into real runs, tool policy enforced, skills only subtract #100
aether auth login opens the approval page on win32 (rundll32, not explorer.exe) #103
Token store refuses planted links; atomic temp+rename write #104
ROUTING_DRIFT banner; a coding run no longer silently becomes a chat #105

Behaviour changes are called out under their own heading in the notes — three
of them, from two PRs:

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

Base SHA merged a845479082e5e1b07337aae95833767d9f8ab4e5
Head SHA pushed 85248956e660bc10de80080c805235756ca21e10
Remote head before e0f94587dfae6876ba7cf7b92799956a9f36a537 (unmoved)

Gates, from a clean npm ci

Command Result
npm ci 4 packages, 0 vulnerabilities
npm run typecheck tsc --noEmit exit 0
npm test 1464 tests — 1460 pass, 0 fail, 4 skipped
npm run verify:production {"ok":true,"version":"0.3.0","packedFiles":575,"packedBytes":3022168,"workflows":3}
npm pack --dry-run 575 files, 739,977 B packed / 3,022,168 B unpacked
npm run release:candidate RELEASE CANDIDATE OK, ok:true, commitBound:true, exit 0
npm run smoke 5 pass / 1 skip / 1 fail — known environmental, see below

npm run smoke fails on local 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 against api.aethersystems.net/cloud) and a live
cloud 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 status
clean 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. to
RELEASE_NOTES.md, with the FEATURE_MANIFEST row the file itself calls the
contract. 2 of 11 gates failed:

✖ every CLI command the release notes promise is in the CLI registry
    mid-run teleport — `aether teleport`: the CLI registry declares no "teleport" command
✖ every feature the release notes promise is present in the packed tarball
    dist/src/commands/teleport.js  (mid-run teleport — `aether teleport`)

2 — a false availability claim. Added
A plain npm i -g aether-agents --ignore-scripts now installs 0.3.0. to
README.md. 1 gate failed:

✖ release documents never state that this version is installable from npm
    AssertionError: README.md claims npm serves 0.3.0 without registry proof

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 review and
aether ship, the gate passed both immediately — not because they were
announced, but because the notes mention the built-in skills named review-pr
and ship. The gate built to catch an unannounced command would have let this
release's two headline commands through in silence.

It now requires the form a user actually types, aether <name>, and a new test
asserts it rejects review-pr as an announcement of review. Two consequences,
both made by the gate rather than by hand:

  • aether auth left the exemption list — the new Authentication section
    genuinely announces it, and the list refuses to hold an exemption for a command
    that is announced.
  • aether output joined it — never announced by command token, only ever
    covered 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.ts

No file under src/ other than version.ts. No feature code.

Release candidate

Tarball aether-agents-0.3.0.tgz
Size 739,977 bytes (3,022,168 unpacked)
Files 575 (counted from the tar itself, not from npm's notice)
sha256 70a48aca8baa8b63f551980256eafa42531cd22fc5ca1146829d31f8b4bd2e4d

Cross-checked with certutil -hashfile and Node's crypto independently; both
agree. The digest is identical at the evidence commit fb96ee44 and at the
pushed head 8524895, which is the expected result: docs/ is not in the files
allowlist, so writing the digest into the operator packet cannot move it.

The digest binds to this PR head. It is not the tag's digest. Once #96 is
squash-merged, the merge commit is a different tree and the candidate must be
re-cut on it before v0.3.0 is created — §6.2 of the operator packet is that
step. Any lane landing before the tag moves it again.

What is skipped

  • Nothing was published, tagged, or released. No tag created, no GitHub
    release, no registry contact. npm i -g aether-agents still installs 0.1.0,
    and the notes say so. Publishing is founder-owned; the sequence is §6 of the
    operator packet.
  • The full suite inside the candidate run. release:candidate reports
    npm-test as not-run by design and runs the release-owned files only
    (25 tests). The full 1464 were run separately, at the evidence commit; CI is the
    authority.
  • Both server-side auth claims. The notes' Authentication section says the API
    accepts long-lived aek_ tokens and that aether auth logout ends the session
    server-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/logout call is also not new in this
    range (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 smoke got an authenticated cloud turn back from
    api.aethersystems.net.
  • aether agent against production. fix(cloud): refuse the silent dev-session to chat-stream downgrade (ROUTING_DRIFT, exit 3) #105 exists because it does not work
    end to end: AETHER_AGENT_DEV_ENABLED is unset on api.aethersystems.net, so
    the run now exits 3 rather than silently degrading. Correct behaviour, still
    a broken path — a server configuration gap this tag does not fix.
  • Cross-machine digest reproducibility. The digest is what this machine
    produced, recorded so CI's tarball can be compared against it.

Inclusion status

fix/cloud-brain-silent-degrade is included: it merged as #105
(a845479082e5e1b07337aae95833767d9f8ab4e5) while this lane was open, was merged
into 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 main as of
a845479. If anything lands before the tag is cut, the release must be
regenerated
— 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)

@AetherAI3

Copy link
Copy Markdown
Owner Author

CI closes the one thing the local candidate reported as not-run.

All four required checks green on 02a8aa8, plus CodeQL:

Check Result
Test (ubuntu-latest) pass, 35s
Test (windows-latest) pass, 1m9s
analyze pass, 1m21s
supply-chain pass, 16s
CodeQL pass

Those Test jobs run the full npm test suite — the step the release-candidate report deliberately marked NOT-RUN on this Windows box rather than guessing at. It is now read from the authority, not from a local skip.

mergeStateStatus: CLEAN. Not merging — this is a release cut and the tag/publish steps after it are founder-owned.

AetherAI3 and others added 4 commits August 22, 2026 11:24
…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>
@AetherAI3
AetherAI3 force-pushed the lane/aa-rel-01-release branch from 02a8aa8 to e0f9458 Compare August 22, 2026 15:35
@AetherAI3

Copy link
Copy Markdown
Owner Author

Rebased onto 426b124 (post-#98) and re-cut. Head is now e0f9458; the body has been rewritten so every figure in it was measured at this base rather than carried forward.

All five checks green at e0f9458 — these readings are at the exact ref, not the pre-rebase one:

Check Result
Test (ubuntu-latest) pass, 30s
Test (windows-latest) pass, 2m18s
analyze pass, 1m23s
supply-chain pass, 14s
CodeQL pass

mergeStateStatus: CLEAN, mergeable: MERGEABLE.

Two things worth flagging to a reviewer:

The digest changed and that is correct. 25f33524… / 524 entries → 8c5c119d… / 527 entries. #98 added dist/src/core/command_dispatch.* and rewrote main.js, so the packed content genuinely differs. A digest that had survived that would have meant the pack was not reading the tree.

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 verify:production caught neither mutation.

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.

@AetherAI3

Copy link
Copy Markdown
Owner Author

MERGE-TRAIN STATE — HELD (2026-08-22T15:56Z)

Head: e0f94587dfae6876ba7cf7b92799956a9f36a537; base/main: 426b12464c2a19549f421adb43348f83d028628e.

Evidence: required Ubuntu, Windows, supply-chain, and CodeQL checks passed on this exact head. Independent release review found the recorded release:candidate artifact/digest is bound to ancestor 22aa02141fba158927cb1f01e4344cfa3e8f1a01, not this final head. No tag, GitHub release, or npm publication is authorized.

Owner: release PR branch writer. Next legal action: run npm run release:candidate on the frozen final head (or exact merge candidate), retain a successful commitBound:true report, then re-fetch head/base/checks and obtain a fresh merge decision.

# 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.
@AetherAI3
AetherAI3 merged commit 84d8767 into main Aug 23, 2026
5 checks passed
@AetherAI3
AetherAI3 deleted the lane/aa-rel-01-release branch August 23, 2026 02:11
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.

1 participant