Files
stack/packages/mosaic/framework/CONTRIBUTING.md
Jason Woltje 528700ceea
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/tag/publish Pipeline was successful
feat(framework): P6 — docs + compliance matrix + resident-budget CI (#607)
Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
2026-06-22 02:20:35 +00:00

9.3 KiB
Raw Blame History

Contributing to the Mosaic Framework

The Mosaic framework is the open-source agent-operating layer that deploys to ~/.config/mosaic/. It is designed to be forked and customized — but the shared core must stay operator-neutral, deduplicated, and upgrade-safe. This guide is the contract for changing framework-owned files.

Governance model and layer rationale: constitution/LAYER-MODEL.md (source-only). Requirements & phase history: docs/design/framework-constitution/.


1. The layer model (where does my change go?)

Layer What Owner On upgrade File(s)
L0 Constitution — the non-negotiable law (hard gates) Framework Overwritten CONSTITUTION.md
L1 Standards & guides — how to do the work well Framework Overwritten; user delta → *.local.md STANDARDS.md, guides/*
L2 Persona (SOUL) — agent name, tone, role User (init) Never overwritten SOUL.md (+ optional SOUL.local.md)
L3 Operator (USER) — human identity, prefs, policy User (init) Never overwritten USER.md (+ optional USER.local.md)
L4 Project / runtime mechanism — per-repo deltas; harness wiring Repo / framework Project user-owned; runtime overwritten <repo>/AGENTS.md, runtime/<h>/RUNTIME.md

The one sentence a user can rely on: edit SOUL.md / USER.md and the .local.md overlays — they survive every upgrade. To change framework behavior, add a .local.md overlay; never edit a framework-owned file in place.


2. Operator hygiene (PII / secrets prohibition) — blocking

Framework-owned files ship publicly. They must not contain:

  • Operator or personal identity (names, handles, pronouns, accessibility notes).
  • Private $HOME paths, private hostnames, or domains.
  • Secrets, tokens, or credentials (use ~/.config/mosaic/credentials.json; the hook URL soft-degrades via ${OPENBRAIN_URL}).

This is enforced by tools/quality/scripts/verify-sanitized.sh, wired blocking in CI (.woodpecker/ci.yml). It runs two rule classes: structural (private-$HOME defaults, dead paths, unrendered tokens) and a labeled current-contaminant denylist. Run it locally before pushing:

bash packages/mosaic/framework/tools/quality/scripts/verify-sanitized.sh

Operator-specific behavior belongs in your SOUL.md/USER.md/*.local.md, never in the shared core. (The "framework-PR firewall" in CONSTITUTION.md §4 states this as law for agents opening framework PRs.)


3. Dedup rule — one source, everyone references it

Hard gates live in CONSTITUTION.md (L0) only. AGENTS.md, STANDARDS.md, and every runtime/<h>/RUNTIME.md reference the law — they never restate it. Restating a gate is a defect: it creates two sources that drift. If you find a gate duplicated outside L0, delete the copy and point to L0.

AGENTS.md is a thin dispatcher (load order + guide router + the tier-aware self-load). Keep it that way; new procedure goes in guides/* (on-demand), not in the resident core.


4. Resident line-count ceiling — blocking

The framework-owned files injected by value (CONSTITUTION.md, AGENTS.md, each runtime/<h>/RUNTIME.md) are budgeted by line count — never by word count (a word cap forces paraphrasing the law, the exact drift vector we removed).

bash packages/mosaic/framework/tools/quality/scripts/check-resident-budget.sh

Wired blocking in CI. Gate wording stays intact; if a file legitimately needs more lines, raise its ceiling in the script deliberately (in the same PR, with rationale). The per-harness total resident prompt (which also sums the user's SOUL.md/USER.md) is a mosaic doctor runtime advisory — CI cannot see user files, so it is out of CI scope by design (DESIGN §7).


5. Dual-installer parity rule

Two installers seed and migrate ~/.config/mosaic/:

  • framework/install.sh (bash) — the canonical installer.
  • packages/mosaic/src/config/file-adapter.ts (TS) — the wizard path.

Any change to seed lists, overwrite/preserve semantics, or migration MUST land in BOTH, validated by the shared fixture suite:

  • framework/tools/quality/scripts/test-install-migration.sh (bash matrix)
  • packages/mosaic/src/config/file-adapter.test.ts (vitest)

Both assert the same behavior: framework-owned files overwrite (backup-once to *.pre-constitution.bak); user-seeded files seed-if-absent; SOUL.md/USER.md/ *.local.md/credentials are preserved. A change in one installer without the other (and its fixtures) is incomplete.


6. Adding a harness adapter

A harness (runtime) is wired by:

  1. runtime/<h>/RUNTIME.mdmechanism only (subagent syntax, hook/MCP wiring, injection method). No restated gates (see §3).
  2. Launcher emission in src/commands/launch.ts — how the composed contract reaches the harness (system-prompt append vs. instructions file). Add the harness to the RuntimeName union and the runtime-path map.
  3. mosaic compose-contract <harness> works automatically once the runtime path exists (it composes base + *.local.md overlays for that harness).

Then add a row to the compliance matrix (§8) and mark which gates are mechanical vs. resident-only for the new harness.


7. Re-contamination rule

A green sanitization gate is not permanent. Before every PR:

  • Do not reintroduce operator identity, private paths, or secrets (§2).
  • Do not copy a gate out of L0 (§3).
  • Do not add an unrendered template token or a dead path to a shipped file.

If verify-sanitized.sh goes red, that diff is your worklist — fix it, don't suppress it.


8. Harness × gate compliance matrix

How each gate is enforced per harness. Mechanical = a hook/CI check the agent cannot bypass. Resident = injected contract prose (strong, but not a hard stop). CI = repo-side, harness-independent.

Gate / mechanism Claude Codex OpenCode Pi
Contract injection (resident-by-value) append SP instructions AGENTS.md append SP
Operator overlays (*.local, composed)
Bare-launch self-load (Tier-3, read L0)
Sanitization (no PII) — verify-sanitized CI CI CI CI
Resident budget ceiling CI CI CI CI
Migration parity (5-fixture, both installers) CI CI CI CI
no-memory-write (PreToolUse hook) mech resident-only ⚠️ resident-only ⚠️ resident-only ⚠️
QA / typecheck (PostToolUse hooks) mech resident-only ⚠️ resident-only ⚠️ resident-only ⚠️
Native heartbeat (fleet ps model/status) sidecar sidecar sidecar native

⚠️ Hook-parity gap (tracked, v2): the mechanical PreToolUse/PostToolUse hooks exist for Claude Code only. On Codex/OpenCode/Pi those gates are currently enforced by the resident contract + CI, not by a per-tool hook. Closing hook parity is a v2 item, not part of this alpha.


9. Known limitations (accepted residual risks)

These are accepted with rationale (DESIGN §9); they are documented, not bugs:

  • Bare-launch overlays are base-only. A harness started without mosaic never ran the composer, so *.local.md overlays are not applied. Mitigated by the unconditional Tier-3 self-load + the mosaic doctor nudge in AGENTS.md; not eliminated. Relaunch via mosaic <harness> to pick up overlays.
  • Bare-launch drift is undetected by mosaic doctor (the launcher never ran).
  • Codex/OpenCode/Pi hook parity is a tracked v2 gap (§8).
  • Live-launch cross-harness verification is v2; the alpha verifies the composer by unit test (per-tier anchor + Tier-3 byte-equality), not a live launch.

Deferred to v2 (explicit): constitution/ deploy directory; capability JSON adapters; 3-way merge; policy/*.md composition; per-layer version stamps as a migration driver.


10. PR checklist

  • No operator identity / private paths / secrets (verify-sanitized.sh green).
  • No gate restated outside CONSTITUTION.md (§3).
  • Resident budget green (check-resident-budget.sh).
  • Seed/migration changes landed in both installers + shared fixtures (§5).
  • New harness → compliance-matrix row updated (§8).
  • prettier --check + pnpm lint + pnpm typecheck + pnpm test green.