Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1719 commits
Select commit Hold shift + click to select a range
d7bb25a
chore(corpus): move the ratchet, and stop stepping over it
giles-bot Sep 14, 2026
8e7beb1
docs(decisions): where a step's daemon comes from
giles-bot Sep 14, 2026
188c683
feat(guest): a step's daemon binary is said, not found
giles-bot Sep 14, 2026
4ee75e8
fix(guest): make somewhere to put an action's declared outputs
giles-bot Sep 15, 2026
744b861
test(examples): a ladder to time remote execution against local
giles-bot Sep 15, 2026
7a1f5fc
test(examples): fit the ladder to a slope and an intercept
giles-bot Sep 15, 2026
08c173f
test(examples): time bazel's startup cold against warm
giles-bot Sep 15, 2026
793031a
feat(exec): build linux/amd64 on an Apple Silicon Mac, through Rosetta
giles-bot Sep 15, 2026
9f1619a
chore(corpus): move the ratchet - the bazel ladder adds two targets
giles-bot Sep 15, 2026
9c8b23a
feat(fleet): a worker announces what it can emulate, not only what it is
giles-bot Sep 15, 2026
3e9509f
docs(plan): a series of experiments for making a fleet move less
giles-bot Sep 15, 2026
e960e8e
docs(plan): a jobserver, so three widths stop multiplying
giles-bot Sep 15, 2026
727562f
docs(plan): the jobserver is per VM, and that dissolves the leak
giles-bot Sep 15, 2026
46d5a06
fix(cli): a fleet wraps the executor, and the wrapper holds no store
giles-bot Sep 15, 2026
566d3e7
docs(fleet): E-F1's first two-machine result, and what it found
giles-bot Sep 15, 2026
00e77fb
docs(fleet): E-F1's number, and a v1 plan built on it
giles-bot Sep 15, 2026
6871979
fix(fleet): a busy worker is not a dead one (F1)
giles-bot Sep 15, 2026
bbd566b
fix(fleet): count what a lazy worker fetches (E-F0)
giles-bot Sep 15, 2026
bdf61c6
docs(fleet): E-F1's number - 1.0 GiB, crossed once
giles-bot Sep 15, 2026
fd14970
fix(interp): a target inherits the platform of the base it stands on …
giles-bot Sep 15, 2026
1ea7154
docs(fleet): F3 verified on hardware, and what it leaves
giles-bot Sep 15, 2026
498a239
fix(store): a store emptied by a full disk says so, where it is noticed
giles-bot Sep 15, 2026
9e03158
docs(fleet): the refusals were a full disk, and what is left after it
giles-bot Sep 15, 2026
bf568c3
fix(fleet): a stack element may be a declaration, and the fleet could…
giles-bot Sep 15, 2026
2cfc657
docs(fleet): the fleet builds the build - 6 delegated, 0 local
giles-bot Sep 15, 2026
334cc05
docs(fleet): correct the transfer rate - wrong unit, wrong ceiling
giles-bot Sep 15, 2026
a3be3b9
feat(fleet): say whether a fetch went direct or through a relay
giles-bot Sep 15, 2026
d2ce1eb
perf(fleet): give hole punching a moment before transferring over a r…
giles-bot Sep 15, 2026
022c30e
feat(fleet): say which route carried the bytes, not which ones exist
giles-bot Sep 15, 2026
dc83238
perf(fleet): waiting for a direct path does not help, so stop paying …
giles-bot Sep 15, 2026
362b46b
feat(fleet): say when a connection has no second path to migrate to
giles-bot Sep 15, 2026
819354c
fix(fleet): a fetcher is a receiver, so report both directions per path
giles-bot Sep 15, 2026
ae45be8
docs(fleet): on GitHub the data plane never leaves the relay
giles-bot Sep 15, 2026
ec61908
perf(fleet): dial the peer directly for blobs instead of hoping to mi…
giles-bot Sep 15, 2026
7ddbcb9
feat(fleet): separate what reaching a peer costs from what the transf…
giles-bot Sep 15, 2026
1efc8be
perf(fleet): the transfer was never the cost - reaching the peer is
giles-bot Sep 15, 2026
2dd45ab
perf(fleet): upgrade to a direct path after the first fetch, not befo…
giles-bot Sep 15, 2026
14010d7
docs(fleet): splitting one number into two ended the argument
giles-bot Sep 15, 2026
64178cf
perf(fleet): open a holder's connection before a step needs it
giles-bot Sep 15, 2026
4a77f8f
fix(fleet): count what priming moved, which is now most of what moves
giles-bot Sep 15, 2026
a32b62d
docs(fleet): setup off the critical path, and the number it briefly hid
giles-bot Sep 15, 2026
63b1fb2
docs(fleet): the two fleets have opposite bottlenecks
giles-bot Sep 15, 2026
f9b7f46
feat(guest): pack a store element in the fleet's format, for a driver…
giles-bot Sep 15, 2026
1335b62
feat(cli): a driver whose store is inside the VM can serve its own ba…
giles-bot Sep 15, 2026
996ebc7
docs(fleet): F4 verified - a Mac drives a fleet with its store where …
giles-bot Sep 15, 2026
8762abd
fix(exec): every exec into the sandbox must name the store the guest …
giles-bot Sep 15, 2026
6d2f360
fix(fleet): count what priming faults in - the same hole, one functio…
giles-bot Sep 15, 2026
f983f5b
docs(fleet): the baseline was crippled, and one machine wins this wor…
giles-bot Sep 15, 2026
29e97b6
docs(fleet): a Mac cannot help an amd64 build, and Rosetta is why tha…
giles-bot Sep 15, 2026
28981af
feat(core): a translator competes for work; an interpreter still does…
giles-bot Sep 15, 2026
a34391a
docs(fleet): Rosetta joins the fleet, and then hits the concurrency c…
giles-bot Sep 15, 2026
018880b
feat(core): a build runs as wide as its fleet, not as wide as its driver
giles-bot Sep 15, 2026
e955362
docs(fleet): the fleet beats one machine - 1.44x, twice each arm
giles-bot Sep 15, 2026
984ad12
docs(fleet): 1.94x, and the missing half was the harness
giles-bot Sep 15, 2026
fd93a9f
docs: a fleet that beats one machine moves from claimed to measured
giles-bot Sep 15, 2026
efa83c3
docs(fleet): E-F5 - a prediction is worth its round trips
giles-bot Sep 15, 2026
f1c162b
feat(core): place a step where its base already is (E-F2)
giles-bot Sep 15, 2026
b1387e7
fix(core): locality is a question for the schedule, not for a store
giles-bot Sep 15, 2026
582d767
revert(core): locality placement hangs a chain on a fleet
giles-bot Sep 15, 2026
27d7623
fix(fleet): serving a blob cannot wedge the machine that serves every…
giles-bot Sep 15, 2026
39b4c21
fix(fleet): the serve's bound has to be the serve's own
giles-bot Sep 15, 2026
16df23b
docs(fleet): the chain hang traced to a serve and a step sharing one …
giles-bot Sep 15, 2026
74bfb81
docs(fleet): the sandbox-contention theory is wrong too
giles-bot Sep 15, 2026
cf78c49
docs(fleet): both sides of the stall - the worker is blocked reading
giles-bot Sep 15, 2026
f941f70
fix(fleet): a fragment request is not answered with a whole layer
giles-bot Sep 15, 2026
69682fa
docs(fleet): locality helps the chain and leaves the fan-out alone
giles-bot Sep 15, 2026
d870584
fix(exec): the package could not be built for windows, so neither cou…
giles-bot Sep 15, 2026
311edee
docs(fleet): this repository's own build cannot use a fleet
giles-bot Sep 15, 2026
3a49693
feat(fleet): a cache mount may cross, because its contents never reac…
giles-bot Sep 15, 2026
383d8d6
docs(fleet): cache mounts cross, verified end to end
giles-bot Sep 15, 2026
6e91a6a
docs(cache): --immutable-except, written before it is built
giles-bot Sep 16, 2026
4041df2
feat(cache): --immutable-except, the author's claim that a cache may …
giles-bot Sep 16, 2026
a90bad9
docs(cache): measure the go module cache instead of asserting it
giles-bot Sep 16, 2026
263ccb9
docs(cache): the go module cache is byte-identical across architectures
giles-bot Sep 16, 2026
c65c134
fix(cache): an empty exclusion list is a claim, not the absence of one
giles-bot Sep 16, 2026
239d1b8
feat(cache): --immutable-except patterns match something
giles-bot Sep 16, 2026
8de6166
refactor(cache)!: --immutable-except becomes --portable-except
giles-bot Sep 16, 2026
8a83525
feat(tools): prototype the cache helper contract before building it
giles-bot Sep 16, 2026
2050a39
feat(fleet): a warm cache mount is a kind of locality
giles-bot Sep 16, 2026
f29a506
feat(tools): measure the working-set fraction stage 2 was gated on
giles-bot Sep 16, 2026
6c928b7
docs(fleet): compression turns the Go tie into a 3x win
giles-bot Sep 16, 2026
3c32421
fix(cache): a portable cache gets a directory of its own
giles-bot Sep 16, 2026
d3c7c6b
fix(cache): an untrusted build writes to a namespace of its own
giles-bot Sep 16, 2026
86fae87
feat(remote): a cache that can say "not here, but I know who"
giles-bot Sep 17, 2026
059e8fe
feat(tools): a Go build cache object is already a CAS blob
giles-bot Sep 17, 2026
220d4b5
docs(fleet): the hash is the helper's business, not a coincidence
giles-bot Sep 17, 2026
d8525f9
refactor(tools): export a batch of framed units, not one opaque stream
giles-bot Sep 17, 2026
59e64ce
docs(fleet): the native number, and two designs that were not needed
giles-bot Sep 17, 2026
3be34f1
docs(fleet): point the floor at the measurement that replaced it
giles-bot Sep 17, 2026
db77a98
docs(fleet): why the store keeps its check
giles-bot Sep 17, 2026
f750f1e
docs(fleet): the hop was not needed, and the third Kind was a trap
giles-bot Sep 17, 2026
04a14d0
feat(fleet): a worker serves the nodes its store holds
giles-bot Sep 17, 2026
e31df16
docs(fleet): a near network is not a far network
giles-bot Sep 17, 2026
bfa5f1e
docs(fleet): a helper is an image, and one process rather than one pe…
giles-bot Sep 17, 2026
4864013
docs(fleet): a long-lived wasm instance does not change the answer
giles-bot Sep 17, 2026
8ee85a2
docs(fleet): the hashing was on the wrong side of the boundary
giles-bot Sep 17, 2026
082b10a
fix(tools): a unit's bytes are a function of the cache, not of its re…
giles-bot Sep 17, 2026
fe068a1
feat(cache): CACHE --helper, and an Earthfile target that builds one
giles-bot Sep 17, 2026
3b2a9f2
feat(helper): the engine can run the program that understands a cache
giles-bot Sep 17, 2026
3dfdc72
feat(helper): a cache mount crosses as content-addressed blobs
giles-bot Sep 17, 2026
7cfbbcf
feat(exec): a step offers its portable caches when it finishes
giles-bot Sep 17, 2026
a64cc35
feat(cli): a build files the units of the caches it was told to share
giles-bot Sep 17, 2026
705be0f
feat(tools): one blob serves every cache format it knows
giles-bot Sep 17, 2026
9fbe209
feat(tools): Cargo, and a real Rust build sharing a real crate
giles-bot Sep 17, 2026
3662876
fix(tools): a unit is all of its files, and npm's content is hex
giles-bot Sep 17, 2026
41129f2
feat(cache): a build stocks a cache mount before the step that needs it
giles-bot Sep 17, 2026
2a81dcb
fix(cache): a helper is pinned by its module, not by the path it was …
giles-bot Sep 17, 2026
27e856f
feat(fleet): a worker shares the caches it fills, which it never did
giles-bot Sep 17, 2026
ced02d8
feat(fleet): a helper crosses the fleet, and fleet.Nodes finds what a…
giles-bot Sep 17, 2026
fb7a41f
feat(fleet): a cold worker fills a cache from a peer, and Hints.Bytes…
giles-bot Sep 17, 2026
63dad02
feat(cache): one writer per cache, no cache from a step that held a c…
giles-bot Sep 17, 2026
b2b13fa
perf(cache): export only what the last map did not name, where the he…
giles-bot Sep 17, 2026
0626e75
fix(store): prune collects a shared cache's units and maps, which it …
giles-bot Sep 17, 2026
9080075
fix(cache): a machine that cannot read its own cache mounts says so
giles-bot Sep 17, 2026
513407b
feat(examples): a worked example per ecosystem, and two bugs found wr…
giles-bot Sep 17, 2026
344bb3b
feat(cache): a helper may be an artifact of this build
giles-bot Sep 18, 2026
edfd34a
fix(mutate): realign twelve anchors the code moved out from under
giles-bot Sep 18, 2026
2d03700
wip(cache): guest-side cache sharing, before diagnosing the empty hel…
giles-bot Sep 18, 2026
7178389
feat(cache): the guest shares its own caches, and says why when it ca…
giles-bot Sep 18, 2026
38e867f
feat(fleet): measure what a step costs, so EstimatedSeconds has somet…
giles-bot Sep 18, 2026
60dfacc
fix(fleet): a step the kernel killed for memory is refused, not failed
giles-bot Sep 18, 2026
92cde11
perf(ls): list an Earthfile by parsing it, not by resolving a build c…
giles-bot Sep 18, 2026
fcb82ec
perf(ls): a command that only reads files needs no container frontend
giles-bot Sep 18, 2026
cb1f0d4
fix(helper): a helper reference crosses the seam resolvable, and stag…
giles-bot Sep 18, 2026
dfe2cb5
fix(fleet): a delegated result carries its declaration
giles-bot Sep 19, 2026
279cdb6
fix(fleet): a reply gives up its observation rather than the result i…
giles-bot Sep 19, 2026
6a9cf83
test(core): the content key joins the guard that covers every other key
giles-bot Sep 19, 2026
fdfeb29
fix(cache): a shared cache mount is scoped by the architecture that f…
giles-bot Sep 19, 2026
a15a1d7
test(core): Λ and the Κ₂ gate join the mutation sweep, and one mechan…
giles-bot Sep 19, 2026
8f45b15
fix(trace): the exec test owns its listener rather than borrowing a d…
giles-bot Sep 19, 2026
01bf90a
fix(trace): the stop-report test gives its pipe one owner, not two
giles-bot Sep 19, 2026
124f9c1
fix(trace): a filtered thread is parked for good, not destroyed at cl…
giles-bot Sep 19, 2026
69e6c6a
fix(trace): xattrs, statfs and io_uring are traced rather than silent…
giles-bot Sep 19, 2026
f75772c
feat(trace): count notifications per syscall, and the cost argument i…
giles-bot Sep 19, 2026
1f24663
fix(trace): the xattr listing calls, which is what a reader actually …
giles-bot Sep 19, 2026
8ae7105
docs(settings): the eight settings a reader could not discover
giles-bot Sep 19, 2026
daf707d
fix(exec): EARTH_GUEST_ROOT is declared host-only, which it already was
giles-bot Sep 19, 2026
06ee0bf
chore(corpus): the linux earthtests ratchet catches up with what plans
giles-bot Sep 19, 2026
779d51c
test(store): a collection budget is measured, not assumed
giles-bot Sep 19, 2026
565180b
fix(guest): a machine that cannot make a namespace is a skip, not fou…
giles-bot Sep 19, 2026
2eea74a
test(cli): the default-backend test is an integration test, by what i…
giles-bot Sep 20, 2026
6faf54f
fix(exec): the runnable-platform tests stop consulting the kernel
giles-bot Sep 20, 2026
d81715b
test(guest): storing one tree twice is one layer, and the fixture now…
giles-bot Sep 20, 2026
0ec18db
test(guest): a step already traced cannot host a second tracer
giles-bot Sep 20, 2026
6dcfe6d
docs(plan): main's 63 commits, one line each, with a verdict
giles-bot Sep 21, 2026
18b76d1
Merge commit 'a898b66ff' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
76337f1
Merge commit '6dca1d306' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
ede3a0b
refactor(engine): a zero is omitted because it is zero, not because i…
giles-bot Sep 21, 2026
20c7c9e
docs(plan): line 2 is settled, and the fear it recorded was the wrong…
giles-bot Sep 21, 2026
515ab62
Merge commit 'b08a1df18' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
9fccfc5
Merge commit 'f476e5b5e' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
de609de
Merge commit '8c0d880bf' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
cb3c18e
Merge commit '7b7643070' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
7fec2fc
Merge commit 'f29ff5af8' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
cdd7f9e
Merge commit '2b87a4dec' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
c81f1b2
docs(plan): lines 3 to 8 are in
giles-bot Sep 21, 2026
e9b0c49
Merge commit '82915a224' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
040c1e1
Merge commit '636f58f56' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
3946624
Merge commit '77100d1e4' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
7923cfc
Merge commit 'd7e536699' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
323cc0a
Merge commit '40efb4605' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
22bb1a9
Merge commit '7d8b9f467' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
de03056
Merge commit 'd87c3e3d6' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
ec7ee03
Merge commit '2d40dc8cb' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
c5707bd
Merge commit '9f47c669e' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
a61423c
Merge commit 'ad012176d' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
dc8bb17
Merge commit '95f940c3a' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
bcd1519
Merge commit '98b6ce68c' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
58bdee7
Merge commit 'ead75d9fc' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
914456f
docs(plan): lines 9 to 21 are in, and three resolution rules to reuse
giles-bot Sep 21, 2026
30ad8b8
Merge commit '5457128ab' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
e0f13cf
Merge commit '8c3016fff' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
f5769c2
Merge commit '6530ea12b' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
845063e
Merge commit 'db6f05e36' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
d92186b
Merge commit '8e0213f33' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
1207792
Merge commit 'b9989ece2' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
0c061ae
Merge commit '7a8318789' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
5ee0919
Merge commit '113ec9d11' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
626e3e6
Merge commit 'fddc4b372' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
c9c922e
Merge commit 'f94310444' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
0d498da
Merge commit 'afc8ebf37' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
c4d938b
Merge commit '1ebfdcda9' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
1888f49
Merge commit '519d93fe9' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
a900e7e
Merge commit '54ab73cfa' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
cbac378
Merge commit '1398a0a5e' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
7a20e8a
Merge commit '9d83e8bef' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
51efbca
Merge commit 'f4ee556ea' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
11d22f8
Merge commit 'f36324182' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
a98c4f1
Merge commit '9a6a43636' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
a0b3fff
docs(plan): lines 22 to 40 are in
giles-bot Sep 21, 2026
3564976
Merge commit '085fc5650' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
067419c
Merge commit '965f3b630' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
8521258
Merge commit 'b64532c89' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
1ff76fc
Merge commit 'b4bae887d' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
71973bd
Merge commit '6a6179ebc' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
06f26c7
Merge commit '59442edcf' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
d46eb4b
Merge commit 'aa4e0d964' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
91b4ddc
Merge commit 'ee6be11dc' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
795614c
Merge commit 'e90b2d72a' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
5ba714c
Merge commit '99c767ebf' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
03fe9a4
Merge commit 'bde5e5f9b' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
188761c
refactor(interp): the CI-runner builtin is retired, and so is the flag
giles-bot Sep 21, 2026
4f8e4c7
Merge commit 'aad7dae16' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
3293f55
Merge commit 'eb2d44c0f' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
ca5cd84
Merge commit '0776f5f67' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
8cc5bd4
Merge commit '90c544fca' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
f49edac
Merge commit 'f6f3e1f58' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
44701c0
Merge commit '5316a944d' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
90bdb13
Merge commit '26037eeb1' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
3232026
fix(app): a global flag's value is not a subcommand
giles-bot Sep 21, 2026
1ed6f69
Merge commit '15389c1b6' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
c705fb0
Merge commit '9562129dc' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
33d7a0e
docs(cli): the build workdir is /earth, and the prose that explains why
giles-bot Sep 21, 2026
773b8a6
Merge commit '38320254f' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
254da68
Merge commit 'e87deb594' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
9cadd83
Merge commit '1dad4e797' into giles-post-buildkit-engine
giles-bot Sep 21, 2026
c51b3b3
docs(plan): main is merged - sixty-three of sixty-three
giles-bot Sep 21, 2026
ee34673
fix(helper): one pass through a mutex, for a global that is not ours
giles-bot Sep 21, 2026
60067be
test(guest): a machine that will not mount is not a test that failed
giles-bot Sep 21, 2026
3c600a4
ci(fleet): a dependency bump is a change to the transport
giles-bot Sep 21, 2026
cced0ea
EXPERIMENT: pin x/crypto to v0.55.0 to bisect the fleet blob failure
giles-bot Sep 21, 2026
d8dad5c
fix(helper): the same global is reached by two constructors, not one
giles-bot Sep 21, 2026
c46786f
test(exec): a defer runs before a cleanup, and the server is still re…
giles-bot Sep 21, 2026
e7257d9
Revert "EXPERIMENT: pin x/crypto to v0.55.0 to bisect the fleet blob …
giles-bot Sep 21, 2026
a7ca2de
fix(fleet): a worker that gives up first is a fleet that never forms
giles-bot Sep 21, 2026
32357c8
ci: the skip ceiling was exceeded for a fortnight, unreported
giles-bot Sep 22, 2026
7b576db
test(autocompletion): two commands this branch added, said out loud
giles-bot Sep 22, 2026
8f163cc
ci(examples): the reference cannot build an example built on native-o…
giles-bot Sep 22, 2026
7e27afd
ci(setup): one retry on a call every job in the matrix makes
giles-bot Sep 22, 2026
925490c
bench: cold was never a tie - the network was, and it hid a loss
giles-bot Sep 22, 2026
98726ce
ci(setup): retry the GHCR pull as well as the artifact download
giles-bot Sep 22, 2026
a6e46df
feat(cacheshare): a bound mount that shares nothing says which nothing
giles-bot Sep 22, 2026
00a4130
fix(cli): the share hook reports its own failure, because nobody else…
giles-bot Sep 22, 2026
d914899
fix(exec): stage a helper where the guest can read it, not in /tmp
giles-bot Sep 22, 2026
bf833a3
fix(bulk): an export cannot write through a symlink it planted itself
giles-bot Sep 22, 2026
215b8d1
fix(unpack): guard every archive loop with filepath.IsLocal, inline
giles-bot Sep 22, 2026
2fe2749
fix(core): a COPY --sync result is served only by Κ₁, which names its…
giles-bot Sep 22, 2026
fc940bb
fix(guest): COPY --sync prunes once, against every layer the source b…
giles-bot Sep 22, 2026
6e72536
test(sync): pin each half of the --sync guards on its own
giles-bot Sep 22, 2026
03362bd
fix(mutate): restore the I3 anchor and catalogue the --sync guards
giles-bot Sep 22, 2026
2d2c468
test(core): the determinism test runs every leaf, and says which order
giles-bot Sep 22, 2026
25ef85b
fix(image): a registry on this machine may answer in HTTP
giles-bot Sep 23, 2026
776890f
fix(export): AS LOCAL without a trailing slash names the artifact, an…
giles-bot Sep 23, 2026
687ddde
test(image): a blob waits for company, not for a fixed time
giles-bot Sep 23, 2026
8f489f0
feat(image): a pinned FROM is served from what SAVE IMAGE wrote
giles-bot Sep 23, 2026
3bd43e5
fix(cli): an image saved with no platform is Linux, not the host
giles-bot Sep 23, 2026
1cea94e
fix(exec): SAVE IMAGE writes the environment expanded
giles-bot Sep 23, 2026
c9b5a98
ci(engine-daemon): the integration binaries get a test timeout
giles-bot Sep 23, 2026
8be7c5b
feat(exec): a Firecracker microVM gives the host back the memory its …
giles-bot Sep 24, 2026
63b2be0
style(mutate): gofmt the catalogue
giles-bot Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
135 changes: 135 additions & 0 deletions .claude/skills/green-paper/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
name: green-paper
description: Conventions for writing and amending docs-internals/green-paper.md, the EarthBuild engine specification. Use when adding a section, defining a symbol or equation, changing an invariant, or reviewing a change to the Green Paper. Also covers the sibling docs (rfc, plan, experiments, test-plan) where they cite it.
---

