Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 194 additions & 2 deletions BUILDLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,199 @@ gate live and clean. Worktree rebased onto main.
(live) dashboard beyond static HTML; multi-instance registry telemetry.

### Known-untested / deferred
- Publishing 0.17.0 to GitHub Packages (needs operator's npm auth).
- Tone generation quality (needs `claude` CLI at runtime; engine tested with a stub).
- DSAMind adoption of the new engine (separate repo, separate session).
- Multi-instance/registry telemetry, web dashboard beyond static HTML — later phases.

---

## Session 3 — 2026-07-04 (same worktree; DSAMind adoption; v0.17.2 published + operator's global updated)

### Context at start
Operator published 0.17.1/0.17.2 and updated their global CLI (pre-commit hook now
enforces for real). Scope: point the engine at DSAMind (`~/Workspace/dsa_project`) — a
real, independently-ratified constitution (11 Articles, its own Amendments Ledger back to
[0.1.0]) — the first test of the engine against a document it wasn't hand-built against.

### What happened — real bugs found by dogfooding, not hypothesized
Running `constitution audit` against DSAMind's actual `CONSTITUTION.md` surfaced the
engine's format assumptions were narrower than "the framework's own documents" — they
were narrower than *this repo's own dogfood shape specifically*. Fixed four real parser/
audit bugs in `cli/src/engine/{parse,audit}.ts` (tests added, `cli/test/engine.test.ts`):

1. **P-line parser required bare `**P1.**`** — DSAMind titles its P-lines
(`**P1 — Fluency, not coverage.**`). Fixed to accept an optional `— Title` before the
closing `.**`, folding the title into the statement text (nothing discarded).
2. **Article parser required exactly `### Article <id>`** — DSAMind groups Articles under
`### §A` domain sections, so Articles are one level deeper: `#### Article <id>`. Fixed
to accept `###`/`####`, and widened the bullet-block end-boundary to stop at either
level so one Article's bullets don't swallow the next.
3. **Serves-list parser choked on parenthetical commentary** — DSAMind annotates each
served P-line inline (`P1 (fluency is measured...), P4 (create-value: ...)`); the old
split-on-comma fragmented *inside* the parens, and no fragment matched the exact
`^P\d+$` filter, so real Articles read as serving nothing (cascading into false
`ART-SERVES` / `ART-SERVES-DANGLING`/`L0-UNSERVED` findings). Fixed by stripping
`(...)` groups before splitting.
4. **`ART-STATUS` rejected `SUPERSEDED — <date>`** — the exact shape `ratify-amendment`
itself is speced to produce for a superseded Article. Fixed to accept the dated form.
5. **`LEDGER-SYNC` fired unconditionally** — it compared the header's `framework:
constitution@X` pin against the newest Amendments Ledger entry version, which is only
the same axis when `selfHosted` (this repo pins itself). A downstream consumer's ledger
tracks *its own* constitution version, independent of the framework spec version it
pins — DSAMind's ledger is at its own `[0.11.0]` while pinning `framework@0.16.12`,
legitimately. `doc.selfHosted` was already parsed but never read anywhere — wired the
existing field into the one check that needed it, rather than adding new plumbing.

### Verified by running
- `cd cli && npm test` — **21/21** (19 prior + 2 new: real-world format-variance parsing,
LEDGER-SYNC scoped to self-hosted only).
- `npm run build` — clean; self-audit (`node cli/dist/index.js audit` on this repo) —
**0 findings**, unchanged by the fix (confirms nothing regressed on the format the
engine already handled).
- Before the fix: `constitution audit` on DSAMind → 1 error (`LEDGER-SYNC`), 13 warnings,
most cascading false positives (`L0-EMPTY` even though DSAMind has a real 4-line
Preamble; 9× `ADR-SERVES-DANGLING` because zero Articles parsed at all).
- After the fix, same repo → **16 errors, 6 warnings, all real**:
- `L0-SIZE` (F-V caps L0 at ≤3; DSAMind has 4 — P1–P3 Mission + P4 Mandate). **Not an
engine bug** — checked framework's own `Article F-V` fitness text
(`CONSTITUTION.md:89`, "L0 holds ≤3 statements") and it has no Mission/Mandate
carve-out, even though the framework's own ledger ([0.5.0]) later adopted the
Mission/Mandate split as a first-class L0 shape. This is a genuine above-firewall
open question for the ratifier — does F-V need an amendment for the two-part shape it
already adopted, or should the Mission+Mandate total stay ≤3? **Flagged, not
resolved** — no amendment drafted this session.
- 5× `ART-MECH-DEBT` (A4, B1, B2, C1, D2 = `HOLDS`+`UNGUARDED`) — **matches DSAMind's
own hand-audited "mechanization backlog" list in its Amendments Ledger exactly**, an
independent cross-check that the engine's derivation logic is sound.
- `L0-UNSERVED` for P2 — genuine: no Article's `Serves` cites P2 anywhere in the document
(checked by hand).
- 15× `LOCK-UNACCEPTED` — genuine: DSAMind's `constitution.lock.json` exists
(`acceptedBy: Chinmay`, timestamp today) but has `units: {}` — accepted before any
units existed, or accepted against a version the parser couldn't see yet. Needs a
fresh `constitution lock accept` now that parsing surfaces the real units.

### Still open after session 3
- **DSAMind's own `constitution lock accept`** — operator's act (F-IV), now meaningful
since parsing works. Also `npm install` in `dsa_project` (or a fresh publish pull) to
pick up the fixed engine — verification above used the worktree's local `dist/`, not
DSAMind's installed `node_modules` copy.
- **The F-V / Mission-Mandate `L0-SIZE` question** — needs the ratifier's call: amend F-V's
fitness signal, or trim DSAMind's L0. Either path goes through `propose-amendment` +
`ratify-amendment`; not started.
- DSAMind's own below-firewall findings (P2 unserved, mechanization backlog) are
candidates for `constitution doctor` / manual statute-writing in that repo, but that's
DSAMind's own governance work, not this framework's.
- This session's fixes are uncommitted in this worktree — not yet published.

### Addendum — upgrading an existing consumer, found by trying it on DSAMind (same session)
Operator asked how to bring an old consumer (DSAMind: scaffolded 2026-07-01, before this
overhaul existed) up to date — compiled skills stuck at pre-engine versions
(`audit-structure` 1.3.2, not the engine-consuming 1.4.0), no CI firewall gate, no
pre-commit hook, `@chinmaygit/constitution-cli` present in `node_modules` but **not
declared** in `package.json`/lockfile (an unreproducible local artifact — absent on any
fresh clone or in CI). Investigated whether `constitution init` (re-run non-interactively)
is a safe update mechanism, since `setupAgents` already unconditionally overwrites every
compiled `SKILL.md` — and found two real bugs that would have made it unsafe:

1. **`scaffold.ts`'s "does AGENTS.md already have a governance map" check was
case-sensitive** (`includes('Governance Map')`) while the engine's own detection
(`engine/parse.ts`) is case-insensitive (`/Governance Map/i`). DSAMind's actual heading
is `## Governance map (entry point)` (lowercase "map") — re-running `init` would have
silently appended a second, generic governance-map block on top of DSAMind's
already-customized one. Fixed to match the engine's own case-insensitive check.
2. **`scaffold.ts` wrote a blanket `.constitution/` line to the consumer's root
`.gitignore`.** `engine/events.ts`'s `ensureOps` also writes its own nested
`.constitution/.gitignore` (`tone/`, `compiles/`, `board.html`) specifically so
`events.jsonl` and `proposals/` stay committed — "the delivery record and the
ratification queue are worth committing," per its own comment. Verified empirically
(a throwaway git repo) that a parent-directory ignore makes git never even look for a
nested un-ignore: the blanket rule silently swallowed `events.jsonl` and
`proposals/*.json` too, contradicting the ops-plane's explicit design and — for
DSAMind specifically, which already has `.constitution/process`/`templates` **committed**
from its original init — adding a rule that (harmlessly, since git doesn't retroactively
untrack) would have gone on to block any future ops-plane commits. Fixed: the ignore is
now scoped to just `.constitution/templates/` and `.constitution/process/` (the
regenerable vendored copies), leaving the ops subdirectories to the nested
`.gitignore`'s finer-grained rules.

**Verified by running:** dry-run `init` against a full copy of DSAMind (scratch dir, not
the real repo) — CONSTITUTION.md/AGENTS.md byte-identical before/after, only
`audit-structure`/`compile-prompt` (the two skills that changed upstream) rewritten in
`.claude/skills/` + `.agents/skills/` to 1.4.0/1.2.0, the other 9 untouched. Separately, a
fresh-consumer dry run (`git init` + `constitution init` + `feature declare` + `git add -A`)
confirms `.constitution/events.jsonl` is now stageable while `templates/`/`process/`/
`tone/`/`compiles/`/`board.html` stay ignored. Two new tests
(scaffold `.gitignore` scoping; case-insensitive governance-map re-init) — **25/25** total.

**The upgrade runbook for an existing consumer** (DSAMind or any pre-overhaul repo),
in order:
1. `npm install --save-dev @chinmaygit/constitution-cli@latest` in the consumer repo
(DSAMind currently has it in `node_modules/` but undeclared — not reproducible on a
fresh clone or in CI).
2. `constitution init --name <Name> --ratifier <Ratifier> --agents claude,antigravity`
(non-interactive, safe to re-run) — refreshes compiled skills only; CONSTITUTION.md/
AGENTS.md are left alone if already present.
3. `constitution doctor` — self-heals below-firewall findings, queues above-firewall ones
as proposals.
4. `constitution hooks install` — arms the pre-commit audit+firewall gate.
5. Add a CI workflow calling `constitution audit` + `constitution firewall` (DSAMind has
`ci.yml`/`version-changelog.yml` but no governance gate yet — port
`.github/workflows/governance.yml` from this repo).
6. **Operator-only, F-IV:** `constitution lock accept` — DSAMind's current
`constitution.lock.json` has `acceptedBy: Chinmay` but `units: {}` (accepted before
parsing worked), so every RATIFIED unit currently reads `LOCK-UNACCEPTED`.
7. Bump DSAMind's `framework: constitution@0.16.12` header pin to the installed version
once steps 1–6 land — not done automatically; no L0/L1 *schema* changed between
0.16.12 and 0.17.2 (this overhaul added CLI tooling, not new Article fields), so the
bump is a formality once the tooling catches up, but it's still a header edit inside
the ratified document and should be a deliberate, reviewed step, not silent.
Steps 2–5 are mechanical/below-firewall; 6–7 are the ratifier's own act. **Not yet run
against the real `dsa_project` repo this session** — only against scratch copies, pending
the operator's go-ahead to touch a live product repo.

### Addendum — proposed amendment: three version axes, three homes (same session)

Operator asked, given the LEDGER-SYNC fix's two-axis distinction: where should the
*installed tooling* version live (they suggested `package.json`), and floated skills
self-checking + auto-migrating tooling on every run — then explicitly invoked
`/propose-amendment`. Ran that skill end to end; drafted, did **not** ratify:

- **Ran the L1 inclusion test** on the candidate before drafting: general, traces to L0
(P1, via F-II), falsifiable, survives a tech swap — passes. Considered a brand-new
Article ("F-VIII") vs. extending F-II; chose **extending F-II** (already the "one home
per rule" Article, already amended once by ADR-0001 for the closely related
package-managed-distribution question) — flagged in the ADR's "Alternatives considered"
that if the ratifier disagrees this is a fitting extension rather than genuinely new
territory, the correct redirect is `harvest-articles`, not a bigger amendment here.
- **decisions/0002-version-axis-separation.md** (`status: proposed`, `serves`/`amends:
[F-II]`, `trigger: certiorari`) — names the three axes and gives each one home: an
instance's own Amendments Ledger version; the adopted-spec `framework:` header pin
(ratified conformance claim, never auto-bumped past what's adopted); the installed
tooling version (consumer's own package manifest — confirming the operator's
`package.json` instinct, since that's already the natural, existing home for "what's
installed," no new field needed). Drafted F-II `Principle`/`Fitness` additions
(additive only — nothing superseded, no forward-link needed) plus `Why`/`Proven`
bullets citing this session's actual LEDGER-SYNC bug as the evidence. `decisions/
INDEX.md` updated in the same change per `decisions/AGENTS.md`'s own statute.
**CONSTITUTION.md itself was not touched** — the drafted text lives only in the ADR,
per the firewall; only `ratify-amendment` may write it into ratified law.
- **Agreement-only, not measured** — explicit reason on record (per the skill's hard
rule against silently skipping the experiment path): this clarifies already-adopted
practice (`sync-operator`'s existing "never bump a consumer's pin past what it has
adopted") and is evidenced by a bug already found and fixed in code this session;
there's no catch-rate/friction hypothesis to pre-register.
- **Explicitly split off, not ruled on**: the "skills self-check tooling + auto-migrate"
half of the operator's proposal. No mechanism exists yet to evaluate — open questions
recorded in the ADR's Consequences: what "check is current" means without a silent
network call on every skill invocation; whether `doctor` should only *report* tooling
drift (consistent with existing propose-don't-enact discipline) or actually run `npm
update` unattended (a supply-chain-trust question, separate from version-tracking); and
where per-version migration steps would live (a `migrations/` dir keyed by version
range, run from `constitution doctor`, is the natural extension of doctor's existing
`versionSync` mechanism — unbuilt). Once a concrete mechanism exists, *that's* a genuine
F-III pre-registration candidate; this ADR is not it.
- Verified: `constitution audit` and `constitution firewall` both stay clean with the new
ADR present (L3, outside the lock) — confirms the proposal touched nothing above the
firewall.
- **Open**: awaiting the ratifier's decision (`ratify-amendment`) — accept the F-II
extension as drafted, request changes, or redirect to `harvest-articles` if a standalone
Article is preferred after all.
33 changes: 31 additions & 2 deletions CONSTITUTION.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# The constitution framework — Constitution

```
framework: constitution@0.17.2 (self-hosted)
framework: constitution@0.17.3 (self-hosted)
ratifier: Chinmay
```

Expand Down Expand Up @@ -52,10 +52,18 @@ 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.
- **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. Verified by the `audit-structure` skill.
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.

### Article F-III — Experiments are pre-registered
`status: RATIFIED` · `conformance: HOLDS` · `enforcement: AUDITED` · `party: N/A`
Expand Down Expand Up @@ -157,6 +165,27 @@ 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.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
consumer's adopted-spec header pin against its own Amendments Ledger version and flagged
a real, correct mismatch as an error. Those are two different, legitimately independent
numbers. Fixed in code the same day (`cli/src/engine/audit.ts`); this entry writes the
distinction into law so it isn't lost.
- **Article F-II — Principle and Fitness extended** (`status: RATIFIED`, unchanged). Names
three version facts, each with exactly one home: an 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 adopted), and the framework tooling installed (the instance's
own package manifest, e.g. `package.json`). Purely additive — nothing existing changed or
was superseded, no forward link needed.
- Agreement-only — no pre-registered experiment. There was no catch-rate or friction
hypothesis to measure, just a fact to state clearly.
- **Not part of this amendment**: whether skills should auto-check installed tooling is
current and auto-run migrations when it isn't. No mechanism exists yet to rule on; left
as open follow-up work (see ADR-0002's Consequences).
- Above the firewall — F-II's `status` did not change (already `RATIFIED`); its Principle
and Fitness text did, transcribed per `ratify-amendment`.

### [0.17.2] — 2026-07-04 — Publish-on-merge: every merge to main ships the package (operator-directed)
- Operator directive: "every PR merge should publish the package." New
`.github/workflows/publish.yml`: on push to main — build (vendor + strict tsc), test,
Expand Down
4 changes: 2 additions & 2 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chinmaygit/constitution-cli",
"version": "0.17.2",
"version": "0.17.3",
"description": "The constitution governance engine: scaffold, audit, firewall-gate, compile, render, and track AI-native product development",
"license": "MIT",
"author": "Chinmay",
Expand Down
Loading
Loading