Context
The “Working” section of CLAUDE.md listed five commands and said: “Run all of
them before pushing”. That predates the record’s CI in its present shape.
.github/workflows/docs.yml now has a docs-check job on every pull request.
It repairs the sources (reference links, a journal entry’s missing
created:), pushes the repair onto the branch as the bot, and lints the
repaired tree in the same job. No view is written on a branch. So a local run
before a push repeats exactly what the pull request’s CI does next.
The repetition has a cost, and it has grown with the record. The record now holds about five thousand files. On 2026-10-26, filing an exchange and reading its thirteen works, one local lint ran for over two minutes. A local repair, link and lint of the merged branch ran past ten minutes and had to be moved to the background. During those runs, finished work sat committed but unpushed or not even committed. The session’s own guard asked several times for it to be pushed. The owner’s verdict: “just make a PR and push your commits there and let the CI handle the linting instead of duplicating work and waiting around locally … we encounter this a lot.”
There was a second cost. Because CI pushes its repair commit onto the branch, a branch that had also been repaired locally diverged from it, and the next push was rejected until the bot’s commit was merged in. Running the repair in one place removes the double write.
Decision
- Open the pull request early, and push to it as you work. Each commit is
pushed when it is made. A draft pull request is fine. The pull request,
not the push, is the gate: nothing reaches the default branch without a
green
docs-check. - CI does the repair and the lint. Contributors do not run
luria repair,luria link --fixorluria lintas a step before pushing. Write bare codes; the repair spells the link targets.luria indexis never run for a commit (views land on the default branch through CI, as before). - A red check is work on the branch. Read the
docs-checklog, fix what it names, and push again. A narrow local command may be run to diagnose or to check a fix, for exampleluria link --fix --links-only <file>, or a lint run if the CI log is unclear. That is a tool, not a gate. - Pull before pushing. The bot’s repair lands on the branch as its own
commit, so fetch and merge the branch before the next push. A push made
with
GITHUB_TOKENdoes not retrigger workflows, so the head after a repair can show no checks. Thedocs-checkrun that pushed the repair has already linted the repaired tree. luria newstays local. It assigns an entry’s identity and scaffolds its fields, which CI cannot do.
Alternatives considered
- Keep the local gate. That is the status quo. It doubles every check, costs minutes per push at the record’s present size and more as it grows, and leaves work unpushed in the meantime. In return it would catch a red check a few minutes sooner, on a branch where a red check harms nothing.
- Run only the lint locally. This would skip the repair but still costs the longest step, and the lint CI runs is the one on the repaired tree. A local lint of the unrepaired tree can disagree with it.
- Push straight to the default branch and let
docs-lintjudge. Rejected by the existing rule that work goes to a branch and a pull request. The record needs a chance to be read before it becomes what the project believes.
Consequences
-
Some pushes will go red. That is expected and cheap on a branch. A pull request is merged only when
docs-checkis green on its head. -
Each push costs a CI run. The record’s CI was already run on every push to a pull request, so pushing more often costs more runs, not new kinds of run.
-
Fork contributions get no pushed repair. On a fork the repair cannot be pushed. The action warns, the lint still runs on the repaired tree, and the contributor applies the repair the log names.
-
CLAUDE.md changes with this decision. Its “Working” section and the rule on link targets now say what is above.
-
Scope. The decision covers this record. PerspectiveLab’s CLAUDE.md gives its own working rules; whether it follows suit is its own decision.
-
Overtaken runs are cancelled (added 2026-10-27). Pushing as work is made means a push can land while the previous push’s
docs-checkis still running. That run’s repair commit is rebased onto the branch before it is pushed (git pull --rebasein luria’s generate action), so it pulls in the newer push’s unrepaired commits. The lint in the same job then reads their bare codes and goes red. The newer run repairs them, so the red was always stale, but it read as a failure and cost a ten-minute run. This happened on nucleation#334 and #338.docs.ymlnow puts each pull request’s runs in one concurrency group withcancel-in-progress, so the overtaken run is cancelled and only the newest repairs and lints. Every other run gets a group of its own, so nothing on the default branch is cancelled or held back. The same race can reach any luria project that pushes as it goes, so a fix in the generate action itself was proposed to luria.