Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/sync.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Reusable: one mirror, one run. The caller is a workflow_dispatch of a few lines that
# jshvn/dispatch triggers; it passes `vars` through and inherits its repository secrets.
# an external scheduler triggers; it passes `vars` through and inherits its repository secrets.
# 1Password is read once per run: one `op run` resolves op.env around the whole pipeline,
# failure path included. A mirror without an op.env runs on its repository secrets instead,
# exported into the sync step's environment and crossing into the container by the names
Expand Down
45 changes: 15 additions & 30 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,21 @@
# lib

The toolbox every katoptra mirror includes by URL. Read `README.md` for the contract and
`docs/superpowers/specs/2026-09-08-toolbox-library-design.md` for the decisions.
The toolbox every katoptra mirror includes by URL. `README.md` is the manual: the layers,
the verbs, the engines, secrets, storage, the images, the workflows, and how a mirror
uses and changes any of it. `docs/superpowers/specs/2026-09-08-toolbox-library-design.md`
is the record of what was decided when. This file is what a change must not break:
each entry is a verified go-task or platform fact that cost a session to find.

## Constraints
## Hazards

- `toolbox.yml` declares no `vars:` default for anything a mirror owns. Defaults go
inline. This is a go-task fact, verified: a library `vars:` default shadows the
mirror's root value.
- Verb names are reserved across host and container. `plan` is the host-side read-only
run; an engine's batch planner is `split`. The hooks, `prepare`, `verify`, `index`,
`smoke`, `smoke-mirror`, `report-engine` in the rsync engine, `stage` and `prune` in
the proton engine, and `report-mirror` in the toolbox, are the only verbs a mirror
redefines, each excluded on the include that defines it; `pipeline` and
`plan-pipeline` come from the engine and a mirror excludes them only for another
order. `report-engine` exists in both files, so an engine
consumer excludes it on the toolbox include. Extension is a hook, never a copy: a
verb that needs more than the engine does gets a `-mirror` hook the engine calls last.
- A mirror's root var shadows a command-line `KEY=value` inside an included verb, so an
engine tunable is an inline default and never a root var of the example. A var of
another name that reads the tunable, `BATCHES_MAX` from `MAX_BATCHES`, still sees the
command line (verified), so each default is spelled once.
- A called task sees none of its caller's call vars. A hook a verb calls with an
overridable `RUN` or `STAGING` gets them passed on explicitly, as `smoke` does.
- A global var that reads another var is rendered once, from the root's and the command
line's values, never from a call var: `GPGCHECK` takes the fingerprint as an awk `-v`
at each use, where a call var `TL_KEY` is visible.
- A var of another name that reads a tunable, `BATCHES_MAX` from `MAX_BATCHES`, still
sees the command line (verified), so each default is spelled once, inline.
- No `dir:` on an engine verb. In a flattened include read by path, task joins even an
absolute `dir:` onto the include's directory (verified, 3.53.1), so `verify` starts
each command with `cd {{.STAGING}}` instead.
- `render` mounts an empty directory over `.run`, so a `sh:` var read from it at parse
time renders the same from any working tree. A verb that reads `.run` at parse time
must tolerate an empty one.
- `.taskrc.yml` keys are `trusted-hosts` and `cache-expiry`; task ignores a key it does
not know, silently, and refetches on every invocation.
- Every tool in an image comes from `toolchain.lock.toml`, read through `docker/lock.py`,
Expand All @@ -51,12 +35,9 @@ The toolbox every katoptra mirror includes by URL. Read `README.md` for the cont
the `--` as the format. Use `printf '%s %s ' -e "$v"`.
- Task's built-in shell has no `umask`. A file that must be born 0600 is
`install -m 600 /dev/null "$f"` and then written, as the proton engine's `age` does.
- The proton engine keeps no state of the mirror's in the bucket, only the CLI session,
because `filesystem upload` skips a file whose content Proton already holds and
`-f create-new-revision` handles one that changed. Every CLI call goes through `pd`,
which pushes the session back whatever the exit: the refresh token rotates, and a run
that kept a rotated token to itself leaves the next run unable to log in. Two mirrors
never share one session for the same reason.
- Every Proton CLI call goes through `pd`, which pushes the session back whatever the
exit: the refresh token rotates, and a run that kept a rotated token to itself leaves
the next run unable to log in. Two mirrors never share one session for the same reason.
- Actions pinned to a full SHA with the version in a trailing comment. A mirror pins the
two reusable workflows that way; each checks this repository out at its own commit
(`github.job_workflow_sha`) for the toolbox action and the lock, so a workflow pin is
Expand All @@ -78,3 +59,7 @@ example. Regenerate the tree with a new key only to change its shape; the privat
was never kept. The proton one runs `confirm` over `examples/proton/fixtures/`, an
accepting and a refusing upload summary, and the `age` verb round trip with a throwaway
identity.

A README change is a diff `task check` cannot see; the review is reading it. Every
anchor a mirror's README links here (`#secrets`, `#storage`, `#the-rsync-engine`,
`#the-proton-engine`) is a heading in `README.md`; renaming one breaks four repositories.
Loading