Commissioned by Jason 2026-08-13: agents need the branch-handling process written down — next-first for every contribution, Jason-only promotion merges to main, the gate sequence (issue, next-head base, terminal-green CI on the exact head, independent review, no self-merge, pinned-head merge), role responsibilities, and the hotfix/divergence rules motivated by the #1152 main-only landing.
9.7 KiB
Agent Guidelines — Mosaic Stack
Required Load Order
~/.config/mosaic/SOUL.md~/.config/mosaic/STANDARDS.md~/.config/mosaic/AGENTS.md~/.config/mosaic/guides/E2E-DELIVERY.mdAGENTS.md(this file)- Runtime-specific guide:
~/.config/mosaic/runtime/<runtime>/RUNTIME.md
Project Context
Mosaic Stack is a self-hosted, multi-user AI agent platform. It is a TypeScript monorepo with a NestJS gateway, Next.js dashboard, Pi SDK agent runtime, and Discord/Telegram plugin architecture.
Stack
- API: NestJS with Fastify (
apps/gateway) - Web: Next.js 16 with React 19 (
apps/web) - ORM and database: Drizzle ORM, PostgreSQL 17, and pgvector (
packages/db) - Authentication: BetterAuth (
packages/auth) - Agent runtime: Pi SDK (
apps/gateway,packages/mosaic) - Queue: Valkey 8 (
packages/queue) - Build: pnpm workspaces and Turborepo
- CI: Woodpecker CI
- Observability: OpenTelemetry and Jaeger
Package Map
| Package | Purpose | Key Dependencies |
|---|---|---|
apps/gateway |
NestJS API + WebSocket hub | Fastify, Socket.IO, Pi SDK, OTEL |
apps/web |
Next.js dashboard | React 19, Tailwind |
packages/types |
Shared TypeScript contracts | class-validator |
packages/db |
Drizzle schema and migrations | drizzle-orm, postgres |
packages/auth |
BetterAuth configuration | better-auth, @mosaicstack/db |
packages/brain |
Structured data layer | @mosaicstack/db |
packages/queue |
Valkey task queue and MCP | ioredis |
packages/coord |
Mission coordination | @mosaicstack/queue |
packages/mosaic |
Unified mosaic CLI and TUI |
Ink, Pi SDK, commander |
plugins/discord |
Discord channel plugin | discord.js |
plugins/telegram |
Telegram channel plugin | Telegraf |
Architecture and Code Conventions
- Gateway is the single API surface; all clients connect through it.
- Pi SDK is ESM-only; gateway and CLI code must remain ESM.
- Use
"type": "module", NodeNext module resolution, and.jsextensions in imports. - Keep typed Socket.IO events in
@mosaicstack/typesto enforce client/server contracts. - Import OTEL tracing before NestJS bootstrap (
import './tracing.js'). - Use explicit
@Inject()decorators in NestJS because tsx/esbuild does not emit decorator metadata. - Keep DTOs in
*.dto.tsfiles at module boundaries. - BetterAuth owns authentication tables; their schema is defined in
@mosaicstack/db. - Create a task-specific scratchpad for non-trivial work.
Development Workflow
Requirements: Node.js 20+, pnpm 10.6.2, and Docker Compose when optional local services are needed.
pnpm install --frozen-lockfile
pnpm preflight
# Optional local queue service only; do not start the full Compose stack.
docker compose up -d valkey
The pre-push hook requires:
pnpm preflight && pnpm typecheck && pnpm lint && pnpm format:check
Software delivery also requires the applicable tests. Common repository commands are:
pnpm typecheck # TypeScript checks across the workspace
pnpm lint # ESLint across the workspace
pnpm test # Checkout tests and package Vitest suites
pnpm format:check # Prettier check
pnpm build # Build all packages and applications
Branch Model and Merge Process — main and next (CANONICAL)
Every contribution targets next first. No exceptions. Features, fixes, tests,
docs, and policy changes all take the same route; urgency changes queue priority,
never the route. Agents never commit to or merge into main.
| Branch | Role | Who merges into it |
|---|---|---|
next |
Integration trunk — the only PR target for contributions | The designated merge-gate agent, after all gates pass. Never the PR author. |
main |
Stable/release line — receives promotion merges from next only |
Jason only (or an agent he explicitly delegates for a named promotion). |
Contribution sequencing (in order, no skipping)
- Issue first. Work is tracked in a Gitea issue before a branch exists. The issue number appears in the branch name and the PR body.
- Branch from the current
origin/nexthead. Name itfeat/…,fix/…,docs/…, ortest/…with the issue number (e.g.docs/1214-branch-process). Record the base SHA in the PR body. - Develop with evidence. Applicable tests accompany the change. Hooks are
never bypassed (
--no-verifyis prohibited). Stage explicit paths — nevergit add -A. - Open the PR against
next. The body states: scope, base SHA, verification commands with results, and any known pre-existing failures on the base — documented, not retried to green and not absorbed silently. - CI must be terminal-green on the exact head. All bounded Woodpecker
steps succeed (
verify-terminal-greencontract). Pipelines for fork PRs startblocked; a maintainer approves the run — approving CI is not approving the PR. - Independent review. Self-merge is prohibited — for every agent, on every
PR, including trivial ones. Where the change touches protected or
contract-bearing content, the reviewer verifies the exact head
(exact-byte/exact-blob comparison), not a description of it. An
AMENDverdict returns the PR to its author; the reviewer's gate stays held until a fresh exact head passes. - Merge into
nexthappens only after CI green + review pass, pinned to the reviewed head SHA (a post-review push voids the review). - Promotion
next→mainis a deliberate, Jason-owned reconciliation merge — not part of any contribution's lifecycle. Contributors are done at step 7.
Responsibilities
- Contributor — base pinning, green CI, evidence in the PR body, responding to AMEND verdicts, never merging own work.
- Reviewer / merge gate — independent verification on the exact head;
holds and lifts gates; executes the merge into
next. - Orchestrator / adjudicator — cross-PR sequencing, disposition when PRs collide, conflict adjudication.
- Jason —
next→mainpromotions, merge-authority grants, collaborator and token provisioning. Agents cannot grant themselves or each other any of these.
Hotfixes and divergence
- A hotfix follows the same path: branch from
next, PR tonext, gates, merge, then an expedited Jason-owned promotion ifmainneeds it urgently. Committing the fix tomaindirectly is prohibited even under pressure. - Never land work on
mainthat is not onnext. This has happened (issue #1152's goal controller reachedmainwithout reachingnext) and every later PR paid for it. If it happens anyway: transplant the work onto anext-based branch with provenance-preserving commits (git cherry-pick -xor explicit SHA references in the messages), PR it through the normal gates, and let promotion re-alignmain. Do not hand-patchmainto compensate. - Force-pushing a branch you do not own is prohibited; rebasing your own PR branch is fine before review, and voids any review already given.
Database and Local Runtime Safety
- Current local data-layer work uses in-process PGlite; leave
DATABASE_URLunset. - PostgreSQL execution is held until KBN-101-00, KBN-101-03, and KBN-101-05 land.
- Do not invoke a migration runner, initialization SQL, or the Compose PostgreSQL service from this checkout.
- Do not start Gateway/Web or run root
pnpm devas a local PGlite route. The current dotenv loader can inherit a daemon PostgreSQL DSN; KBN-101-02 must make that path fail closed first. - Migration artifact generation is offline and does not authorize PostgreSQL access:
pnpm --filter @mosaicstack/db db:generate
docs/TASKS.md — Schema (CANONICAL)
The agent column specifies the required model for each task. This is set at task creation by the orchestrator and must not be changed by workers.
| Value | When to use | Budget |
|---|---|---|
codex |
All coding tasks (default for implementation) | OpenAI credits — preferred |
glm-5.1 |
Cost-sensitive coding where Codex is unavailable | Z.ai credits |
haiku |
Review gates, verify tasks, status checks, docs-only | Cheapest Claude tier |
sonnet |
Complex planning, multi-file reasoning, architecture review | Claude quota |
opus |
Major cross-cutting architecture decisions ONLY | Most expensive — minimize |
— |
No preference / auto-select cheapest capable | Pipeline decides |
Pipeline crons read this column and spawn accordingly. Workers never modify docs/TASKS.md — only the orchestrator writes it.
Full schema:
| id | status | description | issue | agent | repo | branch | depends_on | estimate | notes |
status:not-started|in-progress|done|failed|blocked|needs-qaagent: model value from table above (set before spawning)estimate: token budget e.g.8K,25K