Skip to content

Constitution-as-Code: Gating MCW with Software Lifecycle Tooling

Status: Proposal · v0.1 · June 2026 Relationship to the framework: Governance instrument. This document does not modify any canonical construct (see Constitution, Article I). It proposes a process for enforcing the Constitution as the framework is cited, extended, forked, and challenged.


Motivation

The MCW Constitution defines eight binding invariants whose entire purpose is to keep cross-study comparison possible as the framework spreads. But a constitution that is only prose is aspirational: nothing stops a contribution — a pull request, a fork, an extension paper's companion repo — from silently redefining a canonical term (Article I), citing a toy-experiment design as a result (Article IV), or compressing a construct in a way that drops its falsification condition (Article VII).

Software engineering solved an isomorphic problem decades ago. Codebases also have invariants that must survive many contributors, and the discipline that protects them is the software development lifecycle (SDLC): version control, branch protection, required reviews, templated change requests, automated checks, and explicit definitions of "done." The Constitution's invariants are, structurally, lint rules for a scientific vocabulary.

This document proposes treating them that way:

  1. A GitHub-native gating method — what existing GitHub SDLC features can enforce today, with zero custom software.
  2. A gap analysis — the invariants GitHub cannot check, and why.
  3. A GitHub App proposal — a "Constitution Sentinel" that closes the gap with LLM-backed semantic checks, designed to respect the framework's own epistemic humility.

A guiding constraint, borrowed from the framework itself: the enforcement tool must not overclaim (Article VI). A linter for an L0–L1 framework must not pretend to L4 certainty. Mechanical violations may hard-block; judgment calls escalate to a human.


Part 1 — The GitHub-native gating method

Each Constitution Article maps to one or more existing GitHub controls. The table below is the core deliverable: a control matrix.

Article Invariant GitHub-native control(s) Enforcement strength
I — Definition Immutability Canonical terms fixed in glossary; departures must be declared CODEOWNERS makes docs/glossary.md + docs/constitution.md require author review on any change; a "definition-change" PR label is required to touch the definitions block; a mechanical Action fails the PR if glossary definition anchors changed without the label Procedural (the fact of change is gated; the semantics are not — see Part 2)
II — Layering Invariant No construct at layer N without a layer N−1 equivalent Issue template "Extension Proposal" forces a "Layer 0 plain-language statement" field; PR checklist requires a traceability claim Procedural only
III — Substrate Independence Restrictions to a substrate must be declared as scope, not definition PR/issue template requires a "substrate scope" declaration field; label scope:substrate-specific Procedural only
IV — Epistemic Floor No claim above its evidence layer Required evidence:L0evidence:L4 label on any PR/issue making an empirical claim; Action fails if an "empirical-claim" doc lacks an evidence-layer marker string Mechanical (presence) + Procedural
V — Extension Protocol Extensions declared, non-contradictory, falsifiable, traceable "Extension Proposal" issue/PR template with four required fields (declaration, non-contradiction statement, falsification condition, lower-layer trace); Action fails if any field is empty Mechanical (completeness) + Procedural
VI — Anti-Capture MCW is not a product/system/model feature Action scans changed prose for overclaim patterns ("implements MCW", "MCW-aware", "solves the MCW problem", "our \<system> reduces MCW") and flags for review Mechanical (pattern) — high false-positive, advisory
VII — Compression Invariance Summaries must keep falsification conditions, evidence level, exclusion list Action requires that any file tagged as a summary contains a falsification-condition marker, an evidence-layer marker, and a "what it is not" block Mechanical (presence only)
VIII — Scope Boundaries Extensions into adjacent layers need justification PR template "adjacent-layer justification" field; label scope:adjacent-layer triggers required review Procedural only
Amendment Procedure Version bump + prior-text + rationale; some Articles unremovable Action fails a PR that edits constitution.md without incrementing the version header and adding an "Amendment Rationale" section; CODEOWNERS forces author approval Mechanical + Procedural

