docs(design): mosaic framework constitution — expert conference output
Some checks failed
ci/woodpecker/push/ci Pipeline failed
Some checks failed
ci/woodpecker/push/ci Pipeline failed
Conference of 7 experts (architect/moonshot/contrarian/coder/aiml/devex/steward) debated layering, sanitization, upgrade-safety, cross-harness robustness. Artifacts: BRIEF, 7 positions, 7 rebuttals, synthesis-v1, 3 red-team passes, canonical DESIGN.md, OPEN-QUESTIONS.md, MISSION.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
426
docs/design/framework-constitution/synthesis-v1.md
Normal file
426
docs/design/framework-constitution/synthesis-v1.md
Normal file
@@ -0,0 +1,426 @@
|
||||
# Mosaic Framework Constitution — Synthesis v1 (Chief Architect Ruling)
|
||||
|
||||
**Status:** Canonical design. Resolves the seven-position debate (`debate/position-*.md`,
|
||||
`debate/rebuttal-*.md`) against the BRIEF (`BRIEF.md`) and the real framework tree at
|
||||
`packages/mosaic/framework/`. This document is the single design of record for the alpha. A PRD
|
||||
derives from it; implementation derives from the PRD.
|
||||
|
||||
**Author:** Neutral Chief Architect.
|
||||
**Scope:** DQ1–DQ5 of the BRIEF, plus the two release-blockers the debate surfaced outside the DQ
|
||||
frame (LICENSE, hardcoded credential path).
|
||||
|
||||
---
|
||||
|
||||
## 0. Where the conference actually converged
|
||||
|
||||
Seven lenses, near-unanimous on the easy 80%. I am banking the consensus as settled and spending the
|
||||
ruling on the contested 20%.
|
||||
|
||||
**Settled (all or nearly all papers agree — adopted without further debate):**
|
||||
|
||||
1. Introduce an explicit **Constitution** layer (framework-owned, immutable law) distinct from
|
||||
persona (SOUL) and operator profile (USER). (every paper)
|
||||
2. Split content by **ownership × upgrade-fate × residency**, not by topic. (architect §1.2,
|
||||
devex DQ1, aiml DQ1, coder DQ1, contrarian DQ1)
|
||||
3. **Delete `defaults/SOUL.md`** (the "Jarvis"/"PDA" file). Persona ships only as
|
||||
`templates/SOUL.md.template`, generated at init. `install.sh:232-241` already refuses to seed it.
|
||||
(every paper)
|
||||
4. **Subtraction before structure:** create the Constitution *by extraction and deletion*, never by
|
||||
addition. A fifth restatement on top of four existing ones yields five disagreeing law files.
|
||||
(contrarian, endorsed in every rebuttal)
|
||||
5. **A blocking CI grep** for personal data + dead paths is the only durable anti-regression control.
|
||||
(every paper)
|
||||
6. **"Hooks are the real enforcement; prose is the spec"** — promote the repo's own
|
||||
`prevent-memory-write.sh` lesson (`runtime/claude/RUNTIME.md:30-32`) to Constitution doctrine.
|
||||
(devex DQ4, contrarian DQ5, aiml §1.2, coder, steward, moonshot)
|
||||
7. **Remove framework-owned files from `PRESERVE_PATHS`** so gate updates reach existing installs.
|
||||
(every paper — this is the literal drift bug)
|
||||
8. **An enforced resident-token budget**, or the new Constitution re-bloats into the old 155-line
|
||||
`AGENTS.md` within two releases. (aiml DQ5, endorsed by devex, coder, moonshot, contrarian)
|
||||
9. **Fix the false `defaults/AGENTS.md:11` claim** ("already in your context… do not re-read") — it
|
||||
is provably false on a bare `claude` launch and teaches agents to skip the gates. (coder,
|
||||
contrarian, devex, aiml, moonshot)
|
||||
|
||||
**Verified live facts (I re-ran the greps, did not trust the papers):**
|
||||
|
||||
- `tools/_lib/credentials.sh:19` AND `tools/git/detect-platform.sh:89` both default to
|
||||
`$HOME/src/jarvis-brain/credentials.json` — a private path shipped as an executable default.
|
||||
- `mosaic/rails/git/` appears in **12 shipped template files** (all of `templates/agent/` +
|
||||
`projects/*`), while `defaults/AGENTS.md:30` uses `tools/git/` and `install.sh:192-194` actively
|
||||
deletes a stale `rails` symlink. A dozen templates emit a command pointing at a path the installer
|
||||
removes.
|
||||
- **No LICENSE** at monorepo root, `packages/mosaic/framework/`, or as a `package.json` field.
|
||||
|
||||
**Contested 20% (resolved in the Decision Records, §3):** number of layers; physical-directory split
|
||||
vs flat files; one Constitution *file* vs a `constitution/` *directory*; 3-way merge vs `.local`
|
||||
overlays; YAML front-matter + hash-refusal vs structural enforcement; capability-manifest JSON vs
|
||||
prose table; injection-by-value vs self-load.
|
||||
|
||||
---
|
||||
|
||||
## 1. The Canonical Layer Model
|
||||
|
||||
Five **concerns**, collapsed into **four owned layers** plus a non-resident governance spec. The
|
||||
collapse resolves the architect-vs-contrarian layer-count fight: the architect's "Standards" and
|
||||
"Operator Policy" are real *concerns* but do not earn *separate sovereign documents* — Standards is
|
||||
framework law that a deployment tightens via an additive overlay; Operator Policy is a section of
|
||||
USER plus optional `policy/` example files. (Decision D1, D2.)
|
||||
|
||||
A layer boundary is legitimate **iff** the two sides differ in **owner**, **upgrade-fate**, OR
|
||||
**residency**. This single test (architect §1.2, banked by every rebuttal) does all the work.
|
||||
|
||||
| # | Layer | Owns | Owner | Upgrade fate | Residency | Canonical deployed path |
|
||||
|---|-------|------|-------|--------------|-----------|--------------------------|
|
||||
| **L0** | **Constitution** | Irreducible non-negotiable law: hard gates, escalation triggers, block-vs-done, mode declaration, precedence rule, the "hooks are the gate" doctrine, the "no operator context in framework PRs" rule | Framework | **Overwritten wholesale every upgrade.** Never in `PRESERVE_PATHS`. User MUST NOT edit. | **Always resident**, byte-budgeted | `~/.config/mosaic/CONSTITUTION.md` |
|
||||
| **L1** | **Standards & Guides** | How to do the work well: secrets/ESO, trunk-based git, image tagging, the E2E procedure, QA matrix, orchestrator protocol, all `guides/*` | Framework (deployment may **tighten** via overlay) | Overwritten; user delta lives in `STANDARDS.local.md` / never edits guides | `STANDARDS.md` resident; `guides/*` on-demand | `~/.config/mosaic/STANDARDS.md`, `~/.config/mosaic/guides/*` |
|
||||
| **L2** | **Persona (SOUL)** | Agent name, tone, role, communication style, persona-scoped principles | User (init-generated) | **Never overwritten.** Generated from template. | Always resident, byte-budgeted | `~/.config/mosaic/SOUL.md` (+ optional `SOUL.local.md`) |
|
||||
| **L3** | **Operator (USER)** | Human name, pronouns, timezone, accessibility/accommodations, comms prefs, projects, **operator policy** (e.g. merge-authority delegation), operator tool paths | User (init-generated) | **Never overwritten.** | Always resident, byte-budgeted | `~/.config/mosaic/USER.md` (+ optional `USER.local.md`, optional `policy/*.md`) |
|
||||
| **L4** | **Project / Runtime mechanism** | Per-repo `AGENTS.md` deltas; harness-specific *mechanism only* (subagent syntax, hook config, MCP wiring, injection tier) | Repo / framework | Project file user-owned; runtime mechanism overwritten | Project loaded in-repo; runtime resident, ~15 lines | `<repo>/AGENTS.md`, `~/.config/mosaic/runtime/<h>/RUNTIME.md` |
|
||||
| — | **Layer-Model spec** (governance) | The definition of these layers + precedence + "what may live in L0" | Framework maintainers | Source-only, **never deployed** | Not resident | `packages/mosaic/framework/constitution/LAYER-MODEL.md` |
|
||||
|
||||
`AGENTS.md` (deployed) is **not a layer** — it is the thin **load-order dispatcher + Conditional
|
||||
Guide Loading table** that routes to L0–L4. It is framework-owned and overwritten on upgrade.
|
||||
|
||||
### Precedence — typed two-axis, not a flat stack
|
||||
|
||||
A flat "L0 > L1 > L2 > L3" ordering is a trap (contrarian DQ1, devex DQ1): persona and law are not on
|
||||
the same axis. The governing rule, stated **verbatim in L0**, in one sentence each:
|
||||
|
||||
> **Safety axis (gates, integrity, destructive actions):** L0 Constitution is supreme. Nothing in
|
||||
> STANDARDS, SOUL, USER, `policy/`, project `AGENTS.md`, runtime, or any injected reminder may relax,
|
||||
> suspend, or contradict a Constitution gate. A lower layer may only make behavior **stricter**, never
|
||||
> more permissive.
|
||||
>
|
||||
> **Taste axis (tone, formatting, verbosity, iconography):** the operator layers (SOUL/USER) win over
|
||||
> generic framework or model defaults. The framework has no legitimate opinion on style.
|
||||
|
||||
This generalizes the two good instincts already half-present in the tree (`SOUL.md:48`, injected
|
||||
reminders never expand permissions; `SOUL.md:32`, user formatting wins) and makes precedence **total
|
||||
and one-sentence-holdable** rather than scattered across runtime files. (D3.)
|
||||
|
||||
### Enforcement strength is ranked, not chosen
|
||||
|
||||
Resolving the conference's central fault line (injection-by-value vs self-load vs metadata-gate): the
|
||||
three are **not alternatives** — they are a **priority ladder** (aiml §3, devex §3, architect §3,
|
||||
coder, contrarian):
|
||||
|
||||
```
|
||||
mechanical (hook/CI) > resident-by-value (system-prompt injection) > file-read (self-load fallback)
|
||||
```
|
||||
|
||||
1. **Mechanical first.** Every *checkable* gate becomes a hook or CI check (no-force-merge,
|
||||
green-CI-before-done, no-hardcoded-secrets, no-PII, no-dead-paths, no-unrendered-template-tokens).
|
||||
A hook does not compete for attention or care about injection tier. This *drains* prose out of the
|
||||
resident core, which is the precondition that makes the next tier work.
|
||||
2. **Resident-by-value second.** The irreducible *non-checkable* gates (the ones governing *when the
|
||||
agent stops* — block-vs-done, escalation, completion-definition) are injected by value at primacy
|
||||
on the strongest channel each harness offers, restated as a ≤5-bullet anchor at the recency
|
||||
position (bottom).
|
||||
3. **File-read third (fallback).** `AGENTS.md` says: *"If `CONSTITUTION.md` is not already in your
|
||||
context, READ IT NOW."* — conditional, never the false unconditional "already loaded." This is the
|
||||
safety net for harnesses/launches where injection silently failed; it is explicitly the weakest
|
||||
tier, never the primary mechanism.
|
||||
|
||||
---
|
||||
|
||||
## 2. File-by-File Plan (what content moves where)
|
||||
|
||||
### 2a. New files
|
||||
|
||||
| New file | Content | Source of content |
|
||||
|----------|---------|-------------------|
|
||||
| `~/.config/mosaic/CONSTITUTION.md` (ships as `defaults/CONSTITUTION.md`) | **L0, one flat file, ~70–90 lines.** The 13 hard gates *minus* the operator-policy clause (see below); the 5 escalation triggers; block-vs-done; mode declaration protocol; the one-sentence precedence rule (both axes); the "hooks are the gate" doctrine; the "no operator context in framework PRs" rule; a single pointer line to the guide index. **Gates keep full unambiguous wording; procedure (wrapper paths, flags) moves to L1.** | Extracted from `defaults/AGENTS.md:23-87` |
|
||||
| `packages/mosaic/framework/constitution/LAYER-MODEL.md` | The §1 layer model + precedence + "what may live in L0" governance spec. **Source-only, never deployed, never resident.** | This document |
|
||||
| `packages/mosaic/framework/examples/personas/execution-partner.md` | The sanitized, placeholdered essence of the Jarvis persona (a worked example, copied on request, never auto-loaded) | `defaults/SOUL.md` (sanitized) |
|
||||
| `packages/mosaic/framework/examples/overlays/e2e-loop.json` | The sanitized, placeholdered essence of `jarvis-loop.json` (`~/src/<your-project>` placeholders) | `runtime/claude/settings-overlays/jarvis-loop.json` |
|
||||
| `packages/mosaic/framework/examples/policy/merge-authority.example.md` | The operator-policy merge-authority decision, as an *example* operator policy a deployment may adopt | `defaults/AGENTS.md:37` ("Policy: Jason, 2026-06-11") |
|
||||
| `LICENSE` (monorepo root) + `packages/mosaic/framework/LICENSE` | MIT license text | new (D8) |
|
||||
| `CONTRIBUTING.md` (framework package) | Layer model, PII/secrets prohibition, the dedup rule, how to add a harness adapter, the re-contamination rule | new (D8) |
|
||||
| `tools/quality/scripts/verify-sanitized.sh` | The blocking CI grep (PII + home paths + dead `rails/` + unrendered tokens) | new (D6) |
|
||||
|
||||
### 2b. Files that shrink / change role
|
||||
|
||||
| File | Change | Why (DQ) |
|
||||
|------|--------|----------|
|
||||
| `defaults/AGENTS.md` | Gut from 155 lines to a **~50-line dispatcher**: load order + Conditional Guide Loading table + the self-bootstrapping "read CONSTITUTION.md if not resident" line. **Zero restated gates.** Remove from `PRESERVE_PATHS`. | DQ1, DQ5 |
|
||||
| `defaults/STANDARDS.md` | Stays L1, but: drop the **"Master/slave model"** framing (line 5); stop re-asserting gates that now live in L0; end with an additive include convention for `STANDARDS.local.md`. Remove from `PRESERVE_PATHS`. | DQ1, DQ3, DQ5 |
|
||||
| `defaults/TOOLS.md` | Delete the `jarvis-brain` MANDATORY rule (line 40). Generic tool index only; operator-specific rules move to the operator's `USER.md`/project `AGENTS.md`. | DQ2 |
|
||||
| `templates/SOUL.md.template` | Already clean and correct. Keep. Ensure every `{{TOKEN}}` has a non-empty default in `mosaic-init` (no placeholder can survive into a resident file). | DQ2 |
|
||||
| `templates/agent/AGENTS.md.template` (+ 11 sibling/project templates) | **Delete the restated Hard-Gates block.** Replace with one line: *"This project is governed by `~/.config/mosaic/CONSTITUTION.md`. Add only project-specific extensions below."* **Fix all `rails/git/` → `tools/git/`.** | DQ4, DQ5 |
|
||||
| `runtime/{claude,codex,pi,opencode}/RUNTIME.md` | Strip restated policy (wrappers-first, mode declaration, caution-doesn't-override-gates). Reduce to **harness mechanism only** + a one-line reference to `CONSTITUTION.md`. | DQ4, DQ5 |
|
||||
| `tools/_lib/credentials.sh:19`, `tools/git/detect-platform.sh:89` | `$HOME/src/jarvis-brain/credentials.json` → `${MOSAIC_CREDENTIALS_FILE:?MOSAIC_CREDENTIALS_FILE must be set}` (fast-fail, consistent with the framework's own `STANDARDS.md:35` ban on `${VAR:-default}` for required values). Document the env var in `USER.md.template` under `## Tool Paths`. | DQ2 (blocker) |
|
||||
| `guides/ORCHESTRATOR.md` (lines 99,111,152), `guides/TOOLS-REFERENCE.md`, `guides/BOOTSTRAP.md` | Replace `jarvis-brain/docs/templates/` with `~/.config/mosaic/templates/` (the canonical install path). | DQ2 |
|
||||
|
||||
### 2c. Files deleted / moved out of the shipped package
|
||||
|
||||
| File | Action | Why |
|
||||
|------|--------|-----|
|
||||
| `defaults/SOUL.md` | **Delete.** Persona is generated at init from the template only. | Primary contamination vector |
|
||||
| `runtime/claude/settings-overlays/jarvis-loop.json` | **Delete**; sanitized essence → `examples/overlays/e2e-loop.json` | Personal project map |
|
||||
| `defaults/AUDIT-2026-02-17-framework-consistency.md` | **Move** to `docs/` at monorepo root (maintainer artifact, not agent context) | Not framework content |
|
||||
|
||||
---
|
||||
|
||||
## 3. Decision Records
|
||||
|
||||
Each contested question, resolved with Decision / Rationale / Rejected.
|
||||
|
||||
### D1 — Layer count: four owned layers (+ a non-resident spec), not five, not three
|
||||
|
||||
- **Decision:** L0 Constitution / L1 Standards+Guides / L2 Persona / L3 Operator / L4 Project+Runtime.
|
||||
"Operator Policy" is a section of L3 (USER) plus optional `policy/*.md`, not a fifth sovereign layer.
|
||||
- **Rationale:** The owner×fate×residency test legitimizes splitting law from persona from operator
|
||||
(so the "Policy: Jason, 2026-06-11" clause at `defaults/AGENTS.md:37` *must* leave L0 — different
|
||||
owner, different upgrade-fate). But it does **not** legitimize a standalone `policy/` *layer*: no
|
||||
paper named a failure mode that "USER.md has a `## Operator Policy` section" cannot handle
|
||||
(steward §2b). Three layers (contrarian/coder) under-serves the merge-authority extraction; five
|
||||
(architect) re-creates the very `AGENTS.md`/`STANDARDS.md` overlap that already drifts (contrarian
|
||||
§2c). Four is the count where every boundary passes the test and none is gratuitous.
|
||||
- **Rejected:** Architect's five layers (Standards + Operator-Policy + Deployment as separate
|
||||
sovereigns) — taxonomy inflation; more documents to keep non-duplicative is the disease, not the
|
||||
cure. Contrarian/coder's strict three — loses the operator-policy seam the merge-authority leak
|
||||
proves is needed.
|
||||
|
||||
### D2 — One flat `CONSTITUTION.md`, not a `constitution/` deploy directory
|
||||
|
||||
- **Decision:** L0 deploys as a **single flat file** `~/.config/mosaic/CONSTITUTION.md`. The
|
||||
`constitution/` directory exists **only in the package source**, holding the non-deployed
|
||||
`LAYER-MODEL.md` governance spec.
|
||||
- **Rationale:** A directory of `GATES.md`+`DELIVERY.md`+… multiplies load-order failure points — on a
|
||||
weak-injection harness an agent can load file 1, get pulled into the task, and operate with
|
||||
incomplete gates (coder §3, devex "load-order indirection"). You can anchor a *file* at
|
||||
primacy+recency; you cannot anchor a *directory* (aiml). One file is injected/read whole and is
|
||||
impossible to partially load. The separation-of-concerns the directory camp wants is real but is a
|
||||
*post-alpha evolution target*, triggered only if L0 exceeds its budget.
|
||||
- **Rejected:** Architect/steward/moonshot `constitution/` deploy directory — correct intuition, wrong
|
||||
alpha granularity; reserve for v2.
|
||||
|
||||
### D3 — Precedence is structural (placement + overwrite + hooks), not metadata/hash-enforced
|
||||
|
||||
- **Decision:** Enforce L0 supremacy and immutability through (a) **directory/overwrite mechanics** —
|
||||
L0 is overwritten wholesale every upgrade, so a user edit simply does not survive; (b) **placement**
|
||||
— L0 at primacy, ≤5-bullet anchor at recency, SOUL/USER in the low-attention middle; (c) **hooks/CI**
|
||||
for every checkable gate. No YAML front-matter, no content-hash launch gate.
|
||||
- **Rationale:** Front-matter (`mosaic-layer: 0`, `mosaic-override: forbidden`) spends the single most
|
||||
valuable primacy-position attention slot on key-value pairs whose audience is a bash script, and
|
||||
teaches the model that override-rules are parseable properties — an injection surface (aiml §2.1,
|
||||
steward §2a, coder §2b, devex §2a). Hash-refusal-on-launch is invisible on the exact direct-launch
|
||||
paths where drift happens (it only runs inside `mosaic <harness>`), bricks the one user who
|
||||
customized, and false-positives on every mid-upgrade state and CRLF/trailing-newline diff (every
|
||||
rebuttal rejected it). Immutability-by-overwrite needs zero hashes: overwrite *is* the guarantee.
|
||||
- **Rejected:** Moonshot's front-matter + "launcher refuses to start on hash mismatch"; steward's
|
||||
`--check-constitution`-as-error. A **post-hoc advisory** `mosaic doctor` drift *warning* (never a
|
||||
launch block, never on model-visible bytes) is acceptable and kept.
|
||||
|
||||
### D4 — Upgrade-safe customization = additive `.local` overlays, not 3-way merge
|
||||
|
||||
- **Decision:** Framework-owned files (L0, L1 `STANDARDS.md`+`guides/*`, `AGENTS.md`, runtime) are
|
||||
**overwritten wholesale** on upgrade. User customization that must survive lives in **never-touched
|
||||
additive overlays**: `SOUL.local.md`, `USER.local.md`, `STANDARDS.local.md`, optional `policy/*.md`.
|
||||
One overlay mechanism, **owned by the launcher/composer**, resolved *before* injection — not a
|
||||
per-guide variant, not an inert `<!-- mosaic:include -->` comment. `TOOLS.md` (generated then
|
||||
hand-tuned) is the one file that may keep the existing `.bak.<ts>` backup-on-regenerate behavior.
|
||||
- **Rationale:** The directory/overwrite split makes 3-way merge **unnecessary** — there is nothing to
|
||||
merge when framework files are clobbered and user deltas are separate (architect §2.2, contrarian
|
||||
§2a). Markdown has no merge semantics: `git merge-file` resolves by line, so a reflowed paragraph
|
||||
produces phantom conflicts, and a half-resolved merge can leave `<<<<<<<` markers **inside the
|
||||
agent's resident identity file** — the same erratic-behavior class as a half-rendered `{{TOKEN}}`
|
||||
(aiml §2.3, moonshot §1). A 3-way merge also needs a `base` that **no current install has**
|
||||
(contrarian §2a) — most fragile exactly at the alpha boundary the BRIEF says must not break.
|
||||
Interactive merge prompts hang headless launches. The three papers that invented *different* overlay
|
||||
schemes (coder per-guide, aiml/devex per-layer, contrarian include-comment) must converge: devex
|
||||
(§2b) correctly rules that **per-layer overlays composed by the launcher** is the only one that does
|
||||
not silently no-op on a pointer harness.
|
||||
- **Rejected:** Architect/devex 3-way `mosaic-reconcile`; moonshot interactive `[Y/n]` auto-merge;
|
||||
contrarian's inert include-comment; coder's per-guide `.local.md` (guides are L1, referenced not
|
||||
forked). Per-layer template-version markers survive **only as a `doctor` advisory signal** ("your
|
||||
SOUL was generated from template v2; v4 ships — review `examples/`"), never as a merge trigger.
|
||||
|
||||
### D5 — Cross-harness: single L0 source + capability-resolved adapters + tiered injection + a smoke test
|
||||
|
||||
- **Decision:** L0 is one canonical text. Adapters carry **mechanism only**. The Constitution speaks
|
||||
in **capability verbs** ("use structured reasoning before planning"); each harness adapter binds the
|
||||
verb to a concrete tool and declares whether absence is a hard stop. For the **alpha**, that binding
|
||||
is a **single markdown table** in the adapter docs (not a JSON manifest). Injection is **tiered and
|
||||
honest about asymmetry**: Tier-1 (system-prompt append: Pi, `mosaic claude`/`codex`) injects L0 by
|
||||
value; Tier-3 (bare `claude`/`codex`/`opencode` pointer) carries the ≤5-bullet irreducible-gate
|
||||
summary **inline** plus the read instruction. A **CI smoke test** launches each harness path and
|
||||
asserts the irreducible gates are present in the effective context — the control that makes
|
||||
"enforced across harnesses" *true* rather than aspirational.
|
||||
- **Rationale:** The four harnesses genuinely do not inject symmetrically (devex §3, verified:
|
||||
`adapters/pi.md:14-16` system-prompt; Claude append-or-pointer with competing harness
|
||||
`<system-reminder>`s; Codex/OpenCode instructions-file). "Byte-for-byte everywhere" is an
|
||||
aspiration, not a switch. The capability-verb split kills the **already-live** contradiction —
|
||||
`defaults/AGENTS.md:143` says sequential-thinking MCP is REQUIRED-or-stop, while `adapters/pi.md`
|
||||
says native thinking replaces it (aiml §1.3). But a bespoke `capabilities.json` schema + validator
|
||||
for a four-row, three-axis table is over-engineering at alpha (coder §2c, contrarian §2c): a
|
||||
markdown table conveys the same and catches errors at review time. The JSON manifest is a good v2
|
||||
evolution once there are 6+ harnesses.
|
||||
- **Rejected:** Devex's `adapters/<h>.capabilities.json` machine-read manifests **for the alpha**
|
||||
(kept as a v2 roadmap item); moonshot's "Pi is the reference harness" (inverts single-source-of-
|
||||
truth — defines abstract law in terms of one runtime's affordances; architect §2.3). Moonshot's
|
||||
`COMPLIANCE.md` harness×gate **matrix as documentation** is kept (good for visibility); machine-read-
|
||||
and-enforced is not.
|
||||
|
||||
### D6 — Sanitization: per-layer strategy + a blocking CI gate that closes the *class*, not the tokens
|
||||
|
||||
- **Decision:** Per-layer, not one global choice (contrarian DQ2): **L0/L1 ship generic-and-complete**
|
||||
(law has no PII once leaks are removed; empty law = no gates = dangerous); **L2/L3 ship as templates
|
||||
only**, generated at init (delete `defaults/SOUL.md`); **examples/ ship the worked Jarvis config**
|
||||
sanitized + placeholdered (`~/src/<your-project>`), copied on request, never auto-loaded. The
|
||||
blocking CI gate (`verify-sanitized.sh`) fails the build on the **structural class**, not just
|
||||
current tokens: `jarvis|jason|woltje|\bPDA\b`, plus `~/src/<word>` / `/home/<word>/` absolute home
|
||||
paths, plus dead `/rails/` tokens, plus unrendered `{{...}}`/`${...}` in resident files — over
|
||||
`defaults/ guides/ templates/ runtime/ adapters/`, excluding `examples/`.
|
||||
- **Rationale:** The contamination reached ~29–55 files because `defaults/README.md:7`'s prose promise
|
||||
has no enforcement; a CI grep is ~15 lines and is the only durable control (every paper). It must
|
||||
close the *class* because the primary author of future framework PRs is an agent running with *some*
|
||||
operator's SOUL/USER in context — a denylist of today's tokens won't catch tomorrow's operator
|
||||
(steward §3, moonshot "biggest risk"). The unrendered-token check closes the half-rendered-template
|
||||
failure class (aiml §2.2): a `SOUL.md` containing `You are **{{AGENT_NAME}}**` makes the model adopt
|
||||
the literal braces.
|
||||
- **Rejected:** Generic-defaults for persona (recreates the bug — "Assistant" becomes the new
|
||||
"Jarvis"; devex DQ2); empty-defaults for persona (terrible first-run); prose-only sanitization
|
||||
(already proven to decay).
|
||||
|
||||
### D7 — Resident-token budget: budget the *container* by line count, keep gate *wording* intact
|
||||
|
||||
- **Decision:** Enforce a **resident line-count ceiling in CI + `mosaic-doctor`** over the
|
||||
always-resident set (`CONSTITUTION.md` + `AGENTS.md` index + `SOUL.md` + `USER.md` + the resident
|
||||
RUNTIME slice). Budget the *container*, not the constitution's clarity. Gates keep full unambiguous
|
||||
wording; *procedure* (wrapper paths, `--purpose` flags) moves to on-demand `E2E-DELIVERY.md`.
|
||||
- **Rationale:** A new top-level `CONSTITUTION.md` is psychologically tempting to fill and will
|
||||
re-bloat to 155 lines within two releases without a mechanical forcing function (aiml "biggest
|
||||
risk," moonshot §1). But moonshot's "exactly 500 words" is asserted, not derived, and is
|
||||
**self-defeating**: gate #13 alone is ~110 words, so a 500-word cap forces *paraphrasing the gates*
|
||||
— paraphrased law is the exact drift vector we are killing (aiml §2.2). Budget the resident *set* by
|
||||
line count (the mechanism several papers converge on); let each gate keep its wording; push
|
||||
procedure to guides.
|
||||
- **Rejected:** Moonshot's "exactly 500 words for CONSTITUTION.md" — right instinct, wrong unit;
|
||||
forces lossy compression of normative text.
|
||||
|
||||
### D8 — Two non-DQ release blockers ship in the alpha DoD: LICENSE and the credential path
|
||||
|
||||
- **Decision:** Add **MIT** `LICENSE` (monorepo root + framework package) + `"license": "MIT"` in
|
||||
`package.json`, on day zero. Fix both hardcoded `$HOME/src/jarvis-brain/credentials.json` defaults to
|
||||
fast-fail env vars. Ship `CONTRIBUTING.md` (with the operator-data-hygiene section) with the alpha,
|
||||
not deferred.
|
||||
- **Rationale:** "Public does not mean licensed" — under Berne, an unlicensed public repo is
|
||||
all-rights-reserved, so every fork/contribution has unclear IP status, and retroactively licensing
|
||||
after the alpha creates ambiguity about the pre-license period (steward, the only paper to surface
|
||||
this; endorsed by architect §1.3, devex §1c). A hardcoded private credential path shipped as an
|
||||
executable default is worse than the persona contamination — it is in the *tooling* layer and it is
|
||||
runnable. MIT maximizes adoption and signals genuine open infrastructure.
|
||||
- **Rejected:** Deferring LICENSE/CONTRIBUTING to "pre-stable" — the alpha will have downstream users;
|
||||
the window to fix legal status cleanly closes at the alpha tag. AGPL/Apache considered; MIT chosen
|
||||
for adoption (revisitable, but pick one now).
|
||||
|
||||
---
|
||||
|
||||
## 4. Sanitization plan for the public package
|
||||
|
||||
**Ships generic (PII-free, complete, in the package):**
|
||||
`defaults/CONSTITUTION.md`, `defaults/AGENTS.md` (dispatcher), `defaults/STANDARDS.md`,
|
||||
`defaults/TOOLS.md` (generic index), all `guides/*` (purged), `templates/*` (token-only),
|
||||
`examples/*` (placeholdered worked configs), `runtime/*/RUNTIME.md` (mechanism-only), `adapters/*.md`,
|
||||
`LICENSE`, `CONTRIBUTING.md`.
|
||||
|
||||
**Generated at `mosaic init` (never in the package, gitignored downstream):**
|
||||
`~/.config/mosaic/SOUL.md`, `USER.md`, `TOOLS.md` (rendered from templates), `*.local.md` overlays,
|
||||
optional `policy/*.md`, per-harness runtime copies.
|
||||
|
||||
**Deleted / relocated from the shipped tree:** `defaults/SOUL.md` (delete);
|
||||
`runtime/claude/settings-overlays/jarvis-loop.json` (delete → `examples/overlays/`);
|
||||
`defaults/AUDIT-2026-02-17-*.md` (move to monorepo `docs/`).
|
||||
|
||||
**Mechanical gate (the durable control):** `tools/quality/scripts/verify-sanitized.sh`, wired into
|
||||
`.woodpecker.yml`, blocking. Fails on: operator tokens; absolute home paths (`~/src/<word>`,
|
||||
`/home/<word>/`); dead `/rails/` paths; unrendered `{{...}}`/`${...}` in resident files. Excludes
|
||||
`examples/`. Plus a structural-firewall **L0 rule**: *"When proposing a framework PR or capturing a
|
||||
`framework-improvement`/`tooling-gap`, you MUST NOT include content derived from SOUL.md, USER.md, or
|
||||
operator-specific context; if you cannot express it operator-agnostically, it belongs in `policy/` or
|
||||
a project `AGENTS.md`, not the framework."*
|
||||
|
||||
---
|
||||
|
||||
## 5. Customization + upgrade-safety mechanism
|
||||
|
||||
**The single sentence a user can now truthfully rely on:** *"Edit `SOUL.md`/`USER.md` and the
|
||||
`*.local.md` overlays freely — upgrades never touch them. Never edit `CONSTITUTION.md`/`STANDARDS.md`/
|
||||
`guides/*`/`AGENTS.md` — they update automatically every upgrade. Want to change framework behavior?
|
||||
Add a `.local.md` overlay or a `policy/` file (tighten-only)."*
|
||||
|
||||
**Mechanism:**
|
||||
|
||||
1. **Physical seam = ownership.** Framework-owned files are overwritten wholesale (`rsync` without an
|
||||
exclude); user-owned files (`SOUL.md`, `USER.md`, `*.local.md`, `policy/`, `TOOLS.md`, `memory`,
|
||||
`sources`, `credentials`) are the *only* `PRESERVE_PATHS` entries. **Remove `AGENTS.md` and
|
||||
`STANDARDS.md` from `PRESERVE_PATHS`** — this single change makes gate updates reach every existing
|
||||
install (the literal drift bug, contrarian §0/§3).
|
||||
2. **Additive overlays, launcher-composed.** `mosaic compose-contract <harness>` concatenates, in
|
||||
precedence order, base + `.local` deltas *before* injection, so the model receives one pre-merged
|
||||
blob and never runs a redundant read-merge ritual. (D4.)
|
||||
3. **One global `FRAMEWORK_VERSION` integer + linear migrations** (the existing `install.sh:160-202`
|
||||
scaffold). No per-layer version matrix — it is a combinatorial test cliff no single maintainer will
|
||||
cover (contrarian, steward §2b). Per-layer template versions survive only as a `doctor` *advisory*.
|
||||
4. **Migration v2→v3 (backward-compatible, the BRIEF's hard constraint):**
|
||||
- Snapshot `~/.config/mosaic/` → `~/.config/mosaic/.backup-v2/` before touching disk.
|
||||
- Install `CONSTITUTION.md` as a **new** file nothing previously owned (avoids the reclassification
|
||||
catastrophe moonshot §2 flags — we do **not** try to diff/split a user-edited flat `AGENTS.md`
|
||||
into "framework vs user" content).
|
||||
- Install the slimmed `AGENTS.md` dispatcher; remove `AGENTS.md`/`STANDARDS.md` from
|
||||
`PRESERVE_PATHS` going forward.
|
||||
- The agent self-loads L0 from `AGENTS.md` regardless of launcher injection (the self-bootstrap
|
||||
fallback), so even a stale-pointer install gets the gates.
|
||||
5. **The migration is the biggest risk; gate it with a falsifiable test matrix** (contrarian §3, the
|
||||
*decider*, not a mitigation). Alpha cannot tag until three fixtures pass with **no interactive
|
||||
prompt, no hang**: (1) fresh install; (2) legacy-flat user-edited install — law moves, user files
|
||||
survive; (3) user-tuned-standard install — change survives as `STANDARDS.local.md`, framework
|
||||
`STANDARDS.md` updates. Smallest design that passes all three wins (it does: `rsync` + linear
|
||||
migration + overlays + a 15-line grep — zero new subsystems).
|
||||
6. **Detection without enforcement:** `mosaic doctor` reports drift/unrendered-tokens/budget-overflow
|
||||
as **advisories** (warn, never block launch). `--check-constitution` is an opt-in diagnostic, not a
|
||||
gate (D3).
|
||||
|
||||
---
|
||||
|
||||
## 6. Cross-harness strategy (single source of truth + adapters)
|
||||
|
||||
**Single source:** L0 `CONSTITUTION.md` is the one law text. No harness gets a forked copy; runtime
|
||||
files and project templates **reference** it, never restate it (kills the four-way duplication and the
|
||||
live `rails/`-vs-`tools/` + sequential-thinking-except-Pi contradictions).
|
||||
|
||||
**Adapter contract (mechanism only):** an `adapters/<h>.md` / `runtime/<h>/RUNTIME.md` may specify
|
||||
**only** (a) the injection channel + tier this harness uses, and (b) how L0's **capability verbs** map
|
||||
to concrete tools (subagent syntax, MCP wiring, hook config). The Constitution says *"use structured
|
||||
reasoning before planning"*; the Claude adapter binds it to `mcp:sequential-thinking` (gate=true), the
|
||||
Pi adapter to native thinking (gate=false). For the alpha this binding is a markdown table; JSON
|
||||
manifests are a v2 item once 6+ harnesses exist.
|
||||
|
||||
**Tiered, honest injection (the four harnesses are not symmetric):**
|
||||
|
||||
| Harness | Channel | Tier | L0 delivery |
|
||||
|---------|---------|------|-------------|
|
||||
| Pi | `--append-system-prompt` (+ no hook backstop) | 1 | By value at primacy; keep L0 tiny — resident fidelity is Pi's *only* enforcement |
|
||||
| `mosaic claude` / `mosaic codex` | system-prompt append | 1 | By value at primacy + ≤5-bullet recency anchor |
|
||||
| Codex / OpenCode (instructions-file) | written file | 2 | Resident-ish; self-load line as backup |
|
||||
| bare `claude`/`codex`/`opencode` | thin pointer | 3 | Pointer carries the ≤5-bullet gate summary **inline** + "READ CONSTITUTION.md NOW" — never the false "already loaded" |
|
||||
|
||||
**Mechanical backstop:** every hookable gate is a hook where the harness supports one
|
||||
(`prevent-memory-write.sh` precedent); Codex/OpenCode hook parity is a **tracked gap** in the
|
||||
compliance doc, not a silent inconsistency. A **CI smoke test** asserts the irreducible gates are
|
||||
resident on every harness path — the control that makes the cross-harness claim true.
|
||||
|
||||
---
|
||||
|
||||
## 7. Alpha Definition of Done (derived, for the PRD)
|
||||
|
||||
Blocking: MIT LICENSE + `package.json` field; credential-path fast-fail fix; `defaults/SOUL.md` +
|
||||
`jarvis-loop.json` deleted; `rails/`→`tools/` fixed in 12 templates; `verify-sanitized.sh` green and
|
||||
wired to CI; `CONSTITUTION.md` extracted (gates one place, dispatcher `AGENTS.md` self-bootstraps);
|
||||
`AGENTS.md`/`STANDARDS.md` out of `PRESERVE_PATHS`; resident line-count budget enforced; per-layer
|
||||
overlay + compose step; migration v2→v3 passing the 3-fixture matrix with no hang; cross-harness smoke
|
||||
test green; `CONTRIBUTING.md` with operator-hygiene section; tag the alpha. PRD precedes implementation.
|
||||
|
||||
**Explicitly deferred to post-alpha (v2):** `constitution/` deploy directory; `adapters/<h>.capabilities.json`
|
||||
JSON manifests; 3-way merge reconciliation; per-layer version stamps as a migration driver; DCO CI.
|
||||
Reference in New Issue
Block a user