infra's scripts/context-sync.sh is the estate canonical, and it moved in infra
262369b (a SIGPIPE fix on the placeholder-reporting path: `printf | grep -o |
head -1` became `head -1 < <(grep -o ...)`). Every other repo still carried the
old line, so ContextSyncScriptDrift and ContextAdapterDrift were both firing.
Also picks up the canonical AGENT.md change from local-dev a01ee80 — rule 5's
GitOps review lane and the new precedence rule — which every repo's adapters
need regenerated for regardless of the script.
Refs mathias/infra#470
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses the blocking finding from the review of this PR.
The harness matched golangci-lint's human-readable summary to decide pass or
fail, and discarded its exit status. Any failure that is not "found issues" --
bad config, unwritable TMPDIR, OOM, a future change to the output format --
produces non-matching text and was scored `ok`.
Since this harness is the only gate covering cmd/__PROJECT_NAME__, a linter
that dies would have left the entrypoint unchecked with CI green. That is the
precise defect class this file was added to end, which is why it blocked the
PR rather than being filed as a follow-up.
golangci-lint exits 0 clean / 1 issues found / >1 the linter itself failed.
Now graded on that, and the >1 case reports the child as UNCHECKED rather than
clean.
Two more from the same review:
- a missing tool now fails instead of `exit 0` with zero assertions, which
was indistinguishable from a real pass to anything reading the exit code.
It was unreachable in CI only by luck of task ordering, not by rule.
- Dockerfile joins the substituted file set. It builds ./cmd/__PROJECT_NAME__
and was outside the pattern, so the harness never validated the one path a
repo rename has historically broken here.
Verified by flipping each case:
crashing linter (exit 3) -> FAIL "the child is UNCHECKED, not clean"
tools absent -> FAIL, 0 passed
normal -> 5 passed, 0 failed
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Closes#12.
The guard that stops this template building itself also stopped it TESTING
itself: check, build and deploy were all gated on is_template, which is always
true here. So the repo that mints every other repo was the one repo with no
working gate — and #8 sat in it for months with CI green throughout, found
eventually by a child rather than by us.
check is now ungated. build and deploy stay gated, because they genuinely
cannot work here: placeholder module path, no image name, no namespace.
Ungating alone would have been a false fix. `go build ./...`, `go vet ./...`,
`go test ./...` and `golangci-lint run ./...` cannot see cmd/__PROJECT_NAME__
at all — Go skips directories whose names begin with an underscore when
expanding package patterns:
$ go list ./...
__MODULE_PATH__/internal/web <- no cmd package
So a newly-ungated check would still have skipped the package every generated
repo is built around.
scripts/tests/generated-child_test.sh substitutes the tracked tree into a
throwaway child and gates the result: templ generate, go list, build, vet,
golangci-lint. Ported from template-go-agent, plus a templ step, which also
proves the pinned generator and pinned library agree.
Proven to fail when it should. With a deliberate errcheck violation added to
the entrypoint:
generated-child harness -> FAIL cmd/childproj/main.go:12:26 errcheck
golangci-lint run ./... -> "0 issues."
The existing gate calls the same broken code clean. That contrast is the
reason this harness exists rather than a wider lint invocation.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Closes#9. Closes#10.
Every child repo born from this template has had fake-green CI: cd.yml's
guard grepped a literal placeholder, and both scaffolders substitute every
file in the tree -- including the guard. In a generated repo the check
became `grep -q 'git.d-ma.be/mathias/<name>' go.mod` against a go.mod whose
first line is `module git.d-ma.be/mathias/<name>`, so it matched forever,
check/build/deploy all skipped, and the run reported success having built
nothing. Confirmed in cad-atlas (#9) and openbanking-api (#10).
The second occurrence landed directly underneath a comment warning against
exactly this. That is the tell: an inline shell block in a workflow cannot
be tested, so a fix for it can only be reviewed by reading, and reading is
what missed it twice.
So the detection moves to scripts/is-template.sh and gets a test.
It greps the SHAPE of a placeholder rather than any literal token, which
also catches leftovers the scaffolders know nothing about, and a missing
target now exits non-zero instead of answering "false" -- failing open
there would skip CI on a repo that is not a template at all, which is the
same fake-green failure by another road.
scripts/tests/is-template_test.sh runs a scaffolder-style substitution over
a copy of the guard and asserts it still answers correctly. Both shipped
bugs fail that test.
The test assembles placeholder tokens at runtime rather than writing them
whole, for the same reason the guard does: a fixture containing a literal
token is substituted before the test runs, and the suite would then fail in
every generated repo while passing here. The first draft of the guard was
itself caught by this -- its explanatory comment named a token literally.
Verified by simulating a generated child (whole tree substituted):
child go.mod module git.d-ma.be/mathias/childproj
guard child -> false (CI runs)
guard template -> true (template still skips its own build)
suite in child -> 8 passed, 0 failed
suite in template -> 8 passed, 0 failed
Wired into `task check`, so the guard that decides whether CI runs at all
in every child is covered by the same gate as the Go tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Caught by the new estate-wide context-sync-drift gate (infra, ADR-0019).
This repo's copy had diverged from the canonical established in dma-cli/
infra -- synced to it, dead Cursor/Aider artifacts removed (2026-09-01
harness decision), Taskfile's drift assertion narrowed to match, adapters
regenerated against the current canonical AGENT.md.
Changed:
D .aider.conf.yml
D .aider.conventions.md
M .context/system-prompt.txt
D .cursorrules
M AGENTS.md
M Taskfile.yml
M scripts/context-sync.sh
Refs: ADR-0019 (infra)