# Writing the Green Paper

`docs-internals/green-paper.md` is the specification of the EarthBuild engine. It **asserts**.
The engine conforms to it; where code and document disagree, one is a defect and the disagreement
gets resolved rather than tolerated.

Read the document before amending it. These are its rules, not general markdown advice.

## Before you finish: the checklist

1. `python3 .claude/skills/green-paper/align-tables.py docs-internals/green-paper.md`
2. Every new symbol is defined before first use, and added to Appendix E.
3. Every new equation is numbered `(n.m)` in section order.
4. Every `§n.m` reference resolves - see "Cross-references" below.
5. A new invariant has a row in §5.1 giving both how it is *enforced* (with its level) and what
*tests* it, or `**[GAP]**`. Prefer making a violation unrepresentable over asserting it, and
asserting it over testing it.
6. `npx markdownlint-cli docs-internals/green-paper.md` - MD013 line-length is the only
tolerated failure, matching the rest of `docs-internals/`.

## Tables

**Aligned.** Pad every cell so the pipes line up; rebuild separator rows as dashes matching the
final column width. Never `| --- | --- |`.

Do not hand-align. Run `align-tables.py`, which counts codepoints rather than bytes - the
document is full of mathematical alphanumerics (𝔅, 𝕂, ℋ) that are multi-byte and single-width,
so byte-length padding produces ragged output. The script skips fenced blocks, where a pipe is
data.

