Summary
ci-pipeline.yml's Nickel job selects files with
mapfile -d '' FILES < <(git ls-files -z -- '*.ncl')
... nickel format --check "$f" ...
... nickel typecheck "$f" ...
That glob is wrong in two independent ways. Measured against rsr-template-repo
@ HEAD, 20 of its 29 tracked *.ncl files cannot pass this gate no matter
what the repository does.
| bucket |
count |
can pass? |
*.k9.ncl — k9 contract files |
18 |
never — not Nickel source |
*.ncl importing generated JSON |
2 |
never standalone |
genuine self-contained *.ncl |
9 |
yes |
Defect A — *.ncl matches *.k9.ncl, which is not Nickel
k9 contract files share the .ncl suffix but are a different format. They
open with a K9! sentinel on line 1:
$ head -1 .machine_readable/arrival-pack/claude-md.k9.ncl
K9!
$ nickel typecheck claude-md.k9.ncl
error: unexpected token
┌─ claude-md.k9.ncl:1:3
│
1 │ K9!
│ ^
Sampled 12 of the 18 *.k9.ncl in the template: 12/12 begin with K9!.
Both nickel typecheck and nickel format --check fail on every one, forever.
The estate already validates these separately — cicd-squabbler runs a
Validate K9 contracts check, which passed on the same commit where this gate
failed.
Defect B — typechecking projections over generated inputs
arrival-pack.ncl and coaptation/coapt.ncl import JSON that is a build
artifact, correctly uncommitted. The template ships the generator, and
generate.sh lines 16–17 make the order explicit:
bash "$AP/extract.sh" .../descriptiles > "$AP/claude-md-data.json"
nickel export --format raw "$AP/arrival-pack.ncl" > "$AP/.region.tmp"
Typechecking them standalone yields
import of claude-md-data.json failed: could not find import. The files are
correct by design; the gate's assumption that every .ncl is self-contained is
what is wrong.
Evidence this is not hypothetical
The 5-repo dry-run wave (#976) produced exactly one subject whose pipeline
actually ran: cicd-squabbler (run 35726516904, job pipeline / Nickel,
runner 1002435839). It went red — and every failing file was one of these
two buckets, none of its own source:
arrival-pack/arrival-pack.ncl Bad format + typecheck (generated import)
arrival-pack/claude-md.k9.ncl Bad format + typecheck (K9! sentinel)
coaptation/coapt.ncl Bad format + typecheck (generated import)
coaptation/coapt.k9.ncl Bad format + typecheck (K9! sentinel)
So the one repo that reached the gate was failed entirely by the gate's own
blind spot. Per this repo's own doctrine a gate that fails for a reason the
repository cannot fix misleads exactly as much as one that passes vacuously.
⚠ This is why .machine_readable/pipeline-allow.txt has not been seeded from
that wave: the only earned red is not the repository's debt.
Separately: a real template bug, not this gate's fault
nickel format --check fails on the template's own current revision of
arrival-pack.ncl (reproduced locally, nickel 1.17.0, rc=1). The 9 genuine
.ncl files should be formatted and kept that way. That belongs to
rsr-template-repo; it is not a reason to keep the glob wrong.
Acceptance criteria
Summary
ci-pipeline.yml'sNickeljob selects files withThat glob is wrong in two independent ways. Measured against
rsr-template-repo@ HEAD, 20 of its 29 tracked
*.nclfiles cannot pass this gate no matterwhat the repository does.
*.k9.ncl— k9 contract files*.nclimporting generated JSON*.nclDefect A —
*.nclmatches*.k9.ncl, which is not Nickelk9 contract files share the
.nclsuffix but are a different format. Theyopen with a
K9!sentinel on line 1:Sampled 12 of the 18
*.k9.nclin the template: 12/12 begin withK9!.Both
nickel typecheckandnickel format --checkfail on every one, forever.The estate already validates these separately —
cicd-squabblerruns aValidate K9 contractscheck, which passed on the same commit where this gatefailed.
Defect B — typechecking projections over generated inputs
arrival-pack.nclandcoaptation/coapt.nclimport JSON that is a buildartifact, correctly uncommitted. The template ships the generator, and
generate.shlines 16–17 make the order explicit:Typechecking them standalone yields
import of claude-md-data.json failed: could not find import. The files arecorrect by design; the gate's assumption that every
.nclis self-contained iswhat is wrong.
Evidence this is not hypothetical
The 5-repo dry-run wave (#976) produced exactly one subject whose pipeline
actually ran:
cicd-squabbler(run35726516904, jobpipeline / Nickel,runner
1002435839). It went red — and every failing file was one of thesetwo buckets, none of its own source:
So the one repo that reached the gate was failed entirely by the gate's own
blind spot. Per this repo's own doctrine a gate that fails for a reason the
repository cannot fix misleads exactly as much as one that passes vacuously.
⚠ This is why
.machine_readable/pipeline-allow.txthas not been seeded fromthat wave: the only earned red is not the repository's debt.
Separately: a real template bug, not this gate's fault
nickel format --checkfails on the template's own current revision ofarrival-pack.ncl(reproduced locally, nickel 1.17.0, rc=1). The 9 genuine.nclfiles should be formatted and kept that way. That belongs torsr-template-repo; it is not a reason to keep the glob wrong.Acceptance criteria
*.k9.nclfrom bothformat --checkandtypecheck(they have their own validator)..nclare either generated first or excluded fromtypecheckby a declared, in-repo mechanism — never silently skipped.format --checkstill runs over every genuine.ncl; the fix narrows thefile set, it does not weaken the check.
files checked: N) and refuses whenthe surviving set is empty, so narrowing cannot create a vacuous pass.
cicd-squabbler: any remaining red is genuinely its own.