# PRD: Mosaic Stack v0.1.0

## Metadata

- **Owner:** Jason Woltje
- **Date:** 2026-03-12
- **Status:** draft
- **Best-Guess Mode:** true
- Repo (target): `git.mosaicstack.dev/mosaic/mosaic-stack`
- Baseline: `~/src/jarvis-old` (jarvis v0.2.0)
- Package source: `~/src/mosaic-mono-v0` (@mosaicstack/\* packages)
- Agent harness: [pi](https://github.com/badlogic/pi-mono) (v0.57.1)
- Remote control reference: [OpenClaw](https://github.com/openclaw/openclaw) (upstream, canonical)

---

## Problem Statement

Jarvis (v0.2.0) is a self-hosted AI assistant with a Python FastAPI backend and Next.js frontend. It handles chat, projects, tasks, and LLM routing but lacks orchestration depth, agent coordination, shared memory, and remote access. The Mosaic framework (`~/.config/mosaic`) provides agent guides, shell-based orchestration tools, and quality rails — but these are loose scripts, not an integrated platform. The `@mosaicstack/*` packages in mosaic-mono-v0 began consolidating these into TypeScript packages (brain, queue, coord, cli, prdy, quality-rails) but have no UI, no auth, and no agent runtime integration.

**The gap:** Three codebases with overlapping concerns, no unified runtime, no remote control surface (Discord/Telegram), no gateway orchestrator, and a Python backend that doesn't align with the target TypeScript-everywhere stack.

**What Mosaic Stack solves:** A single monorepo that brings together many pieces to make one beautiful picture — a self-hosted, multi-user AI agent platform with web dashboard, TUI, remote control, shared memory, mission orchestration, and extensible skill/plugin architecture. All TypeScript. Pi as the agent harness. Brain as the knowledge layer. Queue as the coordination backbone.

---

## Objectives

1. **Unified TypeScript monorepo** — One repo, one language, one build pipeline for all Mosaic Stack components
2. **Pi-powered agent runtime** — Pi SDK embedded as the core agent loop; Pi TUI as the terminal interface
3. **Web + TUI + Remote** — Next.js dashboard for visual management, Pi TUI for terminal work, Discord/Telegram for remote control
4. **Gateway orchestrator** — Central routing layer that dispatches tasks to appropriate agents based on capability, cost, and context
5. **Shared memory** — PostgreSQL canonical store + vector DB for semantic search + tiered log summarization to prevent context creep
6. **Multi-user with SSO** — BetterAuth with Authentik/WorkOS/Keycloak SSO, RBAC for family/team/business use
7. **Full @mosaicstack/\* package integration** — brain, queue, coord, mosaic, prdy, quality-rails, cli all integrated
8. **Extensible** — MCP capability, skill import interface, plugin architecture for LLM providers and remote channels

---

## Scope

### In Scope (v0.1.0 Beta)

1. Chat/conversation UI (web) — carry forward from jarvis-old, rewrite frontend to work with new backend
2. Pi TUI integration — terminal-based agent interaction using Pi SDK
3. Web dashboard — settings, task management, projects, PRDs, missions, agent status
4. Gateway orchestrator (`@mosaicstack/gateway`) — central dispatch for agent tasks with routing logic
5. Task management — CRUD, kanban, mission-scoped tasks, dependency tracking
6. Project management — projects, milestones, PRDs linked to missions
7. Shared memory system — learned preferences, behaviors, defaults; tiered storage with summarization
8. User management — RBAC (admin, member, viewer), multi-user capable
9. SSO — BetterAuth with Authentik/WorkOS/Keycloak adapter
10. Remote control — Discord plugin (high priority), Telegram plugin
11. LLM provider support — Anthropic subs, Codex subs, Z.ai subs, other API-based, Ollama, LM Studio, llama.cpp
12. Agent routing — task-based model/provider selection (cost/capability matrix)
13. MCP capability — server and client, tool registration
14. Skill import interface — browse, install, manage agent skills
15. `@mosaicstack/brain` — structured data layer (migrated to PG + vector DB backend)
16. `@mosaicstack/queue` — Valkey-backed task queue with MCP tools
17. `@mosaicstack/coord` — mission coordination engine
18. `@mosaicstack/mosaic` — install wizard / bootstrap
19. `@mosaicstack/prdy` — PRD wizard
20. `@mosaicstack/quality-rails` — code quality scaffolder
21. `@mosaicstack/cli` — unified `mosaic` CLI
22. Docker Compose deployment + bare-metal capability
23. Agent log service — ingest, parse, tier, summarize agent interaction logs
24. Local durable agent fleet canary — `mosaic fleet` / `mosaic agent` CLI for an isolated tmux-backed canary fleet using a named socket, with roster-driven local customization and rollback-safe verification

### Out of Scope (v0.1.0)

1. SaaS / multi-tenant revenue model — this is a personal/family/team tool
2. Mobile native apps — web responsive is sufficient
3. Public npm registry publishing — Gitea registry only
4. Video/voice agent interaction
5. Full OpenClaw feature parity — we take inspiration, not wholesale migration
6. Calendar integration (deferred — brain tracks events, but no gcal sync yet)
7. GLPI/helpdesk ticket sync (deferred)
8. Woodpecker CI integration tooling (deferred — focus on core platform first)

---

## Compaction Refresh Trust Lifecycle (M1, #827–#830)

### Problem and objective

Context compaction, session replacement, and same-PID runtime reloads can leave a previously VERIFIED runtime lease attached to stale directives. M1 must revoke that authority mechanically for Claude (including Claudex) and Pi without trusting caller-asserted identity or forking the external broker state machine.

### Requirements

1. `CR-REQ-01`: Claude `PreCompact` and `SessionStart` with matcher `compact`, plus Pi `session_before_compact` and the first post-`session_compact` `context`, SHALL independently revoke the active broker lease.
2. `CR-REQ-02`: Runtime generation increases—including same-PID Pi reload/new/resume/fork and Claude resume/clear—SHALL monotonically replace the prior broker incarnation and inherit no VERIFIED lease.
3. `CR-REQ-03`: A fired observer that cannot confirm broker revocation SHALL fail closed through lifecycle cancellation, a private local generation fence, and/or a runtime-local tool latch. The existing all-tools broker gate remains authoritative.
4. `CR-REQ-04`: The lease TTL SHALL remain monotonic and capped at 300 seconds. If both observers are missed, within-TTL consequential actions remain allowed and after-TTL actions are denied. This named bounded residual stale window SHALL be documented without claiming a mutator-action bound inside the window.
5. `CR-REQ-05`: Hook descendants SHALL use the broker-minted session and owner-only current-generation state inherited from register-before-exec. Caller-minted sessions and parallel lease state machines remain forbidden.

### Acceptance criteria

1. `AC-CR-01`: Real-socket tests prove each Claude observer revokes, Pi lifecycle tests prove both observer paths, and Claudex isolated settings preserve and install the mandatory hooks.
2. `AC-CR-02`: A same-PID generation test proves the old generation is stale and the replacement generation is UNVERIFIED across reload/resume/fork-equivalent lifecycle events.
3. `AC-CR-03`: RED-first T12b/T30 evidence explicitly reports dual-hook miss within TTL as **ALLOWED** and after TTL as **DENIED**.
4. `AC-CR-04`: Attributable executable coverage is at least 85%, the full repository suite is green on deterministic main, and independent code/security review completes before merge.

---

## Fleet Declarative Configuration Management Workstream (FCM, #758)

### Problem and objective

The local Mosaic fleet has a roster, generated agent environment files, user-systemd units, tmux
sessions, heartbeat files, examples, profiles, and separate gateway-backed agent records. These
planes have drifted and are not one safe operator lifecycle. The objective is one **local fleet
roster** as the desired-state SSOT, with generated environment, systemd, tmux, and heartbeat
artifacts as rebuildable projections; it does not merge the local fleet control plane with the
gateway-backed agent catalog.

### Normative requirements

| ID           | Requirement                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FCM-REQ-01` | The roster SHALL be the sole writable desired-state source for local fleet membership, launch policy, and persisted lifecycle target. Generated environment files, systemd enablement, tmux sessions, and heartbeat state SHALL be non-authoritative projections.                                                                                                                                                                                                         |
| `FCM-REQ-02` | The implementation SHALL provide one executable structural contract for YAML/JSON input and one shared semantic validator. Roster load, profile validation, provision, migration, and apply SHALL reuse the existing baseline-plus-`roles.local` profile/persona resolver; a parallel role resolver is forbidden.                                                                                                                                                         |
| `FCM-REQ-03` | The local fleet CLI SHALL expose documented programmatic validate, show, plan, apply/reconcile, create, inspect, update, delete, start, stop, restart, status, verify, and doctor operations with stable JSON and exit-code behavior. Existing `fleet add/remove` compatibility aliases may remain during the stated deprecation window.                                                                                                                                  |
| `FCM-REQ-04` | A fresh create SHALL persist `enabled:true` and `desired_state:stopped` unless an explicit persisted start is requested. The model SHALL distinguish enabled state, persisted desired state, and observed state. Migration, apply, reboot, and rollback SHALL not start an agent that was observed stopped before cutover.                                                                                                                                                |
| `FCM-REQ-05` | The launch chain SHALL consume deterministic, digest-stamped generated input only. Optional local overrides SHALL be parsed as strict data, may not shadow authoritative generated keys, and may not contain arbitrary commands, credential values, channels, or unknown `MOSAIC_AGENT_*` keys. Forbidden legacy keys, including `MOSAIC_AGENT_COMMAND`, SHALL be privately quarantined before launch and reported only by key name and content hash.                     |
| `FCM-REQ-06` | Mutations and apply SHALL validate before mutation, use an expected generation/lock, write projections atomically, produce a deterministic plan, and emit recovery information on partial failure. Reconciliation SHALL act only on local, enabled, roster-owned projections and SHALL not kill unmanaged tmux sessions by fuzzy name.                                                                                                                                    |
| `FCM-REQ-07` | Canonical required classes are `code`, `review`, `validator`, `orchestrator`, `team-leader`, `enhancer`, and `interaction`. `validator` issues an independent final certificate but has no merge authority; `merge-gate` remains sole approve-to-land/merge authority. Team-leader capacity is bounded by an orchestrator-issued lease, and interaction is request/status only. Tess and Ultron are configurable instance/display names, not required machine identities. |
| `FCM-REQ-08` | v1 migration SHALL be field-complete, reversible, and explicit about aliases, unresolved classes, lifecycle inference, generated-file regeneration, local override quarantine, schema-only remote/connector fields, and rollback. Every shipped example, profile, and service preset SHALL be migrated and executable, retained as an explicitly versioned v1 fixture, or retired with a replacement and deprecation note.                                                |
| `FCM-REQ-09` | M1–M5 SHALL remain local tmux/systemd control-plane work. Remote/SSH reconciliation, connector mutation, secret references, arbitrary command/channel overrides, gateway/API convergence, and UI configuration storage are excluded and require a separate PRD/threat model.                                                                                                                                                                                              |
| `FCM-REQ-10` | Documentation and examples are delivery gates. The M0 checklist at [docs/fleet/FLEET-CONFIG-DOCS-IA-CHECKLIST.md](./fleet/FLEET-CONFIG-DOCS-IA-CHECKLIST.md) and the baseline disposition inventory at [docs/fleet/LEGACY-EXAMPLE-PROFILE-DISPOSITION-INVENTORY.md](./fleet/LEGACY-EXAMPLE-PROFILE-DISPOSITION-INVENTORY.md) SHALL be maintained as acceptance evidence.                                                                                                  |

### Acceptance criteria

1. `AC-FCM-01`: A valid local v2 roster can be parsed from YAML or JSON, validated structurally and semantically through the shared resolver, and rendered canonically; invalid fields, duplicate names, unresolved classes, unsupported runtime/model combinations, socket ambiguity, and incompatible options fail closed.
2. `AC-FCM-02`: `plan` reports deterministic desired-versus-observed differences for roster, generated environment, systemd enablement, tmux/session, heartbeat, installed-asset revision, and provable orphans without mutation; `apply --check` reports drift without mutation.
3. `AC-FCM-03`: Local create/update/delete is generation-guarded, atomic, idempotent, and safe by default; it permits supported runtime/model/harness/effort/workdir/role changes without direct editing of generated environment files and does not start a newly created agent unless explicitly persisted.
4. `AC-FCM-04`: The generated-env/local-override launch chain rejects generated-key shadowing, arbitrary command override, unknown keys, shell evaluation, and sensitive-value diagnostics before any agent starts; known-safe legacy input is regenerated or strictly relocated, and forbidden input is quarantined.
5. `AC-FCM-05`: Local lifecycle reconciliation implements the persisted/transient start-stop rules, exact default/named tmux socket targeting, systemd/tmux status, stale generated state, unmanaged-session reporting, and rollback without surprise restarts or fuzzy destructive targeting.
6. `AC-FCM-06`: A v1 roster migration previews field-by-field disposition, preserves observed stopped/running state, inventories rather than reconciles remote/schema-only entries, supports a canary and rollback, and classifies every shipped example, profile, and service preset according to the M0 inventory.
7. `AC-FCM-07`: Required role authority is validated: validator certificate is consumed but does not merge, merge-gate is the sole merge authority, team-leader leases do not change roster/credentials/authority, and interaction/Tess cannot claim orchestration or merge powers.
8. `AC-FCM-08`: Documentation, examples, migration, troubleshooting, operational recovery, package/update asset drift, schema/example/profile validation, independent code/security review, validator certificate, and terminal-green CI are complete before #758 closes.

### M0 implementation gate

No source, schema, role, example, profile, systemd, or live-fleet change is authorized before M0
lands. M0 consists only of these normative requirements, the complete task DAG, the scoped
documentation IA checklist, and the legacy example/profile disposition inventory. Subsequent cards
are defined in [docs/TASKS.md](./TASKS.md) and must remain one card/one PR.

---

## Exact Cross-Harness Fleet Communications Contract (#766)

### Problem and objective

Fleet runtime contracts currently combine exact peer rows with generic operational metavariables and
independently parsed roster data. Non-Claude harnesses can mistake those metavariables for values to
infer, producing incorrect host, session, socket, or helper targets. The objective is one
roster-resolved communications contract that every supported harness receives unchanged.

### Normative requirements

1. `FCOM-REQ-01`: Fleet commands and runtime composition SHALL use one shared v1 roster structural
   resolver. A second lenient communications parser is forbidden.
2. `FCOM-REQ-02`: The composed contract SHALL render the local roster member's authoritative host,
   exact agent/session name, resolved tmux socket, exact helper path, and deterministic communications
   generation.
3. `FCOM-REQ-03`: Every known peer SHALL have one exact executable command. Same-host commands SHALL
   omit `-H`; cross-host commands SHALL use only that peer's explicit roster `ssh` target; the one
   supported fleet-wide named socket SHALL use `-L` with its exact value. A per-agent socket declaration
   must equal that fleet-wide value; unsupported independent sockets and missing cross-host SSH data SHALL
   fail closed.
4. `FCOM-REQ-04`: Operational fleet examples SHALL not contain unresolved host, session, socket, or
   helper-path metavariables. Agents SHALL select an exact rendered peer row and SHALL NOT infer,
   substitute, or fuzzy-match targeting values.
5. `FCOM-REQ-05`: An unknown local member or requested peer SHALL fail closed with exact-name discovery
   guidance. Runtime composition SHALL not silently omit a requested fleet member's communications
   contract.
6. `FCOM-REQ-06`: Claude Code, Codex, OpenCode, and Pi SHALL receive equivalent authoritative
   communications data through the common runtime composer.
7. `FCOM-REQ-07`: Tests SHALL prove the contract from framework-source `TOOLS.md`, through a fresh
   installed `TOOLS.md`, to final runtime composition and helper executability. User-owned installed
   `TOOLS.md` content SHALL remain preserved.
8. `FCOM-REQ-08`: Stale installed or active composed context SHALL be reported with deterministic
   generation/repair/relaunch guidance. Currency requires the expected source and installed contract
   marker/version plus bounded byte equality. The supported current-version repair SHALL run independently
   of package updates, preserve divergent `TOOLS.md` bytes in a digest-qualified no-clobber backup, restore
   a regular executable helper without following symlinks, and be idempotent. Detection and reporting SHALL
   NOT rewrite active context, restart a session, or mutate a live fleet.
9. `FCOM-REQ-09`: The shared resolver SHALL preserve and strictly validate every schema-supported v1
   connector kind (`tmux`, `discord`, and `matrix`) from YAML and JSON. Every accepted snake/camel alias
   pair SHALL reject differing dual declarations and accept identical declarations. JSON roster fallback
   SHALL occur only when `roster.yaml` is absent; all other YAML access failures SHALL fail closed.
10. `FCOM-REQ-10`: The communications generation SHALL cover the complete canonical rendered semantic
    contract, including identity, role/class, resolved host/socket/helper, peer metadata, and exact commands.
    Installed helpers SHALL be validated with no-follow filesystem inspection as regular executable files.
    Keep-mode reseed and relaunch discovery SHALL preserve and support both YAML and JSON rosters.

### Acceptance criteria

1. `AC-FCOM-01`: Contract fixtures contain no unresolved operational targeting metavariables; local
   identity contains exact host/session/socket/helper values.
2. `AC-FCOM-02`: Same-host, cross-host, named-socket, literal-default-socket, and missing-SSH tests prove
   exact targeting and fail-closed behavior.
3. `AC-FCOM-03`: Unknown identities and peers report known exact names plus an exact self-scoped
   discovery command; no fuzzy session selection is emitted.
4. `AC-FCOM-04`: Four-harness tests prove byte-equal authoritative communications sections.
5. `AC-FCOM-05`: Source, fresh-install, preserved-custom-install, stale-installed, composed-generation,
   helper executable, agent-send socket isolation, and exact-target tests pass.
6. `AC-FCOM-06`: Documentation defines non-mutating stale-context detection and operator-authorized,
   exact-agent relaunch; no implementation path performs automatic session mutation.
7. `AC-FCOM-07`: YAML and JSON fixtures cover every connector kind; all snake/camel aliases cover
   identical acceptance and conflicting rejection; non-`ENOENT` YAML failures do not fall back.
8. `AC-FCOM-08`: Missing, directory, symlink, and non-executable installed helpers fail closed. Explicit
   current-version repair proves partial-deletion recovery, digest-qualified backup collision safety,
   symlink-target safety, and repeated-run idempotence.
9. `AC-FCOM-09`: Markerless-equal and wrong-version source/installed contracts are stale, and a rendered
   role/class change produces a different communications generation.

---

## KBN-101 Database Runtime/Migration Role Split (#771)

### Problem and objective

PostgreSQL Gateway/storage currently uses one `DATABASE_URL` for runtime queries and migrations. That makes the deployed application identity an owner and prevents certification that KBN immutable event, artifact, checkpoint, and evidence relations reject runtime `UPDATE`/`DELETE`. KBN-101 freezes a least-privilege runtime/migration split before KBN-100 schema work.

### Normative requirements

1. `K101-REQ-01`: `DATABASE_URL` SHALL be the non-owner PostgreSQL runtime connection and `DATABASE_MIGRATION_URL` SHALL be the migration-only owner/migrator connection. They are required respectively for runtime and the dedicated `mosaic-db-migrator --run|--verify` phase in `standalone`/`federated`; local PGlite is the explicit exception. The published `@mosaicstack/db` bin maps exactly `mosaic-db-migrator` to `./dist/cli.js`, its image entrypoint is exactly `mosaic-db-migrator`, accepts no URL/SQL/schema/role argv, and returns stable sanitized exits. Every current/future PostgreSQL DDL entrypoint SHALL route to that runner or be denied, and SHALL reject `DATABASE_URL`-only execution before connection/DDL. Data migration may connect only after the runner prepares and verifies the PostgreSQL target, through dedicated non-DDL `mosaic_data_importer` and exactly `--target-url-file /run/secrets/mosaic-migrate-target-url`, its fixed paired authenticated provider-version file `/run/secrets/mosaic-migrate-target-version`, plus `--target-attestation-file /run/mosaic-attestations/migrate-target.v1.json`. KBN-101-05 obtains URL key `url` and version only from the same successful Vault KV-v2 response at `secret-{env}/mosaic-stack/database/importer` (`data.metadata.version`), renders them as one immutable generation into separate consumer copies, and never infers a provider version from DSN bytes. The trusted runner verifies TLS/identity/manifest, reads its fixed importer URL/version copies only for binding through safe no-follow fd checks, and signs a credential-free JCS/Ed25519 attestation using its runner-only fixed root-owned private-key file; no signing key reaches importer/runtime. The artifact binds secret version and SHA-256 of exact high-entropy credential-file bytes, canonical TLS host/port/database, CA/SPKI, PostgreSQL system identifier/database OID, importer role, manifest/schema fingerprints, producer invocation/build/image digest, issued/expires/nonce, and correlation. Before target connection the importer validates URL/version/attestation/public-key files, signature/key/expiry/replay/authenticated provider version/digest/generation/bindings and the importer-only CA at exact `DATABASE_TLS_CA_CERT_PATH`; after verified TLS and before DML it validates server/database/role/CA/schema identity, with same-fd/in-memory-byte TOCTOU protection, rotation/revocation, a privileged producer-only-to-importer-only artifact handoff controller that verifies/copies/fsyncs/atomically renames/seals before importer start, consumer isolation/no logging-oracle, and sanitized errors. Raw `--target-url`, `DATABASE_URL` fallback, runtime-owner use, missing/unsafe/substituted files, stale/replayed/tampered/wrong-key attestation, wrong binding, and DDL attempt fail before target connection/DDL; post-connect mismatch closes with zero DML/DDL. A reviewed finite classifier inventories executable current source/scripts/package bins, operator docs, deploy manifests, and exact normative contracts by path; active secure records pin both options/files, producer/key/bindings/tests, while normative contracts cannot mask instructions. Unknown active commands, duplicate-owner, ownerless, missing-path, and historical/status-only masking hits fail. `db:push` is forbidden outside an explicitly disposable local developer database and cannot accept a production-like URL.
2. `K101-REQ-02`: Gateway runtime/replicas SHALL not execute migrations or DDL. The runner SHALL hold one `max:1` session and fixed two-int advisory namespace `1297044289` (`MOSA`), `1262636593` (`KBN1`) across preflight, reconciliation, migration, verification, and release. It SHALL compare the versioned canonical manifest v1 tuple (journal logical index/tag plus exact SQL-byte SHA-256) to the complete observed ledger mapping; count/set-only, timestamps, and physical insertion order are non-normative and insufficient.
3. `K101-REQ-03`: PostgreSQL SHALL separate non-login platform database owner, non-login schema owner, dedicated `NOLOGIN SUPERUSER` `mosaic_extension_owner`, login migrator, dedicated login non-DDL data importer, non-login runtime capability, and login runtime roles. For PostgreSQL 17 + pgvector 0.8.2, `vector` is untrusted (`trusted` is absent and `relocatable=true`): only an externally controlled audited platform-bootstrap superuser session may `SET ROLE mosaic_extension_owner` for CREATE/UPDATE/SET SCHEMA, then `RESET ROLE`; the role has `rolcanlogin=false`, `rolsuper=true`, zero members, no runtime credential/Vault secret, and is never provided to app containers. It owns `mosaic_extensions`, fresh `vector`, and owner-bearing extension members, while `mosaic_schema_owner` receives only `USAGE` for type resolution and never ownership/`CREATE`/`ALTER`/`DROP`/member-change/default-privilege authority there. Superuser cannot be constrained by `GRANT`/`REVOKE`; this is identity/non-login/no-membership/external-control/audit isolation, not a false least-privilege claim. Extension operations require control-plane change, independent review, backup/rollback, maintenance window, and audit evidence. Managed targets that cannot establish this exact role are ineligible until an independently approved versioned provider-owned extension-owner profile exists; app/migrator ownership is never silently retained. Existing approved-owner extension relocation validates exact `pg_namespace.nspowner`, `pg_extension.extowner`, member ownership/schema/version, while legacy runtime-owned extension fails closed to a controlled shadow-database migration—never unsupported ownership alteration, catalog mutation, ownership adoption, or `DROP CASCADE`. Runtime, migrator, schema owner, importer, and all service roles must fail `SET ROLE`, catalog/direct `ALTER`/`UPDATE`/`DROP`/membership-change denial, role ownership, superuser/role-creation/schema-creation/TEMPORARY, unsafe membership, untrusted search path, missing grants, unauthenticated TLS, and immutable privilege drift checks. Application schema is fixed `mosaic` with exact `pg_catalog,mosaic` session path; historical public migrations remain byte-immutable legacy bootstrap only, every future Drizzle application declaration targets `mosaic`, and `vector` is explicitly qualified from non-writable `mosaic_extensions`. No config-derived SQL identifier is permitted.
4. `K101-REQ-04`: `mosaicstack/stack` KBN-101-00 SHALL exclusively own `infra/pg-bootstrap/roles.sql`, `infra/pg-bootstrap/extensions.sql`, `infra/pg-bootstrap/README.md`, and bootstrap tests; KBN-101-05 SHALL exclusively own `tools/db/render-postgres-secrets.ts`, its tests, and current Compose/Portainer/two-gateway deployment declarations, consuming the versioned bootstrap interface without overlap. Environment IaC/Vault is named input and Mosaic deployment control plane/Jason is activation authority. Distinct runtime/migrator/importer URL, importer authenticated provider-version, DB-client CA, Gateway leaf, and PostgreSQL server key/certificate materials are provisioned before a production-like database starts. Importer and migrator have separate immutable URL/version copies at fixed `10002:10002`/`10003:10003` identities; runtime/unrelated containers receive neither importer material, attestation private key, or importer artifact. Runtime, migrator, and importer require their mounted CA plus `sslmode=verify-full`. Exact UID/GID/mode/rendering, service-DNS SANs, Vault/compose/Swarm consumer isolation, two-gateway pair ordering, server activation, pre-enforcement legacy-client drain and `hostssl` zero-plaintext-session proof, fresh/existing transition, CA-overlap rotation, TLS-only rollback, and standalone/federated/Swarm/two-gateway positive/negative TLS evidence are required. No application-generated production certificate or plaintext bootstrap exception is permitted.
5. `K101-REQ-05`: KBN immutable relations SHALL permit the real runtime role INSERT/SELECT only and deny UPDATE/DELETE; parent retention remains RESTRICT/no-cascade. Role/password/Vault creation is external platform control, never application migration/source.
6. `K101-REQ-06`: N-1 single-URL compatibility, rollout/rollback, Vault ownership/rotation/redaction, CI, installer, compose/Portainer, observability, and deployment handoffs SHALL be separately bounded one-card/one-PR work. Prepared slices remain inactive while current owner-runtime deployments stay N-1; Mosaic control plane/Jason alone authorizes one final atomic activation or rollback, with no force-on-red/bypass. KBN-101 planning itself SHALL not mutate production.
7. `K101-REQ-07`: KBN-100 SHALL begin only after the KBN-101 foundation role/schema-boundary certificate; it SHALL rebase on that main head, restore generated Drizzle declaration/snapshot/journal consistency, and bound procedural immutable-table grant/trigger/backfill additions to its schema slice. KBN-101 real deployed-role immutable-operation certification SHALL complete after KBN-100 creates those relations and before KBN-105.

### Acceptance criteria

1. `AC-K101-01`: DTO/command-matrix tests prove required modes, PGlite exception, `mosaic-db-migrator --help|--run|--verify`/stable exits/argv refusal, public-import negative, every finite classified DDL/static-bypass inventory path and both harness pairs reject `DATABASE_URL`-only before connection/DDL, no migration-to-runtime fallback, and `db:push` refusal outside an allowlisted disposable DB. Before inventory, ownership, or status masking, the semantic fixture fails README's exact former commented code-fence generic-wrapper form and the user guide's exact former executable generic-wrapper form; source-consistency proves current `packages/storage/src/cli.ts` directly `execSync`s `pnpm --filter @mosaicstack/db db:migrate` and no `mosaic-db-migrator` bin exists, so runner-delegation documentation fails. The active `docs/guides/migrate-tier.md` route is inventoried to KBN-101-07 and proves runner-produced `--target-url-file /run/secrets/mosaic-migrate-target-url`, fixed paired provider-version file, and `--target-attestation-file /run/mosaic-attestations/migrate-target.v1.json`; runner-only signing/private-key isolation; Vault KV-v2 same-response version provenance, separate immutable generation mounts, importer CA, JCS/Ed25519 signature/key rotation/revocation, atomic artifact, expiry/replay, safe-fd secret-version/digest, canonical TLS/CA/server/database/role/manifest/schema bindings, dedicated non-DDL importer, consumer isolation/no log-oracle, and exact no-connection versus zero-DML rejection for missing/wrong/stale/replayed/tampered/wrong-key/substituted/generation-mismatched inputs. The full current non-normative docs inventory—including user guide, federation historical task/MILESTONES status, and non-operative SETUP—has an exact safe disposition. Scanner semantic checks reject automatic first-boot/startup extension/schema/migration wording, Compose-up-before-runner, init-script authority, production `.env`/monorepo auto-load/`EnvironmentFile=`/credential-export-or-argv/restart-as-secret-activation routes, and every unqualified operator-document `mosaic-db-migrator --run|--verify` hit regardless of named/normative/status classification. The exact former README/dev/deployment Compose-first sequences, former SETUP wording, exact former MILESTONES wording `pgvector extension installed + verified on startup`, former architecture-plan/PERFORMANCE/backlog runner routes, and any unqualified runner fixture fail before inventory masking. Only one `Held future procedure` Markdown section—bounded through the next equal-or-higher heading—may contain the explicit non-operative/no-current-command-authority form that names KBN-101-00/-03/-05 and preserves external bootstrap → TLS/roles → `mosaic-db-migrator --run` → `mosaic-db-migrator --verify` → Gateway/Compose readiness; every runner hit outside that section fails. The README assertion for the checked-in direct CI `pnpm --filter @mosaicstack/db run db:migrate` with `DATABASE_URL` passes only as active legacy N-1, uncertified, non-authorizing-as-an-operator-route status against an isolated disposable CI database pending KBN-101-06 removal—not as an ordinary operator or approved DDL-authority route. Only local PGlite data-layer work or non-PostgreSQL Compose is current (Gateway/Web local startup is held pending daemon/inherited/project-DSN rejection).
2. `AC-K101-02`: Fixed namespace lock contention/crash/readiness/non-interference and exact manifest-v1 reconciliation tests prove no replica race/runtime auto-migration and fail closed on every missing/unknown/duplicate/ambiguous/corrupt/stale ledger state.
3. `AC-K101-03`: Actual PostgreSQL 17 + pgvector 0.8.2 control-file, catalog, Drizzle-generation, vector-query/operator, fresh/approved-owner/legacy-shadow/partial/resume/rollback/N-1, and real deployed-role tests prove `trusted` absent/untrusted plus relocatability, external-superuser `SET ROLE` create/update/`RESET ROLE` audit, exact `rolcanlogin=false`/`rolsuper=true`/zero-membership/no-runtime-secret state, platform/schema/extension-owner/migrator/importer/runtime separation, `pg_extension.extowner` plus owner-bearing extension-member/schema/version assertions, and runtime/migrator/schema-owner/importer/all-service-role `SET ROLE`/ALTER/DROP/member-update denial. They also prove `pg_catalog,mosaic` per-session pool safety, `mosaic_extensions` qualification, identifier injection denial, ownership/membership/ledger-read/TEMP/default grants, and unsafe privilege denial.
4. `AC-K101-04`: Disposable standalone, federated/Swarm, and two-gateway verified-TLS positives plus for both pairs missing CA/wrong CA/wrong SAN/sslmode downgrade, server/Gateway key mode, UID/GID, secret-consumer isolation, and legacy-drain/`hostssl` negatives prove server bootstrap, ordering, and readiness; PGlite is expressly excluded from this PostgreSQL evidence.
5. `AC-K101-05`: Real runtime-role evidence proves INSERT/SELECT succeeds and UPDATE/DELETE fails for every frozen immutable KBN relation.
6. `AC-K101-06`: N-1/atomic activation/rollback, Vault/CA-overlap rotation/redaction, health/operator behavior, CI/deployment handoff, independent exact-head security review, and terminal-green CI evidence the foundation before KBN-100; after KBN-100, the real deployed-role immutable-operation certificate and Ultron approval release KBN-105.

**Normative implementation contract:** [`docs/native-kanban-sot/KBN-101-DB-ROLE-SPLIT.md`](./native-kanban-sot/KBN-101-DB-ROLE-SPLIT.md). `ASSUMPTION:` existing `standalone` and `federated` are all PostgreSQL production-like modes; any new PostgreSQL tier inherits these requirements until an explicit versioned amendment.

---

## Tess Interaction Agent Workstream (TESS)

### Problem and Objective

Jason needs one durable, operator-facing Mosaic agent outside Hermes that is reachable through a dedicated Discord channel and CLI, can attach to and operate the Mosaic fleet and transitional Hermes agents, and preserves context across restarts and compaction. Mos remains the coding/general fleet orchestrator; Tess is the complementary human interaction, visibility, control, and migration agent.

The objective is to ship **Tess** (from _tessera_, a piece of a mosaic) as a Pi-native, GPT-5.6 Sol agent with high reasoning. Tess must use Mosaic-owned contracts and plugins so Hermes can be replaced incrementally rather than becoming a permanent architectural dependency.

### Scope

#### In Scope

1. `TESS-ARP-001`: A runtime-neutral `AgentRuntimeProvider` contract supporting `listSessions`, `streamSession`, `sendMessage`, `terminate`, `getSessionTree`, `attach`, health, capability discovery, and normalized events/errors.
2. `TESS-PI-001`: A long-running Pi-native Tess agent profile/service pinned to GPT-5.6 Sol with high reasoning, explicit tool policy, lifecycle hooks, durable checkpoints, and restart recovery.
3. `TESS-DSC-001`: Dedicated Discord channel binding to Tess through the Mosaic gateway, with allowlists/RBAC, thread/reply policy, streaming, attachments, approvals, and correlation IDs.
4. `TESS-CLI-001`: `mosaic tess` CLI commands for chat, status, session listing, attach/detach, send/steer/stop, provider health, and recovery.
5. `TESS-FLT-001`: Fleet plugin capabilities for roster/status/heartbeat inspection, message delivery, session hierarchy, safe attach, and controlled restart/recovery.
6. `TESS-MOS-001`: Explicit Mos coordination boundary and tools: hand off orchestration requests, observe mission/task state, receive results, and never silently compete for orchestration authority.
7. `TESS-HRM-001`: Transitional Hermes adapter for profiles/agents, sessions, streaming/messages, Kanban, skills, memory, tools, cron, and health, using capability negotiation and fail-closed unsupported operations.
8. `TESS-MEM-001`: Unified memory/retrieval plugin with scoped search/recent/capture/stats, startup context injection, provenance, redaction, namespace isolation, and flat-file/project truth precedence.
9. `TESS-STA-001`: Durable agent state, inbox, handoff, compaction-recovery, and resume reconstruction.
10. `TESS-PLG-001`: Plugin/tool catalog covering runtime bootstrap, repository/PR workflow, fleet diagnostics, incident-safe read operations, Discord interaction, and extensible MCP/skill discovery.
11. `TESS-TRN-001`: Replaceable transport providers: tmux/fleet now, Matrix/native Mosaic transport later, with no Discord/CLI business logic coupled to transport details.
12. `TESS-SEC-001`: RBAC, per-operation authorization, explicit approval for destructive/privileged/customer-visible actions, audit events, secret/PII redaction, tenant isolation, and bounded command execution.
13. `TESS-SEC-002`: Command execution SHALL enforce declared scope/role server-side; admin/system and destructive operations SHALL require policy-bound durable approval.
14. `TESS-SEC-003`: Every session list/read/attach/send/terminate operation SHALL enforce server-derived owner and tenant scope; guessed or client-supplied IDs SHALL grant no authority.
15. `TESS-SEC-004`: MCP tools SHALL derive actor/tenant from authenticated context and SHALL NOT accept caller-controlled identity fields.
16. `TESS-SEC-005`: Discord plugin ingress SHALL authenticate service identity, enforce guild/channel/user allowlists, propagate correlation/message IDs, and reject replay.
17. `TESS-SEC-006`: Secret/PII classification and redaction SHALL occur before persistence and before channel egress, including tool metadata and authentication flows.
18. `TESS-SEC-007`: Approvals SHALL be one-time, expiring, actor/tenant-bound, and cryptographically bound to the exact structured action digest.
19. `TESS-SEC-008`: Ingress, provider sends, tool side effects, and responses SHALL use durable inbox/outbox/checkpoints and idempotency records for restart-safe replay.
20. `TESS-SEC-009`: Garbage collection and retention SHALL be session/tenant scoped unless executed as a separately authorized and audited system-wide job.
21. `TESS-OBS-001`: Structured logs, traces, health/readiness, provider latency/errors, session lifecycle, tool audit, and actionable recovery diagnostics.
22. `TESS-MIG-001`: Capability inventory and staged Hermes-to-Mosaic migration matrix with coexistence, cutover, rollback, and deprecation gates.

#### Out of Scope

1. Replacing Mos as coding/general fleet orchestrator.
2. Making Hermes the Mosaic core or coupling Mosaic domain logic to Hermes schemas.
3. Migrating every historical chat verbatim; only policy-compliant indexed summaries and user-selected sessions are migrated.
4. Unrestricted shell execution from Discord.
5. Full web UI parity in the first Tess operational milestone; gateway contracts must remain web-consumable.
6. Replacing tmux before Matrix/native transport reaches operational parity.

### Stakeholder and User Requirements

- Jason must be able to converse with the same Tess session from Discord and CLI.
- Jason must be able to see what is running, stale, blocked, or unhealthy without attaching manually to every session.
- Jason must be able to attach to Tess and authorized fleet sessions through supported CLI controls.
- Tess must collaborate with Mos and the fleet while preserving a single clear orchestration authority.
- The system must migrate useful Hermes/OpenClaw capabilities intentionally, with evidence, instead of copying implementations wholesale.

### Non-Functional Requirements

1. **Security:** default-deny provider/tool capabilities, least privilege, no secrets in logs/prompts/commits, Discord user/channel authorization, and auditable approvals.
2. **Reliability:** durable inbox/checkpoints; idempotent message handling; reconnect with bounded backoff; no message loss or duplicate execution across gateway restart.
3. **Performance:** first acknowledgement within 2 seconds when connected; streamed agent output begins within 5 seconds excluding model/provider delay; status reads return within 2 seconds under nominal local conditions.
4. **Observability:** every ingress message and resulting provider/tool operation carries a correlation ID across Discord, gateway, Tess, provider, and audit events.
5. **Maintainability:** channel, runtime, transport, memory, and external-agent integrations remain adapter-based with contract tests.
6. **Privacy:** only scoped context enters external runtimes; persisted messages/memories follow retention and redaction policy.
7. **Portability:** Tess runs through Pi/Mosaic contracts and does not require Hermes to start or serve native Mosaic operations.

### Acceptance Criteria

1. `AC-TESS-01`: A dedicated Discord channel and `mosaic tess chat` connect to one durable Tess session and stream responses bidirectionally.
2. `AC-TESS-02`: `mosaic tess status|sessions|tree|attach|send|stop` operate against authorized provider capabilities with stable typed outputs and actionable errors.
3. `AC-TESS-03`: Tess runs GPT-5.6 Sol at high reasoning and its effective runtime/model/tool policy is visible through status without exposing credentials.
4. `AC-TESS-04`: Tess can inspect and message the Mosaic fleet, hand orchestration work to Mos, and demonstrate that Tess does not independently claim Mos-owned orchestration work.
5. `AC-TESS-05`: Hermes adapter demonstrates session listing, streaming/message delivery, hierarchy mapping, and at least one approved capability in each of Kanban, skills, memory, tools, and cron—or reports unsupported capabilities fail-closed.
6. `AC-TESS-06`: Restart/compaction test preserves session identity, pending inbox, last durable checkpoint, and a resumable handoff without duplicate side effects.
7. `AC-TESS-07`: Unauthorized Discord users/channels, cross-tenant access, unsafe tool calls, forged approvals, and sensitive-output cases are denied and audited.
8. `AC-TESS-08`: tmux/fleet and Matrix/native transport implementations pass the same provider contract suite; Matrix may remain non-default until readiness gates pass.
9. `AC-TESS-09`: Baseline quality gates, unit/integration/contract tests, Discord+CLI E2E, restart/recovery tests, independent code review, and security review are green.
10. `AC-TESS-10`: Migration matrix documents every audited Hermes/OpenClaw capability as native, adapted, deferred, or rejected, with cutover and rollback evidence.
11. `AC-TESS-11`: User, admin, developer, API/OpenAPI, operations/recovery, and plugin-authoring documentation is current and linked from the sitemap.

### Constraints, Dependencies, Risks, and Assumptions

- Dependency: Mosaic gateway remains the single API surface; Pi is the native runtime; Valkey/PostgreSQL provide canonical durable state where required.
- Dependency: Discord bot credentials and dedicated channel ID are deployment secrets provisioned outside source control.
- Risk: Tess could drift into a second orchestrator. Mitigation: explicit role policy, Mos handoff contract, authority checks, and E2E boundary tests.
- Risk: broad Hermes compatibility can freeze legacy semantics into Mosaic. Mitigation: Mosaic-owned normalized contracts and capability negotiation.
- Risk: Discord creates a privileged remote-control surface. Mitigation: pairing/allowlists, RBAC, approvals, rate limits, audit, and safe tool classes.
- Risk: transcript ingestion can violate privacy or overload memory. Mitigation: scoped opt-in import, redacted summaries, provenance, retention, and deduplication.
- Risk: current root filesystem has limited headroom. Mitigation: isolated worktrees, no duplicated dependency installation unless required, and cleanup only after active-lane verification.
- `ASSUMPTION:` The public name is **Tess**, because the user requested a name and the tessera/Mosaic relationship is distinctive; config must permit later display-name changes without renaming APIs or storage keys.
- `ASSUMPTION:` The dedicated Discord channel ID and final guild policy will be supplied/provisioned during deployment, so implementation uses explicit configuration and fail-fast startup validation.
- `ASSUMPTION:` tmux/fleet is the production transport for the first operational milestone; Matrix/native transport is implemented behind the same contract and promoted only after parity/reliability verification.
- `ASSUMPTION:` Project/task truth remains in canonical Mosaic/project stores; semantic memory systems are retrieval/mirror layers, not hidden authorities.

### Testing and Delivery Intent

Delivery uses five gated milestones: runtime contracts/security; Pi service/state; Discord/CLI; fleet/Hermes/plugin suite; migration/Matrix/recovery/qualification. Every source-code task requires tests, independent review, a PR to `main`, terminal-green CI, and issue/task closure. Production activation additionally requires a clean-host Pi launch, dedicated Discord channel smoke test, CLI attach test, restart/recovery drill, and rollback procedure.

---

## Official Channel Plugin Workstream (#756)

### Problem and Objective

The Discord plugin currently couples Discord event handling, gateway bridging, and reply routing in one implementation and activates only on mentions. Mosaic needs an official channel adapter that behaves the same no matter whether the bound logical agent currently runs through Claude, Codex, Pi, OpenCode, or a future harness. The Discord connection and conversation address must remain stable while the gateway changes the runtime provider behind that logical session.

The objective is to make Discord the first implementation of a transport-neutral official channel contract, with explicit authorization and deterministic channel/thread routing that future Matrix, Slack, and other adapters can share.

### Scope

#### In Scope

1. `CHN-001`: Transport-neutral channel adapter, route, message, attachment, authorization-principal, response-target, and health contracts in `@mosaicstack/types`, including trusted per-binding logical-agent configuration selection.
2. `CHN-002`: Stable channel conversation addresses based on logical agent plus channel/thread identity; harness, model, and runtime-provider IDs are forbidden from channel session keys.
3. `DSC-001`: An authorized untagged message in a configured agent-bound channel routes to the agent and receives its response in that channel.
4. `DSC-002`: A bot mention in a configured parent channel creates a Discord thread, or reuses the thread already attached to that same native message; the mentioned turn and subsequent thread turns route and respond in that thread.
5. `DSC-003`: A message already inside an authorized thread inherits authorization from its configured parent and never attempts a nested thread.
6. `DSC-004`: Guild, parent channel, user, pairing, and role authorization remains default-deny before thread creation or gateway dispatch.
7. `DSC-005`: Discord service authentication, HMAC envelope integrity, replay protection, attachments, approvals, response chunking, and correlation behavior remain intact.
8. `DSC-006`: The Discord adapter exposes lifecycle and health behavior through the shared channel contract without importing a harness SDK.

#### Out of Scope

1. The logical-agent lease, fencing epoch, execution grant, checkpoint, or cross-harness takeover implementation tracked by #754/#755.
2. Dynamic Discord authorization administration in the web UI.
3. Multi-guild tenant isolation, DMs, slash commands, voice, reactions, or production bot deployment.
4. Implementing Matrix or Slack adapters in this slice.

### Non-Functional Requirements

1. **Security:** no thread or dispatch side effect occurs until guild, parent channel, user, pairing, role, and bounded per-user/channel rate checks pass; attachment metadata is shape- and size-bounded; credentials never enter source, messages, session keys, or logs.
2. **Portability:** channel contracts and stable conversation IDs contain no Claude, Codex, Pi, OpenCode, model, process, or provider-specific field; each configuration-owned binding selects its trusted logical agent without changing the channel identity.
3. **Reliability:** repeated messages for one channel/thread resolve the same conversation handle; reconnecting the adapter does not require a harness-specific rebinding.
4. **Maintainability:** Discord-specific API translation stays in the Discord package; gateway and future adapters depend on transport-neutral contracts.
5. **Observability:** thread creation or routing failure is reported without message content or credential material.

### Acceptance Criteria

1. `AC-CHN-01`: Contract and behavior tests prove the plugin route contains only logical agent plus channel/thread identity and produces the same stable conversation handle regardless of underlying harness selection.
2. `AC-CHN-02`: A mentioned authorized parent-channel message creates a thread (or reuses its already-attached thread), dispatches to the thread conversation, and targets the response to that thread.
3. `AC-CHN-03`: An untagged authorized parent-channel message dispatches to the parent conversation and targets the response to the parent channel.
4. `AC-CHN-04`: Untagged follow-ups inside an authorized thread dispatch and respond in that same thread without creating a nested thread.
5. `AC-CHN-05`: Unauthorized guilds, channels, users, unpaired users, insufficient roles, and rate-limited senders produce no thread and no gateway dispatch.
6. `AC-CHN-06`: Shared channel contracts are exported from `@mosaicstack/types`, Discord implements the lifecycle/health seam, and no harness SDK is imported by the plugin.
7. `AC-CHN-07`: Focused routing/auth tests, package tests, typecheck, lint, formatting, coverage, independent code/security review, and terminal-green CI pass.

### Constraints, Risks, and Assumptions

- Dependency: Mosaic gateway remains the policy, durable-session, audit, and runtime-provider boundary.
- Constraint: This work must not modify orchestrator-to-Pi migration or #754/#755 lease/fencing files.
- Risk: accepting untagged messages could create noisy or unintended agent input. Mitigation: only explicitly configured channels and paired, role-authorized users are accepted, with bounded per-user/channel message and thread rates.
- Risk: Discord thread creation can fail because of channel permissions, archived state, or API rate limits. Mitigation: fail without dispatching a turn whose response destination cannot be honored, and emit sanitized diagnostics.
- `ASSUMPTION:` Configured channels are dedicated agent interaction surfaces, so authorized untagged human messages are intentional agent input.
- `ASSUMPTION:` Mention in a parent channel selects a public thread; messages already in a thread remain there because Discord has no nested threads.
- `ASSUMPTION:` One Discord bot may serve multiple configuration-owned logical-agent bindings.
- `ASSUMPTION:` Static allowlists and paired-user roles are the authorization administration surface for this slice.

### Testing and Delivery Intent

Use TDD for remote-ingress routing and permission boundaries. Required evidence includes parent-channel mention, untagged parent message, existing-thread follow-up, existing-thread mention, thread reuse, unauthorized side-effect denial, stable harness-neutral conversation identity, adapter health, and regression coverage for signed envelopes and approvals. Deliver through issue #756, a reviewed squash PR to `main`, terminal-green CI, and issue closure.

---

## Mos Runtime Portability Workstream (MOS-PORT)

### Problem and Objective

Mos is currently identified partly by a harness-native session and communication process. Replacement/rebinding exists, but no gateway-enforced logical identity or fencing prevents a stale harness from continuing to reply or execute effects after takeover.

The objective is to make Mos a server-derived logical Mosaic identity whose authority can move safely among runtime connectors. The gateway owns identity, lease, policy, and audit; harnesses remain replaceable adapters.

### M1 Requirements

1. `MOS-PORT-ID-001`: Define a normalized logical-agent identity independent of Claude Code, Pi, Codex, tmux, Matrix, and provider-native session IDs.
2. `MOS-PORT-LEASE-001`: Persist one exclusive connector lease per tenant/logical-agent/binding with CAS acquisition, monotonic fencing epoch, TTL, heartbeat, explicit release, and takeover.
3. `MOS-PORT-FENCE-001`: Bind every connector dispatch/execution grant to the current server-derived tenant, logical identity, binding, connector, scopes, expiry, and lease epoch.
4. `MOS-PORT-FENCE-002`: Reject and audit stale, expired, forged, cross-tenant, cross-binding, and unauthorized grants before connector, channel, provider, or tool side effects.
5. `MOS-PORT-OBS-001`: Emit credential-safe correlation/audit events for lease acquire, renew, takeover, reject, release, and expiry.
6. `MOS-PORT-ARCH-001`: Runtime/provider adapters consume normalized lease context without adding harness-native schemas to Mosaic core.

### M1 Acceptance Criteria

1. `AC-MOS-PORT-01`: Two contenders for one binding cannot simultaneously hold current authority under concurrency.
2. `AC-MOS-PORT-02`: Successful takeover increments the fencing epoch and every operation from the old epoch fails closed before side effects.
3. `AC-MOS-PORT-03`: Gateway/database restart preserves lease and epoch state; expired leases can be recovered only through the authorized takeover path.
4. `AC-MOS-PORT-04`: Cross-tenant, cross-agent, cross-binding, forged, and expired lease/grant cases are denied and audited.
5. `AC-MOS-PORT-05`: Unit, migration, repository close/reopen, concurrency, abuse, gateway integration, independent security review, CI, and documentation gates pass.

### Deferred to Later #754 Milestones

Canonical checkpoint/handoff payloads, exactly-once connector receipts, concrete Claude/Pi/Codex adapters, channel cutover, and full cross-harness failover/rollback E2E are explicitly out of M1 scope.

---

## Architecture

### High-Level System Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                        Mosaic Stack                              │
│                                                                  │
│  ┌──────────┐  ┌──────────┐  ┌─────────────┐  ┌──────────────┐ │
│  │ Next.js  │  │ Pi TUI   │  │  Discord    │  │  Telegram    │ │
│  │ Web App  │  │ Terminal  │  │  Plugin     │  │  Plugin      │ │
│  └────┬─────┘  └────┬─────┘  └──────┬──────┘  └──────┬───────┘ │
│       │              │               │                │          │
│       └──────────────┴───────┬───────┴────────────────┘          │
│                              │                                   │
│                    ┌─────────▼──────────┐                        │
│                    │  @mosaicstack/gateway   │  ← Central Orchestrator│
│                    │  (NestJS+Fastify)  │                        │
│                    └────┬────┬────┬─────┘                        │
│                         │    │    │                               │
│          ┌──────────────┤    │    ├──────────────┐               │
│          │              │    │    │              │               │
│  ┌───────▼──────┐ ┌────▼────▼──┐ │  ┌───────────▼────────┐     │
│  │ @mosaicstack/brain│ │ @mosaicstack/   │ │  │ Agent Pool         │     │
│  │ (Data Layer) │ │ queue      │ │  │ (Pi SDK sessions)  │     │
│  └───────┬──────┘ └────────────┘ │  │ - Anthropic        │     │
│          │                       │  │ - Codex            │     │
│  ┌───────▼──────────────────┐    │  │ - Z.ai             │     │
│  │  PostgreSQL  │  VectorDB │    │  │ - Ollama           │     │
│  │  (canonical) │  (semantic)│   │  │ - LM Studio        │     │
│  └──────────────┴───────────┘    │  │ - llama.cpp        │     │
│                                  │  └────────────────────┘     │
│                    ┌─────────────▼──────┐                       │
│                    │  @mosaicstack/coord     │                        │
│                    │  Mission lifecycle │                        │
│                    └────────────────────┘                        │
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐      │
│  │ @mosaicstack/cli  │  │ @mosaicstack/prdy │  │ @mosaicstack/         │      │
│  │              │  │              │  │ quality-rails    │      │
│  └──────────────┘  └──────────────┘  └──────────────────┘      │
│                                                                  │
│  ┌──────────────────────────────────────────────────────┐       │
│  │  Valkey (queue backend)  │  BetterAuth (SSO/RBAC)   │       │
│  └──────────────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────────────┘
```

### Technology Decisions

| Layer              | Technology                           | Rationale                                                                                                   |
| ------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| **Web Frontend**   | Next.js 16 + React 19 + Tailwind CSS | SSR, RSC; design tokens from @mosaicstack/design-tokens (mosaic-stack-website)                              |
| **API / Gateway**  | NestJS + Fastify adapter             | Module system, DI, guards/interceptors for complex gateway; Fastify performance underneath                  |
| **Agent Runtime**  | Pi SDK (embedded)                    | Extensible harness with tools, skills, session management                                                   |
| **TUI**            | Pi interactive mode                  | Native terminal agent interaction                                                                           |
| **Auth**           | BetterAuth + SSO adapters            | Multi-user RBAC with Authentik/WorkOS/Keycloak                                                              |
| **Database**       | PostgreSQL 17 + pgvector             | Canonical store; pgvector for embedding search                                                              |
| **Vector DB**      | pgvector + VectorStore interface     | pgvector for v0.1.0; `VectorStore` abstraction in @mosaicstack/memory makes Qdrant a drop-in later          |
| **Cache / Queue**  | Valkey 8                             | Redis-compatible; proven in @mosaicstack/queue                                                              |
| **ORM**            | Drizzle ORM                          | TypeScript-native, lightweight, good migration story                                                        |
| **Validation**     | Zod                                  | Already used across @mosaicstack/\* packages                                                                |
| **Build**          | pnpm workspaces + Turborepo          | Proven in both jarvis-old and mosaic-mono-v0                                                                |
| **Testing**        | Vitest + Playwright                  | Unit/integration via Vitest, E2E via Playwright                                                             |
| **Remote Control** | Discord.js + Telegraf                | Inspired by OpenClaw plugin architecture                                                                    |
| **MCP**            | @modelcontextprotocol/sdk            | Already used in @mosaicstack/brain and @mosaicstack/queue                                                   |
| **Container**      | Docker Compose                       | Self-hosted; bare-metal also supported                                                                      |
| **CI**             | Woodpecker CI                        | Existing infrastructure at git.mosaicstack.dev                                                              |
| **Observability**  | OpenTelemetry + SigNoz               | Wide-event logging from day one; OTEL auto-instrumentation for NestJS/PG/HTTP; SigNoz as all-in-one backend |
| **Log Processing** | Custom ingest service                | Parse agent logs → tiered storage → summarization                                                           |

### Key Architecture Decisions

**AD-1: TypeScript everywhere (no Python backend)**
The jarvis-old FastAPI backend is not carried forward as code. Its domain logic (conversation management, LLM routing, task/project CRUD, auth) is reimplemented in TypeScript. The Python plugin system is replaced by Pi's extension/skill system and MCP tool registration.

**AD-2: Pi SDK as the agent runtime**
Instead of a custom LLM provider abstraction (jarvis-old's `BaseLLMProvider`), Pi SDK manages agent sessions. Pi handles model selection, tool calling, context management, and compaction. The gateway dispatches work to Pi sessions configured with appropriate providers.

**AD-3: Gateway as the central nervous system (NestJS + Fastify adapter)**
`@mosaicstack/gateway` is the single API surface. The web app, TUI, Discord, and Telegram all talk to the gateway. The gateway routes to brain (data), queue (coordination), agent pool (LLM work), and coord (mission lifecycle). This replaces the direct FastAPI-to-DB pattern from jarvis-old.

NestJS was chosen over raw Fastify because the gateway is inherently complex — it hosts channel plugins, agent pool management, routing engine, WebSocket hub, MCP server, auth middleware, and integrates brain, queue, memory, and log services. NestJS provides the module system, dependency injection, guards, and interceptors needed to organize this cleanly. NestJS uses Fastify as its HTTP adapter, so Fastify's performance is preserved. This also aligns with the stated stack preference in USER.md ("NestJS API + Next.js web"). @mosaicstack/brain's existing Fastify code migrates naturally into a NestJS module with Fastify adapter.

**AD-4: Brain migrates from JSON files to PostgreSQL**
`@mosaicstack/brain` currently uses a JSON file store. For Mosaic Stack, brain's data model (tasks, projects, events, agents, missions, tickets) moves to PostgreSQL via Drizzle ORM. Brain's REST + MCP interface is preserved — only the storage backend changes.

**AD-5: Tiered memory with summarization**
Agent interaction logs are ingested into a log service. Raw logs are stored short-term. A summarization pipeline (using a cheap LLM) periodically compresses logs into structured insights stored in the vector DB. This prevents unbounded log growth while preserving searchable context.

**AD-6: Remote control via plugin architecture**
Discord and Telegram plugins follow a channel plugin pattern inspired by OpenClaw (https://github.com/openclaw/openclaw). Each plugin registers as a channel with the gateway, receives messages, and dispatches them through the same routing pipeline as web/TUI messages.

**AD-7: Gateway state persistence via Valkey (restart resilience)**
The gateway persists its orchestration state (active sessions, pending dispatches, routing context, agent assignments) to Valkey. On restart, the gateway reads Valkey state and resumes operations — active agent sessions are reconnected or gracefully recovered. `mosaic gateway restart --fresh` is the nuclear option: clears the Valkey queue and all in-flight state, starting with a clean slate. This prevents context/focus/direction loss that would otherwise occur on every restart.

**AD-8: Multi-session agent architecture**
Each agent operates in a distinct session. Multiple authorized input channels (TUI, web UI, Discord) can connect to the same agent session simultaneously. This means a user can start a conversation in Discord, continue in the web UI, and monitor via TUI — all feeding into the same agent context. OpenClaw has this concept; Mosaic Stack evolves it with proper session authorization and channel multiplexing at the gateway level.

**AD-9: Discord channel-to-agent binding**
Discord channels pair to specific agent/session combinations via channel ID binding. This provides data segregation — messages in #project-alpha route to the project-alpha agent session, messages in #general route to a general-purpose session. Prevents cross-contamination between contexts and provides clear boundaries for multi-channel use.

**AD-10: Agent session barge-in via tmux**
Each agent session runs in a dedicated, named tmux session (e.g., `mosaic-agent-project-alpha`). This enables barge-in — a user can attach to any active agent's tmux session to observe, interrupt, or redirect. `mosaic agent attach <session-name>` connects to the tmux session. This provides direct low-level access when the normal channel interfaces are insufficient.

**AD-11: Cron-based scheduled jobs**
The gateway includes a cron scheduler for recurring tasks: log summarization runs, stale task detection, memory decay, provider health checks, scheduled agent dispatches. Uses node-cron or similar; schedules are configurable via web dashboard and stored in PG. Each cron job is a gateway-dispatched task that goes through the normal routing pipeline.

**AD-12: Web search tool (DuckDuckGo MCP)**
Agent sessions include a web search tool for information retrieval. DuckDuckGo via MCP server is the primary option (privacy-respecting, no API key required). Falls back to other search MCP providers if configured. Registered as a standard MCP tool available to all agent sessions.

**AD-13: Design system from @mosaicstack/design-tokens**
The web dashboard uses the Mosaic Stack design system established in `mosaic-stack-website`. The `@mosaicstack/design-tokens` package provides CSS custom properties, Tailwind preset, and TS color/font/radius exports. Dark theme default with light theme support. Fonts: Outfit (sans), Fira Code (mono). Color palette: deep blue-grays with blue/purple/teal accents.

**AD-14: Multi-tier deployment readiness**
Code is structured assuming eventual multi-node deployment with dedicated roles (gateway nodes, agent worker nodes, brain/DB nodes). Packages communicate via well-defined APIs (HTTP/WS/MCP), not in-process calls where avoidable. Service boundaries are clean: gateway is stateless (state in PG/Valkey), agent pool can scale independently, brain is a separate service. v0.1.0 runs single-node; the architecture doesn't fight horizontal scaling later.

---

## Package Structure

### Monorepo Layout

```
mosaic-mono-v1/
├── apps/
│   ├── web/                    Next.js 16 web dashboard
│   └── gateway/                @mosaicstack/gateway — NestJS API + WebSocket
├── packages/
│   ├── types/                  @mosaicstack/types — shared type contracts
│   ├── brain/                  @mosaicstack/brain — data layer (PG-backed)
│   ├── queue/                  @mosaicstack/queue — Valkey task queue + MCP
│   ├── coord/                  @mosaicstack/coord — mission coordination
│   ├── mosaic/                 @mosaicstack/mosaic — install wizard
│   ├── prdy/                   @mosaicstack/prdy — PRD wizard
│   ├── quality-rails/          @mosaicstack/quality-rails — code quality scaffolder
│   ├── cli/                    @mosaicstack/cli — unified CLI
│   ├── auth/                   @mosaicstack/auth — BetterAuth config + SSO adapters
│   ├── db/                     @mosaicstack/db — Drizzle schema, migrations, connection
│   ├── agent/                  @mosaicstack/agent — Pi SDK integration, agent pool manager
│   ├── memory/                 @mosaicstack/memory — tiered memory + summarization service
│   ├── log/                    @mosaicstack/log — agent log ingest + processing
│   └── design-tokens/          @mosaicstack/design-tokens — CSS vars, Tailwind preset, colors
├── plugins/
│   ├── discord/                @mosaicstack/discord-plugin — Discord channel
│   └── telegram/               @mosaicstack/telegram-plugin — Telegram channel
├── docker/
│   ├── gateway.Dockerfile
│   ├── web.Dockerfile
│   └── init-db.sql
├── docs/
│   ├── PRD.md                  (this file)
│   ├── TASKS.md
│   └── scratchpads/
├── docker-compose.yml
├── pnpm-workspace.yaml
├── turbo.json
├── tsconfig.base.json
├── vitest.workspace.ts
├── AGENTS.md
├── CLAUDE.md
└── README.md
```

### Package Responsibilities

#### `apps/gateway` — @mosaicstack/gateway (NEW — critical path)

The central nervous system. All clients connect here. Built with NestJS (Fastify adapter).

- **NestJS modules** — Each concern (chat, brain, agent, auth, queue, memory, plugins) is a module with clear boundaries
- **Fastify adapter** — Fastify performance under NestJS's organizational structure
- **WebSocket gateway** — NestJS built-in WebSocket support for chat streaming, agent status, notifications
- **Agent routing engine** — Routes tasks to appropriate LLM provider/model based on task type, cost tier, capability requirements
- **Session management** — Tracks active conversations, agent sessions, user contexts
- **MCP server** — Exposes Mosaic capabilities as MCP tools
- **Plugin host** — Loads and manages channel plugins (Discord, Telegram)
- **Auth middleware** — BetterAuth session validation, RBAC enforcement

Key routes:

```
POST   /api/chat                    Send message, get streamed response
GET    /api/conversations           List conversations
POST   /api/conversations           Create conversation
GET    /api/conversations/:id       Get conversation with messages
DELETE /api/conversations/:id       Delete conversation
POST   /api/tasks                   Create task (brain-backed)
GET    /api/tasks                   List/filter tasks
PATCH  /api/tasks/:id               Update task
GET    /api/projects                List projects
POST   /api/projects                Create project
GET    /api/missions                List missions
POST   /api/missions                Create mission
GET    /api/missions/:id            Mission summary with tasks
POST   /api/agents/dispatch         Dispatch work to agent pool
GET    /api/agents/status            Active agent sessions
GET    /api/memory/search           Semantic search across memory
POST   /api/memory/preferences      Store learned preference
GET    /api/skills                  List available skills
POST   /api/skills/install          Install a skill
GET    /api/providers               List configured LLM providers
POST   /api/providers               Configure LLM provider
GET    /api/admin/users             User management (admin)
POST   /api/admin/users             Create user (admin)
WS     /ws/chat/:conversationId     Streaming chat via WebSocket
WS     /ws/agents                   Agent status stream
GET    /mcp                         MCP endpoint (streamable HTTP)
```

#### `apps/web` — Next.js Web Dashboard

Carried forward from jarvis-old with significant refactoring.

- Chat/conversation UI (primary interaction surface)
- Settings management (providers, integrations, profile)
- Task management (list, kanban, detail views)
- Project management (list, detail, linked missions)
- Mission dashboard (status, progress, task breakdown)
- PRD viewer/editor
- Agent status dashboard (active sessions, routing stats)
- Skill browser and installer
- User management (admin RBAC panel)
- Auth pages (login, SSO redirect, registration)

#### `packages/types` — @mosaicstack/types

Migrated from mosaic-mono-v0. Extended with:

- Gateway types (routing, dispatch, agent pool)
- Auth types (user, role, permission)
- Conversation/message types (from jarvis-old domain)
- Memory types (preference, insight, summary)
- Plugin channel types (Discord, Telegram message mapping)

#### `packages/brain` — @mosaicstack/brain

Migrated from mosaic-mono-v0. **Storage backend changes from JSON to PostgreSQL.**

- REST API preserved (mounted as gateway sub-router or standalone)
- MCP tools preserved
- Collections layer rewritten to use Drizzle ORM queries instead of JSON file I/O
- Same entity model: tasks, projects, events, agents, missions, mission-tasks, tickets
- New: computed endpoints (today, stale, stats, search, audit) run against PG
- New: appreciation collection preserved for family use

#### `packages/queue` — @mosaicstack/queue

Migrated from mosaic-mono-v0 with minimal changes.

- Valkey-backed task queue with atomic WATCH/MULTI/EXEC
- MCP server with 8 tools
- Used by gateway for agent task dispatch and coordination

#### `packages/coord` — @mosaicstack/coord

Migrated from mosaic-mono-v0.

- Mission lifecycle: init, run, resume, status, drain
- TASKS.md parsing and management
- Session lock management
- Continuation prompt generation
- Integration with gateway for mission-driven orchestration

#### `packages/db` — @mosaicstack/db (NEW)

Shared database package.

- Drizzle ORM schema definitions (all tables)
- Migration management
- Connection pool configuration
- Shared by gateway, brain, auth, memory

#### `packages/auth` — @mosaicstack/auth (NEW)

Authentication and authorization.

- BetterAuth configuration
- SSO adapters: Authentik, WorkOS, Keycloak
- RBAC: roles (admin, member, viewer), permissions
- API key generation for brain/MCP access
- Session management middleware

#### `packages/agent` — @mosaicstack/agent (NEW — critical path)

Pi SDK integration layer.

- Agent pool manager — spawns and manages Pi agent sessions
- Provider configuration — Anthropic, Codex, Z.ai, Ollama, LM Studio, llama.cpp
- Agent routing logic — selects provider/model based on task characteristics
- Tool registration — registers Mosaic-specific tools (brain access, queue ops, memory search)
- Skill management — loads and configures Pi skills for agent sessions
- Session lifecycle — create, monitor, complete, fail, timeout

#### `packages/memory` — @mosaicstack/memory (NEW)

Tiered memory system.

- Preference store — learned user preferences, behaviors, defaults (PG)
- Insight store — distilled knowledge from agent interactions (PG + vector)
- Semantic search — query across memory using pgvector embeddings
- Summarization pipeline — compress raw logs into structured insights
- Memory API — used by gateway and agent sessions

#### `packages/log` — @mosaicstack/log (NEW)

Agent log service.

- Log ingest — receives structured logs from agent sessions
- Log parsing — extracts decisions, learnings, tool usage patterns
- Tiered storage — hot (recent, full detail), warm (summarized), cold (archived)
- Summarization trigger — invokes cheap LLM to compress aging logs
- Retention policy — configurable TTLs per tier

#### `packages/mosaic` — @mosaicstack/mosaic

Migrated from mosaic-mono-v0, updated for v1.

- Install wizard for Mosaic Stack setup
- Detects existing installations, offers upgrade path
- Configures `~/.config/mosaic/` with guides, tools, runtime configs

#### `packages/prdy` — @mosaicstack/prdy

Migrated from mosaic-mono-v0.

- PRD generation wizard
- Template-based PRD creation with Zod validation
- CLI integration via `mosaic prdy`

#### `packages/quality-rails` — @mosaicstack/quality-rails

Migrated from mosaic-mono-v0.

- TypeScript scaffolder for project quality config
- Generates ESLint, tsconfig, Woodpecker, husky, lint-staged configs
- Supports project types: monorepo, typescript-node, nextjs

#### `packages/cli` — @mosaicstack/cli

Migrated from mosaic-mono-v0, extended.

- Unified `mosaic` binary
- Subcommands: `mosaic coord`, `mosaic prdy`, `mosaic queue`, `mosaic quality`, `mosaic gateway`, `mosaic brain`
- Plugin discovery for installed @mosaicstack/\* packages

#### `plugins/discord` — @mosaicstack/discord-plugin (NEW — high priority)

Discord remote control channel. Architecture inspired by OpenClaw (https://github.com/openclaw/openclaw).

- Channel plugin that registers with the gateway as a NestJS dynamic module
- Single-guild binding only (v0.1.0) — prevents data leaks between servers
- Receives Discord messages, dispatches through gateway routing
- Streams agent responses back to Discord (chunked for 2000-char limit)
- Routes authorized untagged messages in-channel; mentions create threads (or reuse the same message's attached thread) for multi-turn topics
- Uses stable logical-agent/channel conversation addresses independent of the active harness/provider
- Bot pairing and permission management (Discord user → Mosaic user mapping)
- DM support for private conversations

#### `plugins/telegram` — @mosaicstack/telegram-plugin (NEW)

Telegram remote control channel.

- Same channel plugin pattern as Discord
- Telegraf-based bot
- Message routing through gateway
- Inline keyboard for interactive responses

---

## User/Stakeholder Requirements

### US-001 Multi-Channel Chat

**As a user**, I can chat with an AI assistant via web browser, terminal (Pi TUI), Discord, or Telegram and get consistent responses regardless of channel.

### US-002 Task & Project Dashboard

**As a user**, I can manage my tasks, projects, and missions from the web dashboard with kanban and list views.

### US-003 PRD Management

**As a user**, I can view and edit PRDs for active missions from the web dashboard.

### US-004 Agent Visibility

**As a user**, I can see which agents are active, what they're working on, and their status in real-time.

### US-005 Provider Configuration

**As a user**, I can configure which LLM providers to use and set routing preferences (cost vs capability).

### US-006 Skill Management

**As a user**, I can install and manage agent skills through the web dashboard.

### US-007 Persistent Memory

**As a user**, the system remembers my preferences, learned behaviors, and past decisions across sessions.

### US-008 Semantic Search

**As a user**, I can search across my memory, conversations, and knowledge semantically.

### US-009 User Management

**As an admin**, I can manage users, assign roles, and control access.

### US-010 SSO Configuration

**As an admin**, I can configure SSO via Authentik, WorkOS, or Keycloak.

### US-011 Self-Hosted Deployment

**As a user**, I can run Mosaic Stack via Docker Compose or directly on bare metal.

### US-012 Intelligent Routing

**As an agent operator**, the gateway intelligently routes tasks to the cheapest capable model.

### US-013 CLI Tooling

**As a user**, I can use the `mosaic` CLI for PRD creation, quality rail setup, queue management, and mission coordination.

---

## Functional Requirements

- FR-1: Chat System
- FR-2: Gateway Orchestrator
- FR-3: Agent Pool
- FR-4: Task Management
- FR-5: Project Management
- FR-6: Mission System
- FR-7: Memory System
- FR-8: Authentication & Authorization
- FR-9: Remote Control — Discord
- FR-10: Remote Control — Telegram
- FR-11: LLM Provider Management
- FR-12: Agent Routing
- FR-13: MCP Capability
- FR-14: Skill Management
- FR-15: CLI Integration
- FR-16: Log Service
- FR-17: Gateway State Persistence
- FR-18: Multi-Session Agent Architecture
- FR-19: Cron Scheduler
- FR-20: Web Search Tool
- FR-21: Skill Import from skills.sh

### FR-1: Chat System

- Conversation CRUD (create, list, get with messages, delete)
- Real-time streaming responses via WebSocket
- Multi-provider support (route to configured LLM)
- Conversation history with search
- Project-scoped conversations
- System prompt per project/conversation
- Message rendering with markdown, code blocks, tool call display

### FR-2: Gateway Orchestrator

- Central API surface for all clients (web, TUI, Discord, Telegram)
- Agent dispatch — receive task, select provider/model, spawn Pi session, return result
- Routing engine — cost/capability matrix, user preference overrides, task-type heuristics
- Plugin host — load channel plugins at startup, manage lifecycle
- MCP server — expose Mosaic tools via MCP protocol
- WebSocket hub — real-time updates for chat, agent status, notifications
- Rate limiting and request validation

### FR-3: Agent Pool (@mosaicstack/agent)

- Manage concurrent Pi SDK sessions
- Provider configuration: API key management, endpoint URLs, model lists
- Support providers: Anthropic (subscription + API), OpenAI/Codex (subscription + API), Z.ai, Ollama (local), LM Studio (local), llama.cpp (local)
- Tool injection — all agent sessions get Mosaic tools (brain, queue, memory)
- Skill loading — configure skills per agent session based on task type
- Session monitoring — track active sessions, token usage, duration
- Graceful shutdown — drain active sessions on shutdown

### FR-4: Task Management

- Brain-backed task CRUD with full filter/sort
- Task statuses: backlog, scheduled, in-progress, blocked, done, cancelled
- Priority levels: critical, high, medium, low
- Domain categorization
- Dependency tracking (blocks/blocked_by)
- Project association
- Assignee tracking
- Kanban board view in web dashboard
- Due date tracking with stale detection

### FR-5: Project Management

- Project CRUD with domain, status, priority
- Link to repository, branch, current/next milestone
- Progress tracking
- Blocker tracking
- Owner assignment

### FR-6: Mission System

- Mission CRUD (linked to project and PRD)
- Mission tasks with phases, dependencies, ordering
- Mission summary with computed progress
- Mission coordination via @mosaicstack/coord
- Active mission dashboard in web UI

### FR-7: Memory System

- **Preferences**: Key-value store for learned user preferences (e.g., "prefers tables over paragraphs", "timezone: America/Chicago")
- **Insights**: Distilled knowledge from agent interactions, stored with embeddings
- **Semantic search**: Query across all memory using natural language
- **Auto-capture**: Agent sessions automatically log decisions and learnings
- **Summarization**: Periodic compression of raw logs into structured insights
- **Decay**: Old, unused insights decay in relevance score over time

### FR-8: Authentication & Authorization

- BetterAuth integration with Next.js
- Email/password registration and login
- SSO via OIDC/SAML: Authentik, WorkOS, Keycloak
- RBAC roles: admin (full access), member (own resources + shared), viewer (read-only)
- API key generation for programmatic/MCP access
- Session management (web + API)

### FR-9: Remote Control — Discord

- Discord bot that connects to the gateway through a transport-neutral channel adapter contract
- Authorized messages in configured agent-bound channels work without a mention and respond in-channel
- Mentions in parent channels create threads, or reuse a thread already attached to that same native message, for multi-turn conversations
- Messages already in a thread remain there without requiring repeated mentions
- Stable logical-agent/channel conversation identity survives underlying harness/provider changes
- DM support for private conversations
- Chunked message delivery (Discord 2000-char limit)
- Bot configuration via web dashboard
- Permission management (which Discord users/roles can interact)

### FR-10: Remote Control — Telegram

- Telegram bot via Telegraf
- Private and group chat support
- Command-based interaction (`/ask`, `/task`, `/status`)
- Inline keyboard for task management
- Message routing through gateway

### FR-11: LLM Provider Management

- Provider configuration UI in web dashboard
- Per-provider: API key/endpoint, enabled models, cost per token
- Subscription-based providers: detect available models from subscription
- Local providers: Ollama model list, LM Studio endpoint, llama.cpp binary path
- Provider health monitoring
- Usage tracking per provider/model

### FR-12: Agent Routing

- Task-type to model-tier mapping (from AGENTS.md cost matrix)
- User preference overrides (e.g., "always use Claude for code review")
- Fallback chains (if primary provider unavailable, try next)
- Cost tracking and budget enforcement
- Routing transparency — user can see why a particular model was chosen

### FR-13: MCP Capability

- Gateway exposes MCP server (streamable HTTP transport)
- Brain tools registered as MCP tools
- Queue tools registered as MCP tools
- Memory search registered as MCP tool
- Agent sessions can call MCP tools from other services
- External MCP server connectivity (agent can use third-party MCP servers)

### FR-14: Skill Management

- Skill catalog — list available skills from configured sources
- Skill install — install skill to `~/.config/mosaic/skills/` or project-local
- Skill configuration — per-skill settings
- Skill status — installed, available, update available
- Web UI for browsing and managing skills

### FR-15: CLI Integration

- `mosaic gateway start` — start the gateway server
- `mosaic brain` — brain data management
- `mosaic queue` — queue operations
- `mosaic coord` — mission coordination
- `mosaic prdy` — PRD wizard
- `mosaic quality` — quality rail management
- `mosaic tui` — launch Pi TUI connected to gateway

### FR-16: Log Service

- Structured log ingest from agent sessions
- Parse logs for: decisions made, tools used, errors encountered, learnings captured
- Tier management: hot (7 days, full detail), warm (30 days, summarized), cold (90 days, key facts only)
- Summarization pipeline: cheap LLM compresses aging logs on schedule
- Query interface for log search

### FR-17: Gateway State Persistence

- Orchestration state persisted to Valkey (active sessions, pending dispatches, routing context)
- On restart, gateway reads Valkey state and resumes — reconnects to active agent sessions
- `mosaic gateway restart --fresh` clears Valkey queue and all in-flight state (nuclear option)
- Session recovery: detect orphaned agent sessions, offer reconnect or cleanup

### FR-18: Multi-Session Agent Architecture

- Each agent has a distinct session with dedicated context
- Multiple input channels (TUI, web, Discord, Telegram) can connect to same agent session
- Channel multiplexing at gateway level with proper authorization
- Discord channel ID paired to specific agent/session (prevents cross-contamination)
- Agent session runs in named tmux session for barge-in capability
- `mosaic agent attach <session>` connects to agent's tmux session
- `mosaic agent list` shows active sessions with connected channels

### FR-19: Cron Scheduler

- Built-in cron scheduler in gateway for recurring tasks
- Default schedules: log summarization, stale task detection, memory decay, provider health checks
- Custom schedules: user-defined agent dispatches on cron expressions
- Schedule management via web dashboard and CLI
- Cron jobs dispatched through normal gateway routing pipeline
- Persistence: schedules stored in PG, survive gateway restart

### FR-20: Web Search Tool

- DuckDuckGo web search via MCP server (primary — privacy-respecting, no API key)
- Registered as standard MCP tool available to all agent sessions
- Configurable: can swap to other search providers (Brave, SearXNG, Tavily)
- Results formatted for agent consumption (title, snippet, URL)

### FR-21: Skill Import from skills.sh

- Browse skills from https://skills.sh directory via API
- Import skills into `~/.config/mosaic/skills/` or project-local `.mosaic/skills/`
- Vetting workflow: imported skills marked as "unvetted" until admin approves
- Skill review interface in web dashboard (view skill content before approval)
- Vetted skills auto-available to agent sessions; unvetted require explicit enable
- `mosaic skill import <source/skillId>` CLI command
- Track installed skills, versions, update availability

---

## Non-Functional Requirements

### Security

- No hardcoded secrets — all secrets via environment variables or vault
- API key rotation capability
- RBAC enforcement at gateway level
- Input validation (Zod) on all API endpoints
- Rate limiting on public endpoints
- CORS configuration for web app
- Secure WebSocket connections
- SSO token validation
- Database connection encryption (SSL)

### Performance

- Chat response streaming latency < 200ms TTFB (gateway overhead, not LLM latency)
- Dashboard page loads < 2s
- Brain query responses < 100ms for filtered reads
- Semantic search < 500ms
- Support 10+ concurrent agent sessions
- WebSocket connection handling for 50+ concurrent users

### Reliability

- Graceful degradation when LLM provider is unavailable (fallback chain)
- Queue persistence — tasks survive gateway restart
- Database connection pooling with retry
- Health check endpoints for all services
- Structured error responses with correlation IDs

### Observability (Wide-Event Logging — Required from Phase 0)

- **OpenTelemetry instrumentation** across all services from day one
  - `@opentelemetry/sdk-node` + `@opentelemetry/auto-instrumentations-node` for auto-instrumentation (HTTP, PG, Fastify/NestJS)
  - NestJS interceptors for custom spans on agent dispatch, routing decisions, memory writes, summarization runs
  - Every significant operation emits a structured event with rich context (wide events, not just request/response)
- **SigNoz** as OTEL backend (single Docker service: traces, metrics, logs, built-in UI)
- Request tracing with correlation IDs (trace-id propagated across gateway → agent → brain → queue)
- Agent session metrics (duration, tokens, cost, success/failure, model used, routing reason)
- Provider availability monitoring (health check spans)
- Queue depth monitoring (periodic gauge metrics)
- Memory usage metrics (embedding count, search latency, summarization runs)
- Migrate to Grafana stack (Tempo + Loki + Grafana) post-beta if more customization is needed

### Scalability (Multi-Tier Readiness)

- Single-node deployment is the MVP target for v0.1.0
- Code structured with assumption that multi-tiered deployment will follow: dedicated gateway nodes, agent worker nodes, brain/DB nodes
- Service boundaries communicate via HTTP/WS/MCP APIs, not in-process calls where avoidable
- Gateway is stateless (all state in PG/Valkey) to enable horizontal scaling
- Agent pool designed as independently scalable service
- Database migrations support forward-only schema evolution
- Hierarchical deployment with dedicated roles/specialties is the post-beta target

---

## Acceptance Criteria

### AC-1: Core Chat Flow

- [ ] User can log in via web UI, send a message, and receive a streamed response
- [ ] Conversation persists across page refreshes
- [ ] User can create, list, search, and delete conversations
- [ ] Conversations can be scoped to projects

### AC-2: TUI Integration

- [ ] `mosaic tui` launches Pi interactive mode connected to gateway
- [ ] User can chat with same conversation context as web UI
- [ ] Agent has access to brain, queue, and memory tools

### AC-3: Discord Remote Control

- [ ] Discord bot connects through the harness-neutral channel contract
- [ ] Authorized untagged channel messages route through the gateway and respond in-channel
- [ ] Mentioned parent-channel messages create a thread (or reuse their already-attached thread) and respond there
- [ ] Existing-thread follow-ups stay in the thread without repeated mentions
- [ ] Channel/session identity remains stable while the underlying harness/provider changes
- [ ] Responses stream back to Discord (chunked)
- [ ] Unauthorized guilds, channels, users, pairings, and roles create no thread and dispatch no message

### AC-4: Gateway Orchestration

- [ ] Gateway dispatches tasks to appropriate provider/model
- [ ] Routing decision logged and inspectable
- [ ] Fallback when primary provider unavailable
- [ ] Multiple concurrent agent sessions managed correctly

### AC-5: Task & Project Management

- [ ] CRUD operations for tasks, projects, missions via web dashboard
- [ ] Kanban board view for tasks
- [ ] Mission progress tracking with computed stats
- [ ] Brain MCP tools accessible from agent sessions

### AC-6: Memory System

- [ ] Agent sessions auto-capture decisions and learnings
- [ ] Semantic search returns relevant past context
- [ ] Learned preferences are applied in new sessions
- [ ] Log summarization runs on schedule, old logs compressed

### AC-7: Authentication & RBAC

- [ ] Email/password login works
- [ ] At least one SSO provider (Authentik) works end-to-end
- [ ] Admin can create users and assign roles
- [ ] RBAC enforced on API endpoints

### AC-8: Multi-Provider LLM Support

- [ ] At least 3 providers configured and routing correctly (e.g., Anthropic + Ollama + Z.ai)
- [ ] Agent routing selects appropriate model for task type
- [ ] Provider configuration manageable from web UI

### AC-9: MCP

- [ ] Gateway exposes MCP endpoint
- [ ] Brain and queue tools callable via MCP
- [ ] Agent sessions can connect to external MCP servers

### AC-10: Deployment

- [ ] PGlite data-layer work uses no PostgreSQL; optional Compose services are selected individually and do not start PostgreSQL; Gateway/Web local start remains held until KBN-101-02 rejects daemon/inherited/project DSNs before connection or DDL
- [ ] PostgreSQL/federated activation is unavailable until KBN-101-00/-03/-05 deliver external bootstrap, TLS/roles, runner `--run`, runner `--verify`, and Gateway/Compose readiness in that order
- [ ] `mosaic` CLI installable and functional on bare metal after the reviewed KBN-101-05 secret-renderer/process-exec or `LoadCredential` interface exists
- [ ] Local-only configuration documentation is distinct from production generation-pinned Vault-rendered consumer material

### AC-11: @mosaicstack/\* Packages

- [ ] All 7 migrated packages build, pass tests, and integrate with gateway
- [ ] `mosaic` CLI provides subcommands for each package
- [ ] Types package is the single source of shared interfaces

---

## Constraints and Dependencies

1. **Pi SDK** — Core dependency; any Pi breaking changes affect the agent layer. Pin to known-good version.
2. **BetterAuth** — Auth framework; must support SSO adapters. Verify Authentik/WorkOS/Keycloak support before committing.
3. **Drizzle ORM** — Database layer; must support PostgreSQL + pgvector extension.
4. **Discord API** — Rate limits, intent requirements, message size limits (2000 chars).
5. **Valkey** — Queue backend; must be available for queue and caching.
6. **Gitea registry** — Package publishing target; `.npmrc` must be configured.
7. **OpenClaw** — Reference architecture for Discord/Telegram plugin pattern (https://github.com/openclaw/openclaw). Inspiration only, not a dependency.

---

## Risks and Open Questions

### Risks

| Risk                                               | Likelihood | Impact | Mitigation                                                                               |
| -------------------------------------------------- | ---------- | ------ | ---------------------------------------------------------------------------------------- |
| Pi SDK API instability (pre-1.0)                   | Medium     | High   | Pin version, abstract behind @mosaicstack/agent interface                                |
| Brain PG migration complexity                      | Medium     | Medium | Preserve Brain REST/MCP API contract; only storage changes                               |
| Discord plugin complexity (OpenClaw has ~60 files) | Medium     | Medium | Start minimal (DM + mention in channel), single-guild only; expand iteratively post-beta |
| LLM provider subscription auth varies by provider  | Medium     | Medium | Abstract behind provider interface; implement per-provider adapters                      |
| Drizzle + pgvector extension compatibility         | Low        | Medium | Validate in Phase 0 with spike                                                           |
| Agent log volume overwhelming storage              | Medium     | High   | Tiered storage with aggressive summarization; configurable retention                     |
| Scope creep from jarvis-old feature surface        | High       | High   | Strict v0.1.0 scope; features not listed above are post-beta                             |

### Open Questions

| #   | Question                                                                 | Priority | Status                                                                                                                                                                                                       |
| --- | ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1   | Pi SDK version to pin for v0.1.0?                                        | High     | ✅ Resolved — Pin `@mariozechner/pi-coding-agent@~0.57.1` (current stable). Abstract behind `@mosaicstack/agent` interface to insulate from breaking changes. Bump deliberately after testing.               |
| 2   | Authentik vs WorkOS vs Keycloak — which SSO provider to implement first? | Medium   | ✅ Resolved — Authentik first (already in Jason's infrastructure)                                                                                                                                            |
| 3   | Vector DB: pgvector sufficient or need Qdrant from the start?            | Medium   | ✅ Resolved — pgvector with VectorStore interface abstraction. Qdrant drops in later if needed.                                                                                                              |
| 4   | Summarization LLM: which model for log compression?                      | Medium   | ✅ Resolved — Haiku-tier default with structured output guardrails, configurable via routing engine.                                                                                                         |
| 5   | LM Studio and llama.cpp — provider adapters exist in Pi or need custom?  | Medium   | ✅ Resolved — Pi handles both natively. LM Studio and llama.cpp (server mode) expose OpenAI-compatible APIs; configure via Pi's `models.json` with `openai-completions` API type. No custom adapters needed. |
| 6   | Discord bot — single guild or multi-guild from day one?                  | Medium   | ✅ Resolved — Single-guild only for v0.1.0 to prevent data leaks. Bot binds to one guild. Multi-guild with tenant isolation is a post-beta feature requiring explicit data boundary design.                  |
| 7   | Bare-metal install — systemd units or just docs?                         | Low      | ASSUMPTION: Docs + CLI launch commands; systemd units post-beta                                                                                                                                              |

---

## Testing and Verification Expectations

1. **Baseline checks**: `pnpm typecheck && pnpm lint && pnpm test` must pass across all packages
2. **Unit tests**: Vitest for all packages; mocked dependencies for isolation
3. **Integration tests**: Gateway + Brain + Queue with test PG + Valkey (Docker services in CI)
4. **E2E tests**: Playwright for web dashboard critical paths (login, chat, task CRUD)
5. **Agent tests**: Pi SDK session tests with mock provider (verify tool registration, routing)
6. **Evidence format**: CI pipeline green + test count report per package

---

## Milestone / Delivery Intent

All work is **alpha** (< 0.1.0) until Jason approves 0.1.0 beta release.

### Phase 0: Foundation (v0.0.1)

- Scaffold monorepo (pnpm + turbo + tsconfig + eslint + vitest)
- `@mosaicstack/types` — migrate and extend from v0
- `@mosaicstack/db` — Drizzle schema, PG connection, migrations
- `@mosaicstack/auth` — BetterAuth setup with email/password
- OTEL foundation — `@opentelemetry/sdk-node` setup, SigNoz in docker-compose, trace propagation wired
- Docker Compose (PG 17 + Valkey + SigNoz)
- CI pipeline (Woodpecker)
- AGENTS.md, CLAUDE.md, README.md

### Phase 1: Core API (v0.0.2)

- `apps/gateway` — NestJS server (Fastify adapter), auth middleware, health endpoints
- `@mosaicstack/brain` — migrate from v0, swap JSON store for PG via @mosaicstack/db
- `@mosaicstack/queue` — migrate from v0 (minimal changes)
- Gateway routes: conversations, tasks, projects, missions
- WebSocket server for chat streaming
- Basic agent dispatch (single provider, no routing)

### Phase 2: Agent Layer (v0.0.3)

- `@mosaicstack/agent` — Pi SDK integration, agent pool manager
- Multi-provider support (Anthropic + Ollama minimum)
- Agent routing engine (cost/capability matrix)
- Tool registration (brain, queue, memory tools injected into agent sessions)
- `@mosaicstack/coord` — migrate from v0, integrate with gateway

### Phase 3: Web Dashboard (v0.0.4)

- `apps/web` — Next.js app with BetterAuth
- Chat UI (conversation list, message display, streaming input)
- Task management (list + kanban)
- Project and mission views
- Settings (provider config, profile)
- Admin panel (user management, RBAC)

### Phase 4: Memory & Intelligence (v0.0.5)

- `@mosaicstack/memory` — preference store, insight store, semantic search
- `@mosaicstack/log` — log ingest, parsing, tiered storage
- Summarization pipeline
- Memory integration into agent sessions
- Skill management interface (web UI + CLI)

### Phase 5: Remote Control (v0.0.6)

- `@mosaicstack/discord-plugin` — Discord channel plugin
- `@mosaicstack/telegram-plugin` — Telegram channel plugin
- Plugin host in gateway
- SSO configuration (Authentik)

### Phase 6: CLI & Tools (v0.0.7)

- `@mosaicstack/cli` — unified CLI with all subcommands
- `@mosaicstack/prdy` — migrate from v0
- `@mosaicstack/quality-rails` — migrate from v0
- `@mosaicstack/mosaic` — install wizard updated for v1
- Pi TUI integration (`mosaic tui`)

### Phase 7: Polish & Beta (v0.0.8 → v0.1.0)

- MCP endpoint hardening
- Additional SSO providers (WorkOS/Keycloak)
- Additional LLM providers (Codex, Z.ai, LM Studio, llama.cpp)
- Bare-metal deployment documentation
- E2E test suite
- Performance optimization
- Documentation: user guide, admin guide, developer guide
- **Jason approval gate → v0.1.0 beta release**

---

## Assumptions

1. RESOLVED: **pgvector is sufficient** for semantic search at v0.1.0 scale (personal/family/team = thousands to low hundreds-of-thousands of vectors). `@mosaicstack/memory` defines a `VectorStore` interface with pgvector as the default adapter. The interface boundary makes Qdrant a drop-in migration if PG resource contention or scale demands it later. Zero additional infrastructure for v0.1.0. Rationale: Reduces ops burden; pgvector HNSW indexes are fast at this scale; interface abstraction costs almost nothing now.

2. RESOLVED: **Authentik is the first SSO provider** — confirmed, already running in Jason's infrastructure. WorkOS and Keycloak adapters follow in Phase 7.

3. RESOLVED: **NestJS with Fastify adapter for the gateway.** The gateway's complexity (plugin host, agent pool, routing engine, WebSocket hub, MCP server, auth, brain/queue/memory/log integration) warrants NestJS's module system, DI, and guards. Fastify performance preserved via adapter. Aligns with USER.md stated stack ("NestJS API + Next.js web"). @mosaicstack/brain's Fastify code migrates into a NestJS module.

4. RESOLVED: **OpenTelemetry from Phase 0.** Wide-event logging is required from the start. OTEL auto-instrumentation for NestJS/PG/HTTP via `@opentelemetry/sdk-node`. SigNoz as the all-in-one OTEL backend (single Docker service). Every significant operation emits structured events with rich context. Custom spans for agent dispatch, routing decisions, memory writes. Rationale: Retrofitting observability is painful; baking it in from day one means consistent instrumentation across all services.

5. ASSUMPTION: **Single-node deployment for v0.1.0**, but code structured for multi-tier. No Kubernetes yet. Docker Compose + bare metal. Service boundaries use HTTP/WS/MCP APIs (not in-process) so gateway, agent pool, and brain can split to separate nodes later. Rationale: Ship single-node MVP; the architecture doesn't fight horizontal scaling when needed.

6. ASSUMPTION: **Log summarization uses Haiku-tier LLM by default, configurable.** Haiku is well-suited for summarization (compression, not generation — source material is in context). Guardrails: structured output via Zod schema (force extraction of decisions/tools/outcomes/errors as discrete fields), chunked per-session processing (no bulk conflation), extraction-focused prompts. Raw logs stay in hot tier (7 days) as safety net. Users can override the summarization model via routing engine config if they want higher fidelity. Rationale: Haiku is 10-20x cheaper than Sonnet; log summarization runs on schedule against large volumes where cost matters.

7. ASSUMPTION: **Discord plugin starts minimal and single-guild only** — explicitly configured agent-bound channels accept authorized untagged messages in-channel, while mentions create threads or reuse a thread already attached to that same native message; responses are chunked. Single guild binding prevents data leaks between servers. DM support, voice, components, slash commands, and multi-guild operation are post-beta. Rationale: Ship the requested core interaction model while preserving default-deny data isolation.

8. ASSUMPTION: **Telegram plugin is lower priority than Discord** and may ship as v0.0.7 or later if Discord takes longer than expected. Rationale: Jason indicated Discord as the high-priority remote channel.

9. ASSUMPTION: **Brain's REST API is preserved** as a gateway sub-router (mounted at `/api/brain/*` or similar). Existing MCP tools continue to work. Only the storage backend changes. Rationale: Minimize migration risk; brain's API contract is proven.

10. ASSUMPTION: **Conversations and messages get their own PG tables** (not stored in brain's entity model). They follow a chat-specific schema with proper foreign keys to users and projects. Rationale: Chat has different access patterns (streaming, pagination, search) than brain entities.

11. RESOLVED: **Pi handles all target LLM providers natively.** Anthropic, OpenAI/Codex, Z.ai, Ollama, LM Studio, and llama.cpp are all supported via Pi's built-in providers or `models.json` configuration with `openai-completions` API type. No custom provider adapters needed in @mosaicstack/agent — only configuration management.

---

## Greenfield install correctness — C1 (#1050)

### Problem and objective

A from-zero install can report success while leaving the target host unusable because the installer has no transactional state machine capable of certifying its own postconditions. C1 supplies the structural spine and red-first fixture; later cards repair the individual failed postconditions.

### Normative requirements

1. The installer SHALL implement the canonical P0–P9 numbering from the greenfield-install PRD v2: P0 Resolve context; P1 Preflight; P2 Acquire artifacts; P3 Install CLI; P4 Install framework + skills; P5 Identity; P6 Runtime linking / activation; P7 Services; P8 Shell discoverability; P9 Verify + commit. P2 is scoped to installer-distribution artifacts and SHALL NOT foreclose credentialed downstream acquisition. P5 owns validating any credential capability required by requested downstream work; P7 may provision credential-dependent resources only after that P5 postcondition commits.
2. Every phase SHALL declare preconditions, action, committed postconditions, and rollback. An unverifiable postcondition SHALL fail the install non-zero with the named phase and a remediation line; no best-effort failure may still certify success. P1's required-tool closure includes tools invoked by later phases, including `git`; a downstream prerequisite may not remain undeclared and degrade silently.
3. A durable mutation journal SHALL open before the first mutation and commit at P9. Fallible command output needed to diagnose a phase SHALL be journaled and surfaced, never discarded.
4. `--check` SHALL run exactly the P0–P8 postcondition predicates without mutation, report each phase PASS/FAIL, and exit non-zero if any predicate fails.
5. P4 SHALL consume a checkout-free, lane/versioned shipped-set declaration published by the installer. C1 SHALL NOT select among the currently disagreeing framework-payload, repository-root, sync-source, and W-jarvis populations; while no declaration exists, P4 reports `NOT-MEASURED / UNDECLARED` and remains blocking rather than fabricating a count. C5 owns the declaration's contents and containment/loadability fulfillment.
6. The from-zero fixture SHALL be lane-parametric, use Debian/glibc, run the documented install command as a non-root target user with an isolated HOME, and inherit no host credentials, npm cache, home directory, or runtime configuration.
7. The fixture SHALL select `next` with `--next` or `MOSAIC_NEXT=1` and assert the resolved lane version. Internal predicates use P3's absolute CLI path; shell discoverability is tested only at P8.
8. Fault injection after each P2–P8 phase SHALL prove either clean rollback or a durable, honestly reported resumable partial state, with no journal incorrectly left in progress.
9. Unsupported musl/Alpine and unavailable Docker SHALL fail loudly rather than skip as pass. The repository's installer tests SHALL nevertheless run in the canonical Alpine CI image by explicitly modeling a supported non-root/glibc target and using portable filesystem enumeration.
10. P0 SHALL bind the effective uid and username to the authoritative passwd HOME and shell and state/reject unsafe root or sudo-with-inherited-HOME privilege contexts.
11. Created paths SHALL satisfy phase-specific target owner/group and mode policy: P3 executables are not group/world writable, framework/runtime trees are not group/world writable, and identity/credential material is private.
12. The expected-RED comparator SHALL validate the complete manifest before selecting a case: exact case population, one exit and P0–P9 disposition per case, pinned require/forbid classes, and no malformed, duplicate, or unknown rows.
13. The published installer contract SHALL reject failed fetches, HTTP-success empty bodies, and digest mismatch, then execute the exact digest-verified body. The remote CI arm SHALL enumerate every payload-acquisition path and report a bound/found denominator. It SHALL bind both the installer body and the downstream stack framework/source it consumes to the same immutable CI commit, while retaining `--next` as the lane selector. Source resolution/acquisition SHALL fail closed, and the arm SHALL verify the realised source commit and archive digest after installation. Any out-of-scope unpinned sibling SHALL be named and counted rather than silently included in a broader pinning claim. `ASSUMPTION:` the configured repository's authenticated exact-commit endpoint is trusted to map that commit ID to the returned archive bytes; independent signed provenance/authenticity against repository or TLS trust-root compromise remains excluded by canonical greenfield-install PRD v2 §3.
14. Phase diagnostics SHALL be redacted before terminal or durable-log output. A seeded positive-control canary SHALL remain absent from observed argv, output, command logs, npm configuration, generated files, and shell history.
15. The CI fixture SHALL publish pipeline-level execution coverage for both the unconditional case set derived from the expected-RED manifest and the explicitly declared required pipeline-arm set, including the immutable remote-installer contract. Per-case and per-arm success markers SHALL be run-scoped, stored beneath an existing checkout-archive exclusion, and written only after that arm's verifier passes. A final step SHALL depend on the complete fixture matrix, run after prior success or failure, emit both `cases_defined=N cases_executed=M` and `arms_defined=N arms_executed=M`, and invoke the same testable aggregation helper whose complete case/arm PASS/FAIL truth table is covered. It SHALL fail unless both expected/executed name sets are exactly equal; missing, unexpected, stale, newly added unexecuted, or checkout-contaminating state SHALL fail closed. The archive-purity control SHALL bind to the production checkout-archive selector so deleting the production exclusion makes the control RED. Coverage tooling SHALL execute under both the canonical Alpine/BusyBox CI image and the Debian greenfield image; a green result from either runtime alone is insufficient portability evidence.

### C1 acceptance criteria

1. The pre-C1 from-zero matrix records both discriminating controls: with `git` absent, the legacy installer still exits zero while P1 fails and skill sync degrades; with `git` present, P1 passes and the observed sync store/runtime links are 101/101. The C1 installer must fail at P1 before mutation when `git` is absent.
2. The discriminating P3 row passes: the binary exists at the expected absolute path and reports exactly the resolved `next` lane version, while P4, P5, and P8 fail.
3. The `--check` mutation negative control proves host fingerprints are byte-identical before and after observation.
4. Woodpecker executes and validates the expected RED fixture plus the immutable remote-installer contract; its pipeline-level coverage gate reports exact equality for the manifest-derived case set and the declared arm set, while skipped-case and skipped-remote-arm controls prove non-execution is red. C1 does not repair P4/P5/P8 or activate #869.
5. Negative controls prove manifest shrink/duplicates/unknown rows fail, unsafe P0/P3/P4/P5 contexts fail, the P2–P8 fault seam enters real actions rather than synthetic writes, empty/mismatched fetched bodies fail, and a deliberately emitted secret canary is redacted from every persisted/output population.

### Explicit exclusions and dependencies

- C2 owns P8/PATH, C3 owns P5/headless identity, C4 owns P6 activation policy, and C5 owns P4/skills.
- Main-lane execution is a promotion precondition owned by #1037; C1 only makes the fixture lane-parametric.
- RM-02 and #869 activation are out of scope.