## Equations

Numbered `(n.m)`, in a `text` fence, referenced by number in prose:

```text
(4.5) Κ₁(s) ≡ ℋ(0x01 ‖ ids(𝑏) ‖ 𝒮(ω) ‖ 𝒮(ε) ‖ 𝒮(π))
```

`≡` defines, `=` asserts equality. Appendix numbering is `(A.1)`, `(B.1)` and so on.

## Notation

Fixed in §1.1 and not to be extended casually:

| Class | Typography | Examples |
| ------------------------- | ---------------- | ------------- |
| sets | blackboard | 𝔹 𝔻 𝕂 𝕊 𝕃 ℙ ℕ |
| persistent values | lower-case Greek | σ ℓ κ ρ |
| functions introduced here | upper-case Greek | Υ Σ Κ Δ Φ Λ Ω |
| imported functions | calligraphic | ℋ 𝒮 |
| local values | lower-case roman | 𝑖 𝑗 𝑥 𝑦 |

A symbol that cannot be given a one-line definition pointing at its introducing equation was
never properly defined. Writing the Appendix E entry is the test; do it as you add the symbol,
not later.

**Subscripts use Unicode subscript characters, never an underscore.** Unicode has digits ₀-₉ and
a partial Latin set (ₐ ₑ ₕ ᵢ ⱼ ₖ ₗ ₘ ₙ ₒ ₚ ᵣ ₛ ₜ ᵤ ᵥ ₓ) - no `c`, no `d`, no uppercase, almost no
Greek. Where a subscript is not expressible, **change the symbol rather than fake it**: number it
when the number means something (Κ₁, Κ₂ for the L1 and L2 lookups), or use an accessor function
for a tuple component (ω(s), not s_ω - which is more precise anyway). Mixing real subscripts with
underscored ones reads as a typo and invites transcription errors. See §1.3.

