Changes touching this path
- a skipped gate leaves a mark, and landed main gets a canary: the single test gate stops being silent (#642)
Three questions, decided.
1. A test/lint CI workflow — YES, but exactly one, and it runs on landed main
rather than on PRs. The pre-land gate IS the design real gate (loot is the merge
authority, git main is a projection), so a job re-running the same suite on every
review round duplicates it, adds latency, and covers only paths nobody takes.
What it covers instead is SILENCE. The ticket named three ways past the gate that
leave no test run behind; a fourth appeared today and cost a morning — #920 and
#921 each passed their own gate and together left main red, and nobody learned
until the NEXT land failed on a breakage it had not caused. #939 closed that
window; this says so in minutes if anything reopens it. It uploads no artifacts,
so it does not touch the quota blocking releases (#835, #909), and docs-only
pushes are skipped, which is what --skip-tests is documented for.
2. clippy — NO, not yet. ~30 pre-existing warnings mean -D warnings lands
permanently red and warn-only lands permanently yellow, which teaches everyone to
ignore the one signal the workflow exists to make trustworthy. Same argument that
kept an audit gate out of site/ (#916). It wants a cleanup pass and then its own
decision.
3. --skip-tests recording itself — YES, on the verdict line, as tests=ran or
tests=SKIPPED. Shouted like relay=FAILED and branch=FAILED (#519, #625), because
the field is saying the change above it was never proved to build, plus a block
below that cannot be scrolled past. The block also names the thing that is easy
to forget: the perf gate skips WITH it, so such a land writes no point and the
previous one stays the baseline. Before this the only trace of a skip was one
line minutes earlier, above everything anyone was watching for.
Not the commit trailer the ticket offered as the alternative: the projected
commit trailer set is part of the ferry ingest contract, and adding to it is a
wire-adjacent change that wants its own ticket rather than riding this one.
49e4554a · dbf3dbe6… - the docs gate themselves: a land refuses a link that resolves to nothing, five rotted ADR cross-links are fixed, every amended ADR warns in its status, and the artifact sweep retires with its producer
586e3260 · dbf3dbe6…diff - the forge live-database suites now run in CI: test-main.yml stands up a postgres:18 service, provisions it the way setup-forge.js does including its default privileges, migrates it with the commit own loot-forge --migrate, sets every LOOT_FORGE_TEST database url the Rust and site suites read, and runs cargo test and then the site pg tests against it. LOOT_FORGE_TEST_REQUIRE_DATABASE turns a database test skip into a failure through pg::live_opt_in and the site skippingLive helper, and with it set and no url 91 Rust tests and all six site pg files fail, while two half-suites that used to skip silently now say so. The default-privilege tripwires run in CI by decision, and fail on a cluster without provisioning. A new migration that neutralises the roster policy passed the bare suite and failed rls.rs and membership.pg.test.ts against the cluster. It is a canary on landed main and not a pre-land gate, and the prose that said no workflow sets these urls now says that instead (#1735)
c0931f78 · dbf3dbe6…diff - migration 0017 and ADR 0078 now state the deploy window setup-forge.js leaves by migrating before it swaps the container: until the new binary is up the old one reads empty repos and has pushes refused, nothing is corrupted, and the order is kept because migrating first is what the deploy script relies on for every release (#573); the checksum pin stays green and went red on a one-token statement edit, and 0017 says statements rather than bytes. CONTEXT.md and ADR 0078 stop saying no CI runs the live suites, the rls.rs header names the key the workflow sets and says the cluster tests are the ones that return early, and the 2026-09-08 evidence entry gets a dated follow-up rather than a rewrite. binding_census now walks every file under src/pg instead of a hand-kept pair, reads fn items of any visibility, follows SQL held in a module-level const and drops cfg(test) items and files, and Pg::with_conn, with_txn and with_repo are private to pg so the compiler keeps other modules from issuing statements through them. a planted pub(crate) method in a new pg/planted.rs reading such a const went red under the new census (1 passed, 1 failed) and stayed green under the old one, and removing each widened shape turned the census red. the source_walk message on flags.rs drops its stale six-lines count, and a new assertion holds that flags.rs calls into the module on more lines than it has consumers, which went red when that premise was broken. the table counts in CONTEXT.md and pg/mod.rs point at the constants that hold those sets rather than restating a number, pg/mod.rs points at the path include instead of listing its includers, the Admitted doc says within and within_leaf read through the leaf spec they are handed, the test-main.yml provisioning comment names the grant repair it drops as a no-op on a fresh cluster, and the rewrap leftovers are fixed. the bare workspace suite is green, and the loot-forge suite is green against a throwaway cluster with the CI env block (#1953)
f2cbbb4c · dbf3dbe6…diff - the metrics dashboard reader test runs in CI instead of passing by running nothing: test-main.yml already ran every site pg test under LOOT_FORGE_TEST_REQUIRE_DATABASE, and metrics-read.pg.test.ts skipped there with a bare console.warn, so the guard 2010 added fired only by hand. the file now calls skippingLive like its siblings, and it went from exit 0 with all tests skipped to a failure under the flag with no keys. the workflow provisions loot_metrics the way the scripts repos metrics-db.js does, bare LOGIN roles, the database and CONNECT only, so every table, sequence and function grant comes from the migrations as in production; it then applies site/migrations in C-locale order from this commit, and sets the two metrics keys. the step was pulled out of the parsed YAML and run verbatim against a throwaway password-auth PostgreSQL 17, twice to show it is idempotent, and the test then passed 3 of 3 with the exact CI URLs under the flag and failed on syntax error at or near returning when that alias was put back. no CI run proves it yet: GitHub refused to start any Actions job over account billing. the text tests header says the land gate runs it only when the landers environment carries the keys (#2041)
7b84226b · dbf3dbe6…diff - the live-database checks test-main.yml runs can run locally, from the same script CI runs, because the account is out of Actions minutes and a land never ran them: the provisioning, the database keys and the suites move out of the workflow into ci/test-main.sh, which builds every connection URL from a host and a port it requires rather than defaulting to the one a real cluster listens on, and the workflow keeps only what prepares a fresh runner and calls it. ci/local.sh starts a throwaway Postgres on its own port, refuses if anything already answers there, runs that script against it and deletes the cluster on exit, so it runs beside a real cluster and from a lane before a land. run in a lane against a portable Postgres 18.6 it applied forge migrations 0001 to 0017 and the three site migrations, and 122 cargo test results and all seven site live files passed with LOOT_FORGE_TEST_REQUIRE_DATABASE set, so none skipped, before and after the review fixes. with the returning alias put back into read.ts it failed at the site step on syntax error at or near returning, and pointed at the port a real cluster owns it refused with exit 2. the CI-shape pin reads through the script and its STEPS list, because the job is still named cargo test --workspace and a check on the workflow text alone would pass on the name after the command had gone; it went red when the workflow stopped calling the script and when the script dropped --locked. the comments and living docs that said the workflow sets the keys now say the script does, the dated ADR and evidence entries are left as history, and AGENTS.md, docs/agents/workflow.md and the afk-loop security hunt point at the script. the Actions wiring itself is unexercised until minutes return (#2061)
8ff6117c · dbf3dbe6…diff - revset_everywhere names each scratch directory by a per-process counter rather than the clock, so two tests asking for the same row no longer share one copy: on Windows SystemTime ticks in 100 ns steps and the tests here reach scratch(archive) together, so a second caller could empty the first caller copy and fill it with another fixture store, which answers no change matching word for word. reproduced by overwriting one copy with another fixture by hand, and by naming scratch by process id alone (5 passed and 5 failed, the historic test failing at loot archive with the #2258 message). pinned by concurrent_scratch_callers_never_share_a_directory, red under the old clock naming in 18 runs of 18 (0 passed and 1 failed, 9 to 14 of 400 directories handed twice), restored green. ci/test-main.sh runs the workspace suite with --no-fail-fast and runs the site live suites after a red workspace suite, recording a failed suite and exiting non-zero naming it, while a failed provisioning step still stops the run; the bare step-or-record form was measured exiting 0 over a failed step, so a suite step runs in a subshell with set -e. the published_surfaces pin reads the --no-fail-fast line (5 passed and 1 failed with the flag removed). no migration, format byte or wire byte moves. the workspace suite is green under bash ci/local.sh against Postgres 18 (4431 passed over 138 binaries, 13 ignored; site live suites 7 files passed) (#2258)
e39a6465 · dbf3dbe6…diff
Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.