Skip to content

feat(nix): deploy cairn from the PINNED flake package, not a fork in this checkout - #1406

Merged
ZacxDev merged 9 commits into
mainfrom
feat/cairn-flake-pin
Sep 9, 2026
Merged

feat(nix): deploy cairn from the PINNED flake package, not a fork in this checkout#1406
ZacxDev merged 9 commits into
mainfrom
feat/cairn-flake-pin

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Sep 8, 2026

Copy link
Copy Markdown
Member

Rank 3's second slice. devrc consumes ZacxDev/cairn as a pinned flake input and deploys packages.cairn, instead of the mkOutOfStoreSymlink to scripts/cairn. The operator decided the direction on 2026-09-08 (#1394): consolidate onto the pin.

Scope: the pin only. NOT the entry_shape/writer-vocabulary consolidation (slice 3), NOT deleting devrc's scripts/lib/ copies — the writer and cairn-who still import them.

The asymmetry is the point

cairn moves into the store; cairn-who deliberately does not. Both resolve siblings through Path(__file__).resolve().parent / "lib", so what must hold is that the directory holding the REAL file also holds lib/. Out-of-store satisfies that by resolving back into the checkout; the packaged cairn satisfies it a second way, by installing script and lib/ together under libexec. cairn-who has no such package — it is devrc-only and absent from the OSS repo — so a store copy would die on import. Both lines sit together so the difference reads as deliberate, and test_cairn_flake_pin.py pins the relationship, not each side alone.

nixpkgs is deliberately NOT followed

cairn pins python312 because its Dockerfile and CI do; a bare pkgs.python3 there once followed nixpkgs to 3.14 and shipped an interpreter its suite had never run under. Following would rebuild the client against devrc's nixpkgs-unstable — a nixpkgs cairn's CI has never tested.

The guard reads the whole input region (a dotted-spelling draft was walked by the cairn = { url = …; inputs.nixpkgs.follows = …; } form, which is how home-manager is spelled twenty lines above) and checks the lock structurally: a follow is a list, an unfollowed input a plain node name. Positive-controlled in the same file — home-manager records ['nixpkgs'], cairn records 'nixpkgs'.

⚠ The lock currently maps cairn's nixpkgs to devrc's node. That is deduplication, not a follows: cairn's own lock pins the same rev (42f17a57f4f6). When the two diverge, cairn keeps its pin.

Two defects the gate caught, neither visible in the diff

  1. cairnPackage is a REQUIRED argument (no default, deliberately — a broken thread should be an eval error, not a symlink to /bin/cairn), and that broke skills_mapping.py, which evaluates nix/home.nix standalone with a stub arg set. nix refused to apply the function and the check reported "nix cannot evaluate nix/home.nix" — a message that blames home.nix for a defect in the stub set. Its own text says FIX THE CHECK, do NOT delete it. Added cairnPackage = {}{} rather than a string, so forcing it errors instead of silently yielding a plausible path.
  2. The skill description grew 64 chars into a zero-headroom ratchet — four failures, one cause (assert 11256 <= 11192; MEASURED_ALL_TIER_A_CHARS 11366 != 11430). Fixed length-neutrally rather than by re-pinning constants: client `scripts/cairn`client `cairn` on PATH, both exactly 22 chars, so every pinned tier constant stays valid and the description is more accurate after the pin.

The comment explaining (1) then breached a third budget: skills_mapping.py has a 7,400-byte ceiling with 108 bytes free and the first draft added 742. That ceiling's message says an overage is a question about which ambition crept back, never about raising the number — so the comment is three terse lines (7,361 B) and the reasoning lives in the commit.

Test matrix

result
test_cairn_flake_pin.py at base 8 failed / 0 passed
at HEAD, with the touched suites 116 passed

All 8 are real regression coverage — none passes vacuously at base. The follows guard is labelled an invariant guard in its own docstring: the follows line never existed, so it never caught a live bug; its discriminating power was established by mutation.

⚠ It also documents a harness trap worth knowing: nix develop -c pytest rewrites flake.lock, so a lock-only mutant is silently reverted before pytest reads it and scores SURVIVED without ever running. The mtime-cache trap in a different costume.

Gate, and the baseline — which went stale twice today

control (plain main 01956bf0)  collected=13068 passed=13048 failed=20
branch                         collected=13076 passed=13056 failed=20

