| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .. | ||
| project-state | ||
| .gitignore | ||
| ci-status.sh | ||
| claude-hook-push-ci.sh | ||
| README.md | ||
| validate-distribution.py | ||
tools
Cross-repo operational tooling. Lives here rather than in a component repo because it reaches across all of them.
ci-status.sh — what did CI actually do
./ci-status.sh # infer the repo from the cwd's git remote
./ci-status.sh souveraine # name it
./ci-status.sh souveraine 10 # last 10 runs instead of 3
./ci-status.sh --all # newest run for every repo we own
Exits 0 when the newest run is green or still going, 1 when it failed, so it works as a gate as well as a report. On a failure it drills down by itself: the run, then which job, then the tail of that job's log with the docker noise stripped.
Token comes from $GITEA_TOKEN, else ~/.git-credentials, else the Pixel3Arch
remote URL. No new copy of a secret in the tree.
Read this before trusting anything else for build status
journalctl -u gitea-runner is not a status source. It logs task pickup
and never outcome, so a run that died thirty seconds in still shows as
activity. That habit produced three confident wrong diagnoses in a row on
2026-07-28 while the correct answer sat in the API untouched.
The failure that prompted all this: a pinned action SHA rotted, rust-test died
before compiling, and so aarch64-artifact was skipped — not failed. The run
looked unremarkable, edge silently stopped publishing, and the phone kept
installing a build from days earlier for a working day. Full write-up and the
three-layer fix in ../docs/tasks/42-build-outcomes-are-invisible.md.
claude-hook-push-ci.sh — the same thing, without having to remember
A Claude Code PostToolUse hook on Bash. It ignores everything that is not a
git push, and after one it prints that repo's CI status.
Wired in ~/.claude/settings.json:
"hooks": {
"PostToolUse": [
{ "matcher": "Bash",
"hooks": [ { "type": "command",
"command": "/home/casey/Projects/SouveraineOS/tools/claude-hook-push-ci.sh" } ] }
]
}
It always exits 0 — a status reporter that can block a push is a worse problem than the one it solves.
What it cannot do. A cross build takes ~20 minutes, so straight after a push
the honest answer is usually "running". It reliably catches the fail-fast class
— pin rot, lint, attribution, a broken workflow edit — which is what actually
bites. Catching "publishing quietly stopped" needs the staleness comparison in
TASK-42 layer 2, which belongs to souveraine-updater, not to a longer sleep
in a hook.
Pinning actions, since this is where it cost us
- A tag's SHA is immutable.
actions/checkout@34e1148(v4) survived untouched. - A branch tip's SHA is not.
dtolnay/rust-toolchainforce-movesstableevery Rust release, which orphaned the pin — the commit still exists as a GitHub object but is reachable from no ref, so act cannot resolve it. - If an action must track a branch, pin to a commit on an append-only branch and say in a comment why that branch was chosen.