## Normative language

* State requirements as facts: "Λ yields a verified result or a miss", not "Λ should try to".
* No hedging - "we might", "it would be nice", "consider" belong in the plan, not here.
* Invariants are numbered `I1`..`In` and cited by number from the plan, the experiments and the
test plan. Renumbering an invariant means updating every citation; prefer appending.
* Assumptions live in §0.1 as `A1`..`An`, **stated apart from mechanism**. An assumption is a
place where the specification can be true and the system still wrong; that is why they are
segregated rather than woven in.
* Unwritten sections are marked `**[GAP]**` *in place*, never omitted silently. A gap means the
mechanism has no normative definition and implementations may diverge - which is the condition
the document exists to remove.

## Cross-references

Check them mechanically; they rot silently:

```bash
grep -on "§[0-9][0-9.]*" docs-internals/green-paper.md | awk -F'§' '{print $2}' | sort -u
grep -o "^#\+ [0-9A-E][0-9.]*" docs-internals/green-paper.md | sed 's/^#* //'
```

Every value in the first list must appear in the second. This has already caught two dangling
references.

**Never cite another document by line number.** Line numbers rot the moment either file is
edited: seven such citations in `scheduling.md` were stale within a day of being written, one of
them pointing at a blank line. Cite a section (`plan §2a-bis`, `green-paper §4.4`) or a stable
heading. The same applies to citing source: `file.go:123` is acceptable for code, which changes
under review, but a cross-document reference must be symbolic.

