Files
stack/docs/design/framework-constitution/debate/rebuttal-coder.md
Jason Woltje c70b217a5c
Some checks failed
ci/woodpecker/push/ci Pipeline failed
docs(design): mosaic framework constitution — expert conference output
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>
2026-06-15 23:47:49 -05:00

15 KiB
Raw Blame History

Rebuttal — Pragmatic Coder Lens

Author role: Pragmatic Coder — cares about implementability, migration cost, and what a maintainer can actually keep working across releases.

Responding to: all seven position papers (architect, aiml, contrarian, devex, moonshot, steward, and the coder's own opening position).


Part 1 — Strongest ideas from other personas worth keeping

1a. The CI grep gate (Contrarian, DevEx, Steward, AIML — universal agreement)

Every other persona proposes a blocking CI check for personal-data tokens. Every one of them is right. This is the only proposal in the entire debate with zero credible downside. The contamination reached 2955 files (counts differ slightly by grep pattern) precisely because the existing defaults/README.md:7 promise ("no personal data should be committed") is prose with no enforcement. The CI gate is ~15 lines of shell and it makes the entire sanitization discussion permanent rather than aspirational.

Concrete form I'd endorse for alpha DoD (Contrarian's version is the cleanest):

grep -rinE 'jarvis|jason|woltje|\bPDA\b|/home/jwoltje|~/src/jarvis|/rails/' \
  packages/mosaic/framework/ \
  --exclude-dir=examples \
  && { echo "PERSONAL DATA OR STALE PATH IN SHIPPED FRAMEWORK"; exit 1; } || exit 0

Note: /rails/ belongs on this list. The Contrarian and AIML papers both identify the live rails/ vs tools/ path conflict in templates/agent/AGENTS.md.template as a correctness bug that will make agents issue "no such file" errors on ci-queue-wait.sh. That is not a design question — it is a broken template in production and it should be fixed before alpha.

1b. The .local.md overlay pattern for upgrade-safe user customization (AIML)

The AIML paper proposes SOUL.local.md / USER.local.md overlays that are always preserved by upgrade and loaded last-within-layer. This is the best concrete answer to DQ3 of any paper. The insight: framework owns the base shape; user owns the delta; the two never share a file. It mirrors the settings.json / settings.local.json split the Claude runtime already uses (runtime/claude/RUNTIME.md:47) — a pattern that already works in the codebase.

