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>
22 KiB
Red-Team Report: OSS Steward & Security/Compliance Lens
Author: OSS Steward & Security/Compliance (red-team pass against synthesis-v1.md)
Date: 2026-06-15
Scope: Attempt to break the synthesis design. Every claim is grounded in actual files
under packages/mosaic/framework/ — line references are real.
Executive Summary
The synthesis resolves the right architectural problems but ships with at least five conditions that could cause the alpha to fail on its own stated constraints: one that leaks credentials into every downstream fork on day one, two that re-contaminate the public package within the first framework PR authored by an agent, one that bricks the migration on legacy installs with interactive prompts, and one that leaves the cross- harness gate unenforceable for the alpha window. Each is ranked below.
RISK-01 — BLOCKER: Three $HOME/src/jarvis-brain/credentials.json defaults are executable, publicly shipped, and run without MOSAIC_CREDENTIALS_FILE being set
Severity: Blocker
Files:
tools/_lib/credentials.sh:19—MOSAIC_CREDENTIALS_FILE="${MOSAIC_CREDENTIALS_FILE:-$HOME/src/jarvis-brain/credentials.json}"tools/git/detect-platform.sh:89— same pattern, duplicated independentlytools/health/stack-health.sh:23—CRED_FILE="${MOSAIC_CREDENTIALS_FILE:-$HOME/src/jarvis-brain/credentials.json}"
The synthesis (D8, §2b) correctly names two of these for repair but the grep found three
locations. stack-health.sh is missed. Each script is chmod +x by install.sh:244 and
invocable by any user who runs mosaic-quality-verify or stack-health.
Why this is a blocker and not just major: A public OSS package that ships executable
scripts with a hardcoded absolute private home path ($HOME/src/jarvis-brain/...) is not
a style issue — it is a correctness failure. A downstream user's install will silently
default to a non-existent path, causing every credential-dependent tool to fail with a
misleading error. The error message will reference a path (jarvis-brain) that is
meaningless to any user who is not the original author. This leaks the primary maintainer's
directory layout into every fork and install. It also violates STANDARDS.md:35 (the
framework's own rule: ${VAR:-default} for required values is forbidden; use ${VAR:?}
to fast-fail).
The synthesis fix is correct but incomplete: D8 says fix credentials.sh and
detect-platform.sh. It does not mention stack-health.sh. The verify-sanitized.sh
CI gate (synthesis §2a) will catch pattern ~/src/<word> / /home/<word>/ in *.md
files but the grep pattern as specified in the synthesis targets text files — it must
also cover *.sh to catch the three shell-script instances.
Mitigation:
- Fix all three files: replace
${VAR:-$HOME/src/jarvis-brain/...}with${MOSAIC_CREDENTIALS_FILE:?MOSAIC_CREDENTIALS_FILE must be set}perSTANDARDS.md:35. - Extend
verify-sanitized.shto cover*.shfiles, not only*.md. - Add a fixture to the migration test matrix (synthesis §5.5):
MOSAIC_CREDENTIALS_FILEunset should produce a clear error, not a path-not-found on a private directory.
RISK-02 — BLOCKER: The CI sanitization gate (verify-sanitized.sh) does not yet exist; the synthesis treats it as done, but the actual file is a TypeScript quality-gates test (tools/quality/scripts/verify.sh) that checks lint/type/gitleaks — not PII
Severity: Blocker
Files:
tools/quality/scripts/verify.sh— exists, tests TypeScript/lint/gitleakstools/quality/scripts/verify-sanitized.sh— does not exist (synthesis §2a names it as new)- No
.woodpecker.ymlat framework root wires the gate to CI (only project-template woodpecker files exist undertools/quality/templates/)
The synthesis declares verify-sanitized.sh a blocking CI gate (§2a, §4, D6). It does
not exist. This is the single most critical anti-regression control in the entire design —
without it, the "personal data / dead paths / unrendered tokens" contamination can re-enter
on the first framework PR authored by an agent running with someone's SOUL.md in context.
The synthesis notes correctly that an agent's own operator identity is the primary re- contamination vector ("the primary author of future framework PRs is an agent running with some operator's SOUL/USER in context" — §4). Without the gate being real and wired, the entire sanitization guarantee is prose.
Mitigation:
- The alpha cannot tag until
verify-sanitized.shexists and.woodpecker.ymlatpackages/mosaic/framework/(or monorepo root) wires it as a blocking CI step. - The gate must cover
*.shfiles (see RISK-01) in addition to*.md. - Test coverage for the gate itself: the gate must be able to detect a planted
jarvis-braintoken and fail. Without a self-test, the gate can silently no-op on a grep syntax error.
RISK-03 — MAJOR: Personal operator data still live in four shipped guide files and the TOOLS.md default; the synthesis plan misses them
Severity: Major
Files with surviving contamination:
guides/ORCHESTRATOR.md:99,111,152— three references tojarvis-brain/docs/templates/(synthesis §2b explicitly calls for these to be fixed, but they still exist in the working copy at time of review)guides/ORCHESTRATOR-LEARNINGS.md:127—jarvis-brain/data/orchestrator-metrics.json(not in the synthesis fix list)guides/ORCHESTRATOR-PROTOCOL.md:4— "Distilled fromjarvis-brain/docs/protocols/ORCHESTRATOR-PROTOCOL.md" (not in the synthesis fix list)guides/TOOLS-REFERENCE.md:149,182,226— three jarvis-brain references including aMANDATORY jarvis-brain ruleblock and$HOME/src/jarvis-brain/tools/excalidraw_export/(not in the synthesis fix list)defaults/TOOLS.md:40-44—MANDATORY jarvis-brain ruleblock verbatimdefaults/README.md:72—mosaic init --non-interactive --name Jarvis --user-name Jason --timezone America/Chicago(a named example using private personal data)defaults/AGENTS.md:37—(Policy: Jason, 2026-06-11.)at end of Gate 13tools/qa/prevent-memory-write.sh:29— hardcodedhttps://brain.woltje.com/v1/thoughts(a private domain; this hook ships executable in every install)tools/_scripts/mosaic-doctor:312—mosaic-jarvisin the shipped skill list
Why this is major and not blocker: None of these individually break the framework's
functionality for a downstream user. But collectively, they mean a new adopter's first
mosaic-doctor run, first OpenBrain error, or first guide read will surface private data.
More critically, the prevent-memory-write.sh hook prints https://brain.woltje.com/v1/thoughts
in the agent's face every time it blocks a memory write — which happens constantly. Every
user who installs the hook gets an error message pointing to a private individual's domain.
The verify-sanitized.sh gate as specified in synthesis D6 excludes examples/ but must
also catch the guide and tool files listed here. The grep pattern jarvis|jason|woltje|\bPDA\b
will catch these, but only if the gate actually runs against guides/, defaults/, and
tools/ — confirm the exclusion list does not inadvertently omit these directories.
Mitigation:
- Replace
brain.woltje.cominprevent-memory-write.shwith${OPENBRAIN_URL:-https://brain.your-mosaic-instance.dev}/v1/thoughtsand document the env var in the generatedTOOLS.md. - Purge the four guide-level
jarvis-brainreferences in ORCHESTRATOR.md, ORCHESTRATOR- PROTOCOL.md, ORCHESTRATOR-LEARNINGS.md, and TOOLS-REFERENCE.md. - Remove
MANDATORY jarvis-brain ruleblock fromdefaults/TOOLS.md— this is operator-specific memory protocol that belongs in the operator's generatedTOOLS.mdor projectAGENTS.md. - Fix
defaults/README.md:72to use placeholder names. - Remove
(Policy: Jason, 2026-06-11.)fromdefaults/AGENTS.md:37gate 13 — the synthesis identifies this as operator policy that must leave L0 (D1 rationale). - Remove
mosaic-jarvisfrom themosaic-doctorskill list or replace withmosaic-agent(a framework-generic skill name).
RISK-04 — MAJOR: The PRESERVE_PATHS list in install.sh:24 includes AGENTS.md and STANDARDS.md; removing them is the literal drift bug fix, but install.sh is not updated
Severity: Major
File: packages/mosaic/framework/install.sh:24
PRESERVE_PATHS=("AGENTS.md" "SOUL.md" "USER.md" "TOOLS.md" "STANDARDS.md" "memory" "sources" "credentials")
The synthesis calls removing AGENTS.md and STANDARDS.md from this list "the single
change that makes gate updates reach every existing install" (§5.1, D4). The v3 migration
stub in install.sh is a comment: # ── Future migrations go here ── at line 198. The
actual change has not been applied.
Consequence: Until this line is changed, every keep-mode upgrade (INSTALL_MODE=keep,
the default for existing installs at install.sh:99) silently skips overwriting
AGENTS.md and STANDARDS.md. A user who installed v1 and runs upgrade will get
framework updates to everything except the two files carrying the hard gates. The bugs
the architecture is designed to fix will not reach existing deployments.
Secondary issue: The seeding logic at install.sh:235-241 seeds AGENTS.md,
STANDARDS.md, and TOOLS.md from defaults/ only when they do not yet exist. If
CONSTITUTION.md is introduced as a new file (synthesis §2a), it needs to be added to
this seeding block — otherwise the first upgrade will skip seeding it for fresh installs
that happen before CONSTITUTION.md is in PRESERVE_PATHS.
Mitigation:
- Change
PRESERVE_PATHSline to remove"AGENTS.md"and"STANDARDS.md". - Add v3 migration block that (a) snapshots
~/.config/mosaic/to~/.config/mosaic/.backup-v2/(synthesis §5.4), (b) seedsCONSTITUTION.mdas a new file, (c) removesAGENTS.md/STANDARDS.mdfrom any PRESERVE record. - Add
CONSTITUTION.mdto the seeding block at line 235 alongsideAGENTS.md. - Run the three-fixture migration test matrix before tagging alpha (synthesis §5.5): fresh install, legacy-flat user-edited install, user-tuned-standard install — with no interactive prompt and no hang.
RISK-05 — MAJOR: install.sh blocks on interactive prompt in non-TTY environments; the three-fixture migration test cannot pass criterion 3 of "no hang"
Severity: Major
File: packages/mosaic/framework/install.sh:84-101
case "$INSTALL_MODE" in
keep|overwrite) ;;
prompt)
if [[ -t 0 ]]; then # <-- only interactive if TTY
...
read -r selection # BLOCKS
else
INSTALL_MODE="keep" # silently defaults to keep
fi
;;
esac
When running in non-TTY (CI, headless, piped installs) the installer silently defaults
to keep. This means a CI smoke test that upgrades from v2 to v3 will silently not
overwrite AGENTS.md and STANDARDS.md unless MOSAIC_INSTALL_MODE=overwrite is
explicitly passed. The synthesis migration plan (§5.5) requires that fixture 2
(legacy-flat user-edited install) proves "law moves, user files survive" — but the
default non-TTY behavior will quietly preserve the old AGENTS.md, and the test will
pass even though the gate update did not reach the install. The test matrix will produce
a false green.
Similarly, mosaic-init has the same pattern (tools/_scripts/mosaic-init:100-107):
when NON_INTERACTIVE=0 and a value is missing, it prompts and reads from stdin, which
hangs in CI unless --non-interactive is passed.
Mitigation:
- The alpha CI smoke test MUST pass
MOSAIC_INSTALL_MODE=overwriteorkeepexplicitly — never rely on thepromptdefault. - Document the required env vars for headless upgrade in
CONTRIBUTING.md. - For the three-fixture test matrix, pin fixture 2 to
MOSAIC_INSTALL_MODE=keepto exercise the preserve/overwrite split under the exact conditions a user upgrade uses.
RISK-06 — MAJOR: The .local.md overlay compose mechanism is entirely absent; the upgrade-safety guarantee is unimplementable until it exists
Severity: Major
The synthesis resolves DQ3 (upgrade-safe customization) by specifying SOUL.local.md,
USER.local.md, and STANDARDS.local.md as additive overlays composed by
mosaic compose-contract <harness> before injection (§5.2, D4). No such script or
mechanism exists in tools/_scripts/. No *.local.md file handling appears anywhere
in the framework codebase:
grep -rn "\.local\.md|local_overlay|local-overlay" packages/mosaic/framework/ -- (zero results)
The synthesis explicitly defers 3-way merge and relies on .local overlays as the
only upgrade-safe customization path for L1 (STANDARDS.md). Without the overlay
composer, a user who wants to tighten STANDARDS.md has two options: (a) edit
STANDARDS.md directly and lose the change on the next upgrade (the bug the whole
architecture is meant to fix), or (b) do nothing. The alpha ships with no working
customization path for L1.
This is not blocked by the CONSTITUTION.md extraction — overlays are a separate
mechanism — but it must exist before the alpha tags or the upgrade-safety promise is
marketing copy, not engineering.
Mitigation:
- Add
mosaic compose-contract(or equivalent) totools/_scripts/before alpha tag. Minimum viable: a script that concatenates$MOSAIC_HOME/STANDARDS.md+$MOSAIC_HOME/STANDARDS.local.md(if present) into a temp file and injects it. - Update
install.shto document the.local.mdconvention and create emptySTANDARDS.local.md.exampleso users know the escape hatch exists. - The LAYER-MODEL.md governance spec should explicitly enumerate which files are
overlay-eligible and which are not (to prevent users from creating
CONSTITUTION.local.mdand expecting it to work).
RISK-07 — MAJOR: defaults/AGENTS.md:11 contains the false claim the synthesis explicitly flags as a known bug — it is still present and still teaches agents to skip the gates
Severity: Major
File: packages/mosaic/framework/defaults/AGENTS.md:11
"The core contract is ALREADY in your context (injected by
mosaiclaunch). Do not re-read it."
The synthesis (§0, settled point 9) names fixing this false unconditional claim as settled
and required. The file still contains it verbatim. On a bare claude launch (Tier-3,
synthesis §6), AGENTS.md is the self-load fallback — the agent reads it, hits line 11,
and is told the contract is already in context when it demonstrably is not. The agent
skips the self-load of CONSTITUTION.md (once extracted) because the file it just read
told it not to. This is the exact failure mode the self-bootstrap fallback exists to prevent.
The synthesis fix is precise (synthesis §1, "If CONSTITUTION.md is not already in your
context, READ IT NOW" — conditional, not unconditional). The implementation has not
happened.
Mitigation:
Replace defaults/AGENTS.md:10-11:
The core contract is ALREADY in your context (injected by `mosaic` launch). Do not re-read it.
with the conditional self-bootstrap line:
If `~/.config/mosaic/CONSTITUTION.md` is not already in your context, READ IT NOW before proceeding.
This is a one-line change that closes a meaningful gate-skip path.
RISK-08 — MAJOR: The rails/ dead path appears in 60 template occurrences; templates are user-facing, and bootstrapped repos inherit broken wrapper commands
Severity: Major
Count: 60 lines across template files (confirmed by grep):
templates/agent/AGENTS.md.template(6 occurrences)templates/agent/projects/typescript/CLAUDE.md.template(5 occurrences)templates/agent/projects/django/CLAUDE.md.template(5 occurrences)templates/agent/projects/nestjs-nextjs/AGENTS.md.template(multiple)- Plus
templates/agent/projects/python-fastapi/,python-library/
The installer (install.sh:192-194) removes rails/ from the deployed config:
if [[ -L "$TARGET_DIR/rails" ]]; then
rm -f "$TARGET_DIR/rails"
fi
But every project bootstrapped via mosaic-bootstrap-repo using these templates will
receive the dead path ~/.config/mosaic/rails/git/ci-queue-wait.sh baked into its
AGENTS.md or CLAUDE.md. When the agent tries to run the queue guard — a HARD GATE
(synthesis hard gate #6) — it fails. Gate #8 says: "if any required wrapper command fails,
status is blocked; stop." The agent stops and reports a failure on a dead path that
ships in the framework.
The synthesis identifies this (§0, verified live fact; §2b fix). The implementation has not happened.
Mitigation:
A global sed/find-replace of rails/git/ → tools/git/ and rails/codex/ → tools/codex/
across all template files. This is a mechanical change, low risk, and must be in the alpha.
The CI gate (verify-sanitized.sh) should include /rails/ in its dead-path grep.
RISK-09 — MINOR: The defaults/STANDARDS.md:5 "Master/slave model" framing ships to public package and conflicts with OSS community norms
Severity: Minor
File: packages/mosaic/framework/defaults/STANDARDS.md:5
"Master/slave model:
- Master:
~/.config/mosaic(this framework)- Slave: each repo bootstrapped via
mosaic-bootstrap-repo"
The synthesis (§2b) explicitly calls for dropping this framing ("drop the 'Master/slave model' framing (line 5)"). The implementation has not happened. For a public OSS package, this is a contribution-chilling issue that will surface in the first community PR review. It is not a security issue but it is a hygiene issue that the synthesis already resolved and that costs one line to fix.
Mitigation: Replace with "Primary / satellite model" or "Framework / project model".
RISK-10 — MINOR: No LICENSE file exists anywhere in the monorepo; every contribution is all-rights-reserved under Berne until this is fixed
Severity: Minor (but legally time-sensitive)
Confirmed: find /home/jwoltje/src/_ms_stack/ -maxdepth 3 -name "LICENSE" — zero results.
packages/mosaic/package.json has no "license" field.
The synthesis (D8) makes this a blocking release requirement with correct rationale: "An unlicensed public repo is all-rights-reserved under Berne; retroactively licensing after the alpha creates ambiguity about the pre-license period." The synthesis chose MIT.
This is ranked minor only because it does not break runtime behavior, but the legal
window to fix it cleanly closes at the alpha tag. Post-tag contribution history will have
unclear IP status. This is the easiest fix on this list: two files and a package.json
field.
Mitigation: Add LICENSE (MIT) at monorepo root, packages/mosaic/framework/LICENSE,
and "license": "MIT" in package.json before any alpha tag. Ship CONTRIBUTING.md
with the operator-data-hygiene section.
RISK-11 — MINOR: Cross-harness smoke test required by synthesis (§6) does not exist; the "enforced across harnesses" claim is aspirational, not testable
Severity: Minor
The synthesis (D5) requires "a CI smoke test [that] launches each harness path and asserts
the irreducible gates are present in the effective context." No such test exists in
tools/quality/ or anywhere in the framework tree. The existing tools/quality/scripts/verify.sh
tests TypeScript lint/type/gitleaks — not gate residency.
Without this test, the cross-harness claim is documentation. An agent running on OpenCode
or bare claude with a stale pointer can operate without the gates and no CI check will
catch it. The synthesis correctly ranks this as necessary for the alpha claim to be true.
Mitigation: This is a legitimate post-alpha-tag risk for the alpha window. A minimal
smoke test that reads the deployed AGENTS.md, executes the conditional self-load line,
and asserts that the gate keywords (PR-review-before-merge, green CI, no forced merges, completion-defined-at-end, block-vs-done) appear in the resolved context would
close this. Mark as a tracked gap if not achievable before alpha, but the gap must be
explicit in the compliance matrix (synthesis D5).
Interaction Effects
Two risks compound: RISK-02 (no verify-sanitized.sh) + RISK-03 (surviving contamination
in guides/tools) means the sanitization story is wrong at two levels simultaneously —
the surviving tokens will not be caught even after the gate is built, unless the gate's
grep scope covers tools/*.sh and guides/*.md. Fix RISK-02 and RISK-03 together.
RISK-04 (PRESERVE_PATHS not updated) + RISK-06 (no overlay composer) means that even after the v3 migration runs, users cannot safely customize L1 (STANDARDS) without losing changes on the next upgrade. These must ship together.
RISK-01 (credential path in three scripts) + RISK-02 (gate scope misses *.sh) means
the CI gate will not catch the credential path leak even once the gate exists. The gate
scope fix and the credential path fix are co-dependent.
Summary Table
| Risk | Severity | One-liner |
|---|---|---|
| RISK-01 | Blocker | Three shipped scripts default to $HOME/src/jarvis-brain/credentials.json; synthesis misses stack-health.sh |
| RISK-02 | Blocker | verify-sanitized.sh does not exist; no CI gate wires it; the sanitization guarantee is prose |
| RISK-03 | Major | Surviving personal data in 9+ shipped files; synthesis fix list is incomplete |
| RISK-04 | Major | PRESERVE_PATHS still includes AGENTS.md/STANDARDS.md; drift bug not fixed |
| RISK-05 | Major | Non-TTY install silently defaults to keep; migration test matrix will false-green |
| RISK-06 | Major | .local.md overlay compose mechanism does not exist; upgrade-safety guarantee unimplementable |
| RISK-07 | Major | AGENTS.md:11 still says "ALREADY in context — do not re-read"; gates are skippable on bare launch |
| RISK-08 | Major | 60 template lines still emit dead rails/git/ paths; bootstrapped repos hit blocked gate on first run |
| RISK-09 | Minor | "Master/slave model" framing at STANDARDS.md:5 ships to public |
| RISK-10 | Minor | No LICENSE file exists; legal window to fix cleanly closes at alpha tag |
| RISK-11 | Minor | Cross-harness smoke test does not exist; "enforced across harnesses" is aspirational |