Both sides fail identically, every one in test_nebula_relay_apply.py (arrived with #1272). main is red on its own; this branch adds no failure. The +8 is exactly the new suite, all passing.

The age/opencode 7 that were red this morning are gone — main fixed them. Re-derive this baseline rather than quoting it.

Floor re-pinned 12927 → 13026 on the rebased tree per the ORDER note; floor sum 20342 → 20441.

Live verification, through the exact pinned revision

Built github:ZacxDev/cairn/9213726#cairn:

doctor --no-sync, no CAIRN_MIRROR_ROOT frozen-mirror NOT-OBSERVABLE
with it, as sessionVariables.nix now exports frozen-mirror **OK**, all three checks OK, exit 10
ls-entries 226 entries (network path)
recall --repo ~/workspace/devrc exit 0

That env var is not cosmetic: unset, the check stops looking, which is not the same as passing.

Deploy note

🔴 Merging this requires a home-manager switch~/.local/bin/cairn becomes a store path created by activation. Until the switch it still points at scripts/cairn, which keeps working, so unlike #1381 there is no capability gap; the checkout copy simply stays live a while longer.

🤖 Generated with Claude Code

ZacxDev and others added 3 commits September 8, 2026 14:41
…k into this checkout

`~/.local/bin/cairn` was an `mkOutOfStoreSymlink` to `devrc/scripts/cairn`, so
this repo carried a second copy of a reader that now lives in its own extracted
OSS repo. It is now `${cairnPackage}/bin/cairn` from a locked
`github:ZacxDev/cairn` input (rev 9213726), threaded input -> outputs ->
extraSpecialArgs -> nix/home.nix, which takes the argument WITHOUT a default so
a cut thread is an eval error rather than a symlink to `/bin/cairn`.

`cairn-who` deliberately does NOT move. It is devrc-only, absent from the OSS
package, and resolves `scripts/lib/cairn_who.py` through its own `__file__` —
so it keeps `mkOutOfStoreSymlink`. The two deploy modes now differ ON PURPOSE
and every comment saying otherwise was rewritten; `scripts/cairn` and
`scripts/lib/` stay in the tree (the writer and `cairn-who` import them) and
are simply no longer what lands on PATH.

NOT `inputs.cairn.inputs.nixpkgs.follows = "nixpkgs"`, and that is a decision,
not an omission. cairn pins `pkgs.python312` because its Dockerfile is
`python:3.12-slim` and its CI pins 3.12; a bare `pkgs.python3` there once
followed nixpkgs to 3.14 and shipped an interpreter nothing in that repo had
run its suite under. Following would rebuild the client against devrc's
`nixpkgs-unstable`, which cairn's CI has never tested — the thing deployed
would stop being the thing that was tested. The cost is a second nixpkgs node
in the lock.

CAIRN_MIRROR_ROOT is exported, and it is a bug fix rather than configuration.
devrc's fork had the frozen mirror's path hardcoded; the extracted client reads
the env var, and UNSET makes `doctor` report `frozen-mirror NOT-OBSERVABLE` —
a status that contributes nothing, i.e. a check that was PASSING silently
becomes a check that is not RUN. Measured on this host against the real
225-entry cache root:

    devrc scripts/cairn            frozen-mirror OK
    packaged client, var unset     frozen-mirror NOT-OBSERVABLE
    packaged client, var set       frozen-mirror OK   (byte-identical doctor
                                                       output to the fork)

`NIX_DEPLOY_WHY` in test_cairn_split.py pins that comment paragraph verbatim
and went red on this commit by design; it is updated to the rewritten prose,
not weakened. `test_cairn_is_deployed_out_of_store_not_as_a_store_copy` in
test_cairn_cli.py was the second guard asserting the old truth — it now pins
the package spelling exactly, rather than being loosened to "any deploy mode".

New: scripts/tests/test_cairn_flake_pin.py (8 tests) pins the input, the lock
entry, the absence of a nixpkgs follow (flake.nix AND the lock's own shape),
the thread end to end, the two deploy modes AS ONE RELATIONSHIP, and the
CAIRN_MIRROR_ROOT export.

Red -> green matrix (all 8 red at 65d8bfb, green at HEAD), plus a mutation
kill per guard with each guard's OWN message. Two instrument findings recorded
in the file: the first `follows` guard matched only the dotted spelling and a
block-form mutant walked past it, and `nix develop -c pytest` REWRITES
flake.lock, silently reverting a lock-only mutant before pytest reads it —
scored SURVIVED without ever running.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session-Id: 9662077e-18a9-405d-b4ce-f6697e6fa1bb
…s home.nix alone

Both defects were caught by the authoritative gate, not by review, and neither
was visible from the diff.

🔴 `skills_mapping.py` EVALUATES `nix/home.nix` STANDALONE, and its stub set did
not know about the new argument. Making `cairnPackage` REQUIRED (no default) is
deliberate — a broken thread should be an eval error, not a symlink to
`/bin/cairn` — but nix then refuses to apply the function at all, and the check
reported `nix cannot evaluate /build/src/nix/home.nix`. That message reads as a
verdict on `home.nix` when it is a verdict on the STUB SET, which is the
expensive half: the guard's own text says FIX THE CHECK, do NOT delete it.
`cairnPackage = {}` added, `{}` rather than a string because forcing it in an
interpolation errors instead of silently yielding a plausible path.

⚠ THE COMMENT EXPLAINING THAT DID NOT FIT. `skills_mapping.py` carries a
MAX_MODULE_BYTES = 7_400 ceiling whose own message says an overage is a question
about which ambition crept back, never about raising the number. The file was
7,292 B — 108 of headroom — and the first draft of the comment added 742. It is
now three terse lines (7,361 B, 39 of headroom) and the reasoning lives here
instead. That ceiling is doing its job; do not raise it for prose.

🔴 THE SKILL DESCRIPTION GREW 64 CHARS AND BREACHED A ZERO-HEADROOM RATCHET —
`assert 11256 <= 11192`, plus `MEASURED_ALL_TIER_A_CHARS 11366 != 11430` in
test_skill_tiers.py and a second arm in test_skill_descriptions.py: four
failures, one cause. devrc #1381 already recorded that this ratchet has exactly
zero headroom and kept its edit length-neutral; this one did not.

Fixed length-NEUTRALLY rather than by re-pinning the constants: the fragment
`client `scripts/cairn`` (22 chars) becomes `client `cairn` on PATH` (22 chars),
which is both accurate after the pin and the same length, so every pinned tier
constant stays valid. The deploy detail it wanted to add belongs in the BODY,
where it already is — a description's job is deciding whether the skill loads.

MEASURED after: description 303 chars, unchanged from main; the four guards and
both cairn suites 116 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3KEUsTLLUhS37an52rn28
Claude-Session-Id: 9662077e-18a9-405d-b4ce-f6697e6fa1bb
…th the +8 attributed

12927 carried 149 of SLACK against this tree's 13076. Re-pinned to
13076 - min(50, max(1, 13076/20)) = 13026 — the AUTHORITATIVE gate's own printed
count through the documented rule, AFTER rebasing onto origin/main (01956bf),
per the ORDER note: a floor is a claim about the tree you measured.

THE +8 IS ATTRIBUTED, NOT ASSUMED. The same gate ran on PLAIN origin/main in a
separate detached worktree as the control:
  control (plain main 01956bf)  collected=13068 passed=13048 failed=20
  branch                         collected=13076 passed=13056 failed=20
The delta is exactly `test_cairn_flake_pin.py`'s 8 tests, and all 8 pass.

🔴 BOTH SIDES REPORT failed=20, every one in `test_nebula_relay_apply.py`
(arrived with #1272). Identical on both sides, so main is red on its own and
this branch adds no failure. That control is what makes the collected count
trustworthy despite a red gate — without it, "the reds are someone else's" is a
theory, and a theory that explains a failure is not evidence for it.

⚠ THE KNOWN-RED BASELINE WENT STALE TWICE IN ONE DAY. The `age` escrow/backup
and `opencode` engine 7 that were red this morning are GONE — main fixed them —
and 20 new ones arrived from a different commit. The floor comment says to
re-derive this baseline rather than quote it, for that reason.

Floor sum 20342 -> 20441 (+99); no FATAL from TARGET_FLOORS' two-way pin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3KEUsTLLUhS37an52rn28
Claude-Session-Id: 9662077e-18a9-405d-b4ce-f6697e6fa1bb
ZacxDev added a commit that referenced this pull request Sep 8, 2026
…at claimed novelty it did not have, and a superseded "unpushed" (#1413)

Each of these was a sentence in this doc that had become false, in the exact way
the doc itself keeps warning about.

1. THE STORE BULLET IS CLOSED, so the instruction to close it must stop reading
   as open work. `devrc/cairn`'s `2026-08-29: OPEN:` is now `RESOLVED caec932:`
   via `cairn put` (revision `da318a4c6a96f9d8`), naming the implementing site
   rather than asserting closure: `ATTRIBUTION = " [cairn: {actor}/{session}]"`
   in `scripts/subsystem-store-api/server.py`, appended server-side from the
   authenticating token. The control that it did what it claimed is the index row
   moving `17 nuance / 2 OPEN` to `18 nuance / 1 OPEN` — both dimensions touched,
   not merely bytes landing. The surviving OPEN is a different bullet and was
   deliberately left unverified rather than closed on no evidence.

2. THE STALE-DOC GOTCHA CLAIMED TO BE A DISCOVERY AND IS NOT ONE. `/resume` step
   1 already carries the rule, backed by two older measurements (a 276-line-stale
   handoff, a 692-commit-stale skill file), and `scripts/resume-state.sh` exists
   to prevent it — step 2 orders it BEFORE the read for that reason. This session
   hand-rolled git/gh instead, which step 2 forbids, walked into the trap the tool
   was built to prevent, then wrote it up as new. Correction appended rather than
   the block deleted: the measurement is still true, the framing was wrong.
   When the reconciler was finally run it reported the tree copy stale at 829 vs
   930 lines AND a gap block (`gh answered for 5 of 6 referenced PR(s)`) — a
   distinction a hand-rolled check cannot produce, since it reports a gap as
   nothing at all.

3. RANK 3 IS NO LONGER UNPUSHED. The doc says the other session's work is a local
   commit with no PR; it is now open as devrc #1406, found by the pre-create
   `gh pr list` sweep that step 6 asks for and that the previous PR ran only
   afterwards. The claim is untouched and still theirs.


Claude-Session: https://claude.ai/code/session_01MCjWicwrMAwjGTh3uXsSNT
Claude-Session-Id: 054db069-07b1-4abb-962a-f677e633829f

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ZacxDev and others added 2 commits September 8, 2026 18:04
…ol check, and a guard passed while deploying a dangling symlink

Round-1 adversarial audit of #1406. One 🔴, one 🟡, six 🟢; the two that ship
behaviour are below, each with the measurement that made it a finding rather
than a reading.

🔴 **`cairn validate` is no longer the mandated post-write check, silently and
at exit 0.** After this PR `~/.local/bin/cairn` is the pinned OSS package, which
reimplements `validate` on the READER's resolver instead of shelling
`subsystem_touch.py`. Measured on the built package against the live cache:
**76 bytes and rc 0** against the writer's **5,765 bytes** carrying
`entry shape:`, `marker reachability:` and `dropped lines:` — the last meaning
content is ALREADY LOST. Both are "green"; only one looked. So both skills now
name the writer's own invocation, and `test_subsystem_touch.py`'s pinned-sentence
ledger moves with it — it went RED on the old spelling, which is the mechanism
that caught this. Exit codes differ too and both skills say so: the writer exits
3 on a malformed entry, the packaged client 5 (`EXIT_CORRUPT`; its own 3 is
`EXIT_UNREACHABLE_NO_CACHE`).

🟡 **`test_the_package_is_passed_to_the_home_module_through_extraSpecialArgs` ran
its two checks INDEPENDENTLY over the whole region**, so a decoy satisfied both
while the deploy pointed elsewhere. MEASURED SURVIVED at f98be26:

    cairnPackage = pkgs.hello;
    cairnUnused  = cairn.packages.${system}.cairn;

8 passed, and `home.file.".local/bin/cairn".source` became `${pkgs.hello}/bin/cairn`
— home-manager's `insertFileEntry` does an unconditional `ln -s`, so that BUILDS
and deploys a DANGLING symlink, the exact outcome the required-argument design
claims to prevent. `cairnPackage = pkgs.hello;` ALONE was already killed, so the
guard was narrower than its docstring rather than inert. Now the value assertion
is bound to that name's own right-hand side, plus a `count == 1` binding check so
the asserted binding and the threaded one cannot be different lines.

Also `test_home_nix_REQUIRES_the_package_argument_with_no_default` read the header
as `split("\n", 1)[0]`. A nix module header may legally span lines, so on a CORRECT
tree it failed with "does not accept `cairnPackage`" — a red naming a cause the
tree does not have. It now walks to the `:` that closes the argument set.

`run-tests.sh`'s baseline comment claimed "main is red on its own" as a durable
property. An audit round measured the OPPOSITE at the same commit (30 passed /
0 failed in `test_nebula_relay_apply.py` at 01956bf, hours later). Both readings
are real: that suite reads LIVE HOST STATE, and #1272 shipped the sudo apply
beside the check, so applying the relay flips it with no commit involved. Its
result is keyed to the HOST, not the tree — the comment now says so and says
re-derive, never quote.

Regression matrix, measured both ways at f98be26 (pre-fix) and HEAD:

| mutant | pre-fix | post-fix |
|---|---|---|
| the decoy above | **SURVIVED** (8 passed) | KILLED, on the rhs assertion |
| `cairnPackage = pkgs.hello;` alone | KILLED | KILLED |
| a second `cairnPackage =` binding | n/a (no such check) | KILLED, on `count == 1` |
| home.nix drops the argument | KILLED | KILLED |
| a legal MULTI-LINE header (a CORRECT tree) | **RED — false diagnosis** | green |
| the skill reverts to `cairn validate` | n/a | KILLED, on the pinned sentence |

6/6 killed by their intended guard's own message, `PYTHONDONTWRITEBYTECODE=1`,
every anchor required to match exactly once, tree diffed byte-identical against
the battery's snapshot afterwards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTRPN6dhkdf8kZJch3mne5
Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
@ZacxDev

ZacxDev commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

Round 1 — fixes landed, and the base moved under them

Round-1 adversarial audit read f98be263. Its fixes are f9ff05c4; b79cf63a then merges
origin/main in, because the branch had drifted 3 ahead / 17 behind while the audit ran.

git merge-tree --write-tree exits 0 on that pair — no textual conflict, read by exit
code
, never by grepping for markers, which that command does not emit. But a clean textual
merge is not a clean merge: main had touched SECRETS.md, three scripts/tests/ files and two
skills, all of which share ratchets with this diff. So the gate below was run on the merged
tree
, not on the branch.

The 🔴: cairn validate stopped being the write-protocol check, silently, at exit 0

After this PR, ~/.local/bin/cairn is the pinned OSS package, which reimplements validate on
the reader's resolver instead of shelling subsystem_touch.py. Measured on the built
package against the live cache:

output rc contract blocks
packaged cairn validate 76 B 0 0
subsystem_touch.py --validate 5,765 B 0 entry shape: · marker reachability: · dropped lines:, OK — 31 of 31

Both are "green"; only one looked. dropped lines: is the one that means content is already
lost
. Both skills now name the writer's own invocation, and test_subsystem_touch.py's
pinned-sentence ledger moved in the same commit — it went red on the old spelling, which is
the mechanism working rather than a chore. Exit codes diverge too and both skills say so: the
writer exits 3 on a malformed entry, the packaged client 5 (EXIT_CORRUPT; its own 3
is EXIT_UNREACHABLE_NO_CACHE).

The 🟡: a guard that passed while deploying a dangling symlink

test_the_package_is_passed_to_the_home_module_through_extraSpecialArgs ran its name-check and
its value-check independently over the whole region, so a decoy satisfied both while the
deploy pointed elsewhere. Re-measured this session at f98be263:

cairnPackage = pkgs.hello;
cairnUnused  = cairn.packages.${system}.cairn;

8 passed, and home.file.".local/bin/cairn".source becomes ${pkgs.hello}/bin/cairn.
home-manager's insertFileEntry does an unconditional ln -s, so that builds and deploys a
dangling symlink
— the exact outcome the required-argument design claims to prevent.
cairnPackage = pkgs.hello; alone was already killed, so the guard was narrower than its
own docstring rather than inert; the failure only appears when a decoy carries the string the
second assertion looks for.

Also test_home_nix_REQUIRES_the_package_argument_with_no_default read the header as
split("\n", 1)[0]. A nix module header may legally span lines, so on a correct tree it
failed with "does not accept cairnPackage" — a red naming a cause the tree does not have.

Mutation matrix — measured in both directions, at base and at HEAD

Anchors required to match exactly once (0 or 2 ⇒ INVALID, never a pass), run under
PYTHONDONTWRITEBYTECODE=1, tree diffed byte-identical against the battery's snapshot
afterwards.

mutant at f98be263 at b79cf63a
the decoy above SURVIVED (8 passed) KILLED — "cairnPackage is bound to something other than the cairn input's package"
cairnPackage = pkgs.hello; alone KILLED KILLED
a second cairnPackage = binding (no such check) KILLED — "expected exactly one … found 2"
nix/home.nix drops the argument KILLED KILLED
a legal multi-line header (a CORRECT tree) RED — false diagnosis green
the skill reverts to cairn validate (n/a) KILLED on the pinned sentence

The multi-line row is the reachability control: it is expected LIVE, and it staying green is
what makes the header change a fix rather than a tightening.

Gate — both tiers, on the merged tree b79cf63a

pytests    28/28 targets PASS   collected=21135 passed=21133 skipped=2 failed=0  (floor: 20441)
           scripts/tests        collected=13090 passed=13090 skipped=0  floor=13026
nodetests  suites=5 files=41 tests=1449 pass=1449 fail=0 skipped=0        (floor: 1367)
--check-floors  RESULT: PASS    GLOBAL floor 20441

The 20 test_nebula_relay_apply.py failures quoted in this PR's description do not appear
here, and that is not a fix
— that suite reads live host state (/etc/nebula/ca.crt,
/etc/nixos/configuration.nix), so its result is keyed to the HOST, not to the tree. An audit
round measured 30 passed / 0 failed in that file at 01956bf0, hours after the run that
measured 20 failures at the same commit. run-tests.sh's baseline comment used to assert
"main is red on its own" as a durable property; f9ff05c4 corrects it to say re-derive with a
control run, never quote these numbers
.

Still open — reported, not hidden

  • tekton/devrc-pytests is red on this PR at the now-stale head f98be263, naming
    TestARefusedWriteIsIndistinguishableFromAnAbsentOne.test_POSITIVE_CONTROL_…, a test this
    diff does not touch. It passes locally (5 passed, 739 deselected, 7.09 s) and inside the
    hermetic 13090 above. The tier is not broken — feat(bar): AIO pump + case fan RPM pill, and the staged sudo script that keeps its driver #1411 passed it in the same window at
    collected=21163 failed=0. The run has been pruned (keep: 20 per pipeline, hourly), so
    which assertion fired is unrecoverable. Not diagnosed; the fresh verdict on b79cf63a is the
    next reading.
  • Three 🟢 from round 1 are deferred, not fixed, and tracked as rank 18 of the handoff:
    (a) nix/sessionVariables.nix hardcodes .claude/analyze-service-index, a second .nix
    spelling of subsystem_touch.DEFAULT_STORE_ROOT that test_store_root_ledger.py
    structurally cannot see; (b) the packaged lib/host_identity.py honours CAIRN_HOST and
    devrc's copy does not (dormant — nothing sets it); (c) claude/skills/cairn/SKILL.md's
    "consolidated in a later slice" names no owner. (a) and (b) both disappear if slice 3 lands.

Round 2 has not been run. By the stop rule it is warranted, because round 1 produced
findings that needed fixing.

legend: <from> = the tip THIS round's audit READ · <to> = the head THIS round's FIXES produced. Different shas — <from> is older.

1. Both `cairn` and `subsystem-index` skills no longer name `cairn validate` as the mandated post-write check; they name `subsystem_touch.py --store ~/.cache/subsystem-store --validate --scope <scope>`.
2. `test_subsystem_touch.py`'s pinned-sentence ledger was moved to the new spelling in the same commit, so the module and its only caller cannot drift apart silently.
3. Both skills now state the exit-code divergence: writer 3 on a malformed entry, packaged client 5 (`EXIT_CORRUPT`).
4. `test_the_package_is_passed_to_the_home_module_through_extraSpecialArgs` now binds its value assertion to `cairnPackage`'s own right-hand side via `_assignment`, instead of searching the whole `extraSpecialArgs` region.
5. That same test now asserts exactly one `cairnPackage =` binding exists (`count == 1`).
6. `test_home_nix_REQUIRES_the_package_argument_with_no_default` now walks to the `:` closing the argument set instead of reading only the first line, so a legal multi-line nix header no longer produces a false red.
7. `scripts/run-tests.sh`'s `scripts/tests` floor comment no longer asserts "main is red on its own" as a durable property, and instructs re-deriving the baseline with a control run.
8. `SECRETS.md`'s subsystem-store row no longer says the token is read by `scripts/cairn`; it names the `cairn` client on PATH and records that since 2026-09-08 that is the pinned flake package.
9. `origin/main` was merged into the branch as `b79cf63a`, and both gate tiers were run on that merged tree rather than on the branch alone.

ZacxDev added a commit that referenced this pull request Sep 8, 2026
… and deliberately not marked done, because merged is not live (#1419)

`cairn recall`'s digest told readers to run `--ref <name>` / `--limit N` and the
client exited 2 with `unrecognized arguments`, so a reader following the output
it had just been shown fell back to the raw module.

The fix is not the flags. `main()` derived mode/limit/page AND enforced the
flag-conflict rules inline, while the client reaches the module as a LIBRARY and
never through `main()` — so offering the flags meant open-coding both at a second
site. `recall_selection()` and `reject_recall_flags()` are extracted and called
by both, so `main()` got shorter instead of the wrapper growing a copy. All four
flags wired, not the two the item named: fixing only `--ref` leaves the class
open, the same enumeration-vs-derivation shape rank 12 closed.

Evidence is recorded split rather than totalled. Two tests are RED at base on
their own assertions; a third fails at base with AttributeError and is NOT
counted as regression evidence. Four flags measured live against the real store,
because a passing suite and a working client are different claims.

A defect the change introduced is recorded rather than quietly fixed: exposing
`--limit` made `recall()`'s ValueError reachable from the command line for the
first time, and `--limit 0` printed a traceback at rc 1. Guarded, watched before
and after, reachable by measurement.

Also recorded: the two failures the FULL suite found that a four-test subset did
not — the mutation battery refusing orphaned anchors after the guards moved, and
a TEXT ledger tripping on a comment quoting the callee's name. The second is a
false red, so the comment moved and the guard did not; that ledger cannot tell a
call from a comment, which is noted and not fixed.

🔴 The rank is NOT marked done. Its closing condition named a merged devrc PR and
the fix landed in the OSS client, so `readlink -f ~/.local/bin/cairn` still
resolves to devrc/scripts/cairn and `--ref` is still broken on this host. The
condition is re-pointed at "#7 merged AND #1406 landed AND the pin bumped past
059ec17", so it is checkable again rather than quietly unsatisfiable.

Rank 3 is untouched here: the session that owns it had already recorded #1406
across twelve mentions, and duplicating that would be the drift this doc keeps
paying for.


Claude-Session: https://claude.ai/code/session_01MCjWicwrMAwjGTh3uXsSNT
Claude-Session-Id: 054db069-07b1-4abb-962a-f677e633829f

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ZacxDev

ZacxDev commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Round 2 — delta re-audit of f98be263..b79cf63a

No 🔴. Eight 🟡. The payload is sound: input → lock → extraSpecialArgshome.nix header
→ deploy line is wired correctly, and both of round 1's headline fixes reproduce exactly as
claimed — the decoy SURVIVED at f98be263 (8 passed) and is killed now; the multi-line
header was RED at base with the claimed message and is green now. cairnPackage = pkgs.hello;
alone was already killed at base, confirming the round-1 guard was narrower than its own
docstring
, not inert.

What is weak is the scaffolding round 1 added around those fixes. Five findings were
re-measured independently before being accepted
, not relayed on the auditor's word.

Gate, both tiers, on the merged tree — and two independent runners agree

local  nix build .#checks…pytests    collected=21135 passed=21133 skipped=2 failed=0  (floor 20441)
tekton/devrc-pytests   b79cf63a      collected=21135 passed=21133 skipped=2 failed=0  (floor 20441)
local  …nodetests                    suites=5 files=41 tests=1449 pass=1449 fail=0
tekton/devrc-nodetests b79cf63a      suites=5 files=41 tests=1449 pass=1449 fail=0    (floor 1367)

The earlier red on f98be263 DID NOT REPRODUCE — it is not diagnosed.
TestARefusedWriteIsIndistinguishableFromAnAbsentOne.test_POSITIVE_CONTROL_… passes locally
(5 passed, 739 deselected, 7.09 s) and inside the 13090 above. The tier was never broken (#1411
passed it in the same window). The run that produced it has been pruned (keep: 20 per
pipeline, hourly), so which assertion fired is unrecoverable. Recorded as not-reproducing, not
as fixed.


Being fixed in round 3

🟡1 — the header walk goes VACUOUS · scripts/tests/test_cairn_flake_pin.py:283-292 · scaffolding.
If the bracket-depth counter never returns to 0 the loop falls off the end and header keeps
its initial value — the entire file. Nothing asserts the walk terminated. Reproduced
directly: a legal multi-line header that drops cairnPackage and carries a prose comment
with one unbalanced (8 passed, matching vacuously off the two body occurrences. The
guard written to catch a dropped argument is green while the argument is dropped. Round 1 fixed
a false red and opened a path to a false green. Second half of the same class, also open: any
leading file comment false-reds a correct tree, because lstrip() strips whitespace, not comments.

🟡3 — the moved ledger pin is a SUBSTRING of flags · scripts/tests/test_subsystem_touch.py:1593 · scaffolding.
The pin names flags only; nothing binds them to the writer. Routing those same flags at the
packaged client leaves the suite green (79 passed) — the exact 🔴 round 1 closed, re-opened.
Fix is to pin the whole normalised invocation, per this repo's own rule for prose artifacts.

🟡4 — the new comment carries a diagnosis the merged tree REFUTES · scripts/run-tests.sh:1712-1719 · scaffolding.
Round 1 wrote that test_nebula_relay_apply.py's failures are "keyed to the HOST, not to the
tree."
4f12fcefmerged into this branch by b79cf63a, inside the audited range
establishes the real mechanism: a tier split with a tree cause. apply-nebula-relay.sh
dispatched on a #!/usr/bin/env bash shebang; the nix sandbox has no /usr/bin, so every exec
died bad interpreter and the script reported ABORT … (rc=126). Fixed by a tree change. Round 1
replaced a stale fact with a wrong theory — and the refutation was in a commit the same round
merged in.

The writer-invocation fork, decided by the operator: ship a devrc-only cairn-validate on
PATH — the same seam slice 1 already chose for cairn-who — rather than hardcoding
python3 /home/zach/workspace/devrc/scripts/lib/subsystem_touch.py into the PR whose goal is
decoupling the client from the checkout. That also resolves 🟡6 and shrinks the prose rather than
growing it.


Recorded OPEN BY DECISION — not fixed this round, so they read as open rather than absent

🟡2 — count == 1 false-reds two legal nix spellings, and an inline // override still walks it ·
test_cairn_flake_pin.py:256-266.
^\s*cairnPackage\s*= is line-anchored while the assertion
above it is a plain substring, so they disagree. A one-line extraSpecialArgs = { … }; (legal,
correct deploy) fails with "found 0" immediately after the line above confirms the binding is
present — a self-contradictory red, new in f9ff05c4. And
{ cairnPackage = real; } // { cairnPackage = pkgs.hello; }; on one line → 8 passed, deploying
${pkgs.hello}/bin/cairn, the same dangling-symlink outcome round 1 found. The multi-line form of
that override is killed, so the guard has a real catch; the inline form evades both it and
_assignment's first-occurrence split. Confirmed reachable — it fires with its own message at
0 and at 2.

🟡5 — SECRETS.md:26 states a deployment that has not happened · payload. It says the pinned
package "is" the deployed client and scripts/cairn is "no longer deployed". Measured now:
readlink -f ~/.local/bin/cairn/home/zach/workspace/devrc/scripts/cairn. True only after
merge and a home-manager switch on each host — and that row's own scope column is both
(workbench + laptop)
, a second switch nothing in this PR forces. This is "deployed ≠ verified"
written into the tree as done, in the file read during a credential incident.

🟡7 — the skill budget · claude/skills/subsystem-index/SKILL.md. 40,991 B → 42,269 B
against HARD = 40_960 (scripts/skill-audit.py:168): 31 B over became 1,309 B over, in the
commit whose job was to fix a doc. Round 3 shrinks it as part of the cairn-validate change.
🔴 HARD is exercised only against tmp fixtures, never against the tree, so no gate goes red
on this — "all skill gates green" is a much narrower claim than it reads. Merge-brought, not this
PR's authorship: claude/skills/handoff/SKILL.md arrived from main at 26,066 B against an enforced
26,100 — 34 B of headroom, so the next commit to touch it reds a gate that will blame the
wrong change.

🟡8 — the pinned package's own remedy string is unrunnable · upstream lib/subsystem_recall.py.
On the 🔴 MALFORMED — path devrc prints check a file with `subsystem_touch.py --validate <path>` ;
the pinned package prints check a file with `a writer --validate <path>` — the extraction scrub.
Exit codes unchanged, only the human-facing remedy destroyed. This lives in ZacxDev/cairn, not
devrc
, so it cannot be fixed here.

Second-order — rank 16, and it is the structural indictment of round 1's fix. Nothing in
devrc's gate ever executes the deployed cairn; every cairn guard reads flake.nix /
flake.lock / nix/home.nix / sessionVariables.nix as text. That is why the validate
regression stayed invisible through all 13,076 tests — and round 1 answered a runtime 🔴 with
more text pins. test_cairn_cli.py::TestValidateActuallyRuns runs validate against
scripts/cairn, the script nobody will run after this merges, and stays green while the deployed
client's validate has no coverage at all. Round 3's cairn-validate guard is required to be
behavioural, which is a partial answer; rank 16's own closing condition is not met by this PR.

Rank 15 is neither closed nor regressed by this PR. cairn recall --ref exits 2; the lock pins
9213726 and the upstream fix is 059ec17, two commits later. The flag surface of scripts/cairn
and the pinned client is byte-identical (diff of all add_argument lines: empty).


Ledger — payload attribution, round 2

payload      3 files  +32 / −3    SECRETS.md, skills/cairn, skills/subsystem-index
scaffolding  3 files  +65 / −11   test_cairn_flake_pin.py, test_subsystem_touch.py,
                                  run-tests.sh (comment-only)
TOTAL        6 files  +97 / −14   payload = 33% of added lines

Merge b79cf63a contributes 22 files / +2,906 / −323 — origin/main's work, not attributed to
this round.

Could not verify, stated plainly: the exact 5,765 B / 76 B figures were not re-derived
against the 31-entry scope (direction confirmed from source — subsystem_touch.main vs
subsystem_resolver.load_index — and the writer measured live at 1,801 B / rc 0 / 3 blocks on a
3-entry scope); nothing about the laptop host or whether CAIRN_MIRROR_ROOT reaches a
non-interactive shell there, since that guard is textual only.

Ladder status: this round produced findings that need fixing, so it does not end the ladder.

ZacxDev and others added 2 commits September 8, 2026 19:55
…ble, and a comment refuted by a commit in its own merged tree

Round-2 delta audit of `f98be263..b79cf63` returned no 🔴 and eight 🟡. Three of
them were defects in round 1's own fix round; this closes those three, plus the
operator's decision on the writer-invocation fork. The other five are recorded on
the PR as open-by-decision.

🔴 **The header walk fell back to the WHOLE FILE and nothing said so.** Round 1
replaced `split("\n", 1)[0]` — which false-RED a legal multi-line header — with a
bracket walk that, when the depth never returned to 0, simply ran off the end
leaving `header` at its initial value: the entire file. `cairnPackage` occurs twice
in the module BODY, so `THREADED_NAME in header` then passed while the argument was
dropped from the header entirely. MEASURED at `b79cf63a`: a legal multi-line header
that drops `cairnPackage` and carries one unbalanced `(` in a prose comment leaves
the suite at **8 passed**. Fixing a false red opened a path to a false green.
`_module_header()` now skips `#`/`/* */` comments and `"…"`/`''…''` strings so none
of them carry depth, decides "opens with an argument set" on the first CODE token
rather than `lstrip()` (which strips whitespace, not comments, and false-RED any
file with an explanatory line above its header), and **raises** rather than falling
back.

🔴 **The moved ledger pin named FLAGS, so it was walkable back to the defect it
guarded.** `--store … --validate --scope <scope>` bound nothing to the writer.
MEASURED at `b79cf63a`: routing those same flags at the packaged client leaves the
suite **green at 79 passed** — round 1's 🔴, fully re-opened. The pin is now the
whole normalised invocation, `cairn sync && cairn-validate --scope <scope>`, with
whitespace runs normalised on both sides so a rewrap is not read as a deletion.

🔴 **The `run-tests.sh` comment asserted a diagnosis that `4f12fcef` refutes — and
`4f12fcef` is an ancestor of HEAD but NOT of round 1's commit**, so round 1 wrote
its theory before the refutation existed. It said `test_nebula_relay_apply.py` is
"keyed to the HOST, not to the tree". It was a TIER split with a TREE cause:
`apply-nebula-relay.sh` dispatched on a `#!/usr/bin/env bash` shebang, the nix
sandbox has no `/usr/bin`, every exec died `bad interpreter`, and the script
reported `ABORT … (rc=126)` while the dev-host tier stayed green. Retracted in
place, cross-referenced to this file's own tier notes. Comment-only — verified by
`git diff -U0 | grep -v '^[+-]\s*#'` being empty. Re-measured: 30 passed / 0 failed
on the dev-host tier at `b79cf63a`.

**`cairn-validate` ships, on the `cairn-who` seam** (operator decision). The write
protocol has to name the writer, and the only spelling that ran was an absolute
`python3 /home/…/devrc/scripts/lib/subsystem_touch.py` — a checkout path baked into
a protocol whose point is that agents work in other repos; `cairn/SKILL.md` spelled
it bare, which is not on PATH and exits 127. The launcher declares no parser: two
defaults are PREPENDED to the caller's argv, because argparse's last-occurrence-wins
gives the caller the override for free while a scan for an existing `--store` would
be a partial re-copy of argparse's rules. `mkOutOfStoreSymlink`, not a store copy —
`.resolve()` must land beside `scripts/lib/`, and no package ships the writer.

⚠ **Round 1's own figure was superseded by re-measuring rather than carried.** Both
clients, same scope, same moment: the packaged `validate` writes **0 bytes to
stdout** (77 B of banner on stderr) and exits 0; the writer writes **5,766 B** with
all three contract blocks. "76 bytes of output" understated it — a caller reading
stdout gets NOTHING. Every citation of the pair now says so.

Regression matrix, red at `b79cf63a` / green at HEAD, on the REAL `nix/home.nix`:
header drops the argument + unbalanced `(` in a comment → **8 passed (vacuous
green)** → RED with `does not accept 'cairnPackage'`; leading file comment on a
correct tree → **RED (false diagnosis)** → 11 passed. Plus 8 new tests red at base
with their own messages.

Mutation battery, `PYTHONDONTWRITEBYTECODE=1`, every anchor asserted to match
exactly once, tree restored between mutants. 11 mutants, 11 killed by their intended
guard's own message. ⚠ **A-M2 (reinstate the whole-file fallback) SURVIVED on the
first attempt and is reported rather than hidden**: the vacuous-case fixture closes
correctly once comments stop carrying depth, so it never reached the fall-off-the-end
branch — an unreachable guard. `test_an_UNCLOSED_argument_set_…` was added with a
header that has no closing `}` at all, a case no earlier assertion rejects, and the
mutant then died. B3 is a control: a cosmetic rewrap of the pinned command stays
green, so the normalisation is doing work rather than the pin being brittle.
D-M2 swaps `--validate` for `--census` and dies on the contract-block assertion —
the case a structural check type-checks straight past.

`claude/skills/subsystem-index/SKILL.md` 42,269 → **41,591 B** (`HARD = 40_960`).
678 B cut. ⚠ Under the cap is arithmetically unreachable from round 1's block alone:
the file was already 31 B over before round 1 touched it, so deleting that block
entirely lands at 40,991. The residue is pre-existing prose — 🟡7, out of scope.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTRPN6dhkdf8kZJch3mne5
Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
ZacxDev added a commit that referenced this pull request Sep 9, 2026
…sured BLOCKED on #1406 because

Claude-Session-Id: 054db069-07b1-4abb-962a-f677e633829f
@ZacxDev

ZacxDev commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Round 3 — the fix round for round 2's three scaffolding defects, plus the writer-invocation decision

Round 2 read b79cf63a; these fixes are 6ae94c01, re-merged onto current main as 4b27c63c
(main moved 6 more commits mid-round, including a skills refactor that shares the ratchets
this diff touches — so the gate was re-run on the new merged tree rather than the old one).

What was wrong, and it was mine

🟡1 — round 1 fixed a false RED and opened a path to a false GREEN. The bracket walk fell off
the end when depth never returned to 0, leaving header at its initial value: the whole file.
cairnPackage occurs twice in the module body, so the assertion passed vacuously.

🟡3 — the ledger pin named FLAGS, binding nothing to the writer, so the mandated check could be
re-routed at the packaged client with the suite green.

🟡4 — the comment asserted a diagnosis 4f12fcef refutes. Verified: 4f12fcef is an
ancestor of HEAD and is not an ancestor of round 1's f9ff05c4 — so round 1 wrote its theory
before the refutation existed in the branch. It was a tier split with a tree cause
(#!/usr/bin/env bash dispatch; no /usr/bin in the nix sandbox; ABORT … rc=126), fixed in the
tree. Retracted in place. Hunk verified comment-onlygit diff -U0 | grep -v '^[+-]\s*#' is
empty, bash -n clean. Re-measured: 30 passed / 0 failed on the dev-host tier at b79cf63a.

Regression matrix — on the REAL nix/home.nix, not a fixture

at b79cf63a at HEAD
header drops cairnPackage + unbalanced ( in a prose comment 8 passed — vacuous green RED: does not accept `cairnPackage`
leading file comment, header otherwise correct RED — false diagnosis 11 passed
same flags routed at the packaged client green, 79 passed KILLED on the pinned invocation
cairn validate restored, writer demoted to an aside green, 79 passed KILLED, same message

Plus 8 new tests red at base with their own assertion messages.

Mutation battery — 11 mutants, 11 killed, and one that had to be earned

PYTHONDONTWRITEBYTECODE=1, every anchor asserted to match exactly once, tree restored between
mutants.

A-M2 (reinstate the whole-file fallback) SURVIVED on the first attempt — reported, not
hidden.
Once comments stop carrying depth the vacuous-case fixture closes correctly, so it never
reaches the fall-off-the-end branch: an unreachable guard, green for the wrong reason. A third
test with a header that has no closing } at all — a case no earlier assertion rejects — was added,
and the mutant then died.

B3 is a control in the other direction: a cosmetic rewrap of the pinned command across three
lines stays green, so the whitespace normalisation is doing work rather than the pin being
brittle. D-M2 swaps --validate for --census and dies on the contract-block assertion — the
case a structural check type-checks straight past.

cairn-validate — the operator's call on the writer-invocation fork

The write protocol has to name the writer, but the only spelling that ran was an absolute
python3 /home/…/devrc/scripts/lib/subsystem_touch.py — a checkout path baked into a protocol
whose point is that agents work in other repos — and cairn/SKILL.md spelled it bare, which is
not on PATH and exits 127. So it ships on the cairn-who seam: mkOutOfStoreSymlink (not a
store copy — .resolve() must land beside scripts/lib/, and no package ships the writer), and a
launcher that declares no parser, prepending its two defaults to the caller's argv because
argparse's last-occurrence-wins gives the caller the override for free.

🔴 Three of its four guards EXECUTE the binary, deliberately: rank 16's standing point is that
nothing in devrc's gate ever runs the deployed client, which is why the original validate
regression survived 13,076 green tests. Answering a runtime defect with more text pins is what
round 1 did.

Round 1's own figure was superseded by re-measuring rather than carried forward. Both clients,
same scope, same moment: the packaged validate writes 0 bytes to stdout (77 B of banner on
stderr) and exits 0; the writer writes 5,766 B with all three contract blocks. "76 bytes of
output" understated it — a caller reading stdout gets nothing.

The round-2 open item that is now attributable — with a control

Round 2 recorded tekton/devrc-pytests failing at f98be263 on
TestARefusedWriteIsIndistinguishableFromAnAbsentOne.test_POSITIVE_CONTROL_… as not diagnosed,
because the run had been pruned. It now has a discriminator: PR #1417 failed on the same
assertion, and #1417 changes exactly one file — a markdown handoff doc.
A docs-only diff cannot
break a server-API test. Two PRs, disjoint diffs, one failing test ⇒ the failure is in the tier,
not the tree. Still not a root cause, but it is no longer attributable to this change.

Skill budget — the honest arithmetic

claude/skills/subsystem-index/SKILL.md 42,269 → 41,591 B against HARD = 40_960. 678 B cut.
⚠ Under the cap is arithmetically unreachable from round 1's block alone: the file was already
31 B over before round 1 touched it, so deleting that block entirely lands at 40,991. The residue is
pre-existing prose — 🟡7, out of scope.

Noticed and NOT fixed this round — reported so they read as open

  1. claude/skills/resume/SKILL.md:128 carries the same bare subsystem_touch.py (exit 127)
    defect, in a third file; :150 carries the absolute-path spelling. Neither is pinned by any test.
  2. subsystem_touch.validate_command() still emits the absolute checkout-path spelling in the
    RECOVER — block the skill tells writers to run verbatim.
  3. claude/skills/cairn/SKILL.md:89-92 carries the same false deployment tense as SECRETS.md.
  4. The prose pin cannot distinguish "mandated" from "merely mentioned" — an adversary who demotes
    the command to an aside while keeping the full string intact survives it. Killing that needs
    a positional assertion no pin in that ledger makes.
  5. cairn/SKILL.md's frontmatter description does not list cairn-validate, so the new binary
    has no routing keyword. 🟢.

Not verified: nothing here is measured against a switched host — readlink -f ~/.local/bin/cairn is still /home/zach/workspace/devrc/scripts/cairn and cairn-validate is not
on PATH. Every sentence written this round is conditioned on home-manager switch. The laptop
is a second, independent switch that nothing in this PR forces.

legend: <from> = the tip THIS round's audit READ · <to> = the head THIS round's FIXES produced. Different shas — <from> is older.

1. `_module_header()` raises instead of falling back to the whole file when the argument set is never closed, so the caller can no longer pass vacuously while `cairnPackage` is absent from the header.
2. `#`/`/* */` comments and `"…"`/`''…''` strings no longer contribute bracket depth to that walk.
3. "Opens with an argument set" is decided on the first CODE token instead of `lstrip()`, so a leading file comment no longer false-reds a correct tree.
4. The `test_subsystem_touch.py` ledger pins the whole normalised invocation `cairn sync && cairn-validate --scope <scope>` instead of a flag fragment, with whitespace runs normalised on both sides.
5. `scripts/run-tests.sh`'s floor comment retracts the "keyed to the HOST, not the tree" claim and states the tier/tree mechanism from `4f12fcef`; the hunk is comment-only.
6. `scripts/cairn-validate` is added as a launcher that declares no parser and passes the writer's exit codes through untranslated.
7. `nix/home.nix` deploys `cairn-validate` as a `mkOutOfStoreSymlink`, not a store copy.
8. Three of the four new `cairn-validate` guards execute the real binary rather than reading text.
9. Both `cairn` and `subsystem-index` skills name the same command, `cairn-validate --scope <scope>`; the bare `subsystem_touch.py` and absolute-path spellings are gone from those two files.
10. `claude/skills/subsystem-index/SKILL.md` shrank 42,269 → 41,591 B.
11. Every citation of the two clients' output now states 0 bytes on stdout / 77 B on stderr, replacing round 1's "76 bytes of output".

ZacxDev and others added 2 commits September 8, 2026 20:32
… job, and a guard blind to the tier it runs in

The merged-tree gate on `4b27c63c` came back `failed=3`, all three from round 3's
own additions and none from `origin/main`. Each is a different lesson.

🔴 **`test_store_root_ledger` went red because `cairn-validate` is a NEW router
through `subsystem_read_store` — that is the seam guard WORKING**, not an
obstacle. Its ledger fails when the set of routers GROWS as well as when it
shrinks, precisely so a new reader cannot quietly start answering "where do I
read?" for itself. A row was added saying what it reads and why: the launcher
routes here for the SAME reason the ledger's three historical regressions
existed — `subsystem_touch`'s own `--store` default is the FROZEN pre-cutover
mirror, so a launcher that inherited it would parse the PRE-write bytes.

🔴 **`test_cairn_validate_defaults_its_store_to_the_SYNCED_CACHE_not_the_mirror`
was structurally incapable of passing in the sandbox tier, and green on the dev
host is what hid it.** It asserted `f"store: {expected}"` on STDOUT. That holds
where the cache exists and the tool takes its success path; the `nix build`
tier's `$HOME` is `/build/home` and carries no `~/.cache/subsystem-store`, so
the tool exits down the not-found path and names the resolved root on STDERR
instead. The claim is WHICH store the launcher chose, never whether one exists —
so it belongs on the combined output. Pinning it to one stream made a guard that
could only ever be green in one of the two tiers this suite runs in.
⚠ Round 3 said of these tests: *"I believe they are sandbox-safe, but that is
reasoning, not a measurement."* It was reasoning, and it was wrong.

MEASURED AT TWO POINTS, because one is not a general claim: green with a real
cache root, and green under a `$HOME` verified to have none. The mutant that
drops the `--store` prepend is KILLED at BOTH, on this guard's own message —
previously the negative half did not exist at all, so a launcher that inherited
the writer's default could have passed whenever both paths were printed. It is
now asserted explicitly: the frozen mirror's path must NOT appear.

🔴 **`test_runtime_shebangs` flagged a spelled `"#!"` in the new launcher test.**
Rather than register a string in its allowlist — which that file reserves for
sites solving the problem a different, VERIFIED way, not for going green — the
assertion now pins the RELATIONSHIP: `cairn-validate`'s interpreter line must
equal `cairn-who`'s. Both are `mkOutOfStoreSymlink` launchers invoked as bare
commands from PATH, so they must agree on how they find an interpreter, and
asserting one in isolation would pass while the two drifted apart. The literal
disappears as a consequence rather than as the goal.

112 passed across the three affected suites; mutation control restored
byte-identical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTRPN6dhkdf8kZJch3mne5
Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
@ZacxDev
ZacxDev merged commit 9300f23 into main Sep 9, 2026
2 checks passed
@ZacxDev
ZacxDev deleted the feat/cairn-flake-pin branch September 9, 2026 01:56
ZacxDev added a commit that referenced this pull request Sep 9, 2026
…nfetched worktree — #1406 is ME

Claude-Session-Id: 054db069-07b1-4abb-962a-f677e633829f
ZacxDev added a commit that referenced this pull request Sep 9, 2026
…tion is still only HALF met (#1425)

* docs(handoff): rank 3 slice 2 MERGED as devrc #1406 squash 9300f23 and verified by content; three a

Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9

* docs(handoff): the recurring CI intermittent finally carried its evidence — a socket read TimeoutErr

Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9

* docs(handoff): the CI intermittent is DIAGNOSED as SERVER_BLOCKED_IN_FSYNC by the MECHANISM= line th

Claude-Session-Id: 50c86165-b6c3-47d8-9fd7-14e70bb637a9
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