Detect the rot with:

```bash
grep -n "lines\? [0-9]" docs-internals/*.md
```

## House style

* British spelling. ASCII hyphens `-`, never en or em dashes.
* Prose is terse. The specification says what is true; the plan says why and when.
* No attribution creep: the document carries **one** style acknowledgement, in the header. Do not
add "as the Gray Paper does" anywhere else - a specification that keeps citing its influences
is asking permission.

## What belongs here, and what does not

| Content | Home |
| ----------------------------------------- | --------------------------- |
| state, objects, transitions, invariants | green-paper.md |
| why we are doing this, deletion budget | rfc-post-buildkit-engine.md |
| milestones, costs, sequencing, trade-offs | plan-native-engine.md |
| measurements, kill criteria, results | experiments-adversarial.md |
| test mechanisms, CI gates, corpora | test-plan.md |

If a paragraph contains a date, a cost in engineer-weeks, or a decision that could reasonably go
the other way, it belongs in the plan and not in the specification.

## Amending an invariant

Invariants are load-bearing across four documents. To change one:

1. Change it in §5, keeping the number.
2. Update its row in §5.1 - which experiment now tests it?
3. `grep -rn "I[0-9]" docs-internals/` and update every citation.
4. If the change weakens an invariant, say so explicitly in the plan. A quietly weakened
invariant is how a specification stops describing the system.
135 changes: 135 additions & 0 deletions .claude/skills/green-paper/align-tables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""Align markdown tables in place: pad every cell so the pipes line up.

