Skip to content

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

Part of work-graph-github — The projection to GitHub is gated, identified and traversable, and a merged pull request leads back to the outcome it served.

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

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

coverstypecommandresultat commit
drift_gatedtestbash test/run.sh 97_github_gatethe 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 remote21f7ad8
drift_gatedciscripts/ci/github-checkgreen 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 job21f7ad8

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.