Run the instruction drift check as a step - #106
Conversation
The check was a job calling `check-drift.yml` as a reusable workflow. Actions is free on a public repository, so nothing was billed for it; what it cost was a job -- a scheduling slot and a row in all 15 runs of the last thirty days -- for nine seconds of byte comparison. As a step it runs inside a job that already exists, and the fleet's other consumers now carry it the same way. `markdown` hosts it. In the consumers that have a change filter the placement is forced: AGENTS.md counts as inert documentation there, so a pull request confined to a generated region is docs-only and a gated step would be skipped on exactly the change that causes drift. This workflow has no filter, so the choice rests on `markdown` already being the job for this class of file -- and on its being the job that would have to stay ungated if a filter is ever added. A step's default `success()` would skip it whenever the lint ahead of it failed, which the two jobs never did to each other, so the step carries `!cancelled()` and requires only that the checkout succeeded -- the action reports a workspace it cannot read as a problem with the pin. The header of update-instructions.yml named `.agents/instructions.toml`, which exists in no consumer; the pin is `.agent-instructions.toml`. AGENTS.md lists the jobs a contributor should see pass, so it now says what `Markdown` checks beyond the lint. Closes #105
Temporary: proves the drift check still fails from its new home. Reverted in the next commit.
Restores the marked block. The failing run it produced is linked from the pull request.
Test plan resultsA drifted block fails. Run 34420368640 (
Also visible in the log: The revert goes green. Run 34421771992 ( The comment already sitting above |
Closes #105.
The drift check was a job calling
aicers/agent-instructions/.github/workflows/check-drift.yml@mainas a reusable workflow. Actions is free on a public repository, so there is no bill to cut here — what the arrangement cost was a job: a scheduling slot and a row in every one of the 15 runs of the last thirty days, for nine seconds of byte comparison. As a step it runs inside a job that already exists. aicers/agent-instructions#60 shipped the check as a composite action, and the other consumers already carry it this way.What changed
ci.yml: theinstructionsjob is gone;markdowngainsid: checkouton its checkout and- uses: aicers/agent-instructions/check-drift@mainas its last step.AGENTS.md: its CI section lists the jobs a contributor should see pass. It gains a line saying thatMarkdownruns the drift check after the lint, and that the generated regions are not to be edited here. Outside theshared:markers.update-instructions.yml: the header comment said the apply moves the pin in.agents/instructions.toml. No such file exists in any consumer — the pin is.agent-instructions.toml. The other copy of that wrong path was in the job comment this change deletes..agent-instructions.tomland the marked blocks inAGENTS.mdare untouched, the check does the same work with the same messages, andmarkdownkeeps both its runner and its lint action — this is not a runner move and not a tool change.Why
markdownIn the consumers that have a change filter this placement is forced: the filter counts
*.mdas inert,AGENTS.mdis a.mdfile, so a pull request confined to a generated region is docs-only and a step in a gated job would be skipped on exactly the change that causes drift.This workflow has no change filter and no gated job, so that reason does not apply and the choice rests on other grounds:
markdownis already the job for this class of file, it is where every sibling consumer keeps the step, and it is the job that would have to stay ungated if a path filter is ever added here. The comment already abovemarkdownanticipates both — it says the job is kept out ofcheck"so a clippy failure cannot hide the Markdown result, and so the lint survives if the expensive jobs are ever put behind a path filter". The same two reasons apply to the drift check.Why the step is guarded
A step's default is
success(), so without this the drift check would be skipped whenever the lint ahead of it failed — hiding drift on the pull requests that touch the most Markdown. As two jobs they always reported independently, and they are independent.!cancelled()rather thanalways()so a cancelled run stops; thecheckoutclause keeps a failed checkout from being reported as drift, since the action fails outright when it cannot read the pin file and that message names the pin for a problem that is not the pin's.Branch protection
Nothing to edit, and this is the part CI cannot demonstrate.
GET /repos/aicers/multifold/branches/main/protectionanswers 404"Branch not protected", so no status check is required onmainandInstructions / checknever was. Organization-level rulesets needadmin:orgto read and were not inspected — worth a maintainer's glance that no organization rule names the check this removes.Verification
actionlintis clean on the edited file. A drift run and its revert are posted below.