Width is counted in codepoints, not bytes. The Green Paper uses mathematical
alphanumeric symbols (𝔅, 𝕂, ℋ) which are multi-byte but single-width in a
monospace font, so codepoint counting is the right measure and len() on bytes
is not.

Separator rows are rebuilt as dashes matching the final column width, which is
the house style: `| ------ | ------- |`, never `| --- | --- |`.

Fenced code blocks are skipped - a pipe inside a ```text block is data.

Usage: align-tables.py FILE [FILE ...]
"""

import re
import sys
import unicodedata

SEP = re.compile(r"^\s*\|[\s:|-]+\|\s*$")


def width(s):
"""Display width in monospace columns.

Combining marks (category Mn) attach to the preceding character and occupy
no column of their own, so 𝑟̂ is two codepoints but one column. Counting
codepoints misaligns any row containing one.
"""
return sum(1 for c in s if unicodedata.category(c) != "Mn")


def pad(s, w):
return s + " " * (w - width(s))


def split_row(line):
"""Split a table row into cells, dropping the leading and trailing pipe."""
return [c.strip() for c in line.strip().strip("|").split("|")]


def is_row(line):
s = line.strip()

return s.startswith("|") and s.endswith("|") and len(s) > 1


def align(block):
"""Align one contiguous run of table lines."""
rows = [split_row(r) for r in block]
seps = [bool(SEP.match(r)) for r in block]

cols = max(len(r) for r in rows)
rows = [r + [""] * (cols - len(r)) for r in rows]

widths = [0] * cols
for row, sep in zip(rows, seps):
if sep:
continue
for i, cell in enumerate(row):
widths[i] = max(widths[i], width(cell))

# A column must be wide enough for a readable separator.
widths = [max(w, 3) for w in widths]

out = []
for row, sep in zip(rows, seps):
if sep:
cells = ["-" * widths[i] for i in range(cols)]
else:
cells = [pad(row[i], widths[i]) for i in range(cols)]
out.append("| " + " | ".join(cells) + " |")

return out


def process(text):
lines = text.split("\n")
out = []
i = 0
fenced = False

while i < len(lines):
line = lines[i]

if line.lstrip().startswith("```"):
fenced = not fenced
out.append(line)
i += 1
continue

