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>
33 KiB
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):
- Introduce an explicit Constitution layer (framework-owned, immutable law) distinct from persona (SOUL) and operator profile (USER). (every paper)
- Split content by ownership × upgrade-fate × residency, not by topic. (architect §1.2, devex DQ1, aiml DQ1, coder DQ1, contrarian DQ1)
- Delete
defaults/SOUL.md(the "Jarvis"/"PDA" file). Persona ships only astemplates/SOUL.md.template, generated at init.install.sh:232-241already refuses to seed it. (every paper) - 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)
- A blocking CI grep for personal data + dead paths is the only durable anti-regression control. (every paper)
- "Hooks are the real enforcement; prose is the spec" — promote the repo's own
prevent-memory-write.shlesson (runtime/claude/RUNTIME.md:30-32) to Constitution doctrine. (devex DQ4, contrarian DQ5, aiml §1.2, coder, steward, moonshot) - Remove framework-owned files from
PRESERVE_PATHSso gate updates reach existing installs. (every paper — this is the literal drift bug) - An enforced resident-token budget, or the new Constitution re-bloats into the old 155-line
AGENTS.mdwithin two releases. (aiml DQ5, endorsed by devex, coder, moonshot, contrarian) - Fix the false
defaults/AGENTS.md:11claim ("already in your context… do not re-read") — it is provably false on a bareclaudelaunch 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:19ANDtools/git/detect-platform.sh:89both 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 oftemplates/agent/+projects/*), whiledefaults/AGENTS.md:30usestools/git/andinstall.sh:192-194actively deletes a stalerailssymlink. A dozen templates emit a command pointing at a path the installer removes.- No LICENSE at monorepo root,
packages/mosaic/framework/, or as apackage.jsonfield.
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/, projectAGENTS.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)
- 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.
- 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).
- File-read third (fallback).
AGENTS.mdsays: "IfCONSTITUTION.mdis 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:37must leave L0 — different owner, different upgrade-fate). But it does not legitimize a standalonepolicy/layer: no paper named a failure mode that "USER.md has a## Operator Policysection" cannot handle (steward §2b). Three layers (contrarian/coder) under-serves the merge-authority extraction; five (architect) re-creates the veryAGENTS.md/STANDARDS.mdoverlap 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. Theconstitution/directory exists only in the package source, holding the non-deployedLAYER-MODEL.mdgovernance 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 insidemosaic <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 advisorymosaic doctordrift 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, optionalpolicy/*.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-fileresolves 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 abasethat 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 adoctoradvisory signal ("your SOUL was generated from template v2; v4 ships — reviewexamples/"), 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 (bareclaude/codex/opencodepointer) 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-16system-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:143says sequential-thinking MCP is REQUIRED-or-stop, whileadapters/pi.mdsays native thinking replaces it (aiml §1.3). But a bespokecapabilities.jsonschema + 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.jsonmachine-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'sCOMPLIANCE.mdharness×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 — overdefaults/ guides/ templates/ runtime/ adapters/, excludingexamples/. - 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): aSOUL.mdcontainingYou 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-doctorover the always-resident set (CONSTITUTION.md+AGENTS.mdindex +SOUL.md+USER.md+ the resident RUNTIME slice). Budget the container, not the constitution's clarity. Gates keep full unambiguous wording; procedure (wrapper paths,--purposeflags) moves to on-demandE2E-DELIVERY.md. - Rationale: A new top-level
CONSTITUTION.mdis 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"inpackage.json, on day zero. Fix both hardcoded$HOME/src/jarvis-brain/credentials.jsondefaults to fast-fail env vars. ShipCONTRIBUTING.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:
- Physical seam = ownership. Framework-owned files are overwritten wholesale (
rsyncwithout an exclude); user-owned files (SOUL.md,USER.md,*.local.md,policy/,TOOLS.md,memory,sources,credentials) are the onlyPRESERVE_PATHSentries. RemoveAGENTS.mdandSTANDARDS.mdfromPRESERVE_PATHS— this single change makes gate updates reach every existing install (the literal drift bug, contrarian §0/§3). - Additive overlays, launcher-composed.
mosaic compose-contract <harness>concatenates, in precedence order, base +.localdeltas before injection, so the model receives one pre-merged blob and never runs a redundant read-merge ritual. (D4.) - One global
FRAMEWORK_VERSIONinteger + linear migrations (the existinginstall.sh:160-202scaffold). 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 adoctoradvisory. - Migration v2→v3 (backward-compatible, the BRIEF's hard constraint):
- Snapshot
~/.config/mosaic/→~/.config/mosaic/.backup-v2/before touching disk. - Install
CONSTITUTION.mdas a new file nothing previously owned (avoids the reclassification catastrophe moonshot §2 flags — we do not try to diff/split a user-edited flatAGENTS.mdinto "framework vs user" content). - Install the slimmed
AGENTS.mddispatcher; removeAGENTS.md/STANDARDS.mdfromPRESERVE_PATHSgoing forward. - The agent self-loads L0 from
AGENTS.mdregardless of launcher injection (the self-bootstrap fallback), so even a stale-pointer install gets the gates.
- Snapshot
- 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, frameworkSTANDARDS.mdupdates. Smallest design that passes all three wins (it does:rsync+ linear migration + overlays + a 15-line grep — zero new subsystems). - Detection without enforcement:
mosaic doctorreports drift/unrendered-tokens/budget-overflow as advisories (warn, never block launch).--check-constitutionis 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.