diff --git a/AGENTS.md b/AGENTS.md index a3e6675..b7e4eef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,4 +27,13 @@ L2 statutes live wherever *its* governance map says (see `process/statutes.md`). source-vs-installed-artifact split above is specific to this repo, since it is both the framework *and* a CLI consumer of itself. +**Ratifying an amendment in this repo's own `CONSTITUTION.md`** also bumps the header +`framework: constitution@X.Y.Z (self-hosted)` pin to the same number as the new ledger +entry — F-II requires the pin and the ledger to be one axis here, and nowhere else +(ADR-0002; see `cli/AGENTS.md`'s `LEDGER-SYNC` statute for the mechanized check, and +`skills/audit-structure`'s self-hosted-conditional check). This is repo-specific and +does not belong in `skills/ratify-amendment/SKILL.md`, which is vendored into every +consumer — no consumer is self-hosted, so that step would be dead weight in every +installed copy. + *This file serves as the entry-point index for the audit-structure and compile-prompt skills.* diff --git a/CONSTITUTION.md b/CONSTITUTION.md index dbcb552..6cec562 100644 --- a/CONSTITUTION.md +++ b/CONSTITUTION.md @@ -1,7 +1,7 @@ # The constitution framework — Constitution ``` -framework: constitution@0.17.3 (self-hosted) +framework: constitution@0.17.5 (self-hosted) ratifier: Chinmay ``` @@ -35,7 +35,7 @@ Ratification is agreement; conformance is reality; enforcement is reality's half `HOLDS + UNGUARDED` is true-but-fragile, flagged as mechanization debt. ### Article F-I — Discovery before codification -`status: RATIFIED` · `conformance: HOLDS` · `enforcement: AUDITED` · `party: N/A` +`status: RATIFIED` · `conformance: VIOLATED` · `enforcement: AUDITED` · `party: N/A` - **Principle** — No rule is added to this framework until it has been proven in at least one live project. DSAMind is the founding instance. @@ -44,6 +44,12 @@ Ratification is agreement; conformance is reality; enforcement is reality's half the originating experiment + ADR in a consumer project. - **Why** — a framework written from imagination ossifies around guesses; one written from usage carries its evidence with it. +- **Conformance note (2026-07-05 re-audit)** — VIOLATED. [registry.md](registry.md)'s two + promoted-mechanism rows (F-V/F-VI, F-VII) cite ledger version ranges and doc sections + only — neither names an experiment file nor an ADR id. No `experiments/` directory + exists anywhere, in this repo or DSAMind; no promotion has ever gone through F-III's + pre-registered path. Tracked debt, not fixed as part of this audit — see + `audit-conformance` run, same session as ADR-0003. ### Article F-II — One home per rule `status: RATIFIED` · `conformance: HOLDS` · `enforcement: AUDITED` · `party: N/A` @@ -52,18 +58,21 @@ Ratification is agreement; conformance is reality; enforcement is reality's half duplicated across layers, nor across the framework and an instance. A versioned package manager installation (e.g., via a CLI) satisfies this rule: the package is the single home, and the files it writes to the instance are its read-only build artifacts. - A version number is a governed fact too. Three exist, each with one home: the instance's - own Amendments Ledger version, the framework spec version it has adopted (the header - pin — a ratified claim, never bumped ahead of what's actually adopted), and the - framework tooling installed (the instance's own package manifest). These are never - compared to each other as if they were the same number — except in this framework's - own repo, where the pin and the ledger are the same number on purpose. + A version number is a governed fact too, and three exist, each with exactly one home: + 1. the instance's own Amendments Ledger version, + 2. the framework spec version it has adopted (the header pin — a ratified claim, never + bumped ahead of what's actually adopted), + 3. the framework tooling installed (the instance's own package manifest). + + These three are never compared as one axis, with one exception: in the framework's own + self-hosted repo, axis 1 and axis 2 are the same number by design. Axis 3 is never folded + into that collapse, even here. - **Serves** — P1. - **Fitness** — no rule's text appears verbatim in two layer documents; every cross-layer reference (`serves` / `amends` / `supersedes` / `party`) resolves and every layer traces up; - no rule lives outside a layer. No check treats the ledger version, the header pin, and the - installed tooling version as one axis, except for this framework's own self-hosted repo. - Verified by the `audit-structure` skill. + no rule lives outside a layer. No check treats axis 1 and axis 2 as the same number for any + instance except the framework's own self-hosted repo; no check ever treats axis 3 as the + same number as either of the others, anywhere. Verified by the `audit-structure` skill. ### Article F-III — Experiments are pre-registered `status: RATIFIED` · `conformance: HOLDS` · `enforcement: AUDITED` · `party: N/A` @@ -165,6 +174,50 @@ on the same Article is the signal that the Article itself needs amending. Superseded clauses are never deleted — they are kept here with a forward link and the ADR that justified the change. +### [0.17.5] — 2026-07-05 — Re-audit Conformance +- **Audit:** Ran `audit-conformance` against all seven Articles, same session as ADR-0003. +- **Findings:** + - **F-I flips `HOLDS` → `VIOLATED`.** `registry.md`'s two promoted-mechanism rows cite + ledger ranges and doc sections, not an experiment file + ADR id, as the fitness text + requires. No `experiments/` directory exists anywhere (this repo or DSAMind); no + promotion has ever used F-III's pre-registered path. Tracked debt — not remediated + here (human declined the fitness-amendment option this session; left as-is). + - F-II through F-VII all maintain `conformance: HOLDS`, `enforcement: AUDITED`. + - F-III holds only vacuously — zero experiment files exist to check against; the + mechanism has never actually been exercised. + - F-VI's own fitness ("no Article marked HOLDS while its fitness fails") was itself + unmet before this pass, because of F-I's stale label — fixed by the F-I flip above. +- **Result:** One conformance flip (F-I). No `status` changes; nothing above the firewall. + +### [0.17.4] — 2026-07-05 — Ratified by Chinmay: Article F-II's version-axis clause tightened (ADR-0003) +- **Ratified by Chinmay, 2026-07-05**, per [ADR-0003](decisions/0003-tighten-version-axis-clause.md). +- `derive-statutes`, run against F-II this session, found `[0.17.3]`'s two added sentences + disagreed on scope: Principle's self-hosted exception named two axes (pin + ledger); + Fitness listed all three before the same "except," reading like it covered all three. That + ambiguity had already produced a wrong statute (`cli/AGENTS.md` claimed the tooling axis + collapses too, citing F-II) — fixed in the same session, pending this ADR. +- **Article F-II — Principle and Fitness rewritten** (`status: RATIFIED`, unchanged), as a + numbered 3-axis list with the self-hosted exception scoped to axes 1+2 only in both + clauses. No behavior change — code and the statute already assumed this reading. +- `[0.17.3]` **SUPERSEDED — 2026-07-05 → ADR-0003.** The two sentences it added to + Principle: + > A version number is a governed fact too. Three exist, each with one home: the + > instance's own Amendments Ledger version, the framework spec version it has adopted + > (the header pin — a ratified claim, never bumped ahead of what's actually adopted), and + > the framework tooling installed (the instance's own package manifest). These are never + > compared to each other as if they were the same number — except in this framework's own + > repo, where the pin and the ledger are the same number on purpose. + + And the one sentence it added to Fitness: + > No check treats the ledger version, the header pin, and the installed tooling version + > as one axis, except for this framework's own self-hosted repo. +- Agreement-only — no pre-registered experiment. Wording-only fix; the ambiguity itself was + the evidence. +- Above the firewall — F-II's `status` did not change (already `RATIFIED`); its Principle + and Fitness text did, transcribed per `ratify-amendment`. +- Self-hosted repo: header pin bumped to `0.17.4` alongside this ledger entry (F-II's own + pin↔ledger collapse, per this repo's root `AGENTS.md`). + ### [0.17.3] — 2026-07-05 — Ratified by Chinmay: Article F-II extended — three version numbers, three homes - **Ratified by Chinmay, 2026-07-05**, per [ADR-0002](decisions/0002-version-axis-separation.md). - Found auditing DSAMind (`dsa_project`): the engine's `LEDGER-SYNC` check compared a diff --git a/cli/AGENTS.md b/cli/AGENTS.md index a85bc4e..7890bc4 100644 --- a/cli/AGENTS.md +++ b/cli/AGENTS.md @@ -34,17 +34,34 @@ package-managed distribution mechanism, per version and the repo's `package.json` from drifting apart instead. - **`cli/package.json`'s `version` always equals this repo's `CONSTITUTION.md` header - version.** One number for the whole self-hosted repo — not a tool-version axis and a - spec-version axis drifting independently. Every `CONSTITUTION.md` version bump that - lands in the same change as a `cli/` publish updates both together; a bump to one - without the other is the bug, not a valid state. - · serves: F-II (one home for "what version is this") + version.** This is repo-specific practice, not an F-II requirement — F-II's ratified + text only blesses collapsing the header pin and the Amendments Ledger into one axis + here; it says nothing about the installed-tooling axis. Syncing the tooling version + too is a deliberate convenience this repo has chosen (mechanized by publish-on-merge), + not something the constitution mandates. A downstream consumer is not expected to do + this, and its own tooling version stays a genuinely independent third axis (F-II). + · serves: general craft (a repo-specific convenience, not an L1 mandate) · enforced-by: CI (`.github/workflows/publish.yml` fails the publish job on any mismatch between `cli/package.json` and the `CONSTITUTION.md` header; locally, `constitution doctor` auto-syncs via `constitution.config.json`) · why: two independently-numbered versions for one repo is exactly the confusion a consumer hits first — "why does `constitution --version` say 1.0.0 when the spec - ledger is at 0.16.x." One axis removes the question. + ledger is at 0.16.x." One axis removes the question *for this repo*, by choice, not + by rule. + +- **The self-hosted repo's `framework:` header pin and its newest Amendments Ledger + entry are the same axis and must match — this collapse is what F-II's ratified text + actually requires.** A downstream consumer's pin (the framework spec it adopted) and + its own ledger (its product's version) are legitimately independent and must never be + compared this way. + · serves: F-II (the pin↔ledger collapse, scoped to the self-hosted case only) + · enforced-by: CI (`.github/workflows/governance.yml` runs `constitution audit`, + which fails on `LEDGER-SYNC`) + hook (`constitution hooks install`'s pre-commit + gate runs the same check) + · why: this exact confusion is what ADR-0002 traces to — `LEDGER-SYNC` + (`src/engine/audit.ts:87-93`) used to fire unconditionally, wrongly comparing a + downstream consumer's adopted-spec pin against its own product ledger. The + `doc.selfHosted` scoping is the fix; see `decisions/0002-version-axis-separation.md`. - **`skills/`, `templates/`, `process/` are vendored into `cli/` at build time (`scripts/vendor.js`, run via `prebuild`/`prepack`) — never assume they exist as diff --git a/cli/package-lock.json b/cli/package-lock.json index bd0f7cf..6d07dd4 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@chinmaygit/constitution-cli", - "version": "0.17.2", + "version": "0.17.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@chinmaygit/constitution-cli", - "version": "0.17.2", + "version": "0.17.5", "license": "MIT", "dependencies": { "prompts": "^2.4.2" diff --git a/cli/package.json b/cli/package.json index 05344ec..75687a8 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@chinmaygit/constitution-cli", - "version": "0.17.3", + "version": "0.17.5", "description": "The constitution governance engine: scaffold, audit, firewall-gate, compile, render, and track AI-native product development", "license": "MIT", "author": "Chinmay", diff --git a/cli/test/engine.test.ts b/cli/test/engine.test.ts index 305300d..59e4973 100644 --- a/cli/test/engine.test.ts +++ b/cli/test/engine.test.ts @@ -47,7 +47,7 @@ describe('parse', () => { ]); expect(inst.constitution.articles.every((a) => a.status === 'RATIFIED')).toBe(true); expect(inst.statutes.length).toBeGreaterThan(5); - expect(inst.adrs).toHaveLength(2); + expect(inst.adrs).toHaveLength(3); const findings = audit(inst); expect(findings.filter((f) => f.severity === 'error')).toEqual([]); }); diff --git a/constitution.lock.json b/constitution.lock.json index 0c44172..1b16e0a 100644 --- a/constitution.lock.json +++ b/constitution.lock.json @@ -1,8 +1,8 @@ { "lockVersion": 1, - "constitutionVersion": "0.17.3", + "constitutionVersion": "0.17.4", "acceptedBy": "Chinmay", - "acceptedAt": "2026-07-05T08:45:28.047Z", + "acceptedAt": "2026-07-05T10:25:23.000Z", "units": { "P1": { "kind": "preamble", @@ -14,7 +14,7 @@ }, "F-II": { "kind": "article", - "hash": "06ed10f12ad527f757a808764c7ee7f6fcc3432bfb06737a6180ad7a980334a5" + "hash": "1feb6f2adad3979f468a5937302a53e860d63e5b5c46da85bab12996d000b90d" }, "F-III": { "kind": "article", diff --git a/decisions/0003-tighten-version-axis-clause.md b/decisions/0003-tighten-version-axis-clause.md new file mode 100644 index 0000000..0396f4a --- /dev/null +++ b/decisions/0003-tighten-version-axis-clause.md @@ -0,0 +1,51 @@ +--- +id: 0003 +title: Tighten F-II's version-axis clause into three numbered, unambiguous axes +status: accepted +date: 2026-07-05 +supersedes: [] +superseded_by: [] +serves: [F-II] +amends: [F-II] +trigger: certiorari +--- + +## Question of law +ADR-0002 added a version-axis clause to F-II's Principle and Fitness. The two sentences +disagree on scope: Principle's self-hosted exception names two axes (pin + ledger); Fitness +lists all three before the same "except," reading like it covers all three. That ambiguity +already produced a wrong statute this session (`cli/AGENTS.md` claimed the tooling axis +collapses too, citing F-II). + +## Ruling +Rewrite both sentences as a numbered list, with the exception scoped to axes 1+2 only in +both places. No behavior change — code and the corrected statute already assume the 2-axis +reading; this just makes the text say what's already true. + +**Principle**, replace ADR-0002's two sentences with: +> A version number is a governed fact too, and three exist, each with exactly one home: +> 1. the instance's own Amendments Ledger version, +> 2. the framework spec version it has adopted (the header pin — never bumped ahead of +> what's actually adopted), +> 3. the framework tooling installed (the instance's own package manifest). +> +> These three are never compared as one axis, with one exception: in the framework's own +> self-hosted repo, axis 1 and axis 2 are the same number by design. Axis 3 is never folded +> into that collapse, even here. + +**Fitness**, replace ADR-0002's sentence with: +> No check treats axis 1 and axis 2 as the same number for any instance except the +> framework's own self-hosted repo; no check ever treats axis 3 as the same number as +> either of the others, anywhere. + +## Constitutional impact +Replaces those two sentences in F-II. `status`/`serves`/`enforcement`/`party` unchanged. Old +text kept verbatim in the ledger, marked `SUPERSEDED — `, forward-linked here. Does not +supersede ADR-0002 — its ruling still stands, this only fixes the wording. + +## Consequences +Closes the ambiguity; no enforcement changes. + +## Alternatives considered +New Article instead of re-amending F-II — rejected, same reason as ADR-0002: still one home +per rule, just stated more precisely. diff --git a/decisions/INDEX.md b/decisions/INDEX.md index a73b17c..751e7a3 100644 --- a/decisions/INDEX.md +++ b/decisions/INDEX.md @@ -7,3 +7,4 @@ an ADR) are L2 statutes — see [AGENTS.md](AGENTS.md). |----|-------|--------|------| | 0001 | Allow package-managed installation of skills to satisfy F-II | accepted | 2026-07-01 | | 0002 | Three version numbers, three homes | accepted | 2026-07-05 | +| 0003 | Tighten F-II's version-axis clause into three numbered, unambiguous axes | accepted | 2026-07-05 | diff --git a/skills/audit-structure/SKILL.md b/skills/audit-structure/SKILL.md index b1bf8df..9945836 100644 --- a/skills/audit-structure/SKILL.md +++ b/skills/audit-structure/SKILL.md @@ -5,7 +5,7 @@ metadata: scope: project layer: cross-cutting enforces: F-II - version: "1.4.0" + version: "1.4.2" --- # Audit the constitution's structural integrity (L0–L4) @@ -63,7 +63,13 @@ below. **4. Field & firewall integrity:** - Every Article carries all required fields: `status`, `conformance`, `enforcement`, `party`, `serves`, `fitness`. - Every L0/L1 amendment in the ledger names a human ratifier (F-IV). -- The instance's framework pin (`constitution@X`) matches `registry.md`; the header version matches the latest ledger entry and the latest tag. +- The instance's framework pin (`constitution@X`) matches `registry.md`. **Only in the + framework's own self-hosted repo** (header marked `(self-hosted)`) does the header pin + also have to match the latest ledger entry and the latest tag (F-II) — in any other + instance the pin (the framework spec it adopted) and the ledger (its own product + version) are legitimately independent axes and must **not** be compared this way + (ADR-0002; see `cli/AGENTS.md`'s `LEDGER-SYNC` statute for the mechanized version of + this same check). **5. Anything OUTSIDE the layers (the headline):** - A rule in the declared L2 statute homes that no layer claims — not tagged L2, no `serves`, not an Article, not an ADR. **Ungoverned rule** → either annotate it as a statute or delete it. @@ -87,8 +93,12 @@ below. other skill trust at day-to-day speed, with no scanning. **Then, only in this audit, cross-check it against an independent scan** of the tree (e.g. `find . -iname 'AGENTS.md' -o -iname 'CLAUDE.md' -o -iname 'AGENTS.md'`, excluding `.claude/`, `.agents/`, `.cursor/`, - `node_modules/`, `dist/`, `.git/`) to catch a home that exists on disk but isn't declared. This - scan is this skill's job alone — the periodic safety net, not a per-task cost every skill pays. + `node_modules/`, `dist/`, `.git/`, **and anything `git check-ignore` reports** — a hardcoded + name list misses a repo's own generated/vendored copies under other names (e.g. this repo's + own `cli/skills/`, `cli/templates/`, `cli/process/` — gitignored build artifacts per + `cli/AGENTS.md`, not `dist/`-named but the same kind of thing)) to catch a home that exists on + disk but isn't declared. This scan is this skill's job alone — the periodic safety net, not a + per-task cost every skill pays. 2. **Run the checks** above. For each finding, record the exact location and what's broken. 3. **Classify** each: `broken-ref` · `orphan` · `duplication` · `ungoverned` · `map-gap` · `map-drift` · `field-gap` · `pin/version drift` · `promotion/demotion signal`.