The alternative proposals (Architect's 3-way merge, DevEx's mosaic-reconcile, Moonshot's migrations/) are all more complex and require new tooling that must be maintained. The .local.md pattern requires only two lines added to PRESERVE_PATHS and two sentences in AGENTS.md load order. It is implementable in an afternoon and never regresses.

1c. "Prose rules are advisory; hooks are the gate" elevated to doctrine (DevEx, Contrarian)

DevEx's strongest insight, supported by evidence already in the repo: runtime/claude/RUNTIME.md:30-32 explicitly says the prevent-memory-write.sh hook exists because "the rule alone proved insufficient — the hook is the hard gate." That is a framework lesson that should be promoted to the Constitution itself, not left buried in one runtime file.

The Contrarian frames this well: prefer mechanical enforcement (hooks/CI) over prose gates wherever the gate is checkable. A Constitution that instructs maintainers to convert checkable gates into hooks is more durable than one that relies on models reading prose carefully.


Part 2 — Weakest or riskiest proposals with concrete failure modes

2a. The Architect's five-layer model and 3-way merge engine (attack)

The Architect proposes five distinct layers (Constitution, Standards, Persona, Operator Policy, Deployment/Runtime) plus a git merge-file-style 3-way merge for upgraded user files. The layer count is intellectually clean but operationally reckless.

Concrete failure mode: The 3-way merge requires a "base" — the template version the user's file was generated from, stamped at init time. That stamp must be stored somewhere, retrieved during upgrade, and matched against the correct prior template. If any link in that chain breaks (lost stamp, renamed file, manually-edited header), the merge silently degrades to a clobber or a conflict that surfaces as noise. Real users will not resolve SOUL.md.mosaic-merge conflict files. They will either ignore them (drift) or delete them and regenerate (losing customization). The Architect's migration section acknowledges the risk vaguely ("migration test matrix") but provides no concrete implementation. The existing run_migrations() in install.sh is already at 42 lines for two version hops. A 3-way merge adds a class of failure that the current maintainer cannot reasonably test across all permutations of prior edits.

The pragmatic counter: the .local.md pattern (see 1b) achieves the same upgrade safety with zero merge machinery. User adds a section → puts it in SOUL.local.md → upgrade never touches it. No base version needed. No conflict to resolve. The cost is that users must put new additions in .local.md rather than editing SOUL.md directly — which is a good habit to enforce anyway.

What to keep from the Architect: the physical separation of constitution/ (always overwritten) from user files at root (always preserved) is correct and should be adopted. Only the 3-way merge engine should be dropped.

2b. The Moonshot's YAML front-matter layer markers and content-hash launcher enforcement (attack)

The Moonshot proposes adding mosaic-layer, mosaic-owner, and mosaic-override YAML front matter to every Constitution file, with the launcher performing content-hash checks and refusing to start if a layer-0 file has been structurally modified.

Concrete failure mode 1 — agent context pollution. YAML front matter in a Markdown file that agents read as context is not neutral. Models parse it as structured data. A file that starts with:

---
mosaic-layer: 0
mosaic-owner: framework
mosaic-override: forbidden
---

gives the model explicit machine-readable "layer 0" and "forbidden" signals — which sounds useful until you realize that an adversarial project file claiming mosaic-layer: 0 will be treated by the model with the same weight. The metadata is unverifiable by the model. It only helps the launcher — and only if the launcher actually implements the hash check, which is new tooling that doesn't exist yet.

Concrete failure mode 2 — hash check fragility. A content-hash check on Constitution files means any legitimate framework upgrade that changes CONSTITUTION.md will trigger a hash mismatch warning on every user's machine until they run mosaic upgrade. That is the correct behavior for a compromised file — but it is indistinguishable from a normal upgrade. Users will learn to dismiss the warning, rendering the gate meaningless. The Steward proposes mosaic doctor --check-constitution for the same purpose, which is better because it is opt-in diagnostic, not a startup blocker.

What to keep from Moonshot: the 500-word budget for the resident core is correct and the Moonshot is the only paper that proposes it as a hard word count (not just a line count). That discipline should be adopted. The YAML front matter and hash enforcement should not.

2c. The DevEx's capability manifest JSON per harness (attack, with nuance)

DevEx proposes adapters/<h>.capabilities.json machine-readable manifests that map abstract capability verbs ("structured_reasoning") to concrete tool bindings per harness. The goal — removing the four near-duplicate "sequential-thinking required (except Pi)" stanzas — is correct. The mechanism is over-engineered for alpha.

Concrete failure mode: the manifest is a new contract surface. Every new harness must produce a correct JSON manifest. Every new Constitution capability verb must be added to every manifest. If a manifest is wrong or stale (the Pi manifest says "gate": false for structured_reasoning but the Constitution says it's required), behavior diverges silently. The four-way prose duplication is bad, but at least it's human-readable and catches errors at review time. A JSON manifest that no one reads until something breaks is worse.

The pragmatic counter for alpha: Delete the duplicate policy text from the four runtime/*/RUNTIME.md files and replace each with a one-line reference: "Policy: ~/.config/mosaic/CONSTITUTION.md. Harness-specific mechanics below." Total work: four small edits. That removes the duplication and the drift risk without creating a new JSON schema to maintain. The capability manifest is a good idea for a post-alpha v2 — when there are enough harnesses (say, 6+) that prose management becomes genuinely untenable.


Part 3 — The key disagreement most relevant to this lens: how many files is "one Constitution"?

The single sharpest divergence in the debate is not about whether to have a Constitution layer — all seven papers agree on that. The disagreement is: should the Constitution be one flat file or a directory of decomposed files?

  • Flat file camp (Contrarian, AIML, coder's own opening position): one CONSTITUTION.md, ~4080 lines, containing only the irreducible gates. Everything else stays in existing files. Advantage: trivially injected into any harness as a single read; trivially line-count enforced; trivially referenced by path; impossible to partially-load.

  • Directory camp (Architect, Steward, Moonshot, DevEx): constitution/ directory with GATES.md, DELIVERY.md, ESCALATION.md, SUBAGENT.md, GUIDE-INDEX.md, COMPLIANCE.md, migrations/, schema.json, etc. Advantage: cleaner separation of concerns within law. Disadvantage: agents must load multiple files to have the complete law, and the load order becomes a new point of failure.

Why the flat file wins for alpha

The Steward's proposed load order is revealing:

1. ~/.config/mosaic/constitution/GATES.md
2. ~/.config/mosaic/constitution/DELIVERY.md
3. ~/.config/mosaic/SOUL.md
4. ~/.config/mosaic/USER.md
5. Project-local AGENTS.md
6. Runtime RUNTIME.md

Items 1 and 2 are now two separate file reads that must both succeed for the agent to have the complete law. If an agent on a constrained harness (e.g., direct claude launch via ~/.claude/CLAUDE.md) processes item 1 and then gets distracted by the task before loading item 2, it is operating with incomplete gates. The DevEx paper explicitly identifies this as the "load-order indirection chain breaks silently" risk — and it becomes worse, not better, with a directory of multiple constitution files.

The AIML paper has the clearest statement of the primacy/recency principle: the Constitution should be at the very top and anchored at the very bottom of the injected blob. You cannot anchor a directory — you can only anchor a file. A single flat CONSTITUTION.md can be composed into position by the launcher; a directory requires the launcher to decide the ordering, which is a new failure surface.

Resolution: one flat CONSTITUTION.md for alpha; directory structure optional post-alpha

Concrete proposal:

  1. Single CONSTITUTION.md file, ~80 lines, placed in ~/.config/mosaic/ root (not a subdirectory). Content: the 13 hard gates minus the one operator-specific merge-authority policy (which moves to a policy/ file per the Architect's correct insight), plus the 5 escalation triggers, block-vs-done, mode declaration protocol, and a one-sentence precedence rule. Not constitution/CORE.md. Not defaults/CONSTITUTION.md. Just ~/.config/mosaic/CONSTITUTION.md — discoverable, injectable, flat.

  2. AGENTS.md becomes the load-order dispatcher and Conditional Guide Loading table only. ~50 lines. First instruction: "read CONSTITUTION.md (if not already injected by launcher)." No gates restated. No "Non-Negotiable" section. Upgrade-safe because it is not in PRESERVE_PATHS (it's a framework-owned dispatcher, not user content). The self-bootstrapping pattern the coder's opening position identified — "if CONSTITUTION.md is not already in context, read it now" — is the correct defensive pattern and it works equally for system-prompt injection and direct-launch pointer scenarios.

  3. PRESERVE_PATHS in install.sh:24 shrinks to: SOUL.md SOUL.local.md USER.md USER.local.md TOOLS.md memory sources credentials. Constitution and AGENTS.md are removed from the preserve list — they are always overwritten. This single change means gate updates reach users on every mosaic upgrade without manual intervention.

  4. Post-alpha, if the Constitution grows beyond 100 lines, that is a signal to extract a GUIDE-INDEX.md (the conditional loading table) as the first split. The directory structure proposed by Architect/Steward/DevEx is the right evolution target — not the right alpha starting point.

The test for any alpha proposal: a fresh mosaic claude launch and a direct claude launch (using only ~/.claude/CLAUDE.md) must both result in the agent having the complete law resident before its first tool call. With one flat CONSTITUTION.md and a self-bootstrapping AGENTS.md, both scenarios work. With a constitution/ directory, the direct launch scenario depends on the pointer correctly enumerating all files in the directory — a fragile assumption.


Top Contentions (short list for the conference)

  1. Ship one flat CONSTITUTION.md, not a directory. A directory multiplies load-order failure points. The alpha must work on direct launches where injection is weakest. One file is injected whole; a directory requires ordered multi-file loading.

  2. Drop 3-way merge; adopt .local.md overlays. The 3-way merge engine (Architect, DevEx) is unimplementable at alpha quality. The .local.md pattern achieves the same outcome with existing machinery and no new failure modes.

  3. The CI PII grep is mandatory DoD for alpha. Every paper agrees. It is ~15 lines of shell. It is the only durable anti-contamination control. Ship it with the alpha or the sanitization work will re-decay. Include /rails/ in the denylist — that stale path is a live correctness bug that breaks agent-issued ci-queue-wait.sh commands on 12 templates.

  4. Remove AGENTS.md and STANDARDS.md from PRESERVE_PATHS. They are framework-owned dispatchers, not user content. Keeping them preserved means users never receive gate updates — the exact deployed-vs-source drift the brief identifies as "a real problem today."

  5. Promote "hooks are the real gate" to Constitution doctrine. The prevent-memory-write.sh lesson (runtime/claude/RUNTIME.md:30-32) is the most actionable DevEx insight in the repo. It belongs in CONSTITUTION.md as a design principle so future maintainers write hooks, not more prose.

  6. Drop the Moonshot's YAML front matter. Content-hash launcher enforcement is fragile and trains users to dismiss startup warnings. The Steward's mosaic doctor --check-constitution (opt-in diagnostic) is the right mechanism for the same concern.

  7. Drop the DevEx's per-harness capability JSON manifests for alpha. The duplication problem they solve is real, but the fix is simpler: delete the duplicate policy text from the four runtime/*/RUNTIME.md files and replace with a one-line reference to CONSTITUTION.md. Four edits, no new schema surface, done.