P0.4 — γ Server Lifecycle — Agent Prompts

Copy-paste-ready prompts for agents tackling each task in this group. Canonical spec: task-breakdown.md §P0.4 Master bootstrap prompt: agent-bootstrap.md

Group summary

Task ID Title Depends on Effort Unblocks
P0.4.1 Runtime Mode Enum P0.1.4 S P0.4.2, production gates
P0.4.2 Graceful Shutdown P0.2.3 S production-ready runtime

P0.4.1 — Runtime Mode Enum

Spec source: task-breakdown.md §P0.4.1
Extraction reference: docs/reference/extractions/gamma-server-lifecycle-extraction.md
Worktree: feature/p0-4-1-modes
Branch command: git worktree add .worktrees/claude/p0-4-1-modes -b feature/p0-4-1-modes origin/main
Estimated effort: S (Small — 1-2 hours)
Depends on: P0.1.4 (Environment validation)
Unblocks: P0.4.2 (Shutdown uses mode checks), all capability-gated tools throughout codebase

Files to create

  • src/modes.ts — 4 Phase 0 runtime modes with capability sets
  • tests/modes.test.ts — Mode detection and capability tests

Acceptance criteria

  • 4 modes defined: FULL | READONLY | TEST | MINIMAL (Phase 0 floor — WATCH is deferred with file-watcher work; there is no AMS_WATCH_MODE)
  • detectMode() reads COLIBRI_MODE env var, defaults to FULL. Reading any AMS_* variable is forbidden
  • Each mode has capability set: { canWrite, canRunTests, heavyInit }no canSpawnAgents. Agent spawning belongs to Phase 1.5 (there is no src/domains/agents/ in Phase 0 per CLAUDE.md §9.1)
  • READONLY mode: canWrite=false, all write tools return { error: "readonly_mode" }
  • MINIMAL mode: no heavy init, only server/ping and server/health available
  • Test: all 4 modes have correct capability sets
  • Test: invalid COLIBRI_MODE throws (no silent fallback to FULL)

Pre-flight reading

  • CLAUDE.md — worktree rules
  • docs/guides/implementation/task-breakdown.md §P0.4.1 — full spec
  • docs/reference/extractions/gamma-server-lifecycle-extraction.md — mode patterns
  • src/config.ts — how config.ts validates env vars (parallel pattern)

Ready-to-paste agent prompt

You are a Phase 0 builder agent for Colibri.

TASK: P0.4.1 — Runtime Mode Enum
Define the 4 Phase 0 runtime modes and their capability sets for gating features.

