test(aterm): assert against the live roster, not only the fixtures (#1259) #1278

Merged
coilyco-ops merged 5 commits from aos/claude/mu55-contract-tests into main 2026-08-26 08:35:51 +00:00
Member

Closes #1259. Tier 3 of the #1245 dispatch, deliberately last because it is only meaningful once tiers 1 and 2 consumed the fields.

just aterm-contract

--- PASS: TestLiveOverlayDiscardsNoField                    (15 role/seat pairs)
--- PASS: TestLiveRosterEveryLaunchableSeatResolvesToAPlan   (15 role/seat pairs)
--- PASS: TestLiveRosterRefusesEveryNonNativeSeat
--- PASS: TestLiveRoleBackgroundsStaySeparable
        closest background pair eval/sysadmin at dE 3.25 across 7 roles
--- PASS: TestLiveDefaultSeatBelongsToItsRole
--- PASS: TestLiveSoundMarksAllHaveASample

The one the issue says would have caught this whole backlog

Decode the live overlay into a generic map, decode it into the typed struct, re-encode, diff leaf by leaf. Anything present upstream and absent downstream is a failure. The waiver list is empty and an entry in it needs a reason, not a shrug.

Verified against a negative control rather than assumed: retagging motif as json:"-" fails the test 30 times across the live roster, once per personality per role/seat pair, each naming the dropped path. That is what turns sound_mark and form sitting unread into a failure on the day they are added.

The colour floor is a ratchet, not a target

Backgrounds are compared in CIELAB, because hex distance says nothing about whether an eye can separate two windows. Measured today across the seven roles:

21 pairs, closest eval/sysadmin at dE 3.25, furthest at dE 13.59
0 pairs under dE 2, 4 pairs under dE 5

The floor is dE 3.0, which today's roster clears by 0.25. agent-compose#358 raises the ceiling; this stops the floor falling, which is the half aterm can hold on its own. labDistance is a real addition to brand.go rather than test-only arithmetic, since #358's fix will want it too.

Skipping is loud

CI carries no agent-compose, so just aterm-test skips these and stays green. The skip names the escape hatch, and setting it makes the same absence a failure:

$ ATERM_LIVE_ROSTER=1 go test -run TestLive .
    ATERM_LIVE_ROSTER is set but agent-compose is not on PATH: ...
    FAIL

$ go test -run TestLive -v .
    no agent-compose on PATH, so the live roster cannot be read.
    Set ATERM_LIVE_ROSTER to make this a failure.
    --- SKIP

just aterm-contract sets it, so the recipe is the enforcing surface and a plain test run is the permissive one. Both behaviors exercised above.

Also in here

docs/aterm.md had room again after the status-line composer moved out, so this corrects a sentence #1251 left behind: the overlay's non-glyph fields no longer "reach nothing", they reach the identity card. The contract recipe is documented beside it.

Verification

  • just aterm-test, just aterm-contract, just aterm-fmt, just aterm-lint clean; pre-commit run --all-files clean
  • the negative control and both skip behaviors above, run rather than reasoned about
Closes #1259. Tier 3 of the #1245 dispatch, deliberately last because it is only meaningful once tiers 1 and 2 consumed the fields. ## `just aterm-contract` ``` --- PASS: TestLiveOverlayDiscardsNoField (15 role/seat pairs) --- PASS: TestLiveRosterEveryLaunchableSeatResolvesToAPlan (15 role/seat pairs) --- PASS: TestLiveRosterRefusesEveryNonNativeSeat --- PASS: TestLiveRoleBackgroundsStaySeparable closest background pair eval/sysadmin at dE 3.25 across 7 roles --- PASS: TestLiveDefaultSeatBelongsToItsRole --- PASS: TestLiveSoundMarksAllHaveASample ``` ## The one the issue says would have caught this whole backlog Decode the live overlay into a generic map, decode it into the typed struct, re-encode, diff leaf by leaf. Anything present upstream and absent downstream is a failure. The waiver list is empty and an entry in it needs a reason, not a shrug. Verified against a negative control rather than assumed: retagging `motif` as `json:"-"` fails the test **30 times** across the live roster, once per personality per role/seat pair, each naming the dropped path. That is what turns `sound_mark` and `form` sitting unread into a failure on the day they are added. ## The colour floor is a ratchet, not a target Backgrounds are compared in CIELAB, because hex distance says nothing about whether an eye can separate two windows. Measured today across the seven roles: ``` 21 pairs, closest eval/sysadmin at dE 3.25, furthest at dE 13.59 0 pairs under dE 2, 4 pairs under dE 5 ``` The floor is dE 3.0, which today's roster clears by 0.25. agent-compose#358 raises the ceiling; this stops the floor falling, which is the half aterm can hold on its own. `labDistance` is a real addition to `brand.go` rather than test-only arithmetic, since #358's fix will want it too. ## Skipping is loud CI carries no `agent-compose`, so `just aterm-test` skips these and stays green. The skip names the escape hatch, and setting it makes the same absence a failure: ``` $ ATERM_LIVE_ROSTER=1 go test -run TestLive . ATERM_LIVE_ROSTER is set but agent-compose is not on PATH: ... FAIL $ go test -run TestLive -v . no agent-compose on PATH, so the live roster cannot be read. Set ATERM_LIVE_ROSTER to make this a failure. --- SKIP ``` `just aterm-contract` sets it, so the recipe is the enforcing surface and a plain test run is the permissive one. Both behaviors exercised above. ## Also in here `docs/aterm.md` had room again after the status-line composer moved out, so this corrects a sentence #1251 left behind: the overlay's non-glyph fields no longer "reach nothing", they reach the identity card. The contract recipe is documented beside it. ## Verification * `just aterm-test`, `just aterm-contract`, `just aterm-fmt`, `just aterm-lint` clean; `pre-commit run --all-files` clean * the negative control and both skip behaviors above, run rather than reasoned about
test(aterm): assert against the live roster, not only the fixtures (#1259)
Some checks failed
ci / ward-doctor (pull_request) Successful in 8s
ci / aos-cli-tests (pull_request) Failing after 28s
ci / aos-eval-tests (pull_request) Successful in 48s
ci / gate (pull_request) Successful in 54s
3e39070110
The fixtures prove aterm still works on the roster it was written for. The
failure that happens is upstream drift, and nothing caught it.

`just aterm-contract` walks the live roster. Every launchable seat resolves to
a plan whose title leads with its workspace and whose card carries every
personality. Every catalogue seat outside the native set refuses with exit 3
and says which of the two checks it failed. Every role's default seat is one
that role can launch, asked of aos rather than parsed a second time. Every
timbre the roster ships has a committed sample.

The one worth the recipe decodes the live overlay, re-encodes it through the
typed struct, and diffs leaf by leaf, so a field Agent Compose ships and aterm
drops fails on the day it is added rather than sitting unread for months.
Nothing is waived; an entry in that list needs a reason. Verified against a
negative control: retagging one field as discarded fails it 30 times across the
live roster.

Backgrounds get a dE 3.0 floor on the closest pair, measured in CIELAB because
hex distance says nothing about whether an eye can separate two windows. That
is a ratchet rather than a target: the closest pair today is eval/sysadmin at
dE 3.25, and agent-compose#358 raises the floor.

A host without agent-compose skips and names ATERM_LIVE_ROSTER, which turns the
same absence into a failure where the roster was supposed to be. `just
aterm-test` therefore stays green in CI, which carries no roster.

Closes #1259

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Agent-Role: platform
Merge branch 'main' into aos/claude/mu55-contract-tests
Some checks failed
ci / aos-cli-tests (pull_request) Failing after 42s
ci / aos-eval-tests (pull_request) Successful in 9s
ci / ward-doctor (pull_request) Successful in 7s
ci / gate (pull_request) Has been cancelled
22935be34b
The CI image carries agent-compose, so the live contract tests do run there,
which is better than assumed. Its aos is older than main and answers
`_launch-agent` with "integrated launch needs --role", which failed the check.

aterm itself degrades to the catalogue order against an aos too old for the
verb, so this now does the same: every role refusing is an old binary and skips
with the refusal quoted, and some roles refusing while others answer is the
defect the check exists for and still fails. Both branches exercised against
stub binaries.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Agent-Role: platform
Merge remote-tracking branch 'origin/aos/claude/mu55-contract-tests' into aos/claude/mu55-contract-tests
Some checks failed
ci / aos-eval-tests (pull_request) Successful in 6s
ci / ward-doctor (pull_request) Successful in 7s
ci / aos-cli-tests (pull_request) Successful in 28s
ci / gate (pull_request) Failing after 53s
98bf6f98fa
docs(aterm): fit the contract paragraph back under the char cap (#1259)
All checks were successful
ci / ward-doctor (pull_request) Successful in 12s
ci / aos-cli-tests (pull_request) Successful in 34s
ci / gate (pull_request) Successful in 1m5s
ci / aos-eval-tests (pull_request) Successful in 3m38s
cc22cf5ed0
The #1279 bundle fix and this branch both added to docs/aterm.md inside the
same hour and the page went 481 chars over. Trimmed to fit. Fourth instance
on #1274.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Agent-Role: platform
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1278
No description provided.