The call log cannot say what a build spent its night on, and three separate mechanisms are each half of the reason. #996 measured all of it and fixed what could be fixed inside one package; this is the part that cannot be, because it is a change to how every caller in the module reaches a model.
#928 is the spine. Everything below either depends on it or dies with it.
1. The purpose is a precondition of the wire, not a package convention
#996 made internal/session state a purpose on every request, as a compile-time argument to one door, with a go/ast law. That law can only see one package. internal/reflex, internal/head, internal/exec, internal/plan, internal/revision and cmd/aforge all reach the wire by other roads and the law cannot reach them.
The purpose belongs where every road passes: provider.NewClient (or the transport under it) takes it, and the one place calllog.Record is written refuses — or loudly flags — an untagged row.
That deletes withPurpose, purposeInherited, the own-client second pass in nohiddenwork_test.go, and the whole notion of a per-package tagging convention. The law becomes one sentence across the module: no provider.NewClient outside the dispatcher without a purpose.
2. #928: the lane role rides on the record
cmd/aforge-replay's roleOf joins two vocabularies — a tag and a lane.Role — by a hand-maintained table, because the two are joined nowhere a reader can reach. #996 grew that table by four rows and corrected two more that had been wrong for months:
vision was priced as an errand nobody waits on; image.go, its only writer, sets lane.RoleTalk — a look at an image streams into the room during the person's own turn.
spellout is priced RoleAuxiliary by its own call site, and a person sits and watching it write three lines before deciding whether to keep them. Either the lane role or the product is wrong there, and the table cannot be the place that decides.
provider.WithCallRole beside WithCallTag, carried onto the record, deletes the table. It also deletes the one rename #996 had to carry: the standing check's tag is standing-check rather than sentinel purely because cmd/aforge already writes sentinel for the resident's quorum errand. Three packages spell that word for three things; the join fixes that, a rename only moves it.
3. The prefix variance is removed rather than measured around
The fixed prefix is not the same size on every machine:
| what |
bytes |
why |
grep's description |
134 |
a longer sentence where ripgrep is absent |
load_capability's group list |
27 |
edit_video exists only where ffmpeg is on PATH |
load_capability's schema enum |
8 |
same cause |
| the page's working directory |
tens |
fixture artefact |
the page's Workstation: line |
1 |
runtime.GOOS/GOARCH |
#996 made the gate weigh the widest machine, which is correct and is not the same as the variance not existing: the shipped prefix really is 169 bytes bigger on a machine with neither program. widestBelt, bare.WidestGrepDescription, the loadCapabilityDescription members seam and the two normalisations in prefixbudget_test.go all exist to measure around it.
Removing it at source — one grep description everywhere with the ripgrep fact delivered at runtime in the tool result, and load_capability naming what the build could have — deletes all of that and makes the prefix one number for everyone.
This one needs its owner in the room. bare's grepToolDescription states its law explicitly: "the two sentences that differ are the two facts that differ, and they are stated rather than left for the model to discover by being surprised." Moving that fact to runtime contradicts it, and the alternative — one description that states both cases up front — costs every machine a few bytes. That is a call for whoever owns the belt.
Replication
go test ./internal/session/ -run TestTheFixedPrefixStaysUnderItsBudget -v # the widest-machine scaffolding
go test ./cmd/aforge-replay/ -run TestEveryTagTheBuildWritesResolvesToARoleSomebodyDeclared
internal/session/prefixbudget_test.go's header carries the measurements and the dated waivers; cmd/aforge-replay/request.go's callSiteRoles carries the table and the reason each row exists.
Acceptance
- A model call made anywhere in the module without a purpose fails a test that reads the tree, not a review.
aforge chat --once on a real model, then calls.jsonl shows a tag and a lane role on every row, with roleOf's table gone.
- Both prefix arms measure the same number on macOS and Linux with no normalisation in the gate.
The call log cannot say what a build spent its night on, and three separate mechanisms are each half of the reason. #996 measured all of it and fixed what could be fixed inside one package; this is the part that cannot be, because it is a change to how every caller in the module reaches a model.
#928 is the spine. Everything below either depends on it or dies with it.
1. The purpose is a precondition of the wire, not a package convention
#996 made
internal/sessionstate a purpose on every request, as a compile-time argument to one door, with a go/ast law. That law can only see one package.internal/reflex,internal/head,internal/exec,internal/plan,internal/revisionandcmd/aforgeall reach the wire by other roads and the law cannot reach them.The purpose belongs where every road passes:
provider.NewClient(or the transport under it) takes it, and the one placecalllog.Recordis written refuses — or loudly flags — an untagged row.That deletes
withPurpose,purposeInherited, the own-client second pass innohiddenwork_test.go, and the whole notion of a per-package tagging convention. The law becomes one sentence across the module: noprovider.NewClientoutside the dispatcher without a purpose.2. #928: the lane role rides on the record
cmd/aforge-replay'sroleOfjoins two vocabularies — a tag and alane.Role— by a hand-maintained table, because the two are joined nowhere a reader can reach. #996 grew that table by four rows and corrected two more that had been wrong for months:visionwas priced as an errand nobody waits on;image.go, its only writer, setslane.RoleTalk— a look at an image streams into the room during the person's own turn.spelloutis pricedRoleAuxiliaryby its own call site, and a person sits and watching it write three lines before deciding whether to keep them. Either the lane role or the product is wrong there, and the table cannot be the place that decides.provider.WithCallRolebesideWithCallTag, carried onto the record, deletes the table. It also deletes the one rename #996 had to carry: the standing check's tag isstanding-checkrather thansentinelpurely becausecmd/aforgealready writessentinelfor the resident's quorum errand. Three packages spell that word for three things; the join fixes that, a rename only moves it.3. The prefix variance is removed rather than measured around
The fixed prefix is not the same size on every machine:
grep's descriptionload_capability's group listedit_videoexists only where ffmpeg is on PATHload_capability's schema enumWorkstation:lineruntime.GOOS/GOARCH#996 made the gate weigh the widest machine, which is correct and is not the same as the variance not existing: the shipped prefix really is 169 bytes bigger on a machine with neither program.
widestBelt,bare.WidestGrepDescription, theloadCapabilityDescriptionmembers seam and the two normalisations inprefixbudget_test.goall exist to measure around it.Removing it at source — one
grepdescription everywhere with the ripgrep fact delivered at runtime in the tool result, andload_capabilitynaming what the build could have — deletes all of that and makes the prefix one number for everyone.This one needs its owner in the room.
bare'sgrepToolDescriptionstates its law explicitly: "the two sentences that differ are the two facts that differ, and they are stated rather than left for the model to discover by being surprised." Moving that fact to runtime contradicts it, and the alternative — one description that states both cases up front — costs every machine a few bytes. That is a call for whoever owns the belt.Replication
internal/session/prefixbudget_test.go's header carries the measurements and the dated waivers;cmd/aforge-replay/request.go'scallSiteRolescarries the table and the reason each row exists.Acceptance
aforge chat --onceon a real model, thencalls.jsonlshows a tag and a lane role on every row, withroleOf's table gone.