Reproduces the merge gate locally and exits non-zero on any failure.
mix ci runs every merge-gating lane and aggregates all results before
exiting — it never silently skips a gate.
Exit codes
| Result | Exit code |
|---|---|
| All preamble + lane steps passed | 0 |
| Any step failed | 1 |
| pgvector preflight failed | 1 |
| Unknown flag supplied | non-zero |
Local-vs-CI asymmetry (D-C2/D-C3)
mix ci runs a preamble that CI's policy job does NOT:
mix deps.unlock --check-unused— orphan lock entriesmix deps.get --check-locked— lock out of sync with mix.exsmix format --check-formatted— format drift (scoped via .formatter.exs; does not touch vendored deps)mix compile --warnings-as-errors— compile gate
This is a deliberate strict superset: more safety locally, never less.
CI symmetry (adding format/deps-lock to the policy job) is a deferred
follow-up — editing contract-guarded workflow at milestone closeout is
scope creep. The asymmetry is documented here as the canonical reference.
Lane set
The gating lane set is derived from Scoria.VerificationLanes (the SSOT):
closeout_order() ++ [:semantic_fast_path, :knowledge, :connector]:support_copilot_gallery is excluded — its exclusions list contains
"merge-blocking closeout", meaning it is an advisory lane that does not
gate merge.
Opt-out: --skip-optional
mix ci --skip-optional (or env SCORIA_CI_SKIP_OPTIONAL=1) skips the
preflight and the optional/Docker-dependent lanes (:knowledge,
:semantic_fast_path, :connector), prints which lanes were skipped, and
stamps:
RESULT: PARTIAL (knowledge, semantic_fast_path, connector skipped — NOT a merge-gate pass)then exits non-zero unconditionally. It can never be mistaken for a clean gate or wired into a pre-push hook as authoritative.