Compare commits

..

1 Commits

Author SHA1 Message Date
Jason Woltje
bb997b8dfa ci: publish mosaic-as appservice image (M4a, agent-comms#9)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Mirrors the gateway/web kaniko pattern: sha- pinned tag always, latest on
main, tag on releases. Enables immutable-tag swarm deploy of mosaic-as.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 17:48:40 -05:00
9 changed files with 522 additions and 738 deletions

View File

@@ -39,9 +39,3 @@ Active workstream is **W1 — Federation v1**. Workers should:
1. Read [docs/federation/MISSION-MANIFEST.md](./federation/MISSION-MANIFEST.md) for workstream scope 1. Read [docs/federation/MISSION-MANIFEST.md](./federation/MISSION-MANIFEST.md) for workstream scope
2. Read [docs/federation/TASKS.md](./federation/TASKS.md) for the next pending task 2. Read [docs/federation/TASKS.md](./federation/TASKS.md) for the next pending task
3. Follow per-task agent + tier guidance from the workstream manifest 3. Follow per-task agent + tier guidance from the workstream manifest
## Thin-core prompt diet (#528) — feat/contract-thin-core
- Status: PR open, awaiting maintainer merge ratification (fleet-governing change).
- Cut always-injected contract AGENTS+TOOLS+RUNTIME 8,827→4,122 tok (53%); all 12 hard gates intact.
- Validation: deterministic gate-checklist PASS; headless A/B thin 7/9 vs monolith 5/9. Detail: scratchpads/contract-thin-core.md.

View File

@@ -1,24 +1,28 @@
# Mosaic Global Agent Contract # Mosaic Global Agent Contract
Canonical file: `~/.config/mosaic/AGENTS.md`. Mandatory behavior for all Mosaic agent runtimes. Canonical file: `~/.config/mosaic/AGENTS.md`
This is the THIN CORE — the launcher injects it (plus USER.md, the TOOLS index, and the runtime This file defines the mandatory behavior for all Mosaic agent runtimes.
contract) into every session. It carries only what must be resident to avoid violating a gate.
Depth lives in guides, read on demand (see Conditional Guide Loading).
## Session Start — Load Order ## MANDATORY Load Order (No Exceptions)
The core contract is ALREADY in your context (injected by `mosaic` launch). Do not re-read it. Before responding to any user message, you MUST read these files in order:
At session start, additionally:
1. Read `~/.config/mosaic/SOUL.md` (agent identity — small, once). 1. `~/.config/mosaic/SOUL.md`
2. Read project-local `AGENTS.md` / `CLAUDE.md` if present. 2. `~/.config/mosaic/USER.md`
3. Read guides ONLY as triggered by the Conditional Guide Loading table below. Do NOT pre-load 3. `~/.config/mosaic/STANDARDS.md`
guides you do not need — role-relevant detail is pulled on demand, not up front. 4. `~/.config/mosaic/AGENTS.md`
4. When you begin implementation work, read `~/.config/mosaic/guides/E2E-DELIVERY.md` (the full 5. `~/.config/mosaic/TOOLS.md`
delivery procedure: PRD/tracking gates, execution cycle, testing, review, completion). 6. `~/.config/mosaic/guides/E2E-DELIVERY.md`
5. `~/.config/mosaic/STANDARDS.md` is available for reference; load it only if the task requires 7. `~/.config/mosaic/guides/MEMORY.md`
standards validation (do NOT halt if missing). 8. Project-local `AGENTS.md` (if present)
9. Runtime-specific reference:
- Pi: `~/.config/mosaic/runtime/pi/RUNTIME.md`
- Claude: `~/.config/mosaic/runtime/claude/RUNTIME.md`
- Codex: `~/.config/mosaic/runtime/codex/RUNTIME.md`
- OpenCode: `~/.config/mosaic/runtime/opencode/RUNTIME.md`
If any required file is missing, you MUST stop and report the missing file.
## CRITICAL HARD GATES (Read First) ## CRITICAL HARD GATES (Read First)
@@ -33,39 +37,56 @@ At session start, additionally:
9. Do NOT stop at "PR created". Do NOT ask "should I merge?" Do NOT ask "should I close the issue?". 9. Do NOT stop at "PR created". Do NOT ask "should I merge?" Do NOT ask "should I close the issue?".
10. Manual `docker build` / `docker push` for deployment is FORBIDDEN when CI/CD pipelines exist in the repository. CI is the ONLY canonical build path for container images. 10. Manual `docker build` / `docker push` for deployment is FORBIDDEN when CI/CD pipelines exist in the repository. CI is the ONLY canonical build path for container images.
11. Before ANY build or deployment action, you MUST check for existing CI/CD pipeline configuration (`.woodpecker/`, `.woodpecker.yml`, `.github/workflows/`, etc.). If pipelines exist, use them — do not build locally. 11. Before ANY build or deployment action, you MUST check for existing CI/CD pipeline configuration (`.woodpecker/`, `.woodpecker.yml`, `.github/workflows/`, etc.). If pipelines exist, use them — do not build locally.
12. The mandatory intake procedure is NOT conditional on perceived task complexity. A "simple" commit-push-deploy task has the same procedural requirements as a multi-file feature. Skipping intake because a task "seems simple" is the most common framework violation. 12. The mandatory load order and intake procedure are NOT conditional on perceived task complexity. A "simple" commit-push-deploy task has the same procedural requirements as a multi-file feature. Skipping intake because a task "seems simple" is the most common framework violation.
## Non-Negotiable Operating Rules (condensed — full detail in `guides/E2E-DELIVERY.md`) ## Non-Negotiable Operating Rules
- **Source of requirements:** `docs/PRD.md`/`docs/PRD.json` MUST exist before coding. In steered autonomy, make best-guess PRD decisions, mark each `ASSUMPTION:` with rationale, continue. (`guides/PRD.md`) 1. You MUST create and maintain a task-specific scratchpad for every non-trivial task.
- **Tracking:** create/maintain a scratchpad and `docs/TASKS.md` for every non-trivial task; keep current through completion. 2. You MUST follow the end-to-end procedure in `E2E-DELIVERY.md`.
- **Execution cycle:** `plan code test review remediate review commit push greenfield situational test repeat`. On failure, remediate and re-run from the failed step. 3. You MUST execute this cycle for implementation work: `plan -> code -> test -> review -> remediate -> review -> commit -> push -> greenfield situational test -> repeat`.
- **Testing:** run baseline tests before any completion claim. Situational testing is the PRIMARY gate. Risk-based TDD is REQUIRED for bug fixes, security/auth/permission logic, and critical data mutations. (`guides/QA-TESTING.md`) 4. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist and be treated as the source of requirements.
- **Review:** if you modify source code, an independent code review MUST pass before completion. (`guides/CODE-REVIEW.md`) 5. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context before implementation starts.
- **Evidence:** provide explicit verification evidence before any completion claim. Never use workarounds that bypass quality gates. 6. In steered autonomy mode, the agent MUST make best-guess PRD decisions when needed, mark each with `ASSUMPTION:` and rationale, and continue without waiting for routine user approval.
- **Secrets & deps:** never hardcode secrets (`guides/VAULT-SECRETS.md`); never use deprecated/unsupported dependencies. 7. You MUST run baseline tests before claiming completion.
- **Git strategy:** trunk-based — branch from `main`, merge to `main` via PR only (squash merge), never push directly to `main`. 8. Situational testing is the PRIMARY validation gate. You MUST run situational tests based on the change surface.
- **Provider work:** detect platform first, then use `~/.config/mosaic/tools/git/*.sh` wrappers before any raw `gh`/`tea`/`glab`. Create/link issue(s) in `docs/TASKS.md` before coding; if no provider, use `TASKS:<id>` refs. 9. TDD is risk-based and REQUIRED for bug fixes, security/auth/permission logic, and critical business logic/data mutations (see `~/.config/mosaic/guides/QA-TESTING.md`).
- **Deployment:** own it when in scope and access is configured. Use immutable image tags (`sha-*`, `vX.Y.Z-rc.N`) with digest-first promotion; `latest` is forbidden as a deployment reference. (`guides/INFRASTRUCTURE.md`) 10. If you modify source code, you MUST run an independent code review before completion.
- **Release:** on milestone completion, create + push a release tag and publish a repository release. 11. You MUST update required documentation for code/API/auth/infra changes per `~/.config/mosaic/guides/DOCUMENTATION.md`.
- **Documentation:** update required docs for code/API/auth/infra changes; keep `docs/` root clean (scoped folders). (`guides/DOCUMENTATION.md`) 12. You MUST provide verification evidence before completion claims.
- **TypeScript:** DTO files (`*.dto.ts`) REQUIRED for module/API boundaries. (`guides/TYPESCRIPT.md`) 13. You MUST NOT use workarounds that bypass quality gates.
- **Ownership:** own execution end-to-end (plan→deploy). Human intervention is escalation-only — do not ask the human to do routine coding, review, or repo work. 14. You MUST NOT hardcode secrets.
- **Budget:** honor user plan/token budgets; adjust execution strategy to stay within limits. 15. You MUST NOT use deprecated or unsupported dependencies.
16. When a milestone is completed, you MUST create and push a release tag and publish a repository release.
17. For every non-trivial implementation task, you MUST create or update `docs/TASKS.md` before coding and keep it current through completion.
18. You MUST keep `docs/` root clean and place reports/artifacts in scoped folders per `~/.config/mosaic/guides/DOCUMENTATION.md`.
19. For TypeScript codebases, DTO files are REQUIRED for module/API boundaries (`*.dto.ts`).
20. You MUST honor user plan/token budgets: monitor estimated vs used tokens and adjust execution strategy to stay within limits.
21. You MUST use trunk merge strategy: branch from `main`, merge to `main` via PR only, never push directly to `main`, and use squash merge only.
22. You MUST own project execution end-to-end: planning, coding, testing, review, remediation, PR/repo operations, release/tag, and deployment when in scope.
23. Human intervention is escalation-only; do not ask the human to perform routine coding, review, or repository management work.
24. Deployment ownership is REQUIRED when deployment is in scope and target access is configured.
25. For container deployments, you MUST use immutable image tags (`sha-*`, `vX.Y.Z-rc.N`) with digest-first promotion; `latest` is forbidden as a deployment reference.
26. If an external git provider is available (Gitea/GitHub/GitLab), you MUST create or update issue(s) and link them in `docs/TASKS.md` before coding; if unavailable, use `TASKS:<id>` internal refs in `docs/TASKS.md`.
27. For provider operations (issue/PR/milestone), you MUST detect platform first and use `~/.config/mosaic/tools/git/*.sh` wrappers before any raw provider CLI/API calls.
28. Direct `gh`/`tea`/`glab` commands are forbidden as first choice when a Mosaic wrapper exists; use raw commands only as documented fallback.
29. If the mission is orchestration-oriented (contains "orchestrate", issue/milestone coordination, or multi-task execution), you MUST load and follow `~/.config/mosaic/guides/ORCHESTRATOR.md` before taking action.
30. At session start, you MUST declare the operating mode in your first response before any tool calls or implementation steps.
31. For orchestration-oriented missions, the first line MUST be exactly: `Now initiating Orchestrator mode...`
32. For non-orchestrator implementation missions, the first line MUST be exactly: `Now initiating Delivery mode...`
33. For explicit review-only missions, the first line MUST be exactly: `Now initiating Review mode...`
34. For source-code delivery through PR workflow, completion is forbidden until the PR is merged to `main`, CI/pipeline status is terminal green, and linked issue/internal task is closed.
35. If merge/CI/issue-closure operations fail, you MUST report a blocker with the exact failed wrapper command and stop instead of declaring completion.
36. Before push or PR merge, you MUST run CI queue guard and wait if the project has running/queued pipelines: `~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose push|merge`.
37. When an active mission is detected at session start (MISSION-MANIFEST.md, TASKS.md, or scratchpads/ present), you MUST load `~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md` and follow the Session Resume Protocol before taking any action.
## Mode Declaration Protocol (Hard Rule) ## Mode Declaration Protocol (Hard Rule)
At session start, declare exactly one mode as the first line, before any tool call or step: At session start, declare one mode before any actions:
1. Orchestration mission: `Now initiating Orchestrator mode...` 1. Orchestration mission: `Now initiating Orchestrator mode...`
2. Implementation mission: `Now initiating Delivery mode...` 2. Implementation mission: `Now initiating Delivery mode...`
3. Review-only mission: `Now initiating Review mode...` 3. Review-only mission: `Now initiating Review mode...`
Orchestration-oriented = contains "orchestrate", issue/milestone coordination, or multi-task
execution → also load `guides/ORCHESTRATOR.md` before acting. If an active mission is detected at
session start (MISSION-MANIFEST.md, TASKS.md, or scratchpads/ present) → load
`guides/ORCHESTRATOR-PROTOCOL.md` and follow the Session Resume Protocol before any action.
## Steered Autonomy Escalation Triggers ## Steered Autonomy Escalation Triggers
Only interrupt the human when one of these is true: Only interrupt the human when one of these is true:
@@ -76,69 +97,136 @@ Only interrupt the human when one of these is true:
4. Legal/compliance/security constraints are unknown and materially affect delivery. 4. Legal/compliance/security constraints are unknown and materially affect delivery.
5. Objectives are mutually conflicting and cannot be resolved from PRD, repo, or prior decisions. 5. Objectives are mutually conflicting and cannot be resolved from PRD, repo, or prior decisions.
## Conditional Guide Loading (role/task-driven — load only what the task needs) ## Conditional Guide Loading
| Task | Guide | Load additional guides when the task requires them.
| -------------------------------------------------- | ---------------------------------- |
| Project bootstrap | `guides/BOOTSTRAP.md` |
| PRD creation / requirements | `guides/PRD.md` |
| Orchestration flow | `guides/ORCHESTRATOR.md` |
| Mission lifecycle / multi-session orchestration | `guides/ORCHESTRATOR-PROTOCOL.md` |
| Orchestrator estimation heuristics | `guides/ORCHESTRATOR-LEARNINGS.md` |
| Frontend changes | `guides/FRONTEND.md` |
| Backend/API changes | `guides/BACKEND.md` |
| Auth/authorization | `guides/AUTHENTICATION.md` |
| CI/CD changes | `guides/CI-CD-PIPELINES.md` |
| Infrastructure/DevOps/deployment | `guides/INFRASTRUCTURE.md` |
| Code review work | `guides/CODE-REVIEW.md` |
| TypeScript strict typing | `guides/TYPESCRIPT.md` |
| QA / test strategy | `guides/QA-TESTING.md` |
| Documentation (any code/API/auth/infra change) | `guides/DOCUMENTATION.md` |
| Secrets / vault usage | `guides/VAULT-SECRETS.md` |
| Tool/credential reference (service CLIs, wrappers) | `guides/TOOLS-REFERENCE.md` |
| Memory protocol (OpenBrain capture/recall) | `guides/MEMORY.md` |
## Subagent Model Selection (Cost — Hard Rule) | Task | Required Guide |
| ------------------------------------------------------- | --------------------------------------------------- |
| Project bootstrap | `~/.config/mosaic/guides/BOOTSTRAP.md` |
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
| Orchestration flow | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
| Frontend changes | `~/.config/mosaic/guides/FRONTEND.md` |
| Backend/API changes | `~/.config/mosaic/guides/BACKEND.md` |
| Documentation changes or any code/API/auth/infra change | `~/.config/mosaic/guides/DOCUMENTATION.md` |
| Authentication/authorization | `~/.config/mosaic/guides/AUTHENTICATION.md` |
| CI/CD changes | `~/.config/mosaic/guides/CI-CD-PIPELINES.md` |
| Infrastructure/DevOps | `~/.config/mosaic/guides/INFRASTRUCTURE.md` |
| Code review work | `~/.config/mosaic/guides/CODE-REVIEW.md` |
| TypeScript strict typing | `~/.config/mosaic/guides/TYPESCRIPT.md` |
| QA and test strategy | `~/.config/mosaic/guides/QA-TESTING.md` |
| Secrets and vault usage | `~/.config/mosaic/guides/VAULT-SECRETS.md` |
| Orchestrator estimation heuristics | `~/.config/mosaic/guides/ORCHESTRATOR-LEARNINGS.md` |
| Mission lifecycle / multi-session orchestration | `~/.config/mosaic/guides/ORCHESTRATOR-PROTOCOL.md` |
Select the cheapest model capable of the task; do NOT default to the most expensive. Omitting the ## Embedded Delivery Cycle (Hard Rule)
tier defaults to the parent (usually opus) and wastes budget.
- **haiku** — search/grep/glob, codebase exploration, status/health checks, one-line mechanical fixes. - Implementation work MUST follow the embedded execution cycle:
- **sonnet** — code review, lint, test writing/fixing, standard feature implementation. - `plan -> code -> test -> review -> remediate -> review -> commit -> push -> greenfield situational test -> repeat`
- **opus** — complex architecture / multi-file refactors, security/auth logic, ambiguous design decisions. - If a step fails, you MUST remediate and re-run from the relevant step before proceeding.
Start cheapest; escalate only when the task genuinely needs deeper reasoning. Runtime syntax for ## Sequential-Thinking MCP (Hard Requirement)
specifying tier is in the runtime contract.
- `sequential-thinking` MCP server is REQUIRED for Mosaic operation.
- Installation and configuration are managed by Mosaic bootstrap and runtime linking.
- If sequential-thinking is unavailable, you MUST report the failure and stop planning-intensive execution.
## Subagent Model Selection (Cost Optimization — Hard Rule)
When delegating work to subagents, you MUST select the cheapest model capable of completing the task. Do NOT default to the most expensive model for every delegation.
| Task Type | Model Tier | Rationale |
| --------------------------------------------- | ---------- | ------------------------------------------------------- |
| File search, grep, glob, codebase exploration | **haiku** | Read-only, pattern matching, no reasoning depth needed |
| Status checks, health monitoring, heartbeat | **haiku** | Structured API calls, pass/fail output |
| Simple code fixes (typos, rename, one-liner) | **haiku** | Minimal reasoning, mechanical changes |
| Code review, lint, style checks | **sonnet** | Needs judgment but not deep architectural reasoning |
| Test writing, test fixes | **sonnet** | Pattern-based, moderate complexity |
| Standard feature implementation | **sonnet** | Good balance of capability and cost for most coding |
| Complex architecture, multi-file refactors | **opus** | Requires deep reasoning, large context, design judgment |
| Security review, auth logic | **opus** | High-stakes reasoning where mistakes are costly |
| Ambiguous requirements, design decisions | **opus** | Needs nuanced judgment and tradeoff analysis |
**Decision rule**: Start with the cheapest viable tier. Only escalate if the task genuinely requires deeper reasoning — not as a safety default. Most coding tasks are sonnet-tier. Reserve opus for work where wrong answers are expensive.
**Runtime-specific syntax**: See the runtime reference for how to specify model tier when spawning subagents (e.g., Claude Code Task tool `model` parameter).
## Superpowers Enforcement (Hard Rule) ## Superpowers Enforcement (Hard Rule)
Skills, hooks, MCP tools, and plugins are force multipliers you MUST use when applicable; Mosaic provides capabilities beyond basic code editing: **skills**, **hooks**, **MCP tools**, and **plugins**. These are not optional extras — they are force multipliers that agents MUST actively use when applicable. Under-utilization of superpowers is a framework violation.
under-utilization is a framework violation.
- **Skills:** before implementation, scan `~/.config/mosaic/skills/` and load any matching the task ### Skills
domain (e.g. `nestjs-best-practices` for NestJS). Include skill loading in worker kickstarts. Do
not load unrelated skills.
- **Hooks:** never bypass or suppress hook output; treat hook failures like failing tests and fix
them. If a hook is wrong, report it as a framework issue — do not work around it.
- **MCP:** sequential-thinking is REQUIRED for planning/architecture/multi-step reasoning. OpenBrain
(`capture`/`search`/`recent`) is the cross-agent memory layer — search at session start, capture
what you learn. Use web/browser/research MCP tools instead of asking the user to look things up.
- **Plugins:** use code-review / pr-review / architecture plugins proactively after significant
changes and before opening a PR — do not wait to be asked.
- **Self-evolution:** capture recurring patterns (`framework-improvement`), missing tooling
(`tooling-gap`), and value-less friction (`framework-friction`) to OpenBrain.
## Other Hard Rules Skills are domain-specific instruction sets in `~/.config/mosaic/skills/` that encode best practices, patterns, and guardrails. They are loaded into agents via the runtime's skill mechanism (e.g., Claude Code slash commands, Pi `--skill` flag).
- **Sequential-thinking MCP** is REQUIRED. If unavailable, report the failure and stop planning-intensive execution. **Rules:**
- **Missing core file:** if `AGENTS.md`, `SOUL.md`, or the runtime contract is missing, stop and report it.
## Session Closure 1. Before starting implementation, scan available skills (`ls ~/.config/mosaic/skills/`) and load any that match the task domain.
2. When a skill exists for the technology being used (e.g., `nestjs-best-practices` for NestJS work), you MUST load it.
3. When spawning workers, include skill loading in the kickstart prompt.
4. If you complete a task without loading a relevant available skill, that is a quality gap.
Before closing an implementation task, confirm: required + situational tests passed (primary gate); ### Hooks
aligned to `docs/PRD.md`; acceptance criteria mapped to evidence; independent code review passed (if
code changed); required docs updated; scratchpad updated with decisions/results/risks; explicit Hooks provide automated quality gates (lint, format, typecheck) that fire on file edits. They are configured in the runtime settings and run automatically.
completion evidence provided. For PR-workflow delivery: confirm merged PR number + merge commit on
`main`, terminal-green CI, and linked issue closed (or `docs/TASKS.md` equivalent). If any of those **Rules:**
are blocked by access/tooling failure, return `blocked` with the exact failed wrapper command — do
not claim completion. Full checklist: `guides/E2E-DELIVERY.md`. 1. Do NOT bypass or suppress hook output. If a hook reports errors, fix them before proceeding.
2. Hook failures are immediate feedback — treat them like failing tests.
3. If a hook is consistently failing on valid code, report it as a framework issue rather than working around it.
### MCP Tools
MCP servers extend agent capabilities with external integrations (sequential-thinking, web search, memory, browser automation, etc.). Available MCP tools are listed at session start.
**Rules:**
1. **sequential-thinking** is REQUIRED for planning, architecture, and multi-step reasoning. Use it — do not skip structured thinking for complex decisions.
2. **OpenBrain** (`capture`, `search`, `recent`) is the cross-agent memory layer. Capture discoveries and search for prior context at session start.
3. When a task involves web research, browser testing, or external data, use the available MCP tools (web-search, chrome-devtools, web-reader) rather than asking the user to look things up.
4. Check available MCP tools at session start and use them proactively throughout the session.
### Plugins (Runtime-Specific)
Runtime plugins (e.g., Claude Code's `feature-dev`, `pr-review-toolkit`, `code-review`) provide specialized agent capabilities like code review, architecture analysis, and test coverage analysis.
**Rules:**
1. After completing a significant code change, use code review plugins proactively — do not wait for the user to ask.
2. Before creating a PR, use PR review plugins to catch issues early.
3. When designing architecture, use planning/architecture plugins for structured analysis.
### Self-Evolution
The Mosaic framework should improve over time based on usage patterns:
1. When you discover a recurring pattern that should be codified, capture it to OpenBrain with `type: "framework-improvement"`.
2. When a hook, skill, or tool is missing for a common task, capture the gap to OpenBrain with `type: "tooling-gap"`.
3. When a framework rule causes friction without adding value, capture the observation to OpenBrain with `type: "framework-friction"`.
These captures feed the framework's continuous improvement cycle.
## Skills Policy
- Load skills that match the active task domain before starting implementation.
- Do not load unrelated skills.
- Follow skill trigger rules from the active runtime instruction layer.
- Actively check `~/.config/mosaic/skills/` for applicable skills rather than passively waiting for them to be mentioned.
## Session Closure Requirement
Before closing any implementation task:
1. Confirm required tests passed.
2. Confirm situational tests passed (primary gate).
3. Confirm implementation is aligned to the active `docs/PRD.md` or `docs/PRD.json`.
4. Confirm acceptance criteria are mapped to verification evidence.
5. If source code changed, confirm independent code review passed.
6. Confirm required documentation updates were completed and reviewed.
7. Update scratchpad with decisions, results, and open risks.
8. Provide explicit completion evidence.
9. If source code changed and external provider is available, confirm merged PR number and merge commit on `main`.
10. Confirm CI/pipeline status is terminal green for the merged change (or merged PR head when equivalent).
11. Confirm linked issue is closed (or internal `docs/TASKS.md` equivalent is closed when no provider exists).
12. If any of items 9-11 are blocked by access/tooling failure, return `blocked` status with exact failed wrapper command and do not claim completion.

View File

@@ -1,58 +1,257 @@
# Machine Tools — Index # Machine-Level Tool Reference
Tool suites live at `~/.config/mosaic/tools/<suite>/`. This is the index only. Centralized reference for tools, credentials, and CLI patterns available across all projects.
**Full CLI signatures, flags, and examples: `~/.config/mosaic/guides/TOOLS-REFERENCE.md`**
read it (or the relevant service guide) when your task actually touches that service.
Project-specific tooling belongs in the project's `AGENTS.md`, not here. Project-specific tooling belongs in the project's `AGENTS.md`, not here.
## Suites (use wrappers first) All tool suites are located at `~/.config/mosaic/tools/`.
| Suite | Path | Purpose | ## Tool Suites
| ---------- | ------------------------------------------------ | ------------------------------------------------------------------------ |
| git | `tools/git/*.sh` | issues, PRs, milestones, CI queue guard (platform-auto-detected) |
| woodpecker | `tools/woodpecker/*.sh` | CI pipelines (`-a mosaic`\|`usc`; match git remote host) |
| portainer | `tools/portainer/*.sh` | Docker Swarm stacks (status/redeploy/list) |
| coolify | `tools/coolify/*.sh` | **DEPRECATED** — superseded by Portainer; do not use for new deployments |
| authentik | `tools/authentik/*.sh` | identity (users/groups/apps/flows) |
| cloudflare | `tools/cloudflare/*.sh` | DNS (zones/records; `-a` instance) |
| glpi | `tools/glpi/*.sh` | IT tickets/computers/users |
| health | `tools/health/stack-health.sh` | service health checks |
| codex | `tools/codex/*.sh` | code/security review (`--uncommitted`) |
| openbrain | `tools/openbrain/*`, `tools/openbrain_client.py` | semantic memory (see below) |
| excalidraw | MCP `mcp__excalidraw__*` | diagram export/generation |
Git wrappers are MANDATORY-first for issue/PR/milestone ops (see AGENTS.md hard gates 68). ### Git Wrappers (Use First)
Queue guard before push/merge: `tools/git/ci-queue-wait.sh --purpose push|merge`.
## Credentials Mosaic wrappers at `~/.config/mosaic/tools/git/*.sh` handle platform detection and edge cases. Always use these before raw CLI commands.
`source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials <service>` ```bash
Supported: portainer, coolify (deprecated), authentik, glpi, github, gitea-mosaicstack, # Issues
gitea-usc, woodpecker, cloudflare, turbo-cache, openbrain. Never expose or commit values. ~/.config/mosaic/tools/git/issue-create.sh
~/.config/mosaic/tools/git/issue-close.sh
## OpenBrain — Semantic Memory (PRIMARY) — capture when you LEARN, never when you DO # PRs
~/.config/mosaic/tools/git/pr-create.sh
~/.config/mosaic/tools/git/pr-merge.sh
Primary cross-agent memory (pgvector). Capture decisions/gotchas/preferences/patterns; never task # Milestones
starts, commits, PRs, test results, or file edits. At session start, `search` + `recent` to load ~/.config/mosaic/tools/git/milestone-create.sh
prior context. MCP (`mcp__openbrain__capture/search/recent/stats`) preferred when connected; else
REST/`tools/openbrain_client.py`. Full protocol: `guides/MEMORY.md`.
**MANDATORY jarvis-brain rule:** when working in `~/src/jarvis-brain`, NEVER capture project data, # CI queue guard (required before push/merge)
meeting notes, status, timelines, or task completions to OpenBrain — the flat files ~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose push|merge
(`data/projects/*.json`, `data/tasks/*.json`) are the SSOT (use `tools/brain.py` + direct JSON ```
edits). OpenBrain there is for agent meta-observations ONLY (tooling gotchas, framework learnings,
cross-project patterns). Violating this creates duplicate, divergent data. ### Code Review (Codex)
```bash
~/.config/mosaic/tools/codex/codex-code-review.sh --uncommitted
~/.config/mosaic/tools/codex/codex-security-review.sh --uncommitted
```
### Infrastructure — Portainer
```bash
~/.config/mosaic/tools/portainer/stack-status.sh -n <stack-name>
~/.config/mosaic/tools/portainer/stack-redeploy.sh -n <stack-name>
~/.config/mosaic/tools/portainer/stack-list.sh
~/.config/mosaic/tools/portainer/endpoint-list.sh
```
### Infrastructure — Coolify (DEPRECATED)
> Coolify has been superseded by Portainer Docker Swarm in this stack.
> Tools remain for reference but should not be used for new deployments.
```bash
# DEPRECATED — do not use for new deployments
~/.config/mosaic/tools/coolify/project-list.sh
~/.config/mosaic/tools/coolify/service-list.sh
~/.config/mosaic/tools/coolify/service-status.sh -u <uuid>
~/.config/mosaic/tools/coolify/deploy.sh -u <uuid>
~/.config/mosaic/tools/coolify/env-set.sh -u <uuid> -k KEY -v VALUE
```
### Identity — Authentik
```bash
~/.config/mosaic/tools/authentik/user-list.sh
~/.config/mosaic/tools/authentik/user-create.sh -u <username> -n <name> -e <email>
~/.config/mosaic/tools/authentik/group-list.sh
~/.config/mosaic/tools/authentik/app-list.sh
~/.config/mosaic/tools/authentik/flow-list.sh
~/.config/mosaic/tools/authentik/admin-status.sh
```
### CI/CD — Woodpecker
Multi-instance support: `-a <instance>` selects a named instance. Omit `-a` to use the default from `woodpecker.default` in credentials.json.
| Instance | URL | Serves |
| ------------------ | ------------------ | ---------------------------------- |
| `mosaic` (default) | ci.mosaicstack.dev | Mosaic repos (git.mosaicstack.dev) |
| `usc` | ci.uscllc.com | USC repos (git.uscllc.com) |
```bash
# List recent pipelines
~/.config/mosaic/tools/woodpecker/pipeline-list.sh [-r owner/repo] [-a instance]
# Check latest or specific pipeline status
~/.config/mosaic/tools/woodpecker/pipeline-status.sh [-r owner/repo] [-n number] [-a instance]
# Trigger a build
~/.config/mosaic/tools/woodpecker/pipeline-trigger.sh [-r owner/repo] [-b branch] [-a instance]
```
Instance selection rule: match `-a` to the git remote host of the target repo. If the repo is on `git.uscllc.com`, use `-a usc`. If on `git.mosaicstack.dev`, use `-a mosaic` (or omit, since it's the default).
### DNS — Cloudflare
Multi-instance support: `-a <instance>` selects a named instance (e.g. `personal`, `work`). Omit `-a` to use the default from `cloudflare.default` in credentials.json.
```bash
# List zones (domains)
~/.config/mosaic/tools/cloudflare/zone-list.sh [-a instance]
# List DNS records (zone by name or ID)
~/.config/mosaic/tools/cloudflare/record-list.sh -z <zone> [-a instance] [-t type] [-n name]
# Create DNS record
~/.config/mosaic/tools/cloudflare/record-create.sh -z <zone> -t <type> -n <name> -c <content> [-a instance] [-p] [-l ttl] [-P priority]
# Update DNS record
~/.config/mosaic/tools/cloudflare/record-update.sh -z <zone> -r <record-id> -t <type> -n <name> -c <content> [-a instance] [-p] [-l ttl]
# Delete DNS record
~/.config/mosaic/tools/cloudflare/record-delete.sh -z <zone> -r <record-id> [-a instance]
```
### IT Service — GLPI
```bash
~/.config/mosaic/tools/glpi/ticket-list.sh
~/.config/mosaic/tools/glpi/ticket-create.sh -t <title> -c <content>
~/.config/mosaic/tools/glpi/computer-list.sh
~/.config/mosaic/tools/glpi/user-list.sh
```
### Health Check
```bash
# Check all configured services
~/.config/mosaic/tools/health/stack-health.sh
# Check a specific service
~/.config/mosaic/tools/health/stack-health.sh -s portainer
# JSON output for automation
~/.config/mosaic/tools/health/stack-health.sh -f json
```
### Shared Credential Loader
```bash
# Source in any script to load service credentials
source ~/.config/mosaic/tools/_lib/credentials.sh
load_credentials <service-name>
# Supported: portainer, coolify, authentik, glpi, github, gitea-mosaicstack, gitea-usc, woodpecker, cloudflare, turbo-cache, openbrain
```
### OpenBrain — Semantic Memory (PRIMARY)
Self-hosted semantic brain backed by pgvector. Primary shared memory layer for all agents across all sessions and harnesses. Stores and retrieves decisions, context, and observations via semantic search.
**MANDATORY jarvis-brain rule:** When working in `~/src/jarvis-brain`, NEVER capture project data, meeting notes, status updates, timeline decisions, or task completions to OpenBrain. The flat files (`data/projects/*.json`, `data/tasks/*.json`) are the SSOT — use `tools/brain.py` and direct JSON edits. OpenBrain is for agent meta-observations ONLY (tooling gotchas, framework learnings, cross-project patterns). Violating this creates duplicate, divergent data.
**Credentials:** `load_credentials openbrain` → exports `OPENBRAIN_URL`, `OPENBRAIN_TOKEN`
Configure in your credentials.json:
```json
"openbrain": {
"url": "https://<your-openbrain-host>",
"api_key": "<your-api-key>"
}
```
**REST API** (any language, any harness):
```bash
source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials openbrain
# Search by meaning
curl -s -X POST -H "Authorization: Bearer $OPENBRAIN_TOKEN" -H "Content-Type: application/json" \
-d '{"query": "your search", "limit": 5}' "$OPENBRAIN_URL/v1/search"
# Capture a thought
curl -s -X POST -H "Authorization: Bearer $OPENBRAIN_TOKEN" -H "Content-Type: application/json" \
-d '{"content": "...", "source": "agent-name", "metadata": {}}' "$OPENBRAIN_URL/v1/thoughts"
# Recent activity
curl -s -H "Authorization: Bearer $OPENBRAIN_TOKEN" "$OPENBRAIN_URL/v1/thoughts/recent?limit=5"
# Stats
curl -s -H "Authorization: Bearer $OPENBRAIN_TOKEN" "$OPENBRAIN_URL/v1/stats"
```
**Python client** (if jarvis-brain is available on PYTHONPATH):
```bash
python tools/openbrain_client.py search "topic"
python tools/openbrain_client.py capture "decision or observation" --source agent-name
python tools/openbrain_client.py recent --limit 5
python tools/openbrain_client.py stats
```
**MCP (Claude Code sessions):** When connected, `mcp__openbrain__capture/search/recent/stats` tools are available natively — prefer those over CLI when in a Claude session.
**Rule: capture when you LEARN something. Never when you DO something.**
| Trigger | Action | Retention |
| ----------------------------------------- | ----------------------------------------- | --------------------- |
| Session start | `search` + `recent` to load prior context | — |
| Architectural or tooling decision made | Capture with rationale | `long` or `permanent` |
| Gotcha or non-obvious behavior discovered | Capture immediately | `medium` |
| User preference stated or confirmed | Capture | `permanent` |
| Cross-project pattern identified | Capture | `permanent` |
| Prior decision superseded | UPDATE existing thought | (keep tier) |
**Never capture:** task started, commit pushed, PR opened, test results, file edits, CI status.
Full protocol and cleanup tools: `~/.config/mosaic/guides/MEMORY.md`
Smart capture wrapper (enforces schema + dedup): `~/.config/mosaic/tools/openbrain/capture.sh`
### Excalidraw — Diagram Export (MCP)
Headless `.excalidraw` → SVG export via `@excalidraw/excalidraw`. Available as MCP tools in Claude Code sessions.
**MCP tools (when connected):**
| Tool | Input | Output |
| ----------------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
| `mcp__excalidraw__excalidraw_to_svg` | `elements` JSON string + optional `app_state` | SVG string |
| `mcp__excalidraw__excalidraw_file_to_svg` | `file_path` to `.excalidraw` | SVG string + writes `.svg` alongside |
| `mcp__excalidraw__list_diagrams` | (none) | Available templates (requires `EXCALIDRAW_GEN_PATH`) |
| `mcp__excalidraw__generate_diagram` | `name`, optional `output_path` | Path to generated `.excalidraw` |
| `mcp__excalidraw__generate_and_export` | `name`, optional `output_path` | Paths to `.excalidraw` and `.svg` |
**Diagram generation** (`list_diagrams`, `generate_diagram`, `generate_and_export`) requires `EXCALIDRAW_GEN_PATH` env var pointing to `excalidraw_gen.py`. Set in environment or shell profile:
```bash
export EXCALIDRAW_GEN_PATH="$HOME/src/jarvis-brain/tools/excalidraw_export/excalidraw_gen.py"
```
**Manual registration:**
```bash
mosaic-ensure-excalidraw # install deps + register with Claude
mosaic-ensure-excalidraw --check # verify registration
```
## Git Providers ## Git Providers
| Host | Instance | CI | | Instance | URL | CLI | Purpose |
| ------------------- | ---------------- | -------------------------------- | | ----------------------------- | --- | --- | ------- |
| git.mosaicstack.dev | mosaic (default) | ci.mosaicstack.dev (`-a mosaic`) | | (add your git providers here) | | | |
| git.uscllc.com | usc | ci.uscllc.com (`-a usc`) |
Match Woodpecker `-a` and credential instance to the target repo's git remote host. ## Credentials
**Location:** (configure your credential file path)
**Loader:** `source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials <service>`
**Never expose actual values. Never commit credential files.**
## CLI Gotchas
(Add platform-specific CLI gotchas as you discover them.)
## Safety Defaults ## Safety Defaults
- Prefer `trash` over `rm` when available — recoverable beats gone forever. - Prefer `trash` over `rm` when available — recoverable beats gone forever
- Never run destructive commands without explicit instruction. - Never run destructive commands without explicit instruction
- Write it down — "mental notes" don't survive session restarts; files do

View File

@@ -1,257 +0,0 @@
# Machine-Level Tool Reference
Centralized reference for tools, credentials, and CLI patterns available across all projects.
Project-specific tooling belongs in the project's `AGENTS.md`, not here.
All tool suites are located at `~/.config/mosaic/tools/`.
## Tool Suites
### Git Wrappers (Use First)
Mosaic wrappers at `~/.config/mosaic/tools/git/*.sh` handle platform detection and edge cases. Always use these before raw CLI commands.
```bash
# Issues
~/.config/mosaic/tools/git/issue-create.sh
~/.config/mosaic/tools/git/issue-close.sh
# PRs
~/.config/mosaic/tools/git/pr-create.sh
~/.config/mosaic/tools/git/pr-merge.sh
# Milestones
~/.config/mosaic/tools/git/milestone-create.sh
# CI queue guard (required before push/merge)
~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose push|merge
```
### Code Review (Codex)
```bash
~/.config/mosaic/tools/codex/codex-code-review.sh --uncommitted
~/.config/mosaic/tools/codex/codex-security-review.sh --uncommitted
```
### Infrastructure — Portainer
```bash
~/.config/mosaic/tools/portainer/stack-status.sh -n <stack-name>
~/.config/mosaic/tools/portainer/stack-redeploy.sh -n <stack-name>
~/.config/mosaic/tools/portainer/stack-list.sh
~/.config/mosaic/tools/portainer/endpoint-list.sh
```
### Infrastructure — Coolify (DEPRECATED)
> Coolify has been superseded by Portainer Docker Swarm in this stack.
> Tools remain for reference but should not be used for new deployments.
```bash
# DEPRECATED — do not use for new deployments
~/.config/mosaic/tools/coolify/project-list.sh
~/.config/mosaic/tools/coolify/service-list.sh
~/.config/mosaic/tools/coolify/service-status.sh -u <uuid>
~/.config/mosaic/tools/coolify/deploy.sh -u <uuid>
~/.config/mosaic/tools/coolify/env-set.sh -u <uuid> -k KEY -v VALUE
```
### Identity — Authentik
```bash
~/.config/mosaic/tools/authentik/user-list.sh
~/.config/mosaic/tools/authentik/user-create.sh -u <username> -n <name> -e <email>
~/.config/mosaic/tools/authentik/group-list.sh
~/.config/mosaic/tools/authentik/app-list.sh
~/.config/mosaic/tools/authentik/flow-list.sh
~/.config/mosaic/tools/authentik/admin-status.sh
```
### CI/CD — Woodpecker
Multi-instance support: `-a <instance>` selects a named instance. Omit `-a` to use the default from `woodpecker.default` in credentials.json.
| Instance | URL | Serves |
| ------------------ | ------------------ | ---------------------------------- |
| `mosaic` (default) | ci.mosaicstack.dev | Mosaic repos (git.mosaicstack.dev) |
| `usc` | ci.uscllc.com | USC repos (git.uscllc.com) |
```bash
# List recent pipelines
~/.config/mosaic/tools/woodpecker/pipeline-list.sh [-r owner/repo] [-a instance]
# Check latest or specific pipeline status
~/.config/mosaic/tools/woodpecker/pipeline-status.sh [-r owner/repo] [-n number] [-a instance]
# Trigger a build
~/.config/mosaic/tools/woodpecker/pipeline-trigger.sh [-r owner/repo] [-b branch] [-a instance]
```
Instance selection rule: match `-a` to the git remote host of the target repo. If the repo is on `git.uscllc.com`, use `-a usc`. If on `git.mosaicstack.dev`, use `-a mosaic` (or omit, since it's the default).
### DNS — Cloudflare
Multi-instance support: `-a <instance>` selects a named instance (e.g. `personal`, `work`). Omit `-a` to use the default from `cloudflare.default` in credentials.json.
```bash
# List zones (domains)
~/.config/mosaic/tools/cloudflare/zone-list.sh [-a instance]
# List DNS records (zone by name or ID)
~/.config/mosaic/tools/cloudflare/record-list.sh -z <zone> [-a instance] [-t type] [-n name]
# Create DNS record
~/.config/mosaic/tools/cloudflare/record-create.sh -z <zone> -t <type> -n <name> -c <content> [-a instance] [-p] [-l ttl] [-P priority]
# Update DNS record
~/.config/mosaic/tools/cloudflare/record-update.sh -z <zone> -r <record-id> -t <type> -n <name> -c <content> [-a instance] [-p] [-l ttl]
# Delete DNS record
~/.config/mosaic/tools/cloudflare/record-delete.sh -z <zone> -r <record-id> [-a instance]
```
### IT Service — GLPI
```bash
~/.config/mosaic/tools/glpi/ticket-list.sh
~/.config/mosaic/tools/glpi/ticket-create.sh -t <title> -c <content>
~/.config/mosaic/tools/glpi/computer-list.sh
~/.config/mosaic/tools/glpi/user-list.sh
```
### Health Check
```bash
# Check all configured services
~/.config/mosaic/tools/health/stack-health.sh
# Check a specific service
~/.config/mosaic/tools/health/stack-health.sh -s portainer
# JSON output for automation
~/.config/mosaic/tools/health/stack-health.sh -f json
```
### Shared Credential Loader
```bash
# Source in any script to load service credentials
source ~/.config/mosaic/tools/_lib/credentials.sh
load_credentials <service-name>
# Supported: portainer, coolify, authentik, glpi, github, gitea-mosaicstack, gitea-usc, woodpecker, cloudflare, turbo-cache, openbrain
```
### OpenBrain — Semantic Memory (PRIMARY)
Self-hosted semantic brain backed by pgvector. Primary shared memory layer for all agents across all sessions and harnesses. Stores and retrieves decisions, context, and observations via semantic search.
**MANDATORY jarvis-brain rule:** When working in `~/src/jarvis-brain`, NEVER capture project data, meeting notes, status updates, timeline decisions, or task completions to OpenBrain. The flat files (`data/projects/*.json`, `data/tasks/*.json`) are the SSOT — use `tools/brain.py` and direct JSON edits. OpenBrain is for agent meta-observations ONLY (tooling gotchas, framework learnings, cross-project patterns). Violating this creates duplicate, divergent data.
**Credentials:** `load_credentials openbrain` → exports `OPENBRAIN_URL`, `OPENBRAIN_TOKEN`
Configure in your credentials.json:
```json
"openbrain": {
"url": "https://<your-openbrain-host>",
"api_key": "<your-api-key>"
}
```
**REST API** (any language, any harness):
```bash
source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials openbrain
# Search by meaning
curl -s -X POST -H "Authorization: Bearer $OPENBRAIN_TOKEN" -H "Content-Type: application/json" \
-d '{"query": "your search", "limit": 5}' "$OPENBRAIN_URL/v1/search"
# Capture a thought
curl -s -X POST -H "Authorization: Bearer $OPENBRAIN_TOKEN" -H "Content-Type: application/json" \
-d '{"content": "...", "source": "agent-name", "metadata": {}}' "$OPENBRAIN_URL/v1/thoughts"
# Recent activity
curl -s -H "Authorization: Bearer $OPENBRAIN_TOKEN" "$OPENBRAIN_URL/v1/thoughts/recent?limit=5"
# Stats
curl -s -H "Authorization: Bearer $OPENBRAIN_TOKEN" "$OPENBRAIN_URL/v1/stats"
```
**Python client** (if jarvis-brain is available on PYTHONPATH):
```bash
python tools/openbrain_client.py search "topic"
python tools/openbrain_client.py capture "decision or observation" --source agent-name
python tools/openbrain_client.py recent --limit 5
python tools/openbrain_client.py stats
```
**MCP (Claude Code sessions):** When connected, `mcp__openbrain__capture/search/recent/stats` tools are available natively — prefer those over CLI when in a Claude session.
**Rule: capture when you LEARN something. Never when you DO something.**
| Trigger | Action | Retention |
| ----------------------------------------- | ----------------------------------------- | --------------------- |
| Session start | `search` + `recent` to load prior context | — |
| Architectural or tooling decision made | Capture with rationale | `long` or `permanent` |
| Gotcha or non-obvious behavior discovered | Capture immediately | `medium` |
| User preference stated or confirmed | Capture | `permanent` |
| Cross-project pattern identified | Capture | `permanent` |
| Prior decision superseded | UPDATE existing thought | (keep tier) |
**Never capture:** task started, commit pushed, PR opened, test results, file edits, CI status.
Full protocol and cleanup tools: `~/.config/mosaic/guides/MEMORY.md`
Smart capture wrapper (enforces schema + dedup): `~/.config/mosaic/tools/openbrain/capture.sh`
### Excalidraw — Diagram Export (MCP)
Headless `.excalidraw` → SVG export via `@excalidraw/excalidraw`. Available as MCP tools in Claude Code sessions.
**MCP tools (when connected):**
| Tool | Input | Output |
| ----------------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
| `mcp__excalidraw__excalidraw_to_svg` | `elements` JSON string + optional `app_state` | SVG string |
| `mcp__excalidraw__excalidraw_file_to_svg` | `file_path` to `.excalidraw` | SVG string + writes `.svg` alongside |
| `mcp__excalidraw__list_diagrams` | (none) | Available templates (requires `EXCALIDRAW_GEN_PATH`) |
| `mcp__excalidraw__generate_diagram` | `name`, optional `output_path` | Path to generated `.excalidraw` |
| `mcp__excalidraw__generate_and_export` | `name`, optional `output_path` | Paths to `.excalidraw` and `.svg` |
**Diagram generation** (`list_diagrams`, `generate_diagram`, `generate_and_export`) requires `EXCALIDRAW_GEN_PATH` env var pointing to `excalidraw_gen.py`. Set in environment or shell profile:
```bash
export EXCALIDRAW_GEN_PATH="$HOME/src/jarvis-brain/tools/excalidraw_export/excalidraw_gen.py"
```
**Manual registration:**
```bash
mosaic-ensure-excalidraw # install deps + register with Claude
mosaic-ensure-excalidraw --check # verify registration
```
## Git Providers
| Instance | URL | CLI | Purpose |
| ----------------------------- | --- | --- | ------- |
| (add your git providers here) | | | |
## Credentials
**Location:** (configure your credential file path)
**Loader:** `source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials <service>`
**Never expose actual values. Never commit credential files.**
## CLI Gotchas
(Add platform-specific CLI gotchas as you discover them.)
## Safety Defaults
- Prefer `trash` over `rm` when available — recoverable beats gone forever
- Never run destructive commands without explicit instruction
- Write it down — "mental notes" don't survive session restarts; files do

View File

@@ -1,61 +1,131 @@
# Claude Runtime Reference # Claude Runtime Reference
Claude-runtime behavior only. Global rules win if anything here conflicts. ## Runtime Scope
This file applies only to Claude runtime behavior.
## Required Actions ## Required Actions
1. Follow the Session Start load order in `~/.config/mosaic/AGENTS.md`. 1. Follow global load order in `~/.config/mosaic/AGENTS.md`.
2. Runtime config lives in `~/.claude/settings.json` (hooks, model, plugins, permissions) and 2. Use `~/.claude/settings.json` and `~/.claude/hooks-config.json` as runtime config sources.
`~/.claude/hooks-config.json`. 3. Treat sequential-thinking MCP as required.
3. sequential-thinking MCP is required. 4. If runtime config conflicts with global rules, global rules win.
4. First response MUST declare mode per the global contract. 5. Documentation rules are inherited from `~/.config/mosaic/AGENTS.md` and `~/.config/mosaic/guides/DOCUMENTATION.md`.
5. Git wrappers first for issue/PR/milestone ops; runtime-default confirmation prompts do NOT 6. For issue/PR/milestone actions, run Mosaic git wrappers first (`~/.config/mosaic/tools/git/*.sh`) and do not call raw `gh`/`tea`/`glab` first.
override Mosaic hard gates (push/merge/issue-close without routine confirmation). 7. For orchestration-oriented missions, load `~/.config/mosaic/guides/ORCHESTRATOR.md` before acting.
8. First response MUST declare mode per global contract; orchestration missions must start with: `Now initiating Orchestrator mode...`
9. Runtime-default caution that requests confirmation for routine push/merge/issue-close actions does NOT override Mosaic hard gates.
## Subagent Model Selection (Claude Code syntax) ## Subagent Model Selection (Claude Code Syntax)
The Task tool takes `model`: `"haiku"` | `"sonnet"` | `"opus"`. You MUST set it per the tier rule Claude Code's Task tool accepts a `model` parameter: `"haiku"`, `"sonnet"`, or `"opus"`.
in AGENTS.md — omitting it defaults to the parent (usually opus) and wastes budget.
You MUST set this parameter according to the model selection table in `~/.config/mosaic/AGENTS.md`. Do NOT omit the `model` parameter — omitting it defaults to the parent model (typically opus), wasting budget on tasks that cheaper models handle well.
**Examples:**
``` ```
# Codebase exploration — haiku
Task(subagent_type="Explore", model="haiku", prompt="Find all API route handlers") Task(subagent_type="Explore", model="haiku", prompt="Find all API route handlers")
Task(subagent_type="feature-dev:code-reviewer", model="sonnet", prompt="Review src/auth/ changes")
# Code review — sonnet
Task(subagent_type="feature-dev:code-reviewer", model="sonnet", prompt="Review the changes in src/auth/")
# Standard feature work — sonnet
Task(subagent_type="general-purpose", model="sonnet", prompt="Add validation to the user input form")
# Complex architecture — opus (only when justified)
Task(subagent_type="Plan", model="opus", prompt="Design the multi-tenant isolation strategy") Task(subagent_type="Plan", model="opus", prompt="Design the multi-tenant isolation strategy")
``` ```
**Quick reference (from global AGENTS.md):**
| haiku | sonnet | opus |
| ---------------------- | ----------------- | -------------------------- |
| Search, grep, glob | Code review | Complex architecture |
| Status/health checks | Test writing | Security/auth logic |
| Simple one-liner fixes | Standard features | Ambiguous design decisions |
## Memory Policy (Hard Gate) ## Memory Policy (Hard Gate)
OpenBrain is the primary cross-agent memory layer — capture learnings/gotchas/decisions there **OpenBrain is the primary cross-agent memory layer.** All agent learnings, gotchas, decisions, and project state MUST be captured to OpenBrain via the `capture` MCP tool or REST API.
(`capture` MCP tool or REST). `~/.claude/projects/*/memory/MEMORY.md` is **write-blocked** by the
`prevent-memory-write.sh` PreToolUse hook (the rule alone proved insufficient — the hook is the
hard gate). At session start, `search(topic)` + `recent()` to load prior context. Full protocol:
`~/.config/mosaic/guides/MEMORY.md`.
Quick placement: discoveries/decisions → OpenBrain; active task state → `docs/TASKS.md` or `~/.claude/projects/*/memory/MEMORY.md` files are **write-blocked by PreToolUse hook** (`prevent-memory-write.sh`). Any attempt to write agent learnings there will be rejected with an error directing you to OpenBrain.
`docs/scratchpads/`; Mosaic framework notes → `~/.config/mosaic/memory/`.
### What belongs where
| Content | Location |
| ----------------------------------------------- | ---------------------------------------------------------------------- |
| Discoveries, gotchas, decisions, observations | OpenBrain `capture` — searchable by all agents |
| Active task state | `docs/TASKS.md` or `docs/scratchpads/` |
| Behavioral guardrails that MUST be in load-path | `MEMORY.md` (read-mostly; write only for genuine behavioral overrides) |
| Mosaic framework technical notes | `~/.config/mosaic/memory/` |
### Using OpenBrain
At session start, load prior context:
```
search("topic or project name") # semantic search
recent(limit=5) # what's been happening
```
When you discover something:
```
capture("The thing you learned", source="project/context", metadata={"type": "gotcha", ...})
```
### Why the hook exists
Instructions in RUNTIME.md, CLAUDE.md, and MEMORY.md are insufficient — agents default to writing local MEMORY.md regardless of written rules. The PreToolUse hook is a hard technical gate that makes the correct behavior the only possible behavior.
## MCP Configuration ## MCP Configuration
MCP servers are configured in `~/.claude.json` (key `mcpServers`) — NOT `~/.claude/settings.json`, **MCPs are configured in `~/.claude.json` — NOT `~/.claude/settings.json`.**
where that key is ignored. `settings.json` controls hooks/model/plugins/permissions.
`settings.json` controls hooks, model, plugins, and allowed commands.
`~/.claude.json` is the global Claude Code state file where `mcpServers` lives.
To register an MCP server that persists across all sessions:
```bash ```bash
# HTTP MCP (e.g. OpenBrain)
claude mcp add --scope user --transport http <name> <url> --header "Authorization: Bearer <token>" claude mcp add --scope user --transport http <name> <url> --header "Authorization: Bearer <token>"
claude mcp add --scope user <name> -- npx -y <package> # stdio
# stdio MCP
claude mcp add --scope user <name> -- npx -y <package>
``` ```
`--scope user` `~/.claude.json` (global); `project``.claude/settings.json`; `local` (default) `--scope user` = writes to `~/.claude.json` (global, all projects).
→ not committed. `--scope project` = writes to `.claude/settings.json` in project root.
`--scope local` = default, local-only (not committed).
## Required Settings (launcher-audited, advisory) Do NOT add `mcpServers` to `~/.claude/settings.json` — that key is ignored for MCP loading.
`mosaic claude` warns if `~/.claude/settings.json` is missing these (session still launches): ## Required Claude Code Settings (Enforced by Launcher)
- **Hooks** — PreToolUse `prevent-memory-write.sh` (Write|Edit|MultiEdit); PostToolUse The `mosaic claude` launcher validates that `~/.claude/settings.json` contains the required Mosaic configuration. Missing or outdated settings trigger a warning at launch.
`qa-hook-stdin.sh` + `typecheck-hook.sh` (Edit|MultiEdit|Write).
- **Plugins** — `feature-dev`, `pr-review-toolkit`, `code-review`.
- **Settings** — `enableAllMcpTools: true`; `model: "opus"` (orchestrator default; workers use
tiered models via the Task `model` param).
Note: PostToolUse hook plain stdout on exit 0 goes to the debug log, not model context — only **Required hooks:**
`hookSpecificOutput.additionalContext` (or exit-2 stderr) enters context.
| Event | Matcher | Script | Purpose |
| ----------- | ------------------------ | ------------------------- | ---------------------------------------------- |
| PreToolUse | `Write\|Edit\|MultiEdit` | `prevent-memory-write.sh` | Block writes to `~/.claude/projects/*/memory/` |
| PostToolUse | `Edit\|MultiEdit\|Write` | `qa-hook-stdin.sh` | QA report generation after code edits |
| PostToolUse | `Edit\|MultiEdit\|Write` | `typecheck-hook.sh` | Inline TypeScript type checking |
**Required plugins:**
| Plugin | Purpose |
| ------------------- | -------------------------------------------------------------------------------------------------------- |
| `feature-dev` | Subagent architecture: code-reviewer, code-architect, code-explorer |
| `pr-review-toolkit` | PR review: code-simplifier, comment-analyzer, test-analyzer, silent-failure-hunter, type-design-analyzer |
| `code-review` | Standalone code review capabilities |
**Required settings:**
- `enableAllMcpTools: true` — Allow all configured MCP tools without per-tool approval
- `model: "opus"` — Default to opus for orchestrator-level sessions (workers use tiered models via Task tool)
If `mosaic claude` detects missing hooks or plugins, it will print a warning with the exact settings to add. The session will still launch — enforcement is advisory, not blocking — but agents operating without these settings are running degraded.

View File

@@ -1,78 +0,0 @@
# Inter-Agent tmux Comms — Standard & Tooling
Reliable, self-identifying messaging between Mosaic agents running in tmux panes
(Claude Code / Codex / OpenCode REPLs), across hosts.
## The addressing standard (required)
Every cross-agent tmux message MUST begin with an addressing preamble:
```
[<src_host>:<src_session> -> <dst_host>:<dst_session>] <message>
```
- `host` = `hostname -s` of the machine the agent runs on (e.g. `web1`, `sb-it-mgr-0-lt`).
- `session` = the tmux session name (e.g. `mos-claude`, `rev0-4`, `installer-1`).
- **Replies FLIP the preamble**: the recipient answers with `[<dst> -> <src>] ...`.
Why: a fresh or context-wiped agent always knows who sent a message and to whom.
No ambiguity about origin or lane after a tmux wipe / session restart.
Example exchange:
```
[web1:mos-claude -> sb-it-mgr-0-lt:installer-1] status on #29?
[sb-it-mgr-0-lt:installer-1 -> web1:mos-claude] Q2 done, opening PR #34.
```
## The helper: `agent-send.sh`
Prepends the preamble automatically (auto-detecting your own `host:session`) and
delivers reliably to local OR remote panes.
```bash
# Local target (same host)
agent-send.sh -s <dst_session> -m "message"
# Remote target (over ssh)
agent-send.sh -H user@host -s <dst_session> -m "message"
# From a file / stdin
agent-send.sh -H user@host -s <dst_session> -f msg.txt
echo "msg" | agent-send.sh -s <dst_session>
```
Key flags: `-s` dst session (required) · `-H` ssh target for remote · `-n` dst
hostname for the preamble (else auto-resolved) · `-m`/`-f`/stdin body · `-S`
override source label · `-v` verbose · `-r N` Enter-flush attempts.
## Why a helper exists (the submission gotcha)
Pasting into an interactive REPL via raw `tmux send-keys` is unreliable: a
trailing `Enter` is frequently swallowed and the message sits as an **unsubmitted
draft** ("Press up to edit queued messages"). Over an `ssh -> nested tmux` hop the
plain `Enter` keyname often does not register at all — `C-m` is needed.
`send-message.sh` solves this for a **local** pane: bracketed-paste the body
(so multi-line content doesn't submit early), pause, then send `Enter` as its own
keystroke and flush with a second, verifying against a draft heuristic.
`agent-send.sh` solves the **remote** case by _shipping `send-message.sh` over ssh_
(`ssh host bash -s -- ... < send-message.sh`) and running it local to the target
pane — so the reliable send-keys always happens on the pane's own host. The remote
needs only `bash` + `tmux` + `base64`; **no mosaic install required there**. The
message crosses the wire as base64 (`-b`) to avoid all shell-quoting hazards.
## Files
- `agent-send.sh` — inter-agent wrapper (preamble + local/remote dispatch).
- `send-message.sh` — low-level reliable single-pane submitter (`-b` base64 input).
## Distribution
These live in the installed framework copy at
`~/.config/mosaic/tools/tmux/`. `install.sh` rsyncs the framework **source tree**
to each host, so to propagate permanently, land both files in the framework
source repo and re-run the installer on each host. Until then, `agent-send.sh`
already works against any reachable host because it ships `send-message.sh` over
ssh per-send — no pre-install on the target host is needed to _send to_ it.

View File

@@ -1,100 +0,0 @@
#!/usr/bin/env bash
# agent-send.sh — standard inter-agent tmux messaging for the Mosaic stack.
#
# WHAT IT DOES
# Sends a message to another agent's tmux pane (local or on a remote host)
# with the canonical addressing preamble prepended:
#
# [<src_host>:<src_session> -> <dst_host>:<dst_session>] <message>
#
# The preamble makes every inter-agent message self-identifying, so a fresh
# or context-wiped agent always knows who sent a message and to whom — no
# ambiguity about lanes or origin. Recipients replying should FLIP the
# preamble: [<dst> -> <src>] ... (this tool sends; it does not auto-reply).
#
# WHY A WRAPPER
# Reliable submission into an interactive REPL (Claude Code / Codex) is fiddly:
# a trailing Enter is often swallowed and the message sits as an unsubmitted
# DRAFT. tools/tmux/send-message.sh already solves that for a LOCAL pane via
# bracketed-paste + Enter-flush + draft-detection. For REMOTE targets this
# wrapper SHIPS send-message.sh over ssh (stdin) and runs it there, so the
# reliable send-keys happens local to the target pane — sidestepping the
# ssh->nested-tmux Enter/C-m swallow entirely. No mosaic install needed on
# the remote host; only bash + tmux + base64 (standard).
#
# USAGE
# agent-send.sh -s <dst_session> -m "message" # local target
# agent-send.sh -H user@host -s <dst_session> -m "message" # remote target
# agent-send.sh -H user@host -n <dst_hostname> -s <sess> -f msg.txt
# echo "msg" | agent-send.sh -H user@host -s <dst_session>
#
# OPTIONS
# -s DST_SESSION target tmux session (or session:window.pane) [required]
# -H SSH_TARGET ssh target (user@host) for a remote pane; omit for local
# -n DST_HOST hostname to show in the preamble for the target.
# Default: local hostname, or (remote) resolved via one ssh.
# -m MESSAGE message text (single- or multi-line)
# -f FILE read message from FILE instead of -m
# -S SRC_LABEL override source label "<host>:<session>" (default: auto)
# -r N Enter-flush attempts passed through (default 2)
# -v verbose: print pane tail after delivery
# -h help
#
# EXIT CODES (passed through from send-message.sh)
# 0 delivered/queued · 1 target not found · 2 still draft · 3 usage error
set -uo pipefail
SELF_DIR=$(cd -- "$(dirname -- "$0")" && pwd)
SENDER="$SELF_DIR/send-message.sh"
DST_SESSION=""; SSH_TARGET=""; DST_HOST=""; MSG=""; FILE=""
SRC_LABEL=""; RETRIES=2; VERBOSE=0
usage() { sed -n '2,44p' "$0"; exit "${1:-3}"; }
while getopts "s:H:n:m:f:S:r:vh" o; do
case "$o" in
s) DST_SESSION=$OPTARG ;; H) SSH_TARGET=$OPTARG ;; n) DST_HOST=$OPTARG ;;
m) MSG=$OPTARG ;; f) FILE=$OPTARG ;; S) SRC_LABEL=$OPTARG ;;
r) RETRIES=$OPTARG ;; v) VERBOSE=1 ;; h) usage 0 ;; *) usage 3 ;;
esac
done
[ -n "$DST_SESSION" ] || { echo "ERROR: -s DST_SESSION is required" >&2; usage 3; }
[ -x "$SENDER" ] || { echo "ERROR: send-message.sh not found beside this script" >&2; exit 3; }
# Message body from -f / -m / stdin.
if [ -n "$FILE" ]; then [ -r "$FILE" ] || { echo "ERROR: cannot read $FILE" >&2; exit 3; }; MSG=$(cat -- "$FILE")
elif [ -z "$MSG" ] && [ ! -t 0 ]; then MSG=$(cat)
fi
[ -n "$MSG" ] || { echo "ERROR: empty message (use -m, -f, or stdin)" >&2; exit 3; }
# Source label: this agent's host:session (auto-detected, overridable).
if [ -z "$SRC_LABEL" ]; then
src_host=$(hostname -s 2>/dev/null || echo "?")
src_sess=$(tmux display-message -p '#S' 2>/dev/null || echo "?")
SRC_LABEL="${src_host}:${src_sess}"
fi
# Destination host label for the preamble.
if [ -z "$DST_HOST" ]; then
if [ -n "$SSH_TARGET" ]; then
DST_HOST=$(ssh -o ConnectTimeout=8 -o BatchMode=yes "$SSH_TARGET" 'hostname -s' 2>/dev/null || echo "${SSH_TARGET#*@}")
else
DST_HOST=$(hostname -s 2>/dev/null || echo "local")
fi
fi
PREAMBLE="[${SRC_LABEL} -> ${DST_HOST}:${DST_SESSION}]"
FULL="${PREAMBLE} ${MSG}"
B64=$(printf '%s' "$FULL" | base64 -w0)
vflag=""; [ "$VERBOSE" = 1 ] && vflag="-v"
if [ -z "$SSH_TARGET" ]; then
# Local pane: call the canonical sender directly.
exec "$SENDER" -t "$DST_SESSION" -b "$B64" -r "$RETRIES" $vflag
else
# Remote pane: ship the sender over ssh and run it local to the target.
ssh -o ConnectTimeout=10 "$SSH_TARGET" \
"bash -s -- -t '$DST_SESSION' -b '$B64' -r '$RETRIES' $vflag" < "$SENDER"
fi

View File

@@ -1,97 +0,0 @@
#!/usr/bin/env bash
# send-message.sh — reliably deliver a message to a tmux pane running an
# interactive REPL (e.g. a Claude Code / Codex agent).
#
# WHY THIS EXISTS
# Pasting multi-line text into an interactive agent REPL via `tmux send-keys`
# is unreliable: the text lands in the input box but a single trailing Enter
# in the same keystroke stream is frequently swallowed, so the message sits as
# an UNSUBMITTED DRAFT ("Press up to edit queued messages") and the agent never
# sees it. The mechanical fix is: paste as a bracketed paste (so embedded
# newlines don't submit early), pause, then send Enter as its OWN keystroke,
# pause, and send Enter again to flush. An extra Enter on an empty prompt is a
# no-op in Claude Code, so the double-Enter is safe.
#
# USAGE
# send-message.sh -t <target> -m "message"
# send-message.sh -t <target> -f <file>
# echo "message" | send-message.sh -t <target>
# ssh host bash -s -- -t <target> -b "$(base64 -w0 <<<msg)" < send-message.sh
#
# OPTIONS
# -t TARGET tmux target: session, or session:window.pane [required]
# -m MESSAGE message text (single- or multi-line)
# -f FILE read message from FILE instead of -m
# -b BASE64 message as base64 (ssh-safe transport; decoded internally)
# -r N Enter-flush attempts (default 2)
# -v verbose: print a short tail of the pane after delivery
# -h help
#
# EXIT CODES
# 0 delivered (submitted) or queued (agent busy; will process when free)
# 1 tmux target not found
# 2 message still appears to be an unsubmitted draft after retries
# 3 usage error
set -uo pipefail
TARGET=""; MSG=""; FILE=""; B64=""; RETRIES=2; VERBOSE=0
usage() { sed -n '2,34p' "$0"; exit "${1:-3}"; }
while getopts "t:m:f:b:r:vh" o; do
case "$o" in
t) TARGET=$OPTARG ;; m) MSG=$OPTARG ;; f) FILE=$OPTARG ;; b) B64=$OPTARG ;;
r) RETRIES=$OPTARG ;; v) VERBOSE=1 ;; h) usage 0 ;; *) usage 3 ;;
esac
done
[ -n "$TARGET" ] || { echo "ERROR: -t TARGET is required" >&2; usage 3; }
if [ -n "$B64" ]; then MSG=$(printf '%s' "$B64" | base64 -d) || { echo "ERROR: bad -b base64" >&2; exit 3; }
elif [ -n "$FILE" ]; then [ -r "$FILE" ] || { echo "ERROR: cannot read $FILE" >&2; exit 3; }; MSG=$(cat -- "$FILE")
elif [ -z "$MSG" ] && [ ! -t 0 ]; then MSG=$(cat)
fi
[ -n "$MSG" ] || { echo "ERROR: empty message (use -m, -f, or stdin)" >&2; exit 3; }
# Target must resolve to a live pane.
if ! tmux list-panes -t "$TARGET" >/dev/null 2>&1; then
echo "ERROR: tmux target not found: $TARGET" >&2; exit 1
fi
QUEUED_RE='Press up to edit queued messages'
# A distinctive tail of the message to spot an unsubmitted draft on the input line.
snippet=$(printf '%s' "$MSG" | tr '\n' ' ' | tr -s ' ' | sed 's/[^[:print:]]//g' | tail -c 32)
# 1) Paste the body as a bracketed paste so multi-line content does not submit
# line-by-line. load-buffer/paste-buffer is far safer than `send-keys -l`.
printf '%s' "$MSG" | tmux load-buffer -b __mosaic_send -
# -p = bracketed paste when the client supports it; fall back if not.
tmux paste-buffer -d -p -b __mosaic_send -t "$TARGET" 2>/dev/null \
|| tmux paste-buffer -d -b __mosaic_send -t "$TARGET"
sleep 0.5
# 2) Submit, then verify; flush with another Enter if it is still a draft.
status="sent"
for attempt in $(seq 1 $((RETRIES + 1))); do
tmux send-keys -t "$TARGET" Enter
sleep 1.2
pane=$(tmux capture-pane -t "$TARGET" -p 2>/dev/null)
if printf '%s' "$pane" | grep -qF "$QUEUED_RE"; then
status="queued"; break
fi
# Draft heuristic: the prompt glyph line still carries our message tail.
# (Submitted messages scroll up into history; a draft stays on the line.)
promptline=$(printf '%s' "$pane" | grep -E '|^>|│ >' | tail -1)
if [ -n "$snippet" ] && printf '%s' "$promptline" | grep -qF "$snippet"; then
status="draft"; continue
fi
status="delivered"; break
done
[ "$VERBOSE" = 1 ] && { echo "--- pane tail ($TARGET) ---"; printf '%s\n' "$pane" | tail -4; echo "---"; }
case "$status" in
delivered) echo "✓ delivered to $TARGET"; exit 0 ;;
queued) echo "✓ queued to $TARGET (agent busy — will process when it returns to prompt)"; exit 0 ;;
draft) echo "✗ still an unsubmitted draft on $TARGET after $RETRIES flush attempts" >&2; exit 2 ;;
*) echo "✓ sent to $TARGET (submission state indeterminate; verify with -v)"; exit 0 ;;
esac

View File

@@ -1,35 +0,0 @@
# Scratchpad — Thin-core prompt diet (#528)
**Branch:** `feat/contract-thin-core` · **Issue:** #528 · **Mode:** Delivery
## Objective
Cut the always-injected contract (`defaults/AGENTS.md` + `defaults/TOOLS.md` + `runtime/claude/RUNTIME.md`, inlined every turn by the launcher) without losing any hard gate. Restore the original "thin core + on-demand guides" intent.
## Change
- `defaults/AGENTS.md` → thin core: 12 hard gates verbatim, 37 operating rules condensed to ~15 bullets (detail already in `guides/E2E-DELIVERY.md`), Superpowers condensed, load order made on-demand (no halt-on-missing for STANDARDS), conditional guide-loading index retained.
- `defaults/TOOLS.md` → index; full catalog moved to new `guides/TOOLS-REFERENCE.md` (read on demand).
- `runtime/claude/RUNTIME.md` → slimmed (dedup tier table, terser pointers).
## Method (autoresearch-style validation)
1. Built a 9-probe role battery (backend/deploy/review/orchestrate/secrets/docs/simple-trap/no-stop-at-PR/agent-work) + a deterministic 18-signature gate-checklist.
2. Headless interactive runs (Claude Max **subscription**, tmux — no API), scored by per-probe rubric.
3. Keep-or-discard hill-climb (token cost gated by per-probe fidelity) proved the method; final design re-derived against THIS repo's content (diet-only, no drifted-deployment content imported).
## Validation evidence
- Gate-checklist: ALL gates + critical rules + mode lines + sequential-thinking + OpenBrain + Superpowers present.
- A/B on real repo content: **thin 7/9 vs monolith 5/9** probes; strictly better on deploy/review/simple-task; composed **8,827 → 4,122 tok (53%)**.
- p11 (don't-stop-at-PR): 3→2/3 on one rubric line — verified a scorer/phrasing artifact (answer correctly cites gates §5/§9 + close-issue; gate verbatim-present). Variance: thin 2/2/3, v0 3/3/3.
## Decisions / risks
- **Diet-only** vs repo content (user decision). Did NOT import web1's Gate 13-15 / federated memory / OpenViking — canonical repo is behind those deployments; flagged for separate reconciliation.
- AGENTS/TOOLS are shared across runtimes → diet benefits codex/pi/opencode too; RUNTIME change is claude-only.
- p11 accepted as-is (user decision) — not gaming the rubric.
## Status
PR open, paused for maintainer merge ratification (fleet-governing change). `mosaic upgrade` will propagate on merge.