Skip to content

Keep an experiment's code out of the commands the gate runs - #129

Merged
iderex merged 1 commit into
mainfrom
scaffolding/what-the-gate-reads-of-an-experiment
Aug 12, 2026
Merged

Keep an experiment's code out of the commands the gate runs#129
iderex merged 1 commit into
mainfrom
scaffolding/what-the-gate-reads-of-an-experiment

Conversation

@iderex

@iderex iderex commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Closes #122

What this changes

Every command this repository is gated by now names the runner's two roots
rather than the whole module: ./cmd/... ./internal/... where a command takes
a package pattern, and cmd internal where gofmt takes directories. The guide,
the build and test workflow and the headless workflow all run the same strings.
CodeQL moves from autobuild to a manual build of the same two roots.

docs/decisions/0017-what-the-gate-reads-of-an-experiment.md is the record. It
supplies the mechanism that record 0009 decided the property for, names the
three options it was chosen over, and says what each of those would have cost.

What failure it prevents

Record 0009 says nothing that runs on its own builds or executes anything
under experiments/. It named no mechanism, and an experiment lives inside
this module, so the sentence was true of the intention and not of the tree.

The failure that shape produces is the one 0009 was written against. A
prototype abandoned half-written holds the board red on six platforms it was
never about, and the two ways out of a red board are deleting the evidence or
rewriting the answer. Both destroy what the record exists to preserve.

What was run

At the commit being pushed, 24723778bdcdae1b52d7886cab8cc5cc2c5a389e.

The state before, on origin/main at 9807dc7:

git rev-parse HEAD
9807dc783b9b981b652bdf00ac1e1467171a1051
go list ./...
github.com/Flowfin/lab/cmd/lab
github.com/Flowfin/lab/cmd/pullrequest
github.com/Flowfin/lab/experiments/reading-a-tree-of-records
github.com/Flowfin/lab/internal/check
github.com/Flowfin/lab/internal/hardware
github.com/Flowfin/lab/internal/invariants
github.com/Flowfin/lab/internal/prose
github.com/Flowfin/lab/internal/pullrequest

The four commands the guide asks for, at this commit:

go build ./cmd/... ./internal/...
(no output)
go vet ./cmd/... ./internal/...
(no output)
gofmt -l cmd internal
(no output, exit 0)
go test -count=1 -v ./cmd/... ./internal/...
ok      github.com/Flowfin/lab/cmd/lab  2.035s
ok      github.com/Flowfin/lab/cmd/pullrequest  1.697s
ok      github.com/Flowfin/lab/internal/check   1.365s
ok      github.com/Flowfin/lab/internal/hardware        1.104s
ok      github.com/Flowfin/lab/internal/invariants      1.913s
ok      github.com/Flowfin/lab/internal/prose   0.897s
ok      github.com/Flowfin/lab/internal/pullrequest     0.885s

The suite executed 93 top-level tests, skipped none, and printed the
integration-hardware disclosure once, which is what the two workflow jobs count:

grep -cE '^--- (PASS|FAIL): ' suite.log
93
grep -cE '^--- SKIP: ' suite.log
0
grep -cF 'integration-hardware harness was not asked for' suite.log
1

The record checks:

go run ./cmd/lab check .
examined .
1 experiment directory walked, 1 record read
18 decision records read
the time this run read is 2026-08-12T06:06:38Z
0 refused

The command the rejected options would have broken, run at this commit from the
root of a checkout. It is written twice in an answered record, and it still
resolves and still reports its three numbers:

go run ./experiments/reading-a-tree-of-records
windows/amd64, go1.26.5
1000 experiments, 1108000 bytes of records, 7 rounds
walking the directories:        17.5107ms
walking and reading every file: 51.8613ms
reading costs 2.96 times the walk

That is one machine and one platform, and the numbers are not the point here.
Whether the command resolves at all is.

The CodeQL change is the one thing above that was not run locally. Manual build
mode is exercised by this pull request's own run and nowhere else, and if that
check goes red the change is wrong rather than the check.

What this does not do

It refuses nothing new. The mechanism is a pattern in five files, and a Go file
at the root of the tree, or under a root directory the layout names that is
neither cmd/ nor internal/, sits outside all of them with nothing to say so.
root-holds-a-directory-the-layout-does-not-name refuses a new root directory,
so what escapes is a package added under a directory already named. That hole is
written into the record rather than left to be found, and it is smaller than the
one being closed rather than absent.

It does not change what the record checks read. Reading an experiment's record
as text is 0009's own carve-out and is untouched.

It takes nothing back from 0009 and it does not decide anything that record
left to its own reopening condition.

Nobody else has read this change. What stands behind it is the evidence above
rather than a second reader.

Record 0009 decided that nothing which runs on its own builds or executes
anything under experiments/. It named no mechanism, and every command in
the guide and in the workflows walked the whole module, so the sentence
was true of the intention and not of the tree. At 9807dc7 `go list ./...`
returned the experiment's package next to the runner's seven, and six
build entries, three suite entries, the vet job and the static analysis
compiled it on every pull request.

What that would have cost is the failure 0009 was written against. A
prototype somebody abandoned half-written holds the board red on six
platforms it was never about, and the two ways out of a red board are
deleting the evidence or rewriting the answer.

The commands now name the runner's two roots. gofmt takes cmd and
internal, because it reads directories rather than a package pattern, and
it is the one command here that fails on an experiment without compiling
it. CodeQL moves from autobuild to a manual build of the same two roots:
autobuild builds the module, and the first line of that file says its
subject is the runner's own source.

Record 0017 carries the mechanism, the three options it was chosen over
and what each would have cost. The largest of those is measured rather
than argued. An experiment as its own module, or behind a build
constraint, stops `go run ./experiments/reading-a-tree-of-records`
resolving from the root of a checkout, and that command is written twice
in an answered record which gains lines rather than having them replaced.
The command was run at this commit and still reports its three numbers.

What nothing refuses is written in the record rather than left to be
found: a Go file at the root, or under a root directory the layout names
that is neither cmd/ nor internal/, is outside these patterns.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex
iderex merged commit 6b02fc8 into main Aug 12, 2026
24 checks passed
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.

Decide whether an experiment's code is held to the runner's gate

1 participant