← Ledger


Date: 2026-07-07 Status: Accepted

Context

Phase P1a wires every rocky-hq producer to emit KAHN Scope's agent-shape transition stream (agent_run_start, agent_run_end) alongside the pre-existing agent-registration.v1 hatch triple. Plan: docs/plans/2026-07-06-phase-p1a-kahn-agent-emit.md. Motivation: rocky was the largest silent producer against kahn-hq's north-star (kahn-hq/docs/north-star/agent-fleet.md); every ralph run, relay call, sniffer analysis, council persona, and hearth driver invocation was invisible in KAHN Scope.

The plan defined four sub-phases (P1a-1 through P1a-4). During execution two additional slices emerged (P1a-3b, P1a-3c) to close a tenancy gap discovered at deploy time — a single global KAHN_INGEST_TOKEN cannot represent a multi-tenant fleet where each rocky workspace maps to its own KAHN tenant. Both are documented below as landed extensions, not scope creep — they were required for the sub-phases they extend to work in production.

Decision

Phase P1a is closed with all four planned sub-phases + two follow-on slices shipped, per the acceptance criteria below.

Landed sub-phases

Slice Producer Repo / PR Merged
P1a-1 RALPH (Python) — vendor kahn_agent_emit.py + agent_transitions.schema.json; AgentJournal sibling to Journal; HTTP shipper env-gated rocky-hq/ralph#13 (6347ebd) landed
P1a-2 RALPH terminal observer (TS) — console-side SSE watcher forwards run_end to KAHN rocky-hq/console#41 → parent d3a261f landed
P1a-3 RELAY / COUNCIL / SNIFFER (Node) — shared emitter console/src/lib/kahn-agent/; persona-per-agent for COUNCIL rocky-hq/console#42 → parent d720382 landed
P1a-3b Console per-workspace token resolution — KAHN_INGEST_TOKEN_<SLUG_UPPER>KAHN_INGEST_TOKEN fallback → skip; KAHN_DEBUG=1 ship logging rocky-hq/console#43 (cb62c5d) → parent #111 (fbdd3f4) landed
P1a-3c RALPH per-workspace token resolution — mirror console P1a-3b in AgentJournal rocky-hq/ralph#14 (712c406) → parent #112 (7319ece) landed
P1a-4 HEARTH driver (Go) — KAHNEmitter sibling to hatch emitter; one KAHN run per RPC verb; same per-workspace token convention rocky-hq/hearth#8 (e914280) → parent #113 landed

Per-workspace tenancy convention (locked)

Every producer resolves the KAHN Bearer at ship-time from:

  1. KAHN_INGEST_TOKEN_<SLUG_UPPER> — slug uppercased, -/._. Example: iris-hqKAHN_INGEST_TOKEN_IRIS_HQ. Matches the existing ROCKY_POLAR_TIER_<SLUG> / ROCKY_AGENT_APPROVED_<AGENT_ID> env-prefix pattern.
  2. KAHN_INGEST_TOKEN — global fallback (OSS / local dev / single-tenant installs).
  3. Neither set → skip ship entirely. KAHN 401s on missing Bearer; the round-trip is pure waste.

slug_token_env_key(slug) (TS + Python + Go) is exported for provisioning tooling. Every ship call site threads workspace_slug through; empty slug also skips ship (mirrors the console x-rocky-workspace header gating).

Fail-open contract (locked)

Every producer's ship path swallows transport errors, timeouts, non-2xx, marshal failures, and DNS errors. A KAHN outage MUST NOT fault:

File sinks (ralph's agent-transitions.jsonl) are unaffected by ship failures — the durable journal is the source of truth; KAHN is a projection.

Debug logging (opt-in)

KAHN_DEBUG=1 on every producer logs ship completion status + no-token-resolved skips at INFO (slog.Info for hearth, Python logging.info for ralph, console.info for console). Off by default so a well-configured prod stays silent; a mis-provisioned workspace surfaces immediately in Fly / operator logs.

Acceptance criteria (met)

Non-goals (deferred)

Evidence

Consequences

Superseded-by

(none)