Concrete GitHub-native artifacts to add

  • .github/CODEOWNERS — assign canonical files to the author:
    /docs/glossary.md       @rainmana
    /docs/constitution.md   @rainmana
    
    Combined with branch protection's "require review from Code Owners," this makes Article I and the Amendment Procedure procedurally unbypassable.
  • Branch protection on main — require a PR, require the governance status checks to pass, require Code Owner review, require linear history.
  • Issue Forms (.github/ISSUE_TEMPLATE/):
  • extension_proposal.yml — Article V's four conditions as required fields.
  • definition_change.yml — Article I departure-declaration in the canonical form.
  • empirical_claim.yml — Article IV evidence-layer dropdown (L0–L4) + supporting data.
  • PR template — a Constitution checklist:
    ## Constitution compliance
    - [ ] No canonical term is redefined (Article I), OR a departure is declared below.
    - [ ] Any new construct traces to a Layer 0 statement (Article II).
    - [ ] Substrate restrictions are declared as scope, not definition (Article III).
    - [ ] Every empirical claim declares its evidence layer L0–L4 (Article IV).
    - [ ] Extensions are declared, non-contradictory, falsifiable, traceable (Article V).
    - [ ] No anti-capture overclaims (Article VI).
    - [ ] Summaries preserve falsification conditions + exclusions (Article VII).
    - [ ] Adjacent-layer extensions are justified (Article VIII).
    ### Declared departures (if any)
    > This work uses a modified definition of [term]. Canonical: [cite]. Modification: [...]. Rationale: [...].
    
  • Label taxonomy: article:Iarticle:VIII, evidence:L0evidence:L4, type:extension, type:definition-change, scope:substrate-specific, scope:adjacent-layer, status:needs-departure-declaration, governance:blocked.
  • Mechanical Actions (.github/workflows/constitution-lint.yml):
  • glossary structural lint — every canonical construct still present; each has a "what it is not" exclusion block (Article VII / Article I structural floor).
  • anchor/link integrity between constitution.md and glossary.md.
  • amendment guard — editing constitution.md requires a version bump + rationale.
  • marker-presence checks — empirical docs carry an evidence-layer marker; summaries carry falsification + exclusion markers.
  • A governance Project board — views grouped by Article, by evidence layer, and by status, so contributions are visibly gated rather than merged on vibes.

This much is buildable today with only YAML and Markdown — no service to operate.

Phase 0 status: implemented

As of July 2026, the mechanical layer above exists in this repository:

  • scripts/constitution_lint.py runs in CI (.github/workflows/constitution-lint.yml) on every push and pull request: glossary structural lint (every canonical construct present exactly once; exactly six failure modes and five repair operations; Definition blocks; exclusion blocks on core constructs; a Layer 0 gloss per canonical entry), internal link/anchor integrity across docs/, per-page evidence-layer markers, and an advisory Article VI overclaim scan. A strict site build runs alongside it.
  • The amendment guard is hash-based. The frozen fields of each canonical entry (per the glossary change policy) are pinned as plain-text snapshots in governance/canon/ with SHA-256 hashes in governance/canon_hashes.json. Any divergence fails CI. Changing a pin requires the [definition-change] commit marker or the type:definition-change label; editing constitution.md requires a version bump plus an "Amendment Rationale" section (or a [non-normative] marker for formatting-only changes). Downstream implementations can vendor the snapshots to detect upstream drift in their own CI.
  • The evidence-tag convention is lintable: empirical claims carry inline [L0][L4] tags at the claim site, and every docs page carries an evidence marker (tag or Evidence: Ln status line). The lint checks presence — it cannot check truthfulness (see Part 2).
  • CODEOWNERS, the label taxonomy (.github/labels.yml), the three issue forms, and the PR compliance checklist exist as specified above. The label taxonomy is synced automatically to repository settings by labels-sync.yml (create/update only — labels not in the file are reported, never deleted), so the versioned file is the operative source of truth rather than documentation of one.
  • One control remains manual by GitHub's design: branch protection. Making constitution-lint's "Mechanical constitution checks" and "Strict site build" required status checks — and requiring Code Owner review — is set in repository settings (Settings → Branches → protect main), not in any file this repo can carry. Until that is clicked, the checks run on every PR but cannot block a merge; this sentence exists so that gap is stated rather than assumed away.

The single-maintainer degenerate case, stated honestly. This repository currently has one maintainer. Code Owner review is therefore self-review: it gates authorship (nothing merges without the author acting deliberately), but it provides no independent judgment. Until a second reviewer exists, the mechanical lint is the only non-self reviewer this project has — and it can verify only that declarations exist, never that they are true. Semantic verdicts of the flag/uncertain kind (Part 3) have no meaningful disposition under self-review; anything a future Sentinel would flag should instead be recorded as an open issue so the judgment call is at least public. Claims about what this governance layer achieves must be read against that limit.


Part 2 — Gap analysis: what GitHub cannot do