if not fenced and is_row(line):
j = i
while j < len(lines) and is_row(lines[j]):
j += 1
block = lines[i:j]
# A table needs a separator row; otherwise it is prose containing pipes.
if any(SEP.match(b) for b in block):
out.extend(align(block))
else:
out.extend(block)
i = j
continue

out.append(line)
i += 1

return "\n".join(out)


def main():
if len(sys.argv) < 2:
print(__doc__.strip(), file=sys.stderr)

return 1

changed = 0
for path in sys.argv[1:]:
with open(path, encoding="utf-8") as f:
before = f.read()
after = process(before)
if after != before:
with open(path, "w", encoding="utf-8") as f:
f.write(after)
changed += 1
print(f"aligned {path}")
else:
print(f"unchanged {path}")

return 0 if changed or len(sys.argv) > 1 else 1


if __name__ == "__main__":
sys.exit(main())
26 changes: 26 additions & 0 deletions .earthlyignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
build
earthfile2llb/parser/*.go
.git

# Generated content, every line of it gitignored and none of it part of the
# repository. It was in the build context until somebody measured: 958MB of
# node_modules and 81MB of test fixtures, hashed into the cache key of every
# COPY on every build.
#
# Slow, and worse than slow. A cache key that includes untracked files is a key
# that depends on what a machine happens to have lying about, so a fresh clone
# and a developer's checkout of one commit never share a result (E562).
**/node_modules
**/testdata/bigtree-*

# The same argument one directory down. `build` above matches only the top
# level, so `examples/*/build` and `examples/next-js/.next` were still hashed
# into every COPY: 18.8MB across 57 files, all of it gitignored, none of it in a
# fresh clone - which is precisely the machine-dependent key E562 was about.
#
# **Not `**/dist`.** The obvious generalisation is wrong here: `examples/js/dist`
# and `tests/remote-cache/test2/dist` are tracked, so that pattern drops source
# from the context of every build that copies them. One example's `dist` is
# generated and is named on its own; the rule is what git ignores, and the
# pattern language cannot say that, so each one is checked rather than guessed.
# TestNoTrackedFileIsExcludedFromTheContext is that check.
**/build
**/.next
examples/typescript-node/dist
4 changes: 4 additions & 0 deletions .envchk/Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VERSION 0.8
t:
FROM ../tests/git-webserver+server
RUN echo "ENGINE=[$EARTH_ENGINE]" && env | grep -c EARTH_ || true
Loading
Loading