FILES TO READ FIRST:
1. CLAUDE.md (execution rules)
2. docs/guides/implementation/task-breakdown.md §P0.4.1
3. docs/concepts/γ-server-lifecycle.md
4. docs/reference/extractions/gamma-server-lifecycle-extraction.md (heritage — study, don't copy)
5. src/config.ts (for env var validation pattern)

WORKTREE SETUP:
git fetch origin
git worktree add .worktrees/claude/p0-4-1-modes -b feature/p0-4-1-modes origin/main
cd .worktrees/claude/p0-4-1-modes

FILES TO CREATE:
- src/modes.ts
  * Export enum: FULL = "full", READONLY = "readonly", TEST = "test", MINIMAL = "minimal"
  * Capability set interface: { canWrite: boolean, canRunTests: boolean, heavyInit: boolean }
    (No `canSpawnAgents` — agent runtime is deferred to Phase 1.5; there is no
     `src/domains/agents/` in the Phase 0 target tree.)
  * FULL: canWrite=true, canRunTests=true, heavyInit=true
  * READONLY: canWrite=false, canRunTests=true, heavyInit=true
  * TEST: canWrite=true, canRunTests=true, heavyInit=true
  * MINIMAL: canWrite=false, canRunTests=false, heavyInit=false
  * detectMode(): read COLIBRI_MODE env, default FULL, validate against the 4 enum values
  * getCapabilities(mode): return capability set
  * isReadonly(mode): shorthand boolean check

- tests/modes.test.ts
  * Test detectMode() returns FULL for missing env
  * Test detectMode() returns correct mode for each valid COLIBRI_MODE value
  * Test detectMode() throws for invalid COLIBRI_MODE (no silent fallback)
  * Test detectMode() refuses to read AMS_MODE (donor namespace forbidden)
  * Test all 4 modes have expected capability sets
  * Test isReadonly returns true only for READONLY mode

ACCEPTANCE CRITERIA (headline):
✓ 4 modes defined with capability sets
✓ detectMode() reads COLIBRI_MODE env, defaults FULL
✓ READONLY mode: canWrite=false
✓ MINIMAL mode: no heavy init
✓ Test all 4 modes + invalid-value case

SUCCESS CHECK:
cd .worktrees/claude/p0-4-1-modes && npm test && npm run lint

WRITEBACK (after success):
task_update(task_id="P0.4.1", status="done", progress=100)
thought_record(task_id="P0.4.1", branch="feature/p0-4-1-modes",
  commit_sha=<your-sha>, tests_run=["npm test","npm run lint"],
  summary="Implemented 4 Phase 0 runtime modes (FULL, READONLY, TEST, MINIMAL) with capability sets. detectMode() reads COLIBRI_MODE env, defaults FULL. No AMS_* fallback.")

FORBIDDENS:
✗ Do not hardcode capability logic in individual tools (centralize in modes.ts)
✗ Do not skip env validation (invalid COLIBRI_MODE must throw)
✗ Do not read AMS_* variables — donor namespace is not supported
✗ Do not add canSpawnAgents — agent runtime is deferred to Phase 1.5
✗ Do not edit main checkout

NEXT:
P0.4.2 — Graceful Shutdown (uses mode checks, shutdown handlers)

Verification checklist (for reviewer agent)

  • 4 modes all defined with correct capability sets (no WATCH, no canSpawnAgents)
  • detectMode() validates COLIBRI_MODE against enum
  • Invalid COLIBRI_MODE throws error (not silent fallback)
  • Reading any AMS_* variable is a lint/test failure — donor namespace not supported
  • READONLY has canWrite=false
  • MINIMAL has no heavy init and limited tools
  • Test all 4 modes and their capabilities
  • npm test and npm run lint pass

Writeback template

task_update:
  task_id: P0.4.1
  status: done
  progress: 100

thought_record:
  task_id: P0.4.1
  branch: feature/p0-4-1-modes
  commit_sha: <sha>
  tests_run: ["npm test", "npm run lint"]
  summary: "Implemented 4 Phase 0 runtime modes (FULL, READONLY, TEST, MINIMAL) with capability sets {canWrite, canRunTests, heavyInit}. detectMode() reads COLIBRI_MODE env var, defaults to FULL. No AMS_* fallback. READONLY disables writes; MINIMAL disables heavy initialization and exposes only server/ping + server/health. canSpawnAgents is not a Phase 0 capability  agent runtime is deferred to Phase 1.5."
  blockers: []

Common gotchas

  • Centralize capability logic in modes.ts — don’t scatter if statements checking READONLY throughout the codebase. Use getCapabilities(mode) in one place, then all tools can gate on the returned object.
  • COLIBRI_MODE env validation — if the user sets an invalid value, fail loudly at startup with a clear error listing valid modes. Silent fallback to FULL hides configuration errors.
  • No AMS_* fallback — if code reads process.env.AMS_MODE, it’s a bug. The donor namespace is explicitly not supported.
  • MINIMAL mode is for probes and healthchecks — it should not initialize the database or start long-running services. Only expose server/ping and server/health.
  • WATCH mode is deferred. The donor AMS_WATCH_MODE flag belonged to a file-watcher leader-election subsystem Colibri does not have. Adding a WATCH mode in Phase 0 is a scope drift.

P0.4.2 — Graceful Shutdown

Spec source: task-breakdown.md §P0.4.2
Extraction reference: docs/reference/extractions/gamma-server-lifecycle-extraction.md
Worktree: feature/p0-4-2-shutdown
Branch command: git worktree add .worktrees/claude/p0-4-2-shutdown -b feature/p0-4-2-shutdown origin/main
Estimated effort: S (Small — 1-2 hours)
Depends on: P0.2.3 (Two-phase startup)
Unblocks: Production-ready runtime (no hanging processes, clean DB closes)

Files to create

  • src/shutdown.ts — Graceful shutdown handler registry and orchestration
  • tests/shutdown.test.ts — Shutdown sequence tests

Acceptance criteria

  • registerShutdownHandler(fn) registers a cleanup function
  • On SIGINT / SIGTERM: calls all handlers in reverse registration order
  • DB connection closed before process exit
  • In-flight MCP requests allowed to complete (max 5s timeout then force-exit)
  • Exit code 0 on clean shutdown, 1 on error during shutdown
  • Test: mock SIGTERM → verify DB close + handler called

Pre-flight reading

  • CLAUDE.md — execution rules
  • docs/guides/implementation/task-breakdown.md §P0.4.2 — full spec
  • docs/reference/extractions/gamma-server-lifecycle-extraction.md (shutdown section)
  • src/server.ts — how to integrate shutdown handler registration

Ready-to-paste agent prompt

You are a Phase 0 builder agent for Colibri.

TASK: P0.4.2 — Graceful Shutdown
Handle SIGINT/SIGTERM, close DB, wait for in-flight requests, exit cleanly.

FILES TO READ FIRST:
1. CLAUDE.md (execution rules)
2. docs/guides/implementation/task-breakdown.md §P0.4.2
3. docs/reference/extractions/gamma-server-lifecycle-extraction.md (shutdown section)
4. src/server.ts (entry point integration point)
5. src/db/index.ts (Database instance for closing)

WORKTREE SETUP:
git fetch origin
git worktree add .worktrees/claude/p0-4-2-shutdown -b feature/p0-4-2-shutdown origin/main
cd .worktrees/claude/p0-4-2-shutdown

FILES TO CREATE:
- src/shutdown.ts
  * Singleton shutdown manager
  * registerShutdownHandler(fn: () => void | Promise<void>): void
    - Add handler to stack (LIFO)
  * initializeShutdownHandlers(db: Database, server: McpServer)
    - Register handler to close DB connection
    - Register handler to stop MCP server
    - Return function that triggers shutdown sequence
  * Shutdown sequence on SIGINT/SIGTERM:
    1. Log "Shutdown initiated"
    2. Call all handlers in reverse registration order
    3. Wait for in-flight requests (max 5s, then force-exit)
    4. Exit with code 0 (clean) or 1 (error)
  * If any handler throws, log error, continue to next handler, exit with code 1

- tests/shutdown.test.ts
  * Test registerShutdownHandler stores handlers in LIFO order
  * Test shutdown calls handlers in reverse order
  * Test DB connection closed during shutdown (mock db.close())
  * Test SIGTERM signal → shutdown called
  * Test SIGINT signal → shutdown called
  * Test in-flight request timeout (max 5s)
  * Test exit code 0 on clean shutdown, 1 on error

ACCEPTANCE CRITERIA (headline):
✓ registerShutdownHandler stores handlers (LIFO)
✓ On SIGINT/SIGTERM: call handlers in reverse order
✓ DB closed before exit
✓ In-flight requests allowed to complete (5s max timeout)
✓ Exit code 0 clean / 1 error

SUCCESS CHECK:
cd .worktrees/claude/p0-4-2-shutdown && npm test && npm run lint

WRITEBACK (after success):
task_update(task_id="P0.4.2", status="done", progress=100)
thought_record(task_id="P0.4.2", branch="feature/p0-4-2-shutdown",
  commit_sha=<your-sha>, tests_run=["npm test","npm run lint"],
  summary="Implemented graceful shutdown with SIGINT/SIGTERM handlers, reverse-order execution, DB close, 5s timeout for in-flight requests.")

FORBIDDENS:
✗ Do not exit immediately on signal (wait for in-flight requests)
✗ Do not skip DB close (leaves database locked)
✗ Do not use setTimeout(..., 0) for shutdown (use proper async/await)
✗ Do not edit main checkout

NEXT:
P0.5.1 — Intent Scoring Matrix (router uses mode checks from P0.4.1)
Production readiness depends on this task.

Verification checklist (for reviewer agent)

  • Shutdown handlers stored in reverse order (LIFO stack)
  • SIGINT and SIGTERM both trigger shutdown
  • DB close called before process.exit()
  • In-flight requests allowed 5s timeout
  • Exit code 0 on success, 1 on error
  • Test covers all signal types and timeout scenario
  • npm test and npm run lint pass

Writeback template

task_update:
  task_id: P0.4.2
  status: done
  progress: 100

thought_record:
  task_id: P0.4.2
  branch: feature/p0-4-2-shutdown
  commit_sha: <sha>
  tests_run: ["npm test", "npm run lint"]
  summary: "Implemented graceful shutdown handler. registerShutdownHandler() stores cleanup functions in LIFO order. On SIGINT/SIGTERM, calls handlers in reverse registration order, closes DB connection, allows in-flight MCP requests 5s to complete, then exits with code 0 (clean) or 1 (error). Prevents hung processes and database corruption."
  blockers: []

Common gotchas

  • LIFO handler order — shutdown handlers are registered in startup order, but executed in reverse. Register DB close first, then MCP server stop, so DB is cleaned up last. This ensures no tools try to write to a closed database.
  • In-flight request timeout — don’t use a fixed setTimeout. Use a graceful timeout pattern: collect all in-flight promises, wait for them with Promise.race([Promise.all(flights), timeout]), then force-exit if timeout wins.
  • Exit code signals — exit(0) means clean shutdown; exit(1) means error. Kubernetes and systemd respect these. Exit without a code defaults to 0, so be explicit.
  • Process signal handling — SIGTERM is the normal kill signal; SIGINT is Ctrl+C. Both should shut down gracefully. SIGKILL (cannot be caught) will force-kill immediately, so there’s no recovery.

Next group

p0.5-delta-router.md — δ Model Router (2 tasks: Intent Scoring, 8-Model Fallback Chain)

Back to task-prompts index


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.