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:
259
docs/design/framework-constitution/debate/rebuttal-steward.md
Normal file
259
docs/design/framework-constitution/debate/rebuttal-steward.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# Rebuttal — OSS Steward & Security/Compliance Lens
|
||||
|
||||
**Author role:** OSS Steward & Security/Compliance
|
||||
|
||||
**Responding to:** position-architect.md, position-coder.md, position-contrarian.md,
|
||||
position-devex.md, position-moonshot.md, position-aiml.md
|
||||
|
||||
**My original position:** position-steward.md
|
||||
|
||||
---
|
||||
|
||||
## Part 1 — Strongest Ideas from Other Personas Worth Keeping
|
||||
|
||||
### 1a. The DevEx lens on enforcement tiers is the most important cross-cutting insight
|
||||
|
||||
position-devex.md §DQ4 names something my position paper acknowledged but underweighted: **there
|
||||
are two fundamentally different enforcement models in use today, and only one of them actually
|
||||
enforces anything.** Pi gets the contract as a true system prompt via `--append-system-prompt`.
|
||||
Claude, Codex, and OpenCode get a "please read these files" instruction in a user-editable memory
|
||||
file. The DevEx paper (and the AIML paper independently) makes the enforcement-asymmetry concrete:
|
||||
`runtime/claude/RUNTIME.md:30-32` already documents this lesson with respect to the memory-write
|
||||
hook — "the rule alone proved insufficient — the hook is the hard gate." That sentence should be
|
||||
promoted to Constitution doctrine, exactly as the DevEx paper proposes.
|
||||
|
||||
From a security posture: a hard gate enforced only by prose is not a hard gate. My position paper
|
||||
proposed that "Constitution must be injection-resistant by position, not by instruction"
|
||||
(position-steward.md §DQ4), but the DevEx paper gives this the operational teeth it needs —
|
||||
specifically, that `mosaic claude` should inject L0 via `--append-system-prompt` and that
|
||||
`~/.claude/CLAUDE.md` should be explicitly documented as a weaker fallback for bare `claude`
|
||||
launches, not the primary enforcement path. This is strictly additive to my proposals and I
|
||||
endorse it.
|
||||
|
||||
The capability-manifest idea (`adapters/<h>.capabilities.json`) is also worth keeping. My position
|
||||
treated the adapter boundary as documentation; the DevEx formulation treats it as a machine-readable
|
||||
contract that makes cross-harness gaps visible and auditable. This aligns directly with my S10
|
||||
proposal (CI lint for deduplication) and extends it to per-gate enforcement coverage.
|
||||
|
||||
### 1b. The Contrarian on subtraction-first and the "rails" vs "tools" path drift
|
||||
|
||||
position-contrarian.md §DQ5 is right that adding a Constitution document without deleting the
|
||||
four existing restatements produces five law files instead of four. The Contrarian is also the
|
||||
only other paper that calls out the stale `rails/git/` path in `templates/agent/AGENTS.md.template`
|
||||
as a concrete behavior-degrading bug — agents following the template's queue-guard command get
|
||||
"no such file" on a live install because `install.sh:193` deletes the `rails` symlink. This is
|
||||
exactly the kind of failure mode my lens exists to catch, and the Contrarian caught it more
|
||||
explicitly than I did.
|
||||
|
||||
The Contrarian's hard cap of ~40 lines for L0 (versus my "~500 tokens target" in position-steward.md
|
||||
§DQ5) is also the right order of magnitude and the more disciplined constraint. I accept it.
|
||||
|
||||
The "subtraction before structure" principle, while contrarian in framing, is security-consistent:
|
||||
a shorter Constitution has fewer maintenance sites, fewer drift opportunities, and fewer lines
|
||||
that can carry personal data under future commits. Deletion is a compliance control.
|
||||
|
||||
### 1c. The AIML lens on the `{{PLACEHOLDER}}` failure class
|
||||
|
||||
position-aiml.md §DQ2 introduces a failure class my sanitization section did not address:
|
||||
a half-rendered template is *worse* than no file for an LLM. If `mosaic init` fails mid-render,
|
||||
an agent that loads `You are **{{AGENT_NAME}}**` from `SOUL.md` may adopt the literal string
|
||||
"{{AGENT_NAME}}" as a persona or treat the braces as an instruction artifact. The proposed
|
||||
`mosaic-doctor` hard-fail on unrendered `{{...}}` or `${...}` tokens in any resident file is a
|
||||
cheap, mechanical control that closes an entire failure class. I am adding it to my recommendation
|
||||
set as S13 (below in §Part 3).
|
||||
|
||||
---
|
||||
|
||||
## Part 2 — Weakest or Riskiest Proposals
|
||||
|
||||
### 2a. The Moonshot's YAML front matter and hash-check launcher (position-moonshot.md §DQ1)
|
||||
|
||||
The Moonshot proposes adding `mosaic-layer:`, `mosaic-owner:`, and `mosaic-override:` YAML front
|
||||
matter to each deployed file, with the launcher performing a content-hash check and refusing to
|
||||
start if a layer-0 file has been structurally overridden.
|
||||
|
||||
This is the most dangerous-sounding "safety" proposal in the set, and my lens rejects it:
|
||||
|
||||
**Failure mode 1: the launcher is not the agent.** The hash-check-before-launch mechanism only
|
||||
works if every agent session is launched through `mosaic <harness>`. A direct `claude` launch,
|
||||
a Codex session launched through the platform's own tooling, or any future harness without a
|
||||
wrapper binary bypasses the check entirely and silently. The DevEx paper already established that
|
||||
three of four current harnesses enforce the contract only as a memory-file pointer — adding a
|
||||
hash gate that those three harnesses cannot enforce is security theater that creates false
|
||||
confidence.
|
||||
|
||||
**Failure mode 2: YAML front matter in an LLM context file is an injection surface.** A model
|
||||
that reads front matter including `mosaic-override: forbidden` now has "forbidden" in its context
|
||||
as a property of a rule. Adversarial prompt injection that adds `mosaic-override: allowed` to
|
||||
a lower-layer file would read as a structural property to a naive parser, not as a contradiction
|
||||
to check against the Constitution. The Constitution's injection-resistance guardrail
|
||||
(currently `defaults/SOUL.md:48`, which I proposed promoting to L0) is the correct mitigation —
|
||||
but it must not be undermined by teaching the model that override rules are expressed as parseable
|
||||
properties.
|
||||
|
||||
**Failure mode 3: it blocks the alpha without adding OSS hygiene value.** A content-hash
|
||||
check requires that the installed Constitution binary-match the shipped version. This breaks the
|
||||
legitimate use case of a deployment that needs a localized version (translated docs, domain-specific
|
||||
addendum to the gate list). My three-layer model already handles this by making L0 always-overwrite
|
||||
on upgrade — that is the upgrade-safety mechanism, not hash enforcement. The Moonshot's mechanism
|
||||
should be rejected for the alpha and reconsidered only after the simpler layer/directory boundary is
|
||||
proven to work.
|
||||
|
||||
**Resolution:** keep the Moonshot's goal (detecting tampering with L0) but implement it via the
|
||||
Contrarian's simpler mechanism: L0 is never in `PRESERVE_PATHS`, always overwritten, and
|
||||
`mosaic doctor --check-constitution` compares checksums after-the-fact rather than blocking
|
||||
launches. Advisory warnings are appropriate here; hard launch gates are not.
|
||||
|
||||
### 2b. The Architect's five-layer model and per-layer version stamps (position-architect.md §DQ1, §DQ3)
|
||||
|
||||
The Architect proposes five distinct layers (Constitution, Standards, Persona, Operator Policy,
|
||||
Deployment/Runtime) with separate version stamps per layer (`constitution.version`,
|
||||
`standards.version`, `user-schema.version`) and a three-way merge for user-seeded files.
|
||||
|
||||
The per-layer version stamp proposal has a concrete failure mode: **combinatorial migration matrix.**
|
||||
If Constitution is at v5 and User schema is at v2, the installer must have tested and validated
|
||||
the migration path for every `(constitution=N, user-schema=M)` combination where `N > M`. For a
|
||||
project with a single maintainer shipping an alpha, this is a maintenance cliff. The Contrarian
|
||||
named it: "Per-file pins create a combinatorial matrix of (framework vN, user pinned vM) states
|
||||
that no one will test." The Architect's mechanism is correct in theory but wrong for an alpha
|
||||
audience.
|
||||
|
||||
The five-layer model also introduces ambiguity about where the "operator policy" layer sits.
|
||||
The Architect's smoking gun example — `defaults/AGENTS.md:37` ("Policy: Jason, 2026-06-11") —
|
||||
is real and the fix is correct (move operator policy out of the Constitution), but creating a
|
||||
dedicated `policy/*.md` layer for it adds a fourth always-resident file class when "USER.md has
|
||||
a `## Operator Policy` section" is sufficient and simpler. The complexity should be justified by a
|
||||
failure mode that a simpler design cannot handle. No one in this debate has named one.
|
||||
|
||||
**Resolution:** three layers (Constitution, Persona, Operator Profile) with a single
|
||||
`FRAMEWORK_VERSION` integer plus the directory-boundary upgrade mechanism are sufficient for the
|
||||
alpha. The Architect's per-layer stamps and three-way merge are good roadmap items for post-1.0.
|
||||
|
||||
### 2c. The DevEx on symlinks as the copy-on-link fix (position-devex.md §DQ3)
|
||||
|
||||
The DevEx paper proposes inverting the `mosaic-link-runtime-assets` policy to symlink
|
||||
framework-owned runtime pointers and copy only user-editable surfaces. The principle is correct
|
||||
(single source of truth, zero drift), but the concrete symlink proposal introduces a security
|
||||
consideration that the paper acknowledges but does not fully resolve: Windows symlink support.
|
||||
|
||||
More critically for OSS hygiene: symlinks that point from `~/.claude/CLAUDE.md` into
|
||||
`~/.config/mosaic/runtime/claude/RUNTIME.md` mean that the user's Claude harness now has a
|
||||
persistent pointer into the mosaic config directory. If the mosaic config directory is mounted or
|
||||
shared (e.g., in a container, in a dotfiles repo, in a shared dev environment), the symlink
|
||||
exposes the entire `~/.config/mosaic/` tree to any process that can follow symlinks from the
|
||||
Claude config location. The copy model, despite its drift risk, provides a natural isolation
|
||||
boundary.
|
||||
|
||||
**Resolution:** keep the copy model as the default; add a `MOSAIC_SYMLINK_RUNTIME=1` opt-in
|
||||
for users who understand the implications. This is already the DevEx paper's own caveat
|
||||
(`MOSAIC_NO_SYMLINK=1` for Windows) — I am proposing it as the default rather than the
|
||||
exception, because the privacy/isolation boundary matters more than the drift-elegance tradeoff
|
||||
at alpha.
|
||||
|
||||
---
|
||||
|
||||
## Part 3 — Sharpened Key Disagreement: Who Bears Responsibility for PII Re-contamination
|
||||
|
||||
Every paper in this debate agrees on the diagnosis: personal data in shipped files, CI gate to
|
||||
prevent it. There is no disagreement on the *what*. The disagreement my lens must sharpen is on
|
||||
the *who bears ongoing responsibility and how the framework enforces it structurally, not procedurally.*
|
||||
|
||||
### The core disagreement
|
||||
|
||||
The Coder paper (position-coder.md §DQ2) describes the contamination as "surgical, not structural"
|
||||
— approximately three files plus stray guide references. The DevEx paper counts 51 hits across 29
|
||||
files. My position paper's evidence table lists 9 categories of violation. The Contrarian counts
|
||||
55 raw occurrences across 30 files. **The disagreement about the contamination's extent reflects a
|
||||
disagreement about the threat model:** is this a one-time cleanup or a structural re-contamination
|
||||
risk?
|
||||
|
||||
The Moonshot names the ongoing risk most explicitly (position-moonshot.md §Biggest Risk): agents
|
||||
running with the operator's SOUL.md and USER.md in context will generate framework-improvement PRs
|
||||
that embed operator-specific terminology. The self-evolution rules in `defaults/AGENTS.md:136-139`
|
||||
explicitly encourage this. Without a structural firewall, the framework re-contaminates itself
|
||||
through its own best-practice enforcement.
|
||||
|
||||
### My lens's resolution
|
||||
|
||||
The re-contamination threat is structural, not one-time, because **the primary author of framework
|
||||
improvements is an agent that always runs with operator-specific context.** This means:
|
||||
|
||||
1. **The CI grep is necessary but not sufficient.** Every paper agrees on the CI grep (denylist of
|
||||
`jarvis|jason|woltje|PDA` over `packages/mosaic/framework/` excluding `examples/` and test
|
||||
fixtures). That is S5 in my original proposals and it must be in the alpha DoD. But it only
|
||||
catches the operator's *current* identity tokens. A future operator who also runs Mosaic daily
|
||||
will contaminate the framework with *their* tokens, and no denylist written today will catch it.
|
||||
|
||||
2. **The structural fix is a "no operator context in framework PRs" rule enforced by the
|
||||
framework's own scaffolding.** Concretely: the `defaults/AGENTS.md` self-evolution rules
|
||||
(lines 136-139) must include a new hard constraint:
|
||||
|
||||
> When capturing a `framework-improvement` or `tooling-gap` pattern to OpenBrain or proposing
|
||||
> a framework PR, you MUST NOT include content derived from SOUL.md, USER.md, or any
|
||||
> operator-specific context. Framework proposals must be operator-agnostic by construction.
|
||||
> If you cannot express the improvement without operator-specific language, that is a signal
|
||||
> the improvement belongs in `policy/` or a project `AGENTS.md`, not in the Constitution.
|
||||
|
||||
This rule belongs in the Constitution (Layer 0) because it gates framework evolution, not
|
||||
just current sessions.
|
||||
|
||||
3. **The denylist must include a structural-category check, not just known tokens.** The CI grep
|
||||
should also fail on patterns like `~/src/<word>`, `/home/<word>/`, and any absolute home-dir
|
||||
path — not just the current operator's identifiers. This closes the class of violation, not
|
||||
just the current instances.
|
||||
|
||||
4. **The `CONTRIBUTING.md` I proposed (S12) must be written before the alpha tag, not deferred
|
||||
to pre-stable.** Contribution guidelines are the only mechanism that governs PRs from community
|
||||
contributors who are not running the CI grep locally. The BRIEF's backward-compatibility
|
||||
constraint and the "solid alpha release" goal both imply external contributors are in scope.
|
||||
A `CONTRIBUTING.md` without a section on operator-data hygiene is an invitation to
|
||||
re-contaminate.
|
||||
|
||||
5. **The missing LICENSE (my S1/S2) remains a blocker for everything else.** No other hygiene
|
||||
measure matters if the package has no legal open-source status. Under the Berne Convention,
|
||||
a publicly accessible repository without a license is "all rights reserved." Community
|
||||
contributors who submit PRs without a CLA or DCO have unclear IP status. This is the highest-
|
||||
severity finding in my original position and no other paper disputes it. It must be resolved
|
||||
before the alpha tag, because after the alpha tag there will be downstream users whose code
|
||||
depends on this package, and retroactively adding a license creates ambiguity about the
|
||||
pre-license period. **Ship with MIT + DCO on day zero.**
|
||||
|
||||
### Additional proposal from rebuttal review: S13
|
||||
|
||||
Based on the AIML paper's finding (position-aiml.md §DQ2), I am adding:
|
||||
|
||||
**S13 — mosaic-doctor hard-fail on unrendered tokens in resident files.** `mosaic-doctor` must
|
||||
fail non-advisorily if any file in the resident set (`CONSTITUTION.md`/`AGENTS.md`, `SOUL.md`,
|
||||
`USER.md`, `TOOLS.md`, any `RUNTIME.md`) contains a `{{...}}` or `${VAR}` token (excluding
|
||||
documented `${VAR:-default}` safe-defaults tagged with `# safe-default:`). This closes the
|
||||
half-rendered-template failure class, which is a security-adjacent concern: a mis-rendered SOUL
|
||||
with placeholder tokens could cause an agent to adopt an arbitrary string as its governing
|
||||
identity.
|
||||
|
||||
---
|
||||
|
||||
## Summary of Top Contentions
|
||||
|
||||
1. **LICENSE + DCO is a blocker for the alpha — no other proposal matters without it.** A
|
||||
public repository without a license is not open source. Ship MIT + a DCO CI check before
|
||||
the alpha tag; there is no valid reason to defer this.
|
||||
|
||||
2. **CI PII grep must close the structural contamination class, not just the current tokens.** The
|
||||
denylist must include absolute home-dir patterns (`~/src/<word>`, `/home/<user>/`) in addition
|
||||
to operator-specific identifiers. The self-evolution rules in AGENTS.md must prohibit operator
|
||||
context from entering framework PRs by explicit Constitution rule, not just by convention.
|
||||
|
||||
3. **The Moonshot's hash-check launcher gate is security theater for three of four harnesses and
|
||||
should be replaced by the simpler always-overwrite-L0 + post-hoc doctor check.** A launch-time
|
||||
guard that only works when `mosaic <harness>` is the entry point provides false confidence about
|
||||
direct launches, where the Constitution is weakest anyway.
|
||||
|
||||
4. **The Architect's five-layer model and per-layer version stamps are roadmap items, not alpha
|
||||
requirements.** Three layers (Constitution, Persona, Operator) with directory-level ownership and
|
||||
a single `FRAMEWORK_VERSION` integer are sufficient for the alpha and do not create a
|
||||
combinatorial migration test matrix.
|
||||
|
||||
5. **CONTRIBUTING.md and the re-contamination rule in AGENTS.md must ship with the alpha.** The
|
||||
self-evolution mechanism that allows agents to propose framework changes is a structural
|
||||
re-contamination risk. Procedure (contributing guide) and rule (Constitution constraint on
|
||||
framework-improvement proposals) are both required; neither alone is sufficient.
|
||||
Reference in New Issue
Block a user