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>
268 lines
18 KiB
Markdown
268 lines
18 KiB
Markdown
# Rebuttal — The Framework Architect
|
||
|
||
**Lens:** Clean layering, single-source-of-truth, separation of concerns, long-term
|
||
maintainability.
|
||
|
||
**Author role:** Framework Architect
|
||
**Responding to:** position-coder, position-contrarian, position-devex, position-aiml,
|
||
position-steward, position-moonshot (and defending/extending position-architect).
|
||
|
||
**One-line stance:** The six other papers converge on the *shape* I proposed — split law
|
||
from persona from operator, make the seam physical, enforce it in CI. That convergence is
|
||
the real signal of the conference. Where they diverge is on *how much machinery the seam
|
||
needs*, and that is where the architecture is won or lost. My job here is to keep the seam
|
||
**physical and boundary-checked** while killing two proposals that would re-introduce the
|
||
exact coupling we are trying to remove — and to settle the one disagreement that actually
|
||
determines whether this design is maintainable: **is enforcement a property of the launcher,
|
||
or a property of the artifact?**
|
||
|
||
---
|
||
|
||
## 1. Strongest ideas from other personas worth keeping
|
||
|
||
### 1.1 Contrarian's "subtraction before structure" is the correct precondition for my own layering
|
||
|
||
The Contrarian's central claim — *"the framework's biggest defect is not under-layering, it
|
||
is over-volume and internal contradiction"* (position-contrarian §TL;DR) — is the most
|
||
important corrective to my own paper, and I am adopting it as a hard precondition. I argued
|
||
for **five layers**; the Contrarian and Coder argued for **four**. On reflection the
|
||
Contrarian is right that *adding a fifth document called "Constitution" on top of four
|
||
existing restatements yields five disagreeing law files, not one*. The architecture only
|
||
pays off if the new `CONSTITUTION.md` is created **by extraction and deletion**, never by
|
||
addition.
|
||
|
||
I verified the contradiction he cites is live, not hypothetical: 12 template files under
|
||
`templates/` still emit `~/.config/mosaic/rails/git/...` while the canonical contract uses
|
||
`tools/git/...` (`defaults/AGENTS.md:30`), and `install.sh:192-194` *actively deletes* a
|
||
stale `rails` symlink on migration. So the framework already knows `rails/` is dead and
|
||
ships 12 templates that point an agent at a path the installer removes. That is a
|
||
single-source-of-truth violation producing a runnable-command failure — exactly the class
|
||
of bug my lens exists to eliminate. **Keep:** law stated once, everything else references it,
|
||
CI greps for known-dead path tokens. This is non-negotiable and I will not let an elegant
|
||
five-layer diagram obscure it.
|
||
|
||
### 1.2 DevEx's "ownership + mutability is the layer axis" sharpens my owner×cadence basis
|
||
|
||
position-devex §DQ1 draws the layer lines by *"who owns the file and what happens to it on
|
||
upgrade — not by subject matter,"* and position-aiml §DQ1 adds the *token-lifecycle* axis
|
||
(residency). Both are refinements of the basis I proposed (owner × change-cadence). The
|
||
synthesis is clean and I endorse it: **a layer boundary is legitimate iff the two sides
|
||
differ in owner, upgrade-fate, OR residency.** That test does real work — it is precisely
|
||
why `defaults/AGENTS.md:37`'s "(Policy: Jason, 2026-06-11.)" merge-authority clause cannot
|
||
live in the constitution: it has a different owner (operator) and a different upgrade-fate
|
||
(preserved, not clobbered) than the gate mechanism around it. Three independent papers reach
|
||
the same seam from three different axes; that is the convergence worth banking.
|
||
|
||
### 1.3 Steward's license + credentials findings are the genuinely new, blocking facts
|
||
|
||
position-steward is the only paper that surfaces two issues outside the DQ frame that are
|
||
nonetheless **release blockers** and that my own paper missed: (1) there is no `LICENSE` file
|
||
anywhere — *"Public does not mean licensed"* (§Cross-Cutting) — so the package is legally
|
||
all-rights-reserved; and (2) `tools/_lib/credentials.sh:19` hardcodes
|
||
`$HOME/src/jarvis-brain/credentials.json` as a credential default. From a maintainability
|
||
lens these are layer-5 (deployment) contamination of the worst kind: a *security-relevant
|
||
default* baked into shared tooling. **Keep:** both go in the alpha definition-of-done, and
|
||
the credentials default becomes `${MOSAIC_CREDENTIALS_FILE:?...}` (fast-fail), consistent
|
||
with the existing `STANDARDS.md:35` ban on `${VAR:-default}` for required values. The
|
||
framework already has this rule for downstream apps; it is violating it in its own tooling.
|
||
|
||
---
|
||
|
||
## 2. Weakest / riskiest proposals — concrete failure modes
|
||
|
||
### 2.1 Moonshot's YAML front-matter + content-hash "launcher refuses to start" is layer inversion
|
||
|
||
position-moonshot §DQ1 proposes putting `mosaic-layer: 0 / mosaic-owner: framework /
|
||
mosaic-override: forbidden` front-matter in each deployed file, and having *"the launcher
|
||
read these headers and refuse to start if a layer-0 file has been structurally overridden
|
||
(content-hash check)."* position-steward §DQ3 proposes the same mechanism by another name:
|
||
`mosaic doctor --check-constitution` comparing SHA-256 against a shipped `.checksums` file.
|
||
|
||
This is architecturally backwards and I will die on this hill. **It makes the layer model a
|
||
property of runtime metadata and a hashing tool, when the entire point of the re-architecture
|
||
is to make the layer model a property of *directory structure*.** Failure modes:
|
||
|
||
1. **It re-couples what we just decoupled.** If "this file is immutable law" is encoded in
|
||
YAML front-matter *inside the file*, then the immutability claim and the content it governs
|
||
share a file — the same co-mingling (`defaults/SOUL.md` mixing persona + law + accommodation)
|
||
we are eliminating. A user (or an agent) who edits the body can edit the header. The
|
||
guarantee is self-referential.
|
||
2. **The checksum manifest is a fourth source of truth that will drift.** `.checksums` /
|
||
`schema.json` / front-matter `mosaic-layer` all encode "what is framework-owned." So does
|
||
the directory split. So does `install.sh`'s preserve/overwrite logic. That is four encodings
|
||
of one fact. position-aiml §physics-#3 names exactly why this fails: *contradiction is
|
||
silently lossy*. The first time a maintainer adds a constitution file and forgets to
|
||
regenerate the checksum, `mosaic doctor` either false-positives (blocks every start) or the
|
||
check is disabled — and a disabled integrity check is worse than none.
|
||
3. **"Launcher refuses to start" is a denial-of-service against the operator's own work.** A
|
||
content-hash mismatch can be a benign line-ending normalization, an `rsync` mtime quirk, or
|
||
a legitimate hotfix the user applied while waiting for an upstream PR. Hard-failing the
|
||
launcher on byte-inequality turns a maintainability nicety into an availability outage.
|
||
|
||
**The architecturally correct version is what I already proposed and the directory split gives
|
||
for free:** framework-owned content lives under `~/.config/mosaic/constitution/` and is
|
||
**`rsync --delete`'d wholesale on every upgrade** (position-coder §DQ3 `FRAMEWORK_DIRS`,
|
||
position-architect §DQ3). The user *cannot* persist an edit to a clobbered directory across
|
||
upgrade — that is the enforcement, and it requires zero hashes, zero front-matter, zero
|
||
launcher gate. Immutability is enforced by *the file being overwritten*, not by *a tool
|
||
checking whether it was*. Drift-detection-by-checksum is solving a problem that
|
||
overwrite-by-directory deletes. If you want a doctor check, check *structure* ("is there a
|
||
stray flat `AGENTS.md` shadowing `constitution/`?"), not *content bytes*.
|
||
|
||
### 2.2 Moonshot/DevEx's `.local.md` + 3-way-merge reconciliation engine is over-engineering the wrong layer
|
||
|
||
position-moonshot §DQ3 and position-devex §DQ3 both propose a per-file template-version marker
|
||
plus a **3-way merge** (base = old template, theirs = user file, ours = new template) that
|
||
surfaces `SOUL.md.mosaic-merge` conflicts "exactly like git," plus copy-vs-symlink policy
|
||
inversion in `mosaic-link-runtime-assets`. position-coder §DQ3 proposes the lighter
|
||
`E2E-DELIVERY.local.md` overlay variant.
|
||
|
||
The instinct (don't make users edit framework files) is right and is the same one I argued.
|
||
But a 3-way-merge engine over Markdown prose is a maintainability liability that fails its own
|
||
goal:
|
||
|
||
1. **Markdown has no merge semantics.** `git merge-file` resolves by *line*, not by *meaning*.
|
||
A reflowed paragraph in the new template (one logical edit) produces a wall of phantom
|
||
conflicts against a user's reflowed copy. The user is now hand-resolving `<<<<<<<` markers in
|
||
their persona file on every upgrade — the precise "clobbered on upgrade" pain the BRIEF set
|
||
out to kill, re-introduced as "conflict-resolution toil on upgrade."
|
||
2. **It is aimed at the layer that least needs it.** SOUL/USER are *small, user-owned, rarely
|
||
re-templated*. The thing that genuinely evolves is the *framework* law (layer 1–2), and that
|
||
is solved by overwrite, not merge. Building a merge engine for the stable layer while the
|
||
volatile layer needs none is effort spent against the gradient.
|
||
3. **The simpler, strictly-better primitive already exists in this very ecosystem.** Additive
|
||
override files — `policy/standards-overrides.md` (my §DQ3), Contrarian's
|
||
`<!-- mosaic:include STANDARDS.local.md -->`, AIML's `.local.md` loaded-last-within-layer —
|
||
give upgrade-safe customization with **zero merge conflicts**, because the framework file is
|
||
never edited and the user delta is a separate, append-only file the composer concatenates.
|
||
This is the config-layering pattern (base + drop-in) that `settings.json` /
|
||
`settings.local.json` already use (`runtime/claude/RUNTIME.md:47`). Adopt the drop-in;
|
||
reject the merge engine.
|
||
|
||
**Verdict:** keep template-versioning *as a doctor signal* ("your SOUL was generated from
|
||
template v2; v4 ships — review `examples/` for new sections"), but the resolution mechanism is
|
||
an **additive overlay**, not a 3-way merge. Reserve any merge at all for the single
|
||
genuinely-hand-tuned generated file (`TOOLS.md`), and even there surface conflicts in `doctor`
|
||
rather than auto-resolving.
|
||
|
||
### 2.3 Moonshot's "Pi is the reference harness" inverts the single-source-of-truth dependency
|
||
|
||
position-moonshot §DQ4: *"Pi is the Mosaic reference harness. When designing a new Constitution
|
||
gate, first define it as a Pi extension behavior, then define the equivalent approximation for
|
||
other harnesses."* position-devex's capability-manifest idea is the better-engineered cousin of
|
||
this, and I keep that — but the "Pi-first" framing is a layering error.
|
||
|
||
If the constitution is the single source of truth (every paper agrees it must be), then gates
|
||
must be authored as **harness-agnostic capability requirements**, and *each* adapter — Pi
|
||
included — resolves them to mechanism. Making one harness the reference means the abstract law
|
||
is defined in terms of one concrete implementation's affordances; the day Pi's extension model
|
||
changes, the *constitution* needs editing. That is the tail wagging the dog. position-devex
|
||
§DQ4 already states the correct rule: the constitution speaks in **capability verbs**
|
||
("use structured reasoning for multi-step planning"), and `adapters/<h>.capabilities.json` binds
|
||
the verb to `mcp:sequential-thinking` (gate: true) on Claude or `native-thinking` (gate: false)
|
||
on Pi. **Keep the capability manifest; drop the "Pi is canonical" framing.** No harness is
|
||
canonical; the *capability vocabulary* is canonical, and it lives in layer 1, owned by no
|
||
runtime.
|
||
|
||
---
|
||
|
||
## 3. The key disagreement, sharpened — and how to resolve it
|
||
|
||
Strip away the agreements and exactly one fault line determines whether this architecture is
|
||
maintainable long-term:
|
||
|
||
> **Is the constitution enforced because the launcher injects it, or because the artifact is
|
||
> self-bootstrapping and the directory layout makes it un-clobberable?**
|
||
|
||
The two camps:
|
||
|
||
- **Launcher-trust camp** (implicit in position-moonshot, parts of position-steward §DQ4): the
|
||
launcher injects `CONSTITUTION.md` as system-prompt text, and we add metadata/hash checks so
|
||
the launcher can *refuse to run* if law was tampered with. Enforcement is an active runtime
|
||
behavior.
|
||
- **Artifact-trust camp** (position-coder §"Single Strongest Recommendation", position-devex
|
||
§"Biggest risk", position-aiml §DQ4): on 3 of 4 harnesses the "constitution" arrives only as a
|
||
*user-editable pointer file that says "go read this,"* which a busy model can skip and a user
|
||
can edit away (`defaults/AGENTS.md:11` even asserts the contract is *"ALREADY in your
|
||
context... Do not re-read it"* — which position-devex §0 and position-contrarian §DQ4 both show
|
||
is **false for a direct `claude` launch**). So the law must be (a) a file the agent is
|
||
*unconditionally told to read*, and (b) backed by a *mechanical hook* where the harness has one
|
||
(`runtime/claude/RUNTIME.md:30-32`: *"the rule alone proved insufficient — the hook is the hard
|
||
gate"*).
|
||
|
||
**My resolution — and I think it is the load-bearing decision of the whole conference:**
|
||
enforcement is a property of the **artifact and the directory**, not the launcher. Three rules,
|
||
in priority order:
|
||
|
||
1. **Immutability via directory, not metadata.** Framework law lives in `constitution/`,
|
||
`rsync --delete`'d every upgrade. There is nothing to tamper-check because tampering does not
|
||
survive an upgrade and the upgrade is the enforcement. This deletes the entire
|
||
front-matter/checksum/launcher-refusal apparatus from §2.1.
|
||
2. **Residency via self-bootstrapping read, not launcher trust.** The thin `AGENTS.md` must say
|
||
*"if `constitution/CONSTITUTION.md` is not already in context, READ IT NOW"* — never "it is
|
||
already loaded" (fix `defaults/AGENTS.md:11`). This makes the law harness-agnostic by
|
||
construction (position-coder's single strongest rec) and removes the dependency on every
|
||
launcher getting injection order right. The launcher injecting by value is an *optimization*
|
||
on strong harnesses, not the *guarantee*.
|
||
3. **Hard gates that are checkable become hooks/CI, not prose.** position-contrarian §DQ5,
|
||
position-devex §DQ4, and position-aiml §DQ4 all converge here and they are right:
|
||
no-force-merge, green-CI-before-done, no-hardcoded-secrets, no-PII-in-shipped-files, and
|
||
no-dead-path-tokens are all mechanically checkable. Each becomes a hook (PreToolUse) or a CI
|
||
grep. Prose law is the *spec*; the hook/CI is the *enforcement*. This is the only thing that
|
||
kept memory-write discipline honest (the hook, not the rule), and it is the only thing that
|
||
will keep the 29-file contamination from re-accreting.
|
||
|
||
Why this resolution and not launcher-trust: **launcher-trust adds runtime machinery (metadata,
|
||
hashes, refusal logic) to compensate for a structural weakness; artifact-trust removes the
|
||
structural weakness so no machinery is needed.** A maintainable framework prefers the design
|
||
where the invariant holds *because of how the files are laid out*, not *because a tool remembered
|
||
to check*. Every checksum manifest is a liability that drifts; every directory that is
|
||
unconditionally overwritten is a guarantee that cannot.
|
||
|
||
**Concrete reconciliation for the alpha (what I'd put to a vote):**
|
||
|
||
- Adopt **four ownership layers** (Constitution / Persona / Operator / Project), defined by the
|
||
owner×upgrade-fate×residency test (§1.2), with a typed two-axis precedence: *safety → framework
|
||
supreme; taste → user supreme* (position-contrarian §DQ1). Drop my fifth layer into a `policy/`
|
||
*directory* under operator, not a new top-level layer.
|
||
- **Physical seam:** `constitution/` (clobbered) vs root user files (preserved). No
|
||
`PRESERVE_PATHS` entry for any framework file. This is the whole upgrade-safety story.
|
||
- **Customization = additive overlays** (`policy/*.md`, `*.local.md` loaded-last-within-layer),
|
||
**not** 3-way merge.
|
||
- **Enforcement = self-bootstrapping read + hooks/CI**, **not** front-matter/checksum/launcher
|
||
refusal.
|
||
- **CI gates in the alpha DoD:** `verify-sanitized.sh` (no PII/home-paths/dead `rails/` tokens
|
||
outside `examples/`), `verify-no-duplicate-gates.sh` (one normative MUST per file),
|
||
`verify-constitution-budget.sh` (resident line ceiling — position-aiml/coder/devex all demand
|
||
this), and a LICENSE/credentials-default check (position-steward).
|
||
|
||
If we get the directory seam and the CI gates, *every other proposal in these seven papers is
|
||
either mechanical or optional polish*. If we get a beautiful five-layer precedence diagram
|
||
without them, we ship the 29-file contamination with prettier filenames.
|
||
|
||
---
|
||
|
||
## Top contentions (summary)
|
||
|
||
1. **Agree with the convergence, on one condition:** introduce the Constitution layer **by
|
||
extraction and deletion, never addition** — verified live drift (12 templates emit dead
|
||
`rails/git/` paths the installer deletes at `install.sh:193`) proves a fifth restatement
|
||
yields five disagreeing law files, not one.
|
||
2. **Reject metadata/checksum/launcher-refusal enforcement** (moonshot front-matter, steward
|
||
`--check-constitution`): it re-couples the immutability claim to the file it governs and adds
|
||
a 4th drifting source of truth. **Enforce immutability by `rsync --delete` of `constitution/`**
|
||
— overwrite *is* the guarantee; nothing to tamper-check.
|
||
3. **Reject the 3-way-merge reconciliation engine** (devex/moonshot): Markdown has no merge
|
||
semantics, so it re-creates upgrade-time toil on the *stable* layer. **Use additive overlays**
|
||
(`policy/*.md`, `*.local.md`) — zero conflicts, framework file never edited.
|
||
4. **Reject "Pi is the reference harness"** (moonshot): it defines abstract law in terms of one
|
||
runtime's affordances. **Keep devex's capability-manifest** — the constitution speaks
|
||
capability verbs; each adapter binds them; no harness is canonical.
|
||
5. **Resolve the core fault line toward artifact-trust:** the law is enforced because it is
|
||
**self-bootstrapped (`AGENTS.md` says "READ IT NOW", never "already loaded" — fix
|
||
`AGENTS.md:11`) and un-clobberable by directory**, plus **hooks/CI for every checkable gate** —
|
||
not because the launcher injects it and a tool checks a hash.
|
||
6. **Keep, and put in the alpha DoD:** the four CI gates (sanitization, no-duplicate-gates,
|
||
resident-budget) plus steward's two new blockers (**MIT LICENSE**, **credentials default →
|
||
`${VAR:?}` fast-fail**) — the only durable controls against regression.
|