I1404 — The drift check is a gate, so a projection that stops being applied cannot stay silent
Run `scripts/github-sync --check` from CI on every change that can move the canonical model or the adapter, and fail the build on drift with the record and the remedy named.
DONE wave 2 · p0 · implementation profile · runs alone
Objective
Run `scripts/github-sync --check` from CI on every change that can move the canonical model or the adapter, and fail the build on drift with the record and the remedy named.
Why
This is the root cause of the milestone. The adapter has exited 11 on drift since it was written and nothing has ever called it, so the projection decayed from complete to 10 per cent without one red build. `core-check` runs --plan and --render, which prove the adapter runs, not that the projection is current.
Current state
scripts/ci/core-check lines 67 and 69 run --plan and --render. .ai/repo/ci/gates.yaml line 178 already lists scripts/github-sync in the paths that trigger the core gate, so the trigger exists and the check does not.
Desired state
A drift finding is a build failure. The gate needs a token to read the remote, so it declares what it needs and says so when it is absent rather than passing quietly.
Scope
- scripts/ci
- .ai/repo/ci/gates.yaml
- .github/workflows
- .ai/repo/rules/project
- test/cases
Out of scope
- Applying the projection from CI, which stays a deliberate human act
Dependencies
What waits on this
- I1403READY Backfill the projection once, deliberately, and record what it created
- I1407DONE One issue travels the whole path and back, as an executable case
- I1408DONE The documents stop claiming a projection nobody runs
Acceptance criteria
- The gate runs the drift check on every change to the model or the adapter, refuses behind, edited, conflict, unmanaged, state and milestone outright, and ratchets missing and adopt against a committed baseline
- A missing or unauthorised token is reported as an unusable gate, never as a passing one
- A rule states that the projection is gated, and doctor verifies the gate is wired rather than merely present
- Introducing a canonical issue without projecting it turns the gate red, proved by a case
- Moving a canonical record that was already projected turns the gate red, proved by a case
- The baseline may fall and may never rise, and the gate refuses to run without one
Validation
- scripts/ci/core-check
- majordomus doctrine
- bash test/run.sh
Evidence required
- drift_gated
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| drift_gated | test | bash test/run.sh 97_github_gate | the gate refuses a record whose canonical text moved, breaks the ratchet on a record added to the model and never projected, refuses an edited region and an unmanaged remote issue, passes at the baseline, and refuses to run with no baseline; all proved offline against a fixture remote | 21f7ad8 |
| drift_gated | ci | scripts/ci/github-check | green on this tree at the committed baseline (missing 181, adopt 19); wired as gate github-projection in .ai/repo/ci/gates.yaml, selected by the layer and shell path classes, with issues:read and GH_TOKEN added to the structure job | 21f7ad8 |
Risk
Wiring a zero-tolerance gate before the backfill would make master red on a backlog nobody introduced today. The two tolerances are the mitigation: the states that mean new drift are refused from the first run, and the backlog is ratcheted against a committed baseline that may only fall. That inverts the dependency — the gate no longer waits for I1403, and I1403 becomes the act that lowers the baseline to zero.
Timeline
- started
- 2026-09-09T17:37:02Z
- verified
- 2026-09-09T17:37:27Z
- completed
- 2026-09-09T17:37:41Z
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I1404.yaml. Read it back with majordomus plan show I1404.