Architecture
This document describes the current repository architecture. Punk is under active development, so package boundaries are intentionally explicit and testable.
High-Level System
flowchart LR
Agent["Customer Agent"] --> Gateway["Punk Gateway / SDK"]
Gateway --> Router["Runtime Router"]
Router --> Provider["Live Provider"]
Router --> Cache["Caches"]
Router --> Artifact["Artifact Runtime"]
Router --> Web["Semantic Web Runtime"]
Router --> Gov["Governance Runtime"]
Gateway --> Ledger["Trace Ledger"]
Ledger --> Learning["Learning Loop"]
Learning --> Synthesis["Artifact Synthesis"]
Synthesis --> Replay["Replay / Shadow"]
Replay --> Artifact
Ledger --> Dashboard["Dashboard / API"]
Runtime Request Flow
/v1/chat/completionsreceives an OpenAI-compatible request.- Auth resolves tenant, gateway mode, admin flag, optional pinned app, and API key id.
- Request is normalized with
X-Punk-App,X-Punk-Agent, andX-Punk-Subject. - Governance checks
model:chatfor the resolved agent. - Router checks policy, exact cache, promoted artifacts, observe-mode ghost route, and live fallback.
- Provider response or optimized response is returned with
x-punk-run-idandx-punk-route. - Run, trace events, route explanation, savings, and audit data are persisted.
- Durable jobs and the learning loop update patterns, artifacts, replays, shadows, approvals, and retention.
Apps
| Path | Role |
|---|---|
apps/api | Gateway, REST API, dashboard static assets, router, providers, approvals, jobs wiring. |
apps/worker | Standalone durable job worker for scale-out deployments. |
apps/demo | Narrated support-triage demo and local fixture server. |
apps/menubar | Native macOS PunkBar companion. |
Packages
| Package | Responsibility |
|---|---|
@punk/trace-schema | Canonical runtime contracts and shared types. Dependency-free by design. |
@punk/database | PunkStore contract plus SQLite, memory, and Postgres adapters. |
@punk/cache-core | Exact/tool/SOM/evaluation/negative cache behavior over PunkStore. |
@punk/fingerprint | Stable prompt, request, tool, and output fingerprints. |
@punk/governance-core | Policy parsing/evaluation, trust, side-effect classification, redaction, optional MeshGuard-compatible bridge. |
@punk/web-core | SOM compiler/runtime, Plasmate-compatible AWP client, session/action primitives, SOM cache, semantic diff, extraction, prompt context. |
@punk/artifact-core | Artifact representation and execution contract. |
@punk/replay-core | Replay bundles and replay suite execution. |
@punk/synthesis | Candidate artifact synthesis from patterns and traces. |
@punk/learning | Pattern discovery, confidence updates, replay/shadow scheduling, promotion eligibility. |
@punk/jobs | Durable job queue and worker abstraction. |
@punk/sdk | Dependency-free TypeScript client. |
Persistence
All runtime packages depend on the PunkStore interface, not raw SQL.
Adapters:
- SQLite: default local path from
PUNK_DB_PATH, defaultdata/punk.db. - Postgres: selected when
PUNK_DATABASE_URLis set. - Memory: used for serverless/demo contexts where durability is not required.
Important persistence properties:
- Trace events are append-only.
- Per-run trace events have an integrity hash chain.
- Derived data can be rebuilt from runs and trace events.
- Tenant id appears on runtime records.
- API tokens are stored as hashes only.
Durable Jobs
Punk uses durable jobs for async work:
learning_tick- replay evaluation
- shadow evaluation
- webhook notification
- approval sweep
- retention sweep
Local dev starts an embedded worker by default. Production with Postgres can run bun run worker in a separate process.
Dashboard
The dashboard is static HTML/CSS/JS served by apps/api. It uses the same REST API as the SDK and PunkBar. Keep dashboard-only behavior out of private server internals when possible.
Package Boundary Rules
packages/trace-schemamust remain dependency-free.packages/databaseowns storage details.- Runtime packages should depend on interfaces and shared types, not Hono route internals.
- App packages wire IO, providers, auth, dashboards, and process lifecycle.
- If a feature needs new persistence behavior, add a named method to
PunkStoreinstead of reaching for raw SQL.