LISAOS // DOCS
GATEWAY // CURATOR

Gateway Module — `curator/`

1. Purpose

The curator/ module stores and serves agent health cards — the per-agent snapshot the Hermes-side Curator computes during the Self-Improvement Pipeline (SIP Phase 1, Dispatch 818): dispatch volume, quality score + trend, stall/affinity/escalation rates, priority-skill health, binding-ref validity, open proposals, and tune history. The Curator bulk-upserts a batch of cards after each run; the dashboard armoury tab and agent-tune consumers read them back. It is a thin CRUD-over-one-table module keyed by agent_name (UNIQUE), with JSON array fields stringified on write and parsed on read.

2. File Inventory

FileLinesResponsibility
repository.ts152INSERT … ON CONFLICT(agent_name) DO UPDATE upsert + list/get; JSON (de)serialisation
routes.ts771 POST bulk-upsert + 2 GET list/single
types.ts115Zod input schemas + row/record interfaces + repository contract
Total344(No index.ts — the router is wired directly in server/index.ts via createCuratorRouter(curatorRepo).)

3. Public API Surface

REST Endpoints

Mounted at /api/curator (index.ts line 762). Auth (post-AK-415):

MethodPathAuthBody / QueryResponse
POST/api/curator/health-cardsBearer (write only)BulkHealthCardInputSchema (cards: 1–8)201 { data: { upserted: N, run_id } }
GET/api/curator/health-cardsBearer?agent_name= (optional filter){ data: CuratorHealthCardRecord[] }
GET/api/curator/health-cards/:agent_nameBearer{ data: record } or 404

Note: /api/curator is the "worked idiom" the AK-415 closure generalised from — it was already Bearer-gated on GET before the mega-OR was deleted.

MCP Tools

None.

4. Internal API

  • createCuratorRepository(db): CuratorRepositoryupsertHealthCards(cards) (wrapped in a db.transaction, returns the re-fetched parsed records), getHealthCards(agentName?), getHealthCard(agentName).
  • createCuratorRouter(repo): Router.

5. Background Services

None. Write is push-driven from the Hermes Curator; reads are request-driven.

6. Data Contracts

  • CuratorHealthCardInputSchemaagent_name, domain, dispatch_volume_30d (int ≥0), quality_score (0–1), quality_trend (up/down/stable), stall_rate/affinity_rate/escalation_rate (0–1), priority_skills_health (array of { skill, status ∈ Active|Low-use|Dormant|Dead }), binding_refs_health (array of { ref, valid }), last_definition_update (nullable), open_proposals (int), open_proposal_types (string[]), active_monitoring (nullable), tune_history (array of { rule_id, date, status ∈ completed|rolled_back }), curator_run_id.
  • BulkHealthCardInputSchema{ cards: array(min 1, max 8) } (8 = the CyberShinobi roster size).
  • Row vs record split: CuratorHealthCardRow holds the JSON array fields as strings; CuratorHealthCardRecord is the parsed application shape.

Storage pattern: INSERT … ON CONFLICT(agent_name) DO UPDATE SET … (upsert). This requires the agent_name UNIQUE constraint declared in db.ts — without it the upsert throws "ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint" (Dispatch 1011 R-8). JSON array fields are JSON.stringify'd on write, JSON.parse'd on read.

7. Dependencies

  • Gateway modules consumed: shared/ (formatZodError); the curator_health_cards table (schema in db.ts).
  • External libraries: better-sqlite3, express, zod.
  • Environment variables: none.

8. Test Coverage

LayerFileCases
Repositorytest/curator-repository.test.ts (281 L)(upsert, JSON round-trip, filter)
Routestest/curator-routes.test.ts (374 L)21 it blocks

Covers bulk upsert idempotency (re-upsert same agent updates in place), 1–8 card bounds, JSON field round-trips, and 404 on missing card.

9. Known Limitations

  • Bulk-upsert batch capped at 8 cards (the roster size); a future roster expansion needs the .max(8) bumped.
  • Module has no index.ts layer factory — repository + router are wired inline in server/index.ts, a minor inconsistency with the vault-index/analytics layer pattern.
  • Schema history: the module was removed and restored verbatim from the vault mirror (Dispatch 1011, R-8, AK-328) after the R-10 cutover — a provenance note, not a live limitation.

10. Change History

DateDispatchSummary
2026-07-042297Initial module spec (smoke-clone-3, LisaOS audit campaign Phase 4)
1011 (R-8, AK-328)Verbatim restore from vault mirror into lisa-os main
818 (SIP Phase 1)Module created — agent health cards

On this page