Every "Procedural only" and "presence only" row above shares the same ceiling: GitHub can verify that a declaration exists; it cannot verify that the declaration is true. The Constitution's hardest invariants are semantic — they require reading comprehension and judgment. Specifically:

Gap The semantic question GitHub can't answer Article
Undeclared redefinition The glossary text changed — but did the meaning change? If so, is the departure declaration adequate, or cosmetic? I
Fake traceability A "Layer 0 statement" field is filled — but does it actually compress this construct, or is it unrelated boilerplate? II
Overclaiming A claim is stated — does the supporting evidence actually reach the declared layer, or is an L1 anecdote dressed as L3? IV
Extension validity The four fields are filled — but is the extension genuinely non-contradictory and genuinely falsifiable, or falsifiable-in-name-only? V
Anti-capture in prose Pattern matching flags "implements MCW" — but misses "our architecture maintains shared understanding across turns," which is the same overclaim in disguise; and false-flags legitimate quoted critique VI
Compression fidelity A falsification-condition marker is present — but does the summary actually preserve the original condition, or did it keep the heading and gut the content? VII
Adjacent-layer justification A justification field is filled — does the coordination-layer lens actually add value, or is it scope creep with a paragraph stapled on? VIII

These are not edge cases; they are the substance of the Constitution. A vocabulary collapses through plausible-looking contributions that pass every mechanical check while quietly violating meaning. Mechanical gating raises the floor; it does not reach the ceiling.

This is precisely the seam where an LLM-backed check earns its keep — and, fittingly, it is itself a coordination problem between a human reviewer and an automated reader.


Part 3 — Proposed GitHub App: "Constitution Sentinel"

Concept

A GitHub App, installable on the canonical repo and on forks, that runs as a required status check on pull requests and as an issue triager. It is backed by a language model that loads the Constitution and glossary as ground truth and performs the semantic checks from Part 2 that mechanical tooling cannot.

Working name: Constitution Sentinel (alt: Canon Keeper, MCW Warden). It is deliberately not named or marketed as "MCW-aware" — per Article VI, a tool does not implement MCW. It is a linter for a document, nothing more, and says so.

What it checks (each maps to a Part 2 gap)

  1. Definition-drift detector. On any diff to glossary.md/constitution.md, compare changed definitions against the canonical baseline and judge whether meaning changed. If it did and no adequate departure declaration is present → flag.
  2. Layer-trace verifier. For new constructs, judge whether the provided Layer 0 statement genuinely compresses the higher-layer construct (Article II).
  3. Epistemic-floor / overclaim detector. For each empirical claim, judge whether the supporting data reaches the declared evidence layer; flag claims stated above their support (Article IV) — the framework's most important and most violated rule.
  4. Anti-capture scanner. Read prose for capability-claim-dressed-as-coordination and product/marketing overclaims, including paraphrases pattern-matching misses (Article VI).
  5. Compression-invariance checker. For summaries, judge whether falsification conditions, evidence level, and exclusion lists were preserved in substance (Article VII), not merely whether headings exist.
  6. Extension-protocol validator. Judge declaration, non-contradiction, falsifiability, and traceability of proposed extensions (Article V).

Design principles (so the tool obeys the framework it guards)

  • Mechanical violations hard-block; judgment calls escalate. The App never fails a PR on a semantic verdict alone. A semantic flag posts an inline review comment and sets the check to "action required → human review," not "failed." Only mechanical rules (missing version bump, empty required field, missing exclusion block) hard-fail. This mirrors StoryLoom's proportional gates and prevents the linter from overclaiming certainty it does not have.
  • Every verdict is grounded and cited. Output references the specific Article and quotes the offending text and the canonical text it conflicts with. No bare verdicts.
  • Reproducibility. Model id and prompt version are pinned and recorded in the check output (Article IV/VII spirit: claims carry their provenance). Re-running on the same diff yields a comparable, auditable result.
  • Uncertainty is first-class. Verdicts are pass | flag | uncertain, never a forced binary. uncertain routes to the human, who is the authority (the framework is L0–L1; the reviewer outranks the tool).
  • Self-non-claim. The App's README must state: "This App enforces document invariants. It does not implement, embody, or measure MCW (Constitution Article VI)."

Architecture sketch

GitHub (PR / issue webhook)
Constitution Sentinel (GitHub App)
  ├── event router (pull_request, issues, issue_comment)
  ├── context loader  → pins canonical constitution.md + glossary.md at base ref
  ├── diff extractor  → changed docs, claims, summaries
  ├── semantic checker → LLM with Constitution as system context; per-Article prompts
  ├── verdict composer → Check Run (per-Article pass/flag/uncertain) + inline comments
  └── status setter    → commit status that branch protection can require
