- pnpm workspaces + Turborepo - tsconfig.base.json strict ESM - @mosaic/types stub package - Woodpecker CI pipeline with Valkey service - docs/PRD.md, docs/TASKS.md, CONTEXT.md
18 KiB
PRD: Mosaic Monorepo & @mosaic/* Package Ecosystem
Status: Draft
Created: 2026-03-06
Updated: 2026-03-06 (post-bootstrap audit)
Owner: Jason Woltje
Repo (target): git.mosaicstack.dev/mosaic/mosaic
1. Problem Statement
Mosaic tooling is currently spread across five polyrepos. Each repo duplicates TypeScript config, ESLint rules, Vitest setup, and core type definitions. Cross-repo changes require synchronized PRs with a window of inconsistency. Agent workers lose context when they must span multiple repos. There is no standardized installation path — getting the full Mosaic toolkit requires knowing which repos exist and cloning them individually.
Symptoms:
tsconfig.json,eslint.config.js,vitest.config.tsduplicated across every repoTask,Mission,Agent, and related types redefined in each package- A feature touching
coord+queuerequires 2 PRs, 2 CI runs, 2 merges - No
npm installstory — setup is tribal knowledge - Agent workers clone one repo with no visibility into sibling packages
2. Goals
- Reduce duplication — One
tsconfig, one ESLint config, one set of shared types, inherited by all packages - Standardize naming — All packages published under
@mosaic/scope to the Gitea npm registry - Single install entry point —
npm i -g @mosaic/mosaicruns guided onboarding, installs selected packages - CI publishes packages — Push to
maintriggers Turborepo affected-only build + publish to registry - Agent-friendly context — One monorepo means one clone, one
TASKS.md, one rootCONTEXT.mdfor workers - Eventual full TypeScript —
coordandprdystart as shell distribution, graduate to TypeScript packages over time
3. Non-Goals
- Not replacing OpenBrain — Queue is for coordination, OpenBrain is for memory. No overlap.
- Not open-sourcing — These are personal/internal tools. Public registry not in scope.
- Not containerizing packages — Packages are CLI tools and libraries, not services.
- Not forced independent versioning — All packages use fixed/synchronized versioning (simpler for solo developer).
agent-skillsnot included — Skills are files consumed by agents, not npm packages. Stays in its own repo.- Not rewriting coord/prdy immediately — Shell scripts are distributed first; TypeScript rewrite is a later phase.
4. Bootstrap Audit (Current State)
mosaic-bootstrap contains four distinct categories of content. Understanding this is critical before migrating:
4a. Installation Wizard (TypeScript) — becomes @mosaic/mosaic
28 TypeScript source files. Handles fresh Mosaic install: creates SOUL.md, USER.md, TOOLS.md, configures MCP for Claude/Codex/opencode, selects and installs skills. Currently published as mosaic-wizard@0.2.0. This is the npm i -g @mosaic/mosaic entry point. Already substantially complete — needs rename, cleanup, monorepo integration.
4b. Shell Tool Suite — distributed as files, not npm packages
~150 shell scripts, ~2,500+ lines of bash across:
tools/git/— PR, issue, milestone management (Gitea API)tools/orchestrator/— ~1,800 lines:mission-init,session-run,session-resume,session-statustools/prdy/— ~470 lines:prdy-init,prdy-update,prdy-validate,prdy-statustools/orchestrator-matrix/— Python Matrix transport for multi-agent coordinationtools/qa/— hook handlers, memory write prevention, QA monitorstools/woodpecker/,portainer/,cloudflare/,authentik/,coolify/,codex/,glpi/— infra integrations
These are NOT npm packages today. They are bash/Python scripts distributed by the wizard to ~/.config/mosaic/. The wizard is the install vehicle.
4c. Agent Guides (Markdown) — distributed as files
17 markdown guides: ORCHESTRATOR.md, E2E-DELIVERY.md, CODE-REVIEW.md, etc. Loaded by agents at runtime from ~/.config/mosaic/guides/. Not code, not packages. Distributed by the wizard.
4d. Runtime Configs — distributed as files
Per-agent config overlays for Claude, Codex, opencode. Distributed to ~/.config/mosaic/runtime/ on install.
5. Package Structure
Migration Philosophy: Staged
The monorepo is built in waves. Existing TypeScript code migrates first. Shell-based tools (coord, prdy) are distributed as-is initially, then rewritten as TypeScript packages in a later wave when the monorepo foundation is proven.
Wave 1 — Foundation
@mosaic/types Shared type definitions (new)
@mosaic/queue Migrate from mosaic/queue (TypeScript, already mature)
Wave 2 — Entry Point
@mosaic/mosaic Migrate wizard from mosaic-bootstrap (TypeScript, already built)
@mosaic/openclaw-context Migrate from mosaic/openclaw-openbrain-context (TypeScript)
Wave 3 — TypeScript Rewrites (future)
@mosaic/coord Rewrite of tools/orchestrator/ bash suite
@mosaic/prdy Rewrite of tools/prdy/ bash suite
@mosaic/quality-rails Rewrite of quality-rails template distributor (shell+templates → TS scaffolder)
@mosaic/cli Unified CLI binary composing all @mosaic/* packages
Repository Layout
mosaic/mosaic (monorepo)
├── packages/
│ ├── types/ @mosaic/types Shared interfaces — zero deps
│ ├── queue/ @mosaic/queue Task queue + MCP server
│ ├── quality-rails/ @mosaic/quality-rails Quality gate enforcement
│ ├── mosaic/ @mosaic/mosaic Install wizard + meta package
│ ├── coord/ @mosaic/coord [Wave 3] Mission coordination
│ ├── prdy/ @mosaic/prdy [Wave 3] PRD generation
│ └── cli/ @mosaic/cli [Wave 3] Unified CLI binary
├── plugins/
│ └── openclaw-context/ @mosaic/openclaw-context OpenClaw → OpenBrain plugin
└── docs/
├── PRD.md (this file, symlinked from jarvis-brain)
└── TASKS.md (orchestrator-owned)
Package Responsibilities
@mosaic/types (Wave 1)
- Shared interfaces:
Task,TaskStatus,TaskPriority,Mission,Agent,QueueConfig - No runtime code — types only, zero dependencies
- Every other
@mosaic/*package imports from here; never defines its own copies - Published first; version bump propagates to all consumers
@mosaic/queue (Wave 1)
- Task queue backed by Valkey/Redis with atomic WATCH/MULTI/EXEC ownership
- MCP server with 8 tools:
queue_list/get/claim/heartbeat/release/complete/fail/status - Migrated from
mosaic/queue— code mature (Phase 1 + atomicity fixes complete) - Updates imports to use
@mosaic/types
@mosaic/quality-rails (Wave 3 — TypeScript rewrite)
- Audit result:
mosaic/quality-railsis shell scripts + template files, no TypeScript. Nopackage.json. - Current form:
scripts/install.sh,verify.sh+ config templates for monorepo/nextjs/node/python project types - Wave 3 rewrite: TypeScript scaffolder that generates/installs config files programmatically rather than distributing static copies
- Until Wave 3: templates bundled as wizard distributed assets alongside other shell tools
- Migrated from
mosaic/quality-rails(archive after wizard bundles it)
@mosaic/mosaic (Wave 2)
- Entry point:
npm i -g @mosaic/mosaic - Onboarding wizard (migrated from
mosaic-wizardin bootstrap) - Stages: detect installs → mode select → soul/user/tools setup → skill selection → runtime config → finalize
- Copies shell tool suite (
tools/,guides/,runtime/) to~/.config/mosaic/ - Prompts which additional
@mosaic/*packages to install - Config validation: checks OpenBrain connectivity, Gitea token, etc.
- When Wave 3 completes: wizard shifts from "copy shell scripts" to "just install TypeScript packages"
@mosaic/openclaw-context (Wave 2, plugins/)
- OpenClaw → OpenBrain context engine plugin
- Lives in monorepo for shared tooling, published standalone
- Installable independently:
openclaw plugin install @mosaic/openclaw-context - Migrated from
mosaic/openclaw-openbrain-context
@mosaic/coord (Wave 3 — TypeScript rewrite)
- TypeScript rewrite of
tools/orchestrator/bash suite - Mission lifecycle:
init,run,resume,status,drain - Reads/writes
docs/TASKS.mdin target project - CLI subcommand:
mosaic coord <init|run|resume|status> - Will replace shell scripts in the distributed toolkit
- Prerequisite: Wave 1+2 complete and stable
@mosaic/prdy (Wave 3 — TypeScript rewrite)
- TypeScript rewrite of
tools/prdy/bash suite - AI-assisted PRD generation, update, validation
- CLI subcommand:
mosaic prdy <init|update|validate|status> - Depends on LLM client (OpenAI / Anthropic / Z.ai — configured via env)
- Prerequisite: Wave 1+2 complete and stable
@mosaic/cli (Wave 3)
- Unified
mosaicbinary — thin shell over all@mosaic/*packages - Plugin discovery: checks installed
@mosaic/*packages, registers CLI contributions - Subcommand routing:
mosaic coord,mosaic prdy,mosaic queue,mosaic prdy, etc. - Does NOT bundle everything — loads plugins dynamically
6. Tooling
Package Manager
pnpm workspaces — single lockfile, workspace-linked packages during development, content-addressed store.
Build Orchestration
Turborepo — affected-only builds, remote cache (optional), pipeline definitions per task type.
// turbo.json (root)
{
"pipeline": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"test": { "dependsOn": ["^build"] },
"lint": {},
"typecheck": { "dependsOn": ["^build"] },
"publish": { "dependsOn": ["build", "test", "lint", "typecheck"] }
}
}
Shared Root Config (inherited by all packages)
tsconfig.base.json— strict mode, ESM,NodeNextmodule resolutioneslint.config.js— shared ruleset (fromtools/quality/templates/in bootstrap — already exists!)vitest.workspace.ts— workspace-level test runner
Each package tsconfig.json extends ../../tsconfig.base.json.
Versioning
Fixed (synchronized): All packages share a version number. @mosaic/queue@0.2.0 implies @mosaic/types@0.2.0. Revisit if packages diverge significantly in maturity.
Tool: Changesets (@changesets/cli) — human-authored change descriptions → automated version bumps + changelogs on release.
7. Registry & CI
Gitea npm Registry
Packages published to https://git.mosaicstack.dev/api/packages/mosaic/npm.
.npmrc (root):
@mosaic:registry=https://git.mosaicstack.dev/api/packages/mosaic/npm
//git.mosaicstack.dev/api/packages/mosaic/npm/:_authToken=${GITEA_TOKEN}
CI Pipeline (Woodpecker)
Trigger: push to main
Steps:
pnpm install --frozen-lockfilepnpm turbo lint typecheckpnpm turbo test(with Valkey service container for@mosaic/queuetests)pnpm turbo build- Detect changed packages (Turborepo affected output)
pnpm changeset publish→ publish affected packages to Gitea registry
PR pipeline (no publish): steps 1–4 only + pnpm changeset status.
Valkey service for queue tests:
# .woodpecker.yml
services:
- name: valkey
image: valkey/valkey:8-alpine
ports: ["6379:6379"]
8. Migration Plan
Prerequisites (check before starting)
mosaic/queueatomicity fix (issue #4) mergedmosaic/openclaw-openbrain-contextcompact/ingest fix (issue #4) merged- No active agent branches on repos being migrated
Wave 1 — Foundation
Phase 0: Scaffold Monorepo
- Create
mosaic/mosaicrepo on Gitea - Initialize pnpm workspace + Turborepo
- Add root
tsconfig.base.json,eslint.config.js,vitest.workspace.ts - Add
.npmrcpointing to Gitea registry - Smoke-test publish (empty
@mosaic/types@0.0.1) to validate CI+registry auth - Add Woodpecker pipeline with Valkey service
- Add root
CONTEXT.md,docs/TASKS.md,docs/PRD.md
Phase 1: @mosaic/types
- Extract all shared types from
queue,coord,prdy,quality-rails(audit each for duplicates) - Publish
@mosaic/types@0.1.0 - No other package migrates until types are published
Phase 2: @mosaic/queue
- Move
mosaic/queue/packages/queue/src→mosaic/mosaic/packages/queue/src - Update imports to use
@mosaic/types - All tests green including integration (Valkey CI service)
- Publish
@mosaic/queue@0.1.0 - Archive
mosaic/queuerepo (read-only, redirect notice in README)
Wave 2 — Entry Point
Phase 4: @mosaic/mosaic (wizard migration)
- Move
mosaic-bootstrap/src/→packages/mosaic/src/ - Update package name:
mosaic-wizard→@mosaic/mosaic - Update wizard to reference monorepo packages where applicable
postinstallscript: run wizard on first install- Shell tool suite (
tools/,guides/,runtime/) bundled as static assets - Publish
@mosaic/mosaic@0.1.0 - Validate:
npm i -g @mosaic/mosaicon clean machine completes setup - Archive
mosaic/bootstrap(read-only, redirect notice)
Phase 5: @mosaic/openclaw-context
- Move
mosaic/openclaw-openbrain-context/src→plugins/openclaw-context/src - Update shared tooling to use root configs
- Publish
@mosaic/openclaw-context@0.1.0 - Validate standalone install works:
openclaw plugin install @mosaic/openclaw-context - Archive
mosaic/openclaw-openbrain-context
Wave 3 — TypeScript Rewrites (future, no timeline set)
Phase 6: @mosaic/coord
- Design TypeScript API mirroring current bash behavior
- Implement:
init,run,resume,status,drain - CLI subcommand registration for
@mosaic/cli - Migrate shell scripts to integration tests (parity verification)
- Wizard updated: stop distributing orchestrator shell scripts once this ships
- Publish
@mosaic/coord@0.1.0
Phase 7: @mosaic/prdy
- Design TypeScript API mirroring current bash behavior
- LLM client abstraction (supports Anthropic / OpenAI / Z.ai via config)
- Implement:
init,update,validate,status - CLI subcommand registration for
@mosaic/cli - Wizard updated: stop distributing prdy shell scripts once this ships
- Publish
@mosaic/prdy@0.1.0
Phase 8: @mosaic/quality-rails
- TypeScript scaffolder API — generates ESLint, tsconfig, Woodpecker, husky, lint-staged for a project
- Supports project types: monorepo, typescript-node, typescript-nextjs, python
- CLI:
mosaic quality install [--type monorepo|node|nextjs|python],mosaic quality verify - Replaces static template distribution from wizard
- Archive
mosaic/quality-rails - Publish
@mosaic/quality-rails@0.1.0
Phase 9: @mosaic/cli
- Unified binary with plugin discovery
- Subcommands:
mosaic coord,mosaic prdy,mosaic queue,mosaic prdy - Wizard updated to install
@mosaic/clias primary binary instead of path-based scripts - Publish
@mosaic/cli@0.1.0
9. Open Questions
| # | Question | Priority | Status |
|---|---|---|---|
| 1 | Bootstrap audit: what in tools/ is safe to archive vs still needed? Shell scripts will coexist during Wave 1+2 |
High | ✅ Answered — shell tools distributed by wizard until Wave 3 |
| 2 | quality-rails audit complete: shell scripts + templates, no TypeScript, no package.json |
High | ✅ Wave 3 rewrite |
| 3 | @mosaic/prdy LLM client: peer dep or bundled? |
Medium | Open |
| 4 | Valkey CI service in Woodpecker: verify swarm runner can spin Docker services | High | Open |
| 5 | Changesets vs manual semver? (Recommendation: Changesets) | Low | Open |
| 6 | Matrix orchestrator (tools/orchestrator-matrix/, Python) — migrate to TypeScript in Wave 3 or keep Python? |
Medium | Open |
| 7 | mosaic/agent-skills — stays polyrepo, but should the wizard install it? |
Low | Open |
10. Success Criteria
Wave 1+2 (MVP)
npm i -g @mosaic/mosaicon a clean machine completes setup end-to-endmosaic coord init,mosaic prdy init,mosaic queue listall work (bash, distributed by wizard)- Zero duplicated TypeScript config files across Wave 1+2 packages
- One PR for a shared type change, no follow-up PRs in sibling repos
- CI publishes affected packages on every merge to
main - All existing functionality preserved — no regressions
Wave 3 (Full TypeScript)
mosaic coordandmosaic prdyrun as native TypeScript packages, no bash distribution needed- Wizard no longer ships shell scripts for coord/prdy
@mosaic/cliis the singlemosaicbinary entry point
11. Risks
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
mosaic/quality-rails is also shell (not TypeScript) |
Medium | Medium | Audit before Phase 3; if shell, it becomes Wave 3 |
| Wizard migration breaks existing installs on Jason's machines | Medium | High | Keep bootstrap installable alongside; wizard detects existing config and upgrades safely |
| Turborepo cache invalidation surprises | Low | Low | Start without remote cache; add later |
| Gitea npm registry auth in CI | Medium | High | Smoke-test publish in Phase 0 before any real migration |
| Breaking installed tools mid-migration | Low | High | Keep old repos live until new packages verified working |
| Matrix orchestrator (Python) creates a language gap in Wave 3 | Low | Medium | Decision deferred; can keep as Python microservice or wrap in TypeScript subprocess |
Start: Phase 0 scaffold after current fix workers complete (queue + openclaw-context issue #4).
Wave 3 timeline: TBD — start after Wave 1+2 are stable in production.