Pinned model API (provider-agnostic; model + prompt version recorded)
  • Config file .mcw/constitution.yml in each repo: maps Articles → enabled checks → severity (block vs advisory), and pins the canonical source paths/refs. Forks can tune severity but cannot silently disable Article I or IV without it showing in the config diff (which CODEOWNERS gates).
  • State: mostly stateless per-PR; optional store for verdict history/metrics.

Phased rollout (build-vs-buy)

Phase Deliverable Operating cost Fork PRs
0 GitHub-native only: CODEOWNERS, branch protection, issue forms, PR template, mechanical Actions (Part 1) None — YAML/Markdown only ✅ Works (no secrets needed)
1 A CI job (GitHub Actions) that calls an LLM API on PR diffs and posts an advisory governance comment API usage only; no service to host ⚠️ Needs a secret-safe path (see below)
2 Promote the semantic check to a required status check; add issue triage/labeling API usage only ⚠️ Same caveat as Phase 1
3 Package as a distributable GitHub App installable on forks, so the ecosystem can self-gate Hosted App + API ✅ Works (App holds the credential)

Phase 0 captures the entire mechanical layer with no secrets and works identically on fork PRs. Phase 3 is what actually serves the Constitution's deepest goal: if forks and citing repos can install the same Sentinel, definitional drift across the ecosystem becomes measurable and resistible, which is the entire point of having a Constitution.

Fork PRs and secret handling (a Phase 1/2 constraint)

The semantic checks (Phases 1–2) need an LLM API key. By GitHub's security design, a workflow triggered by pull_request from a fork does not receive repository secrets — it gets only a read-scoped GITHUB_TOKEN. This is correct and protective (it stops an attacker from opening a PR that exfiltrates your keys), but it means a naïve "Actions calls an LLM API" job will be unusable on exactly the outside contributions the gate most needs to check. The proposal must therefore pick a secret-safe path before relying on Actions for fork contributions:

Option How it handles the secret Trade-off
A. Same-repo only + maintainer label Run the semantic check only on branches in the canonical repo, or on a fork PR after a maintainer applies a safe-to-scan label and re-dispatches Simple and safe; fork PRs get the check only after a human opt-in (acceptable — a human is in the loop anyway)
B. pull_request_target with strict hygiene This event runs in the base repo's context and does have secrets; check out the base ref, treat the PR diff/text purely as data, and never execute fork-supplied code, scripts, or actions Powerful but a well-known footgun; mishandled pull_request_target is a classic secret-exfiltration vector. Only safe if the job never runs untrusted code
C. GitHub App / external proxy (Phase 3) The App (or a tiny proxy service) holds the credential server-side and posts the Check Run; the workflow never sees the key The robust answer for an open ecosystem; costs a hosted component

Recommendation: forks get Phase 0 (mechanical) checks immediately and unconditionally; semantic checks on fork PRs wait for Option A (label-gated) until the project is ready to operate Option C. Do not reach for pull_request_target unless the job is provably free of untrusted-code execution. This caveat is itself an instance of the secret discipline the framework cares about — the enforcement tooling must not become the weakest link it was built to protect.


Part 4 — Does the governance method itself work? (falsification)

In keeping with Article IV and Article V, the governance method makes a falsifiable prediction about itself:

Hypothesis. Constitution-as-code gating reduces undeclared invariant violations reaching main relative to ungated contribution.

Observable. Track, per merged PR, the rate of (a) undeclared term redefinitions, (b) claims stated above their evidence layer, (c) summaries that dropped falsification conditions. Compare gated vs. ungated periods/forks.

Falsification. If gating produces no measurable reduction in (a)–(c) — or if the review burden so suppresses contribution that the framework stops evolving — the method has failed and should be simplified back toward Phase 0, or abandoned.

Evidence layer of this proposal: L0 — Illustration. It is a design, not a result. No gating run has been piloted. Stated explicitly per Article IV.


Relationship to StoryLoom

This is the research-governance instance of the same philosophy used to build the StoryLoom application (rainmana/storyloom): proportional gates, evidence over vibes, hard rules where the blast radius is large, human judgment where automation would overclaim. One project gates a codebase; this one gates a vocabulary. The shared move is using ordinary SDLC tooling to make invariants enforceable instead of merely stated.