Skip to main content

Changelog

All notable changes to Prism are documented here. Format follows Keep a Changelog. Dates are UTC. Prism started without semver-tagged releases — the project is a single-tenant per-user install with ongoing migration. As of v0.2.0 (2026-04-26) the line is tagged. Entries are still grouped by date and reference the commits + specs that landed; release tags surface above the relevant date header. Operators upgrade by git pull + rebuilding the backend image (and the optional standalone session-manager container, as of v0.2.0).
This file is updated per commit arc, not per individual commit. Entries are curated for what changed for operators, agents, or developers — not a replay of every git log line. The git log is the source of truth for per-commit detail; this changelog is the human-readable arc.

2026-05-13

Architectural

  • SPEC-113 v0.3 — Bootstrap path resolution + immutable $PRISM_ROOT model (Texi architecture, Donna PO, Frank ratified). Ring 2 methodology lives immutably at $PRISM_ROOT/templates/ (prism-base.md + ptype overlay) and is read at runtime by agents — not copied into customer projects. ./PRISM.md is no longer a customer project file; it exists only in the Prism repo itself, where $PRISM_ROOT == $PROJECT_ROOT. Customer dirs ($PROJECT_ROOT/<name>) get only the thin edge: CLAUDE.md / AGENTS.md Ring 1 replicas, .prism/, and .agent/ in contributor mode. Upgrades touch $PRISM_ROOT only; never customer dirs. See SPEC-113 for the full contract, failure-mode names, and acceptance criteria. Motivated by postmortem 13b4a879 (DPA-Crawl bootstrap cascade).
  • SPEC-112 v0.3 — Client vs Contributor scaffold boundary (Texi architecture, Donna engineering / Plan #18 integration, Frank ratified). Two install/scaffold modes. Client (default): customer install — $PROJECT_ROOT gets only CLAUDE.md / AGENTS.md Ring 1 replicas + .prism/ dotfile metadata + editor MCP config. No .agent/ tree, no roster files, no start-all launchers, no PRISM.md. Contributor (explicit opt-in via scaffold_profile='contributor'): adds the full .agent/ tree, role/persona config, launch.local, roster compatibility files, start-all launchers, and contributor ptype/profile metadata. prism_adopt and prism_create default to client unless scaffold_profile='contributor' is passed (or an existing contributor tree is explicitly accepted, or $PROJECT_ROOT == $PRISM_ROOT for the Prism repo self-reference). See SPEC-112.
  • SPEC-114 v0.1 — Sage and Clara customer-care incident personas (Texi architecture, Donna PO + engineering, Frank greenlight 16:00Z). Plan #19 v0.1 customer-care persona pair. Sage is the intake classifier — receives reporter signals and classifies as info / incident / enhancement / recommendation / unclear, routing incident-like cases to Clara. Clara (named for Clara Barton) is the incident manager — executes a five-tier init checklist (mandatory init reads → conditional reads by symptom → privacy gates → severity/scope/kind classification → output discipline). Clara is the gate that decides whether prism_phone_home fires under SPEC-115. v0.1 launches terminal-launched on server1 for observability; headless daemon mode deferred to a later phase. See SPEC-114.
  • SPEC-115 v0.1 — prism_phone_home verb + ET GitHub-issue transport (Texi architecture, Donna PO + backend, Frank greenlight 16:00Z). Adds the controlled Prism-product phone-home channel before Prism Cloud exists. New prism_phone_home verb (rejects scope='customer-internal'; requires passed redaction_report + operator_review.approved=true); ET gitapp_helper service validates the packet, applies idempotency dedupe, and transports through gh CLI to the private invite-only FrankTewksbury/Prism repository. Operator must be invited as a collaborator before phone-home can succeed (phone_home_repo_access_denied failure mode otherwise). Customer-internal incidents never leave the local environment; mixed scope phones home only the redacted Prism-product subset after operator review. v0.2 will swap gh CLI transport for a Prism-Bot GitHub App; v0.1 redaction + operator-review-before-send invariants must be preserved. See SPEC-115.

Added

  • PR #344 — BIOS template wording + resolvePid env fallback + offline-fallback gate (Donna, ships SPEC-113 v0.3). templates/CLAUDE.md + templates/AGENTS.md bumped to bios_version 2.6.0. Boot step 1 changes from Read ./PRISM.md to “Read Ring 2 methodology from $PRISM_ROOT/templates/prism-base.md + ptype overlay”. Boot step 4 (offline fallback to _ACTIVE_CONTEXT.md / _TODO.md) is gated on step 1 success — prevents DPA-Crawl-class bootstrap cascade where Codex fell back to DFW global constitution and read offline context before prism_start. mcp-node resolvePid fallback order locked: explicit pid > explicit name > PRISM_PROJECT_NAME env > PRISM_PROJECT_DIR env > structured failure. Conflict detection: throws env_project_mismatch / name_arg_mismatch_env_project when explicit args disagree with launcher-injected env — defense in depth against the identity_as_project_name class. templates/prism-application.md A6 paragraph rewritten from “PRISM.md composition writes to project root” to “Ring 2 methodology resolution reads at runtime from $PRISM_ROOT/templates/.

Fixed

  • PR #343 — coder.sh launcher: remove PRISM.md from project-root sentinels (Lafonda). Mac/POSIX launcher no longer treats PRISM.md as a project-root sentinel. Sentinel set is now .prism/ directory + AGENTS.md / CLAUDE.md Ring 1 replicas + backend project metadata. Customer projects without PRISM.md (the new normal) now resolve correctly.
  • PR #342 — coder.ps1 launcher: remove PRISM.md from project-root sentinels (Cherry). Windows-side counterpart to PR #343. Cherry’s Windows smoke (signal 913833f9) confirms coder.ps1 + BIOS 2.6.0 templates load correctly on a project root without PRISM.md.

2026-05-11

Architectural

  • Marconi — in-memory signal-mesh switch shipped (SPEC-101 v0.4, Donna engineering driver, Texi ratified, Frank operator GO). The signal-delivery hot path is now sender shim → Marconi → receiver shim, with Redis Stream + PG audit as an asynchronous fan-out off the hot path. The legacy synchronous-PG / Redis-pubsub forwarder is removed from send_signal. Live-verified on server1 PROD 2026-05-11 01:03Z via signal c8f4d0cb landing in both signal_queue and signal_queue_shadow with stage=model_acted_ack. v0.4 target: p99 < 5ms on the same-instance hot path.
    • Stage 0 — design gate (PR #279). Loss budget, recovery invariants (R1/R2/R3/R5/R6/R8), and rollback procedures locked. Frank loss-budget signoff captured: “if Redis is down, messages are delivered but never recorded at this stage of the build.”
    • Stage 1 — process-local routing + registration cache (PR #280). backend/app/marconi/{_cache,routing,registration}.py + flag-gated wiring. Flags MARCONI_ROUTING_TABLE_READS / MARCONI_REGISTRATION_TABLE_READS.
    • Stage 2 — cache lifecycle: direct write-through hooks + startup warmup (PR #282). Wires direct invalidation at every site that mutates session state (controller_service.register/deregister/handoff_master/claim_master, KeyspaceReaper, WS connect/disconnect). No pubsub subscriber anywhere.
    • Stage 3 — in-memory audit queue + Redis Stream writer (PR #293). Audit fan-out pipeline lands before the hot-path cutover so accepted signals continue producing parallel records during cutover. Flags MARCONI_AUDIT_QUEUE_WRITE / MARCONI_REDIS_STREAM_WRITER.
    • Stage 3.5 — envelope enrichment for byte-perfect shadow comparison (PR #295). Marconi-archived envelopes match legacy-PG envelopes byte-for-byte; shadow harness (PR #292) compares.
    • Stage 4 — PG archiver (PR #294 shadow, PR #299 PRIMARY flip). Consumer group on Marconi Cache Redis Stream with XREADGROUP COUNT 1 BLOCK 0; idempotent UPSERT into signal_queue / signal_trace_events / signal_obligations. No batching — the archiver optimizes for near-immediate audit persistence, not throughput batching. Flags MARCONI_PG_ARCHIVER_SHADOW / MARCONI_PG_ARCHIVER_PRIMARY.
    • Stage 5 — hot-path inversion (PR #283, flipped ON in PR #284). send_signal looks up the recipient’s WS handle in Marconi’s routing table and pushes directly. Synchronous PG INSERT removed from the hot path. Flags MARCONI_HOT_PATH_SEND / MARCONI_OBLIGATIONS_MEMORY_PRIMARY.
    • Sign-coded result envelope (PR #285, PR #286). [stage=…] banner the shim renders alongside the doorbell to make the delivery stage observable without a separate trace call. Possible stages: model_acted_ack, surface_observed, pushed, queued_offline.
    • PR #299 — flip MARCONI_PG_ARCHIVER_PRIMARY ON. Frank GO, no soak. PG archiver is the canonical writer to signal_queue / signal_trace_events / signal_obligations.

Added

  • SPEC-100 — operator-invoked signal-mesh loopback diagnostic (PR #276, Donna). prism_channel_probe and prism_channel_probe_ack verbs send a synthetic envelope from a sender shim through Marconi to a receiver shim and back, surfacing whether the sender’s WS handle is healthy, whether the receiver’s daemon is attached and forwarding, whether the surface strategy rendered the doorbell, and whether the receiver model called prism_channel_probe_ack. The loopback probe is what surfaced the legacy-path drift that motivated SPEC-101.
  • Channel-probe client-cap discovery + end-to-end probe verbs (PR #287). Sender-side capability discovery before issuing a probe; full end-to-end verb wiring through MCP shim.
  • SPEC-104 — Marconi cache-first trace/read path. Recent signal trace lookup now has a cache-first contract: prism_signal_trace defaults to Marconi Cache for real-time state, while source="pg_audit" is the explicit historical/reporting/reconciliation path. Responses expose source metadata such as source, cache_hit, pg_audit_used, cache_stream_id, and trace_state.

Changed

  • Signal trace compatibility semantics. A recent Marconi Cache miss no longer silently implies historical absence. Callers that need the old PG audit behavior must request source="pg_audit" or opt into history with include_history=true.

Fixed

  • Rejected Marconi sends are auditable. Sends to an unregistered recipient now enqueue a rejected audit envelope when Marconi Cache write-through is enabled, so misspelled-recipient attempts can be traced instead of returning IDs without a cache/audit path.
  • marconi-archiver — translate publish_path pushed_to_marconipushed_to_ws (PR #300). Marconi emitted the internal label pushed_to_marconi in the API response while older shims and the dashboard expected pushed_to_ws. The archiver now normalizes the value at the boundary so external surfaces see a stable vocabulary.
  • SPEC-101 — remove AUDIT_PENDING_MARCONI + ACK_DEFERRED_MARCONI dead branches (PR #301). Stage 5 cutover obsoleted these intermediate ack stages; cleanup landed post-deploy.
  • channel-probe — bump default ACK timeout 5s → 10s (PR #290). Accommodates per-persona daemon turn-boundary holds; was tripping false-negative probe failures on busy receivers.
  • launcher — restore --channels server:prism (PR #288). The flag name had drifted; channels-push delivery required the explicit flag.

Docs

  • SPEC-101 v0.4 marconi audit flow lock (PR #291). Operator architecture lock: Marconi switch (in-mem) → Marconi Cache (Redis Stream marconi:signals:{tenant}, MAXLEN ~7d) → PG audit. Pre-stamps Stage 5 status path so the code PR could mark it shipped without another architecture revision.
  • SPEC-101 v0.3.1 — operator architecture lock + Texi precision (PR #281). Restored §3.6 in-memory audit queue as a named Marconi internal (replacing floating ring references); reordered stage ladder so audit fan-out lands BEFORE hot-path cutover.
  • SPEC-101 Stage 0 sub-doc + v0.2 scope reduction (PR #279, updated v0.3+). Loss budget, recovery invariants, rollback. Local durable spool removed (Frank operator scope reduction).
  • SPEC-101 v0.1 — Marconi: in-memory signal mesh, zero backend on hot path (PR #277). Initial draft, Texi concept ratification.
  • Signal Mesh + Marconi docs rewrite (Desiree). /signal-mesh rewritten around the three-tier topology with 5 new mermaid diagrams (two flows, hot-path sequence, audit fan-out, surface delivery, recovery). New /marconi explainer page covering in-memory tables, cache invalidation hooks, stage ladder, full §9 counter catalog, and failure-mode summary. Cross-doc consistency sweep across index, vision, agent-surfaces, and metrics. Amendment banners on the superseded signaling spec series (SPEC-034 / 037 / 044 / 045 / 052 / 058 / 070 / 071 / 091).

Operability

  • OTel → Prometheus bridge RESTORED (PR #298, Donna postmortem 3c1f986c). /metrics endpoint now exposes the full marconi_* namespace plus the existing signals_sent_total, system_signals_emitted_total, controller_* counters. Trust Prometheus again. Memory project_otel_prometheus_bridge_dead updated to reflect restoration; PID label drift defect on PeerLeft path noted for follow-up.

2026-05-08

Added

  • Memorules — SPEC-094 Phase 2 a-d (Donna, four-PR arc). Memorules ship as the first concrete artifact of the persona-behavioral-memory layer. Persona-scoped behavioral records — what a persona has learned to do or not do across sessions — are now written, recalled, and audited through TriGraph-backed primitives instead of host-editor local files. Working names pending legal clearance.
    • Phase 2a — Memorule schema + write service (PR #235, 28 unit tests). New Cypher schema for :Memorule nodes carrying scope (persona / specialization / project / global), applicability rules, payload, source-of-record reference, and lifecycle status. Write service validates shape, deduplicates against existing recordings, and emits journal entries on first-write.
    • Phase 2b — Memorule recall + applies_to ranking (PR #236, 12 unit tests). prism_remember recall path scores Memorules by applicability — persona match > specialization match > project match > global — with deterministic tie-break.
    • Phase 2c — prism_remember kind='memorule' contract expansion (PR #237). The verb’s payload contract grows to accept memorule- specific fields (rule body, applicability scope, supersedes pointer, invariants list).
    • Phase 2d — Watson :MemoruleAudit emission (PR #238, 10 unit tests). Every recall, write, supersede, and invalidate event emits a :MemoruleAudit entity into TriGraph for governance visibility. Closes the audit-trail gap raised in Texi’s review.
  • Dewey (Recallgate) — SPEC-099 Phase 3 advisory wiring (Donna, four-PR arc). Dewey is the memory-enforcement-gate archetype that ensures recall actually fires under stuckness. Phase 3 wires the advisory layer into existing verbs so prior memorules / postmortems / decisions surface at the moment of action. Working names pending legal clearance.
    • Phase 3 — classifier + window + audit primitives (PR #239). Backend service that classifies whether a given interaction should trigger recall, computes the lookback window, and emits audit primitives.
    • Phase 3 — single-call advisory orchestrator (PR #240). Wraps classifier + recall fetch + scoring into one MCP-callable entry point.
    • Phase 3 — advisory live in prism_todo create (PR #241). When an agent creates a TODO, the orchestrator fires and surfaces relevant prior memorules / postmortems / decisions in the response.
    • Phase 3 — advisory wired into signal/ack (PR #242). Signal acknowledgement path now consults the advisory to surface contextual memory at the point of action.
  • SPEC-096 v0.2 — wrap-time pre-flight (Donna, slices 1-4). Catches ratified-but-uncommitted artifacts at prism_wrap and prism_checkpoint time so they don’t get lost in the wrap delta — the recurrence pattern that surfaced in the 2026-05-08 dirty-tree incident (RCA c3fb59b3).
    • v0.2 spec doc (PR #225) — wrap-time pre-flight check for uncommitted ratified artifacts.
    • Slice 1 — backend wrap_preflight service skeleton (PR #228, 53 unit tests). Pure backend; not yet wired into lifecycle.
    • Slice 2 — mcp-node wrap_preflight_shim helper (PR #231, 17 tests). Surface-side helper for the MCP shim.
    • Slice 3 — wire into delta endpoint + lifecycle (PR #232). The check now actually fires inside prism_wrap and prism_checkpoint.
    • Slice 4 — telemetry surface in runtime_diagnostics (PR #234). Operators can watch wrap_preflight pass/fail rates over time.
  • Miranda (Wallbreak Protocol) — method.wall-break.persistence v0.2 published (PR #222, Donna engineering author with Texi architecture approved_with_required_revisions, Candi governance acceptance). Canonical method fragment defining Prism’s stuckness- and-persistence protocol — five trigger conditions, solution-table forcing, self-critique loop, wrap-time handoff gate, recall-on-task- start, and postmortem-on-structural-walls. Phase enforcement by social contract (Phase 1); SPEC-094 advisory integration (Phase 2) and prism_stuck verb (Phase 3) deferred until adoption gaps are observed. Working names pending legal clearance.
  • Plan #003 — memory-activation implementation plan (Miranda-style) (PR #227, Donna). Sequences SPEC-094 Memorules + SPEC-099 Dewey (Recallgate) + SPEC-096 wrap-pre-flight into a coherent multi-phase execution arc.
  • Dashboard topology — host name on agent + service nodes (Porsche, PRs #217 + #218). Topology surface displays the host machine for each agent and service node. PR #218 follows up by passing the host’s HOSTNAME through to the dashboard container as PRISM_MACHINE_ID so the surface uses the same identifier as the rest of the stack.
  • Seed-input PDF archive at docs/inputs/ (PR #245). Project seed-input PDFs preserved under version control for ownership and timestamp record. Pairs with the legal/copyright initiative that shipped the visible Ntecdev / NtecLabs footer + per-page last-updated badge + /legal page (PR #223).

Fixed

  • Signal — canonical PID label on system_signals_emitted_total (PR #243). The metric was carrying drifting PID labels across cardinality boundaries; now stable. Part of the 2026-05-08 signal-quality fix arc (RCA c3fb59b3).
  • Signal — zero subscribers treated as queued, agent → session fall-back (PR #244). Zero-subscriber emits are no longer silently dropped; recipient resolution now falls back from agent identity to session id when the agent is offline. Same RCA arc as PR #243.

Documentation

  • BIOS v2.5.0 — local auto-memory deprecated (SPEC-094 Phase 1) (PR #216, Donna). templates/CLAUDE.md + templates/AGENTS.md carry the rule that Anthropic editor host auto-memory (~/.claude/projects/*/memory/, MEMORY.md, equivalent Codex / Cursor stores) is deprecated; all persistent memory operations route through Prism verbs (prism_remember, prism_journal, semantic_recall, etc.). Operator-locked rule — only the operator can re-enable, and only after SPEC-094 acceptance criteria pass.
  • SPEC-094 v0.4 + SPEC-099 v0.1 drafts (PR #229, Donna). Memorules delta + Dewey (Recallgate) first drafts.
  • SPEC-094 v0.5 + SPEC-099 v0.2 — Texi revisions applied (PR #230).
  • SPEC-099 — Texi second-pass text fix on ACK-only test case (PR #233).

2026-05-07

Added

  • SPEC-093 — Tenant → Org → Department → Project hierarchy (Donna, PR-A). Four-level identity chain replaces the prior flat tenant/project model. Every Project now carries tenant_id + org_id + department_id + pid, with FK constraints enforcing the chain at insertion. Personal-install (LAN) backwards compatibility is preserved by flat-LAN seeding: when no Department is specified, a default Department is created under the default Org under the default Tenant — existing single-user installs continue to work without operator action. PR #211 — schema + service + bootstrap + migration; PR #210 — A5/A6/A7/A8 LAN dept-hierarchy smokes + upgrade rehearsal scaffold.
  • SPEC-090 — prism_adopt verb + /projects/adopt 409-idempotent surface (PR #212, Donna). New MCP verb that registers an existing git repo into Prism without recreating PIDs. The 409-idempotent surface means re-running adopt against an already-registered project returns the existing PID rather than erroring or duplicating. Solves the bootstrap-second-machine and bootstrap-from-existing-clone cases.

Fixed

  • CLI Windows statusline platform-split (PR #215, Lafonda). Claude Code statusline now uses bin/coder.ps1 via PowerShell on Windows; the existing .sh path stays for Unix. Closes the cross-platform parity gap that surfaced during the Windows install rehearsals.

2026-05-06

Added

  • SPEC-087 cloud bring-up (Render Blueprint) — Phase 1 lands (Donna). Phase 1 OAUTH_REDIRECT_URI + containerized Neo4j (Frank §7 amendment) lands in PR #188, completing the Render bring-up cascade that started 2026-05-04 with the v0.1 spec doc and Phase 0 Blueprint. Neo4j is now containerized inside the prism-neo4j pserv (no external Neo4j dependency); the OAuth redirect URI is threaded through env vars; the Blueprint applies cleanly against a fresh Render workspace. The cascade across PRs #182–#188 — port-contract / dashboard-probe-URLs (#185), pserv dockerCommand + port bindings (#187), DATABASE_URL dialect normalization (#186), neo4j plan upgrade standard → pro_plus per the full-capability sizing rule (#191) — is documented in the research postmortem (#189).
  • SPEC-089 — Cloud Customer Onboarding + Auth (Donna). First customer-onboarding spec for the cloud surface.
    • v0.1 spec doc (PR #209). Covers the provider-agnostic identity model, the WorkOS auth provider integration, /whoami
      • /logout surfaces, and the parametric auth router design.
    • Phase 1 — provider-agnostic user identity + auth-provider setting (PR #194). Identity layer abstracted from any specific provider; auth_provider settings field selects which provider implementation to load.
    • Phase 2 (slices 2.1 + 2.3) — WorkOSProvider + parametric auth router + /whoami + /logout (PR #195). First concrete provider implementation; routes shape themselves around the configured provider.
    • Phase 2 — WorkOS auth smoke + rollback-rehearsal scaffolds (PR #196). End-to-end smoke for the WorkOS path; rollback rehearsal scaffolds for ops practice.

Fixed

  • Auth — default Org seeded per Tenant in OAuth provision_from_identity (PR #192). New Tenants no longer landed without an Org row, which later broke project creation that assumed org_id was always resolvable. The default-Org-per-Tenant invariant matches what SPEC-093 then formalized in the four-level hierarchy the next day.
  • Backend — uvicorn --proxy-headers (PR #203). request.base_url now returns https behind the Render edge proxy, fixing OAuth redirect-URI generation that was emitting http:// and breaking the WorkOS round-trip.
  • Signal — stale session resurrection loop stopped (commit fa73c35). Fixed a path where dropped sessions could be resurrected by out-of-order signal frames, creating ghost rows that confused prism_status.
  • Signal — Redis pattern subscribers no longer count for push gating (commit 37971ec). Pattern-subscriber count was inflating the push-gating decision and causing zero-real-subscriber emits to be treated as live. Fixed to only count direct (non-pattern) subscribers.
  • Smoke — recall-tier3 payload shapes (PR #199). Tier-3 recall payloads were drifting from the live shape after Phase 2 ran; smoke updated to track current contract.
  • Smoke — rollback per-key PUT, count-preservation guard, SERVICE_ID self-resolve (PR #207). Render env-var sync now patches per-key, avoiding the wipe-on-PUT class postmortem 6b351dc6; a count-preservation guard catches accidental list truncation; SERVICE_ID self-resolves from local context if not supplied.
  • Smoke — rollback poll deploy.status=='live' (PR #208). Rollback smoke now polls for actual live status instead of returning on first deploy_id reply, surfacing honest SLO. Also adds ?limit=100 to the deploy-list query so older deploys aren’t truncated.
  • Smoke — auth https assertion on redirect_uri (PR #204). Smoke now asserts https on the redirect URI, catching the reverse-proxy regression that PR #203 fixed downstream.

Documentation

  • Render bring-up cascade postmortem (PR #189, Donna research note). Documents the PR #184–#188 cascade — what the Blueprint got right, what fell over, what surfaced via Render’s native error reporting, and how the cascade was recovered. Useful reference for any future Cloud bring-up work.

2026-05-05

Added

  • SPEC-082 v0.3 — Operator-Driven Master Handoff Verbs (Donna PO, Texi reviewed v0.1 → v0.2 → v0.3). Two new MCP verbs that turn master election from “implicit first-registered wins, hope nobody preempts” into an explicit operator surface:
    • prism_master_handoff(pid, to_identity, to_session_id?) — cooperative transfer. Caller MUST be current master.
    • prism_master_claim(pid, to_identity, operator_id, operator_password, to_session_id?) — operator-authorized preempt. Caller proves authority via SPEC-038 §3.2 credentials; target identity is independent of caller. (The v0.1 contract had the claim verb promoting the caller — Texi’s first finding flipped this so the motivation actually works.)
    Target resolution is a deterministic 6-step algorithm: to_session_id wins → otherwise candidate set is active rows for the identity within the heartbeat-freshness threshold → exactly-one fresh selects → multiple fresh rows returns target_ambiguous with a candidate session_ids list → no fresh rows returns target_stale → zero rows returns target_not_registered. Both verbs return stale_master on a CAS-lost concurrent race. State updates are Redis-first per SPEC-032: the Session Manager facade flips the master slot atomically, then the Postgres controller_status rows are reconciled. prism_status reflects the new master immediately on return. No MasterChanged enum was introduced — the existing MasterPreempted signal carries the delta (see below).
  • prism_session_deregister(session_id) — surgical cleanup verb. Idempotent; releases both the Postgres controller row and the Redis hash + sessions-set entry for one session_id. The lever for scrubbing stale rows that piled up before the leak fix landed.
  • MasterPreempted payload extension. All emission paths now carry previous_master_identity, previous_master_session_id, new_master_identity, new_master_session_id, and a reason field ("preempt" or "handoff"). Operator-driven preempts also carry by_operator=<operator_id> so the previous master can attribute the flip in audit logs. Delivery contract unchanged — direct to the previous master per the existing system-signal semantics. [PR #150 b83d502]

Fixed

  • Controller-row Redis leak (postmortem f7ff9a8e, companion fix to SPEC-082). The silent-reconnect path in controller_service.register (§2.2) and the cross-machine force- preempt path (§2.4) both released the prior session’s Postgres row but left the Redis hash + sessions-set entry alive until the 90s TTL lapsed. Result: prism_status could report two active sessions for one identity for up to 90 seconds — the leak that surfaced 2026-05-04 evening and triggered the SPEC-082 motivation in the first place. Both paths now release Redis state immediately; prism_session_deregister exists for surgical cleanup of any rows that pre-date the fix. [PR #150 b83d502]
  • SPEC-082 split-flush ordering (postmortem 695d29b3, hotfix to PR #150). handoff_master and claim_master set the current master’s is_master=False and the target’s is_master=True in the same SQLAlchemy unit of work and issued a single session.flush(). Migration 016’s partial UNIQUE constraint (is_master=true AND released_at IS NULL per project) forbids two active masters at any instant — and SQLAlchemy is free to reorder the target promotion ahead of the demotion inside one flush, which raised IntegrityError after the Redis transfer_master had already succeeded. Net effect: a Redis-vs-Postgres dual-plane split where prism_status reported one identity as master while the caller-must-be-master gate inside handoff recognised the other (the partial-UNIQUE diagnosis loop, surfaced by Texi diagnosis signal 7a948a45). Fix is the same demote-flush-promote pattern register() already uses for preemption: demote the current master
    • flush, then promote the target + flush. claim_master also now demotes ALL active is_master rows in the project as defense-in-depth against zombie rows from prior outages. New test test_spec082_hotfix_split_flush.py pins the ordering by spying on session.flush(). [PR #152 0d0935a]
  • SPEC-082 test infra — fakeredis Lua + asyncio_mode. The new SPEC-082 unit tests needed fakeredis[lua] (the Lua extra is required for the CAS scripts that drive transfer_master) and asyncio_mode=auto in pytest.ini so the async fixtures pick up the right loop without per-test markers. Pinned both in requirements-dev.txt and the pytest config so the suite runs green on a clean ephemeral container. [PR #154 92424be]

2026-05-04

Added

  • Plan #10 closure — Governance Foundation at Machine Speed. Single ratification arc executed in approximately 3.5 hours end-to-end. Stat block:
    MetricValue
    Artifacts ratified6 (3 ADRs, 3 SPECs)
    PRs merged9 (#114-#122)
    Production deploys4 (avg 31.8s wall-time)
    Smoke assertions passed67
    RCAs (production incidents)0
    Concurrent agents8
    Signals exchanged80–120 (zero lost or misrouted)
    Three feature flags shipped default-off: PRISM_GOVERNANCE_RESOLVER_ENABLED, PRISM_CONSENSUS_PARALLELISM_ENABLED, PRISM_MEMORY_DOMAINS_ENABLED. Default-off invariant maintained throughout — every implementation PR proved behavioral inertness of its gated path before merge. Server1 final state: image fc4428729bf, alembic migration 034 stable, prism_status GREEN. See Plan #10 case study for the full timeline, agent roster, and lane retrospectives.
  • Plan #10 Wave 3 ratified — SPEC-080 v0.2 (Donna PO, Texi review, Candi authored). Tri-Graph Governance Recall + Capability Index. Graph-backed rule/capability lookup with source, citation, freshness, and supersession reporting. Advisory-only — never outranks Ring authority or live prism_start state. Texi’s hardest review of the session: preventing graph recall from accidentally becoming a second authority system. Resolution anchored in concrete invariants — SPEC-020 Entity vs EntityState boundaries, type/edge registration before extractor writes, live prism_start state winning over graph projection, SPEC-065 telemetry isolation. v0.1 → v0.2 fold of 12 binding amendments completed in approximately 4 minutes. SPEC-080 Phase 2 verb (prism_governance_lookup) shipped same-day in PRs #126–#131 with a default-off PRISM_GOVERNANCE_LOOKUP_ENABLED flag and a one-shot governance_backfill CLI seeding 196 :Artifact / 48 :Decision / 12 :SourceDocument+:InstructionSurface entities for PID-PGR01.
  • Plan #10 Wave 2 ratified — SPEC-078 v0.2 + SPEC-079 v0.2 (Donna PO, Texi review, Candi authored).
    • SPEC-078 v0.2 — Consensus-First Parallelism + Method Fragments. Formalizes a 3-tier consensus workflow (low / medium / high-architectural). Introduces method-fragment schema with a proof fragment shipped same-session.
    • SPEC-079 v0.2 — Memory Domain Contracts + CI Loop. Defines 12 memory domains with read/write contracts that prevent cross-domain pollution. CI loop for continuous governance improvement.
  • Governance Foundation — Plan #10 Wave 1 ratified (Donna PO). Three artifacts sealed in ADR #47 v0.2 → SPEC-077 v0.2 → ADR #48 v0.2 order:
    • ADR #47 v0.2 — Governance Layer Precedence + Override Semantics (supersedes ADR #45 v0.1). Establishes the 5-layer narrower-wins model (global / tenant / org / project / user-session-runtime) with file-level mandatory: true frontmatter as the only override gate. Mandatory canonical org guardrails cannot be bypassed by a narrower layer.
    • SPEC-077 v0.2 — Canonical Boot + Governance Resolution. Boot model (static BIOS → prism_start → governance block); 5-state per-layer classification (found_nonempty / found_empty_stub / missing / skipped / invalid); PRISM_GOVERNANCE_RESOLVER_ENABLED feature flag default-OFF for safe rollout.
    • ADR #48 v0.2 — Persona / Identity / Specialization Field Model (supersedes ADR #46 v0.1). 5-field model (persona / identity / specialization / assignment / style); specialization is routing/memory/skill authority, not governance authority.
  • Launcher governance-var forwarding (Lafonda, PR #114 6f70b43). bin/coder.sh sources $HOME/.prism/env early (set -a / set +a wrap so vars auto-export to children) and forwards 8 governance vars (PRISM_GOVERNANCE_LAYOUT, PRISM_GOVERNANCE_ROOT, PRISM_TENANT_SLUG, PRISM_ORG_SLUG, PRISM_PROJECT_SLUG, PRISM_CONFIG_PROFILE, PROJECT_ROOT, PRISM_ROOT) to both Codex agent invocations + the Codex app-server background launch. Defensive [ -f ] test makes the source line a no-op when the env file doesn’t exist yet, so the launcher patch is independently shippable without the install-verb work.
  • Install-lane governance helpers (Lafonda, PR #115 de33529). New module tree at mcp-node/src/ops/governance/: slugValidator.ts ([a-z0-9-]+ validation, refuses silent normalization per Texi review), envBlockWriter.ts (atomic write to $HOME/.prism/env preserving operator extras + the operator-set PRISM_GOVERNANCE_RESOLVER_ENABLED toggle on re-run), templateCopier.ts (PRISM_GLOBAL.md template-copy per SPEC-077 §6, schema-version-compatible only). Install verbs do not auto-call runGovernanceSetup() yet — held for the post-ratification activation flip.
  • Runtime governance resolver + prism_start extension (Donna, PR #116 1dcf5f3). New module mcp-node/src/ops/governance/resolver.ts: resolveGovernance() reads $HOME/.prism/env, classifies all 4 file-bearing layers per the SPEC-077 §4 5-state taxonomy, surfaces conflicts (invalid_frontmatter / dual_org_sources / layout_collision / schema_version_mismatch / layer_mismatch / slug_mismatch), reports mandatory guardrails, and composes the gov:N/M summary per §8. ORG dual-source resolution per ADR #47 §4: narrower-wins by default; canonical wins only when broader is mandatory: true. Default-OFF — when PRISM_GOVERNANCE_RESOLVER_ENABLED is not exactly "true", the resolver returns null and the prism_start response shape exactly matches pre-SPEC-077 (no governance field). Resolver failures are non-fatal in lifecycle — caught + logged, treated as flag-off so bootstrap never crashes on a malformed env file. 27/27 smoke assertions pass.
  • BIOS templates bumped to bios_version 2.4.0 (Donna, PR #116). templates/CLAUDE.md + templates/AGENTS.md replace the old “Ring precedence: ORG.md > PRISM.md > this file” line with the SPEC-077 5-layer narrower-wins model + mandatory: true override semantics. Behavior unchanged when the resolver flag is off. Local CLAUDE.md / AGENTS.md replicas (and the Ring 2 PRISM.md composed file) refresh on next prism_sync_bios and re-compose.

Documentation

  • docs/architecture/governance-precedence.md (new, Desiree). Agent-facing reference for the 5-layer model: per-layer table, narrower-wins rule, mandatory: true override gate, ORG dual-source resolution, layout disambiguation, and the prism_start governance block shape. Cross-references SPEC-077 v0.2 + ADR #47 v0.2 + ADR #48 v0.2 + the install-lane plan.
  • docs/research/instruction-surface-inventory-2026-05-04.md v0.1 → v0.2 (Desiree). Wave 1 ratification flip on the pending-state entries: SPEC-077 / ADR #47 / ADR #48 marked ratified; CLAUDE.md / AGENTS.md replicas note the 2.4.0 SOR vs 2.3.0 local-replica drift expected until next prism_sync_bios; coder launcher entries flipped from “PR #114 in flight” to “PR #114 merged”; templates/prism-base.md reference bumped to v1.3.0.
  • templates/prism-base.md v1.2.0 → v1.3.0 (Desiree). Replaces the 3-tier ring-precedence callout with the same 5-layer narrower-wins + mandatory: true text the BIOS templates carry at 2.4.0. PRISM.md replicas re-compose to pick up the new text; this repo’s PRISM.md was hand-recomposed in the same PR so the project’s own instructions match its own BIOS.

2026-05-03

Added

  • Hybrid RAG fourth leg — temporal recency-decay (Donna, Plan #8 Phase 5). semantic_recall fusion is now four-leg: vector + lexical + graph + temporal. Temporal scores each candidate as exp(-age_days / half_life) with half_life=180d and re-weights the existing fused candidate set rather than introducing new candidates — result-set composition is unchanged but recent-but-relevant memories rank ahead of stale ones at the same semantic score. temporal_score is exposed on each RecallHit and persisted into memory_recall_events.rrf_weights.legs.temporal. Closes the SPEC-059 §3.2 deferral. [PR #103 99561fb, follow-up 71a43d1]
  • Graph leg traverses the tri-graph for entity-anchored queries (Donna, Plan #8 Phase 4). When the query mentions SPEC-N or ADR-N tokens, the graph leg now 1-hop bidirectional-walks all Semantic-layer typed edges (:REFERENCES, :IMPLEMENTS, :EXTENDS, :RELATES_TO, :SUPERSEDES, :DEPENDS_ON, :SPECIFIES, :FORMALIZES, :RESOLVES, :DOCUMENTS) and sums per-target edge counts. Queries without entity anchors fall back to the legacy :MENTIONS co-occurrence path, so existing callers see no behavior change. Closes the TRIGRAPH.md §8 Phase 5 deferral. [PR #102 6771f46]
  • Granular semantic edge taxonomy (Donna, Plan #8 Phase 3). The spec / ADR / plan / retro / journal extractor now promotes section headings into typed edges instead of collapsing them all into :REFERENCES: ## Implements:IMPLEMENTS, ## Extends:EXTENDS, ## Supersedes:SUPERSEDES, ## Related / ## See also / ## Complements / ## Informs:RELATES_TO. The :CAN_REFERENCE whitelist on Canonical type pairs gates every subtype the same way it gates :REFERENCES. Existing scripts/backfill_spec_059_references.py is idempotent and re-runs the extractor across the full corpus. [PR #101 c9bb9b4]
  • Recent postmortems surface on bootstrap (Donna, Plan #8 Phase 2). prism_status (consumed by prism_start) now returns up to 5 most-recent unresolved postmortems for the calling persona, sorted captured_at DESC. Identity resolves from the session record first, falls back to the X-Prism-Identity header when no session exists. Implements SPEC-063 §3.5; raises failure-relevant memory salience before the agent has to remember to recall, addressing the filed-but-not-recalled failure mode that drove the 2026-05-01 branch-confusion recurrence. [PR #100 ea752f4, follow-up 37dd978]
  • rrf_weights telemetry shape populated + X-Prism-Identity client header (Donna, Plan #8 Phase 1). memory_recall_events.rrf_weights is no longer None — it carries {k, top_n, legs.{vec,lex,graph,temporal}.{top_n_count, mean_score, fetched, ...}} per recall, capturing observed leg contribution rather than static equal weights. The Node MCP shim now sends X-Prism-Identity on outbound HTTP calls so the backend can attribute every recall to a persona; expected to drive captured_via='unknown' rate from effectively 100% to ~5%. Unblocks the SPEC-059 §3.4 dashboard panels that were rendering empty. [PR #99 eb936d5]
  • Dashboard /memory page — per-leg lift, per-agent recall, postmortem-rate trend (Porsche, PR #104). Three panels behind a new “Memory” sidebar entry between Telemetry and Daemons. Per-leg lift is a stacked-area read of memory_recall_events.rrf_weights.legs.{vec,lex,graph,temporal}.top_n_count with legImplemented data-driven so the temporal series only appears once a non-zero contribution exists in the bucketed window. Recall-by-agent is per-captured_via stacked area with a separate unknown bucket. Postmortem trend is weekly stacked filings per persona with an unresolved-now overlay. [PR #104 7c12b1d]
  • Dashboard /memory page — Phase 3-5 panels (Porsche, PR #105). Second wave: a Graph Edge Inventory panel reads Neo4j directly (12-hour stacked-area buckets per edge type, plus current per-type totals in the legend), tracking the 11-edge taxonomy from PR #101 including the backfill spike as honest signal. The per-leg lift chart gains a count↔mean_score toggle: score view is a non-stacked line overlay (scores are not additive across legs) so the Phase 4 graph-leg lift over :MENTIONS becomes visible as the graph line crosses above lex. [PR #105 b12fb99]
  • Dashboard /memory page — cross-cycle KPI summary panel (Porsche, PR #106, Plan #8 Phase 6). Top-of-page panel cross-tabs each Plan #8 cycle’s locked hypothesis text against live measurements with an explicit verdict tag — Cycle 1 (granular edge backfill) REJECTED with the corpus-discipline gap captured; Cycle 2 (graph-leg rewire) and Cycle 3 (temporal-score leg) MECHANISM VALIDATED with live rrf_weights.legs.{graph,temporal}.mean_score reads. The retrospective probe-set landed the same day (5a8c739, docs/research/probe-set-2026-05-03.md) upgrades Cycle 2’s verdict to CONFIRMED on 4/4 query classes. Plan #8 final state captured in docs/research/plan-9-closure-summary-2026-05-03.md; tag plan-8-truly-complete. [PR #106 59aa11b]

Notes

The five memory-correction PRs (#99–#103) shipped as a single bundled batch on 2026-05-03 evening rather than as five independent cycles. The pre-registered single-variable-per-cycle protocol from the closed-loop validation method was deliberately collapsed for this correction push; treat phases 1–5 as one super-cycle with a lumped pre/post measurement window beginning at the latest merge timestamp. Per-cycle records live on research/memory-system-improvements under docs/research/cycles/cycle_0{1,2,3,4}_preregistration.md and are re-labelled as retroactive validation records (not pre-registered hypotheses) per the Texi architecture note 3b594f61. Forward-going, any memory-system retrieval/scoring change requires a frozen probe-set as a precondition — fixed query text, expected targets, baseline snapshot, scoring rule, threshold rule, no post-hoc query editing.

2026-04-28

Added

  • prism_deploy MCP verb — SPEC-051 Phase 1 (Donna). Replaces bin/prism-deploy-server1.sh (the highest-traffic agent script in the repo by token volume) with a structured-return MCP verb. Returns parsed JSON instead of dumping ~150–300 lines of rsync + docker-compose + cypher-shell scrollback into agent transcripts per call. New mcp/deploy.py with a deploy(target, mode) dispatcher + deploy_server1 implementation; single ssh ControlMaster socket shared across the rsync, build, restart, health, and verify stages so the ~200ms handshake is paid once per verb call instead of per stage. bin/prism-deploy-server1.sh shrinks from 90 lines to a ~50-line thin wrapper invoking the verb (retained for non-agent callers — CI, ad-hoc operator runs). Hardcoded API key removed per the no-hardcoded-machine-values rule; verb sources from ~/.prism/credentials.personal.json or env. mcp/smoke_spec051_deploy.py contract smoke against live server1 verifies {ok:true, verify:{alembic:023, trigraph_types:14, trigraph_edges:37, type_count:14, api_health:true}, duration_s:7.69}. Tracked by SPEC-051 + ADR-28. [commit b840d85, PR #7]
  • prism_backup + prism_clone_from MCP verbs — SPEC-051 Phase 2 (Donna). Two more bash scripts ported per ADR-28 (TTY-as-the-line), plus a shared mcp/ssh_session.py helper extracted out of mcp/deploy.py so every server-touching verb amortizes the ~200ms SSH ControlMaster handshake. mcp/backup.py captures Prism creds + every editor MCP config known to host_config (cross-platform via PRISM_APP_SUPPORT) + Claude Code settings + shell rc files; writes MANIFEST.txt in the legacy rel|size format so bin/prism-restore.sh keeps working unchanged. mcp/clone_from.py orchestrates ssh + pg_dump → local docker compose up postgres → drop+recreate → docker cp + pg_restore → full stack up → verify (alembic, live vs. retired specs). Both registered as non-bootstrap-gated host-side operator verbs, async via asyncio.to_thread. bin/prism-backup.sh shrinks 95 → 30 lines; scripts/clone-server1-to-local.sh shrinks 82 → 20 lines. Backup smoke verified end-to-end (7 files captured, 2 skipped, manifest matches prism-restore.sh reader); clone smoke is preflight-only by default and gated behind PRISM_CLONE_RUN=1 for the destructive full-cycle test (drops the local prism DB). prism_deploy re-verified post-refactor (alembic 023, 14 types, 37 edges, 7.21s). Tracked by SPEC-051 + ADR-28. [commit d5ad49e, PR #9]

2026-04-27

Added

  • Signal mesh architecture page (Desiree). New /signal-mesh doc consolidates the signal subsystem into a single architecture page: lifecycle, identity-targeted addressing, three planes (verb HTTP / data WebSocket / liveness HTTP), four delivery strategies (ChannelsPush, AppServerInject, Piggyback, startup-drain), the doorbell pattern, durability backstop on signal_queue, system signals (PeerJoined/Left/MasterPreempted), and the sender contract. Cross-refs SPEC-034/037/044/045/048 plus the Multi-Prism Controller and Agent Surfaces pages. Wired into the Architecture nav and the Project footer in docs.json. [commit 637d786]
  • install-lan doc — refreshed for SPEC-045 unified WebSocket data plane (Desiree). Diagram edge label updated, Troubleshooting row on real-time signal delivery rewritten, and the stale “What LAN install does NOT cover” bullet about Redis exposure removed — real-time signal push works on LAN out of the box now via the authenticated WebSocket fan-out, so the old caveat misled readers. [commit 637d786]

Changed

  • bin/coder launchers — Codex bootstrap prompt (Donna). Mirrors the auto-bootstrap pattern shipped earlier for Claude Code. Both bin/coder.sh and bin/coder.ps1 now append a positional bootstrap prompt on the codex invocation that instructs Codex to (1) call prism_start(name=<project>, identity=<persona>), (2) display the Prism status card as the first line of the first substantive response, (3) fall back to the documented “MCP unavailable — operating in offline cache mode” string on bootstrap failure, and (4) summarise active context before proceeding. Closes the gap where Codex sessions launched via coder started cold without hitting prism_start. The Claude Code launchers got the equivalent prompt in PR #5 (still open at time of writing). [commit 42aeabe, PR #3]

Fixed

  • ADR-27 Phase 1+2 — SM facade is honestly Redis-fronted (Donna). Surfaced after a server1 restart on 2026-04-27 demoted Donna’s stale registration in Redis and promoted Candi (mini1, registered 70s earlier). prism_status (Postgres-backed) reported Donna as master; prism_whois (Redis-backed) reported Candi. Two services held competing copies of the same runtime fact. ADR-27 ratifies the invariants — (1) the session manager owns all realtime state and reads come from Redis on the hot path, never Postgres; (2) storage backends stay hidden behind their owning service, with no cross-service Redis-client imports or controller_registrations reads for runtime data. Phase 1 (164fd30): controller_service.get_prism_status switches from _active_master / _active_peers (Postgres) to SessionStore.get_active_sessions(...) (Redis); last_heartbeat populated from registered_at as a temporary proxy. Phase 2 (0b88641): SessionRecord gains last_seen_at, last_verb_at, and a freshness_at convenience property; refresh_ttl HSETs last_seen_at on every heartbeat; new stamp_verb_at and get_tenant_sessions(tenant_id) SCAN aggregator; controller_service.stamp_engagement dual-writes Redis (hot path) and Postgres (audit) with non-fatal failure on either side; signal_service._resolve_identity_to_session drops its direct ControllerRegistration tiebreak query and orders entirely from SessionRecord; persona_service.whois drops the Postgres GROUP BY for tenant-wide last_heartbeat aggregation in favor of SessionStore.get_tenant_sessions(...); session_manager/api.py rewritten to be honestly Redis-fronted (was a sham reading ControllerRegistration directly). [commits 164fd30, 0b88641, PR #1]
  • SPEC-049 §3.4 — manager_stream keeps Starlette’s headers cache in sync with injected session_id (Donna). Cursor Bugbot flagged this on PR #1 (high severity). The previous implementation read websocket.headers.raw, which triggered Starlette’s cached_property on WebSocket.headers and materialised a Headers snapshot from the current scope["headers"]. The subsequent mutation of scope["headers"] to inject x-prism-session-id left the cache stale, so the legacy handler reading websocket.headers[...] saw the pre-injection value (missing) and closed the WebSocket on auth failure. Net effect: /api/v1/sm/stream/{session_id} (the SPEC-049 §3.4 documented happy path used by mcp/session_stream.py) silently dropped the URL-form session_id. Symptoms were masked because signals fell through to the SPEC-044 piggyback fallback, but the WS plane wasn’t actually delivering live. Fix: read websocket.scope["headers"] directly without ever touching .headers.raw, then defensively clear the cached_property slot so the legacy handler rebuilds from the mutated scope. No upstream framework behavior monkeypatched. [commit 1d0a6f4, PR #2]

v0.2.0 — 2026-04-26

First semver-tagged Prism release. Tag v0.2.0 was pushed at commit b0d1584 on feat/spec-045-unified-stream. Backend + the new standalone session-manager container both report version 0.2.0. v0.2.0 is non-breaking for running clients — legacy /api/v1/controller/* and /api/v1/personas/* paths still respond. The breaking 410-Gone flip is a follow-up release after the agent fleet has restarted onto the SPEC-049 /api/v1/sm/* paths. Headline specs shipping in this release: SPEC-049 (Identity & Session Manager service), SPEC-045 (Unified WS stream), SPEC-046 (agent surface adapters), SPEC-040 (hd_exec handoff pickup), SPEC-042 (WIP type vocabulary), SPEC-043 (start-delta symmetry), SPEC-038 v0.2 (collision policy + operator-gated force), SPEC-044 (channel push idle-wake fix), SPEC-037/045 §5.1 (server-side delivered_at).

Added

  • SPEC-049 — Identity & Session Manager Service (Donna’s design + implementation). Single-writer service that owns all identity, registration, election, and routing state under one process and one HTTP namespace, replacing the scattered /controller/* + /personas/* surface. New backend module backend/session_manager/ ships in seven phases: (1a) module skeleton, (1b) session endpoints, (1c) personas endpoints + identity canonicalization, (1d) election endpoints (read-only in Phase 1), (1f) Redis-keyspace-event reaper retiring the old ControllerSweepWorker, (1g) WebSocket streaming under the manager + service.delegate cutover, (2) MCP client cuts over to /sm/* endpoints, (3) grep-guard + cleanup of legacy import surface, (4) standalone session-manager container that can run separately from the API gateway. Canonical paths now live under /api/v1/sm/sessions, /api/v1/sm/personas, /api/v1/sm/elections, /api/v1/sm/ws. The legacy /controller/* and /personas/* paths still respond in v0.2.0 for fleet-wide rolling restart compatibility; the 410-Gone flip will land in a follow-up release once all live agents have restarted onto the new MCP client. [commits eb8e1ee..45b0a0b, release b0d1584]
  • SPEC-040 — hd_exec handoff pickup verb (Donna’s implementation). Symmetric to prism_wrap. After a session has wrapped (with next_actions recorded on the wrap delta), a successor agent can call hd_exec to pick up where the predecessor left off — the verb is a thin wrapper over _prism_start_impl with delta_kind="pickup" and predecessor metadata threaded through. Closes a two-year-old vapor entry in the lifecycle plan and pairs with SPEC-043’s start-delta symmetry to make handoffs first-class events in the delta log. [commit e41528a]
  • SPEC-042 — WIP Type Vocabulary (Donna’s implementation). Extensible, table-driven taxonomy for in-flight work concepts that predate a formal SPEC: concept, research, spec, plan, general. New table wip_types (alembic migration 023), new MCP verb prism_wip_types to inspect the live vocabulary, and prism_wip writes now type-tag entries against this table. Catalog is data-driven so adding a new WIP kind no longer requires a code change. [commit 3bfca51]
  • SPEC-043 — Session-Start Delta Symmetry (Donna’s implementation). prism_start now emits a delta_kind="start" lifecycle delta on every bootstrap, mirroring the wrap delta on session close. Pairs with SPEC-040’s pickup deltas to give the delta stream a complete three-event lifecycle (start → checkpoint(s) → wrap | pickup). Visible in prism_start.recent_deltas payload and via the WS event stream. [commit 1d4ac66]
  • SPEC-045 — Unified Session+Coordination Stream (Lola’s design, Donna’s implementation). Closes the SPEC-044 LAN-reachability gap surfaced in live test: MCP-side Redis subscriber was unreachable from LAN clients because Redis :6379 is docker-internal on server1. SPEC-045 consolidates the live data plane onto an authenticated WebSocket served by the existing FastAPI port (/api/v1/session/ws), with Bearer + X-Prism-Session-Id + X-Prism-Identity + X-Prism-Project-Id headers and server-side Redis pubsub fan-out to JSON envelopes. MCP gains mcp/session_stream.py (daemon thread
    • own asyncio loop, websockets>=12.0, exponential backoff 1s→30s ±20% jitter, Last-Event-Id resume) and the SPEC-034 §8 Redis subscriber is deleted. Same singleton API kept the channel_bridge + ChannelsPushStrategy callers untouched. Heartbeat stays out-of-band on its own HTTP POST endpoint per the telecom rule (D1). gRPC CoordinationStream service kept in place during rollout (D3); LAN-facing role retired, full retirement tracked as TODO #97. Single auth boundary, single LAN port. Live e2e (cross-identity Lola→Donna) verified ~300ms end-to-end. [commit 2e1a344]
  • SPEC-046 — Agent surface adapters (Donna’s design + implementation). Generalizes mcp/strategies/ into a per-surface adapter layer that owns bootstrap + wrap hooks alongside signal-strategy selection. New mcp/agent_surfaces/ package: AgentSurface Protocol + BootstrapContext / WrapContext dataclasses + SURFACE_REGISTRY + memoized get_surface() driven by PRISM_AGENT_SURFACE. Phase 1 ships ClaudeCodeSurface (owns channel_bridge.capture_session_lazy
    • reset_coalescing on bootstrap, reset_all on wrap); Phase 2 ships best-effort ClaudeDesktopSurface, CursorSurface, CodexSurface, and OtherSurface fallback. prism_start / prism_wrap no longer reference channel_bridge by name — surface-specific lifecycle hooks are the only caller. CodexSurface carries explicit polish-queue comments naming Texi as designated owner; placeholder fields flag where SPEC-035 App Server inject hooks land. smoke_spec046_agent_surfaces.py covers 18 checks across dispatch + Protocol conformance + bootstrap/wrap idempotency for every surface. SPEC-044 + SPEC-045 smokes re-run green. [commit 1b7859a]
  • SPEC-038 v0.2 — Identity-collision policy + operator-gated force preempt (Donna’s implementation). Three branches now formally distinguished in controller_service.register. (1) Same-machine reconnect (§2.2) — silent release-and-replace on terminal restart inside the 90s SessionStore TTL, release_reason='reconnect'; closes the UX gap where /exit + relaunch as the same identity got 409’d. (2) Cross-machine identity_conflict (§2.3) — structured 409 augmented with same_machine: false so the caller can tell honest collision from spoof. (3) Operator-gated force preempt (§2.4) — force=true now requires operator_id + operator_password matching the tenant’s bcrypt hash; missing or invalid creds → HTTP 403 force_denied. Closes the v0.1 gap where any agent with the API key could silently preempt any session. Migration 022 adds controller_registrations.process_pid (PID fingerprint), tenants.force_operator_id + force_password_hash (bcrypt). New router POST /api/v1/operator/force-credentials; bcrypt-hash on receipt, plaintext never logged. New MCP verb prism_set_force_credentials (bootstrap-skipped). All 6 branches verified live against deployed server1. [commit 4652772]
  • SPEC-044 idle-wake fix (Donna). prism_start now calls channel_bridge.capture_session_lazy() before returning, so a freshly-bootstrapped idle agent has the bridge ready when a signal arrives. Previously capture only fired on the next non-lifecycle verb (SPEC-041 skip), which left the doorbell silent for the exact “wake idle agent” use case SPEC-044 was written for. channel_bridge.push_doorbell now returns a status string ("rang" | "coalesced" | "uncaptured" | "loop-closed") instead of bool — the prior bool collapsed uncaptured into coalesced and hid this bug for a release cycle. [commit 4652772]

Changed

  • bin/coder launchers — Codex CLI 0.125.0 mapping. The Codex agent path no longer invokes the stale codex start subcommand; it launches codex directly with -C <project_dir> and explicit flag mapping. Prism autonomy → Codex --sandbox (safe-writeworkspace-write, full-localworkspace-write, readread-only); Prism mode → Codex --ask-for-approval (interactiveon-request, autonomousnever); -god--dangerously-bypass-approvals-and-sandbox and overrides the normal mapping. Launcher also exports PRISM_AGENT_SURFACE via agentsurface mapping (claudeclaude_code, codexcodex, cursorcursor) so Codex sessions stop registering as other. New bin/smoke_coder_codex.sh covers interactive/read, autonomous/safe-write, autonomous/full-local, and -god override. PowerShell port matches line-for-line; pwsh runtime verification pending. -mode and -autonomy are real CLI controls for Codex (versus Prism env metadata only for Claude Code, where -god adds --dangerously-skip-permissions). [commit 56a9a17]

Fixed

  • SPEC-037 / SPEC-045 §5.1 — server-side delivered_at on WS push (Donna). The signal envelope’s delivered_at is now stamped at the WebSocket fan-out layer, not at the recipient client. Closes a reliability gap where a recipient that crashed mid-receive could re-deliver a signal that the sender already saw acknowledged. Pairs with the SPEC-037 piggyback drain to keep the “no signal lost, no signal duplicated” floor honest under WS reconnect. [commit eedee95]
  • prism_whois — case-insensitive identity join + is_master propagation. prism_whois no longer misses registrations whose agent_identity differs only in case from the query, and the is_master flag is now correctly populated from the live election table on the response. Both gaps had been masked by the long-running Donna/Lola single-master assumption; surfaced as the multi-agent fan-out on 2026-04-26 brought Candi, Texi, Desiree, and Lafonda online. [commit 2971f01]

2026-04-26 — post-v0.2.0 tag

Same-day commits that landed after the v0.2.0 tag at b0d1584 (16:15 EDT). Operators pinned to the exact tag will not see these; operators tracking main will.

Added

  • SPEC-048 (draft) — Codex app-server signal injection (Texi). Adds a fallback-safe CodexAppServerInject strategy plus the launcher plumbing it needs: bin/coder.sh and bin/coder.ps1 gain -codex-app-server, -codex-app-server-url, and -codex-app-server-port flags (modes off | local | auto, default auto) which export PRISM_CODEX_APP_SERVER_* env into the child Codex process. The injection strategy is best-effort — if the local Codex app-server isn’t reachable, signals fall back to the SPEC-037 piggyback path rather than failing loudly. CodexSurface selects this strategy when the env signals an active app-server. Smoke at mcp/smoke_spec048_codex_app_server.py. Spec stays at status draft pending Frank’s ratification of Texi’s design. [commit edd1d67]

Fixed

  • Stream envelope — null-safe optional wire fields. wrap_signal_envelope now coerces signal_type and signal_id to strings via a _string_or(default, value) helper before placing them in the SPEC-045 §4.2 envelope, so WebSocket clients never see null where the contract promises a subtype/event_id string. Defaults: subtype="Unknown", event_id="". Closes a wire-shape gap that surfaced when raw signal_queue rows occasionally carried null signal_type after legacy backfill. [commit 2f48aa7]

2026-04-25

Added

  • SPEC-044 — Channel-Based Signal Push (Donna’s implementation). Wires the Prism MCP server as a Claude Code Channel so signal notifications push into idle sessions instead of waiting for the next verb response. New _PrismFastMCP subclass advertises the experimental claude/channel capability and captures the main MCP loop for cross-thread notification scheduling. mcp/channel_bridge.py lets the Redis subscriber thread fire notifications/claude/channel doorbells onto the main loop with one-outstanding coalescing per drain cycle. ChannelsPushStrategy.deliver buffers AND rings the doorbell — the piggyback path stays intact for the next-verb-call path. Launchers gain --dangerously-load-development-channels server:prism. mcp pinned to ~=1.27.0 because the FastMCP override touches private API. Three smoke files, 11 guards, all green. [commit 0f9f937]
  • SPEC-037 — Backend-side signal piggyback (Donna). Eliminates the silent-loss class where a signal landed in signal_queue while the recipient’s session existed but was idle. Server now drains pending signals onto the response of every bootstrapped verb the recipient calls, marking delivered_at + delivery_method='piggyback' in the same transaction. Closes the SPEC-034 honesty gap where the bridge reported delivered=true for queued-but-undelivered signals. [commit bd2367d]
  • SPEC-039 — NYI runtime contract (Donna). mcp/nyi.py adds the canonical not_yet_implemented payload + @prism_nyi decorator + audit_nyi_markers() scanner. prism_audit now surfaces every PRISM-NYI marker in source plus unmarked references in constitution markdown (Rings 1-2.5 only). Hybrid failure mode: tracked stubs are advisory, untracked stubs and constitution drift flip exit_status to fail. 20 unit tests. [commit f40d3a0]
  • SPEC-041 + ADR-25 — Lifecycle / messaging separation (Donna). prism_start no longer drains pending signals — the legacy startup-drain block is gone. New _LIFECYCLE_VERBS set in mcp/server.py special-cases prism_start / prism_checkpoint / prism_wrap inside require_bootstrap so they skip the SPEC-037 piggyback drain too. prism_wrap docstring now points callers at prism_signals_pending for last-chance delivery. Single responsibility, race correctness, hd_exec composition. ADR-25 captures the principle. Supersedes the 2026-04-24 changelog claim that signals “drain on the target’s next prism_start when offline” — delivery is now via prism_signals_pending or piggyback on any non-lifecycle verb. [commit f40d3a0]

Changed

  • ADR-26 v2 — Auto-declare on first use (Donna, replacing v1 strict-reject from the same day). Live testing of strict-mode surfaced the wrong default for a solo-operator AI-FIRST workflow: the elicitation picker forced human-in-the-loop friction every time a fresh identity launched. Frank’s design intent: typed identity not in registry → auto-declare and proceed. prism_start on whois miss for non-Bot identity now calls create_persona with focus="(auto-declared on first launch)" and surface_hint from PRISM_AGENT_SURFACE, then continues bootstrap. Elicitation picker preserved as a fallback only when auto-declare itself fails (rare: backend race or validation collision). Migration is implicit — orphans self-heal on relaunch. [commit c863227]
    ADR number 26 was later filled in Postgres by an unrelated Diagnostic Tool Library decision (filed 2026-04-27, see /adrs/adr-026-diagnostic-tool-library-container-side-python-host-side-node), so the published ADR-26 page is no longer the auto-declare design. The auto-declare design lives canonically in the memory namespace per Frank’s standing field-collapse workaround — retrievable via semantic_recall(query="persona auto-declare on first use"). Commit c863227 remains the implementation reference.

Fixed

  • prism_wrap restored as MCP tool. The SPEC-031 refactor extracted _do_hygiene out of prism_wrap but left @mcp.tool()
    • @require_bootstrap on the inner helper. Net effect: _do_hygiene was exposed as mcp__prism___do_hygiene (private API leak) and prism_wrap was unreachable from MCP — operators could not cleanly close a session, only checkpoint. Decorators swapped back; _do_hygiene is internal-only, called by both prism_wrap and prism_checkpoint which gate bootstrap at the outer layer. [commit a14f586]
  • SPEC-036 v0.2 — Scaffold persona-leak fix (Lola’s design, Donna’s implementation). CLAUDE.md boot reads PRISM.md (step 1) before prism_start (step 3), so a persona: <name> line in composed frontmatter was being absorbed as the agent’s identity, racing with runtime identity resolution. Two failure modes confirmed in the field: offline mode (Lofanda on Candi’s Windows install) adopted Lola for the entire session; online mode (Donna on mini2) greeted as Lola before self-correcting at step 3. Scaffolder now strips persona: from composed frontmatter and _ACTIVE_CONTEXT.md. [commits 5bbb138, c439ebf]

2026-04-24

Added

  • SPEC-034 — Agent-to-Agent Signal Delivery (Lola’s design, Donna’s implementation). Redis pub/sub transport + pluggable per-surface delivery strategies let Prism agents send structured signals (ReviewRequested, ReviewCompleted, TaskAssigned, Acknowledgment, StatusUpdate) to named peers without human relay. Signals persist in signal_queue (durability backstop) and drain on the target’s next bootstrapped verb when offline. Broadcast support via to="*". Full §3 Lola↔Donna round-trip verified end-to-end by mcp/smoke_spec034_signal.py. Deployed to server1. [commits f1c536f, d8abf06, 186efec, 8d9d0e3]
  • SPEC-035 — Agent engagement signal + routing preference (Donna). Active sessions advertise an engagement state on the controller registration (active vs idle), and signal_service.send now prefers an active peer over idle when the same identity has multiple registrations. Eliminates the racing-Donnas case where a signal addressed to “Donna” could land on whichever session registered last instead of the one currently doing work. [commit 11537f7]
  • SPEC-031 — prism_checkpoint verb + enriched prism_status payload (Lola’s design, Donna’s implementation). prism_checkpoint runs all prism_wrap hygiene (delta flush, memory triggers, last_wrapped_* write-back) without deregistering the caller from the controller — so agents can “save the game” between discrete work units without re-bootstrapping. prism_status response reshaped to SPEC-031 §4.2: project block, session block, agents flat list, top-N pending TODOs, pending_nudges stub (ready for SPEC-029), pre-formatted status_line matching the SPEC-021 Ring-0 format. bios_version bumped 2.1.0 → 2.2.0 with checkpoint-vs-wrap guidance in CLAUDE.md / AGENTS.md. [commits 2a1bc33, 9aad2d5]
  • Persona registry + runtime identity (Lola’s design). Tenant-scoped personas table (alembic 020) records persistent agent identities decoupled from editor surfaces — surface stays baked (physical), identity is runtime-assigned. Two MCP verbs: prism_persona_create (bootstrap-gated) and prism_whois (NOT bootstrap-gated — needed to answer the “who should I be?” question before bootstrap completes). Redis cache at prism:personas:{tenant_id} with Postgres preload on backend lifespan; no TTL, write-through invalidation. bin/coder --as <identity> launcher flag exports PRISM_AGENT_IDENTITY to the child editor process without touching editor config. prism_start gained an identity arg and an identity-elicitation branch — when the env var is unset, start returns {requires_elicitation: true, elicitation_kind: "identity", personas: [...]} carrying the whois payload so the agent can prompt the operator and re-enter with the chosen identity. install/install.py no longer bakes identity defaults into the MCP env block. [commit 09e53ae]
  • MCP heartbeat auto-reregister on 410 Gone — session-drift recovery. Previously, a stale-swept session (controller_sweep_worker marking released_at=now after ≥10min of no verb calls) would silently drop the agent off the routing table; the heartbeat loop would log the 410 and stop. Now the heartbeat mints a fresh session_id, calls POST /controller/register with the same identity/surface/machine_id, and fires a caller-supplied callback that updates the MCP’s _SESSION_IDS and the HTTP client’s session header. Agents self-heal without operator intervention. [commit d38ee76]
  • /metrics Prometheus endpoint. FastAPI now mounts prometheus_client.make_asgi_app() at /metrics. An always-on PrometheusMetricReader writes into prometheus_client.REGISTRY alongside the OTLP exporter (when OTEL_EXPORTER_OTLP_ENDPOINT is configured). SPEC-030 Phase 6 counters + SPEC-034 signal counters are now scrapeable without an external collector. [commit b89c710]
  • SPEC-034 observability counters. signals_sent_total (by pid + signal_type + delivered|queued|broadcast outcome), signals_drained_on_startup_total (per drain call, quantity = signals delivered), system_signals_emitted_total (PeerJoined / PeerLeft / MasterPreempted × session|broadcast target). Mirrors SPEC-030 Phase 6 pattern; lazy import + try/except so metric bugs never fail the service. [commit 920e42a]
  • Cross-platform backup + restore scripts. bin/prism-backup.sh + bin/prism-restore.sh (bash, Mac/Linux) and bin/prism-backup.ps1 + bin/prism-restore.ps1 (pwsh 7+, Windows) snapshot user-scoped Prism state (credentials, editor MCP configs, shell rc, PowerShell profile) into ~/.prism/backups/<TS>/. Restore is interactive with per-file diff
    • confirm + pre-restore safety copies. Manifest format is identical cross-platform. [commits d3cc767, 371ed88]

Changed

  • prism install — cross-platform industrialization (Lafonda + Donna, parallel). Mode-aware install with --mode local|lan|cloud + interactive 1/2/3 prompt. Local mode preflights Docker (CLI + Compose v2 + daemon); LAN mode preflights /health + /api/v1/projects auth before touching any config. Cross-platform launcher setup: macOS/Linux chmod + symlink + managed ~/.zshrc / ~/.bashrc block; Windows coder.cmd shim
    • User PATH via [Environment]::SetEnvironmentVariable. Per-editor PRISM_AGENT_IDENTITY / PRISM_AGENT_SURFACE written into every MCP block (Lola for Claude Desktop, Donna for Claude Code, etc.). Auto-detect existing backend URL+key from editor configs before falling back to defaults — never clobbers a working install without --force. Backend preflight symmetric for both local and lan. MCP venv auto-provisioned on first run; Python dep preflight. cmdUp guards against accidental second-backend starts on LAN clients (installed mode must be local). [commits 65d47c7, 543440c, 48f7b1d, 9538981]
  • bin/coder.sh self-sufficient + native bin/coder.ps1 port. Launcher derives PRISM_ROOT from script location and reads PRISM_API_URL / PRISM_API_KEY / PROJECT_ROOT from ~/.prism/credentials.personal.json. Env vars still override; only PRISM_API_KEY hard-fails when absent from every source. PowerShell 7+ port matches the bash contract line-for-line. Drops the DFW-Helpers.ps1 dependency the legacy launcher carried. [commit 678ffb3]
  • docs/INSTALL.md restructured into Local / LAN / Cloud (deferred) client-install modes. Separate preflight + cred-handling for each mode. Server-side install (backend host) moved to a trailing section pointing at DEPLOY.md + bin/prism-server-install.sh. [commits 0e58558, a075a99]
  • **coder launcher arc — single-dash long flags + identity un-baking
    • Windows PATH parity.** Both bin/coder.sh and bin/coder.ps1 flipped to single-dash long flags (-as, -mode, -autonomy, -god) so the bash/pwsh contracts match line-for-line. The TS CLI no longer bakes PRISM_AGENT_IDENTITY at install time, so coder --as <Identity> actually overrides instead of fighting the baked default. coder.ps1 gained Windows User-PATH install via [Environment]::SetEnvironmentVariable so a fresh Windows install picks up coder without a manual PATH edit. [commits 1726e64, b7a440b, b74424a]

Fixed

  • Lease conflict path — ASYNC SQLAlchemy gotcha. lease_service.request’s try: await session.flush() except IntegrityError: pattern was hitting two stacked bugs on unique-violation: (1) MissingGreenlet during asyncpg’s dialect-level exception translation (context lost); (2) PendingRollbackError from outer-transaction poisoning even with a savepoint. Rewrote using postgres_insert.on_conflict_do_nothing( index_elements=[...], index_where=text("released_at IS NULL")) against the partial UNIQUE index — no exception raised, no greenlet/rollback recovery needed, gRPC servicer correctly surfaces ALREADY_EXISTS instead of UNKNOWN. [commit 6b2727f]
  • smoke_spec030_phase1 assertion shape. Updated to match SPEC-031 §4.2’s new prism_status payload (project block, session block, agents flat list, total_agents, status_line) instead of the pre-SPEC-031 {pid, master, peers, caller, total_active} fields. [commit 6b2727f]
  • docker-compose.personal.yml — Redis loopback bind. Redis was internal-network-only; SPEC-034 MCP subscribers run host-side and need pub/sub access. Added ports: ["127.0.0.1:6379:6379"] with loopback-only binding (same posture as backend’s 8765 mapping). Server LAN deployment intentionally unchanged — exposing server1’s redis is a separate deployment decision with ufw/auth implications. [commit 8d9d0e3]
  • backend-grpc container healthcheck. The Dockerfile’s default HTTP curl :8000/health HEALTHCHECK could never pass in a gRPC-only container. Compose now overrides with a real grpc_health_probe -addr=:50051 against a properly wired grpc.health.v1.Health service. No more perpetually-unhealthy backend-grpc confusing operators during real incidents. [commit b960f21]
  • Prism self-host bootstrap + reserved-name error shape. The RESERVED_NAMESPACES guard (last touched in the DFW→Prism rename at commit 7f26450) was blocking the legitimate self-host seed — a fresh personal stack couldn’t bootstrap its own Prism meta-project because the reserved-name check fired before the tenant had any rows to collide with. bootstrap_service.bootstrap now detects the self-host seed case (name="prism" and zero Prism-named projects in this tenant) and passes allow_reserved_name=True through to scaffold_service.build_manifest. The guard still blocks users naming their own project “Prism” on a tenant that already has one, plus the other reserved names (tools, vault, shared, _framework). Router now returns a structured HTTP 422 on reserved-name violation instead of a raw 500 + stack trace. Caught by Candi on mini2 during a clean prism up + prism install --mode local walk-through. [commit 823521b]
  • Windows-clone install flow — CRLF guardrails + missing cli/dist/ note. Windows Git’s default core.autocrlf=true was silently corrupting backend/docker-entrypoint.sh on cold clone — the shebang became #!/usr/bin/env bash\r, the Linux kernel read bash\r as the interpreter name, and backend-grpc crash-looped with no clear error surface (prism up still reported the HTTP backend healthy on 8765). Two-layer defense: (1) repo-level .gitattributes forcing LF on shell / Dockerfile / Python / YAML / TOML / JSON / Markdown, keeping *.ps1 / *.cmd / *.bat at CRLF for native Windows tooling; (2) Dockerfile-level sed -i 's/\r$//' on the entrypoint before chmod, so the image self-heals regardless of how the source reached the host. docs/INSTALL.md picked up a “Windows line-ending note” subsection, a cli/dist/-not-committed note (the npm install prepare script builds it — a fresh clone must run that before prism ... works), and two new troubleshooting rows covering the env: 'bash\r' symptom + the missing-dist module-not-found symptom. Caught by Candi during the 2026-04-24 Windows retest. [commit a5fbb9c]

Runtime verification

All four SPEC-030 smokes pass against server1 after this arc: smoke_spec030_phase1, smoke_spec030_leases, smoke_spec030_approvals, smoke_spec030_phase3 — 100% green. SPEC-034 full §3 Lola↔Donna round-trip verified via smoke_spec034_signal.py against localhost.

2026-04-23

Added

  • SPEC-032 Phase A — Redis session plane dual-write (Option B). MCP clients never connect to Redis directly — coordination flows through SessionStore on the backend (register/refresh_ttl/release/ get_master/get_active_sessions/publish_*). CD-vs-CD tie handling + fakeredis integration tests. Hard prereq on backend startup: session_store connected log line or backend refuses to start. [commits 642bc61, dc68c14]
  • SPEC-030 Phase 5 — Approval flow + Phase 6 — Observability. approval_requests table with CHECK-constrained statuses (pending| approved|rejected|timed_out). Partial indexes on pending-only rows (hot path: push + timeout sweep + requester listing). Phase 6 brings OTel MeterProvider + five controller counters (elections, stream events, lease grants, approval lifecycle, stream drops) + active-registrations observable gauge. OTLP exporter via gRPC; no-op when OTEL_EXPORTER_OTLP_ENDPOINT unset. [commits 6c95f48, 31f6fa8]

Fixed

  • Installer stamps per-editor identity vars. Every editor’s MCP block now carries PRISM_AGENT_IDENTITY + PRISM_AGENT_SURFACE so the controller can tell Lola (Claude Desktop) from Donna (Claude Code) from Cursor from Codex instead of all four registering as unknown/other. Caught during a multi-agent session where both Desktop + Code ended up unregisterable-as-peers. [commit ac47715]

Earlier

For entries older than 2026-04-23, see git log --oneline on main. The project history from DFW → PrismGR → Prism is told narratively in History. The changelog proper starts when the controller plane (SPEC-030) + session plane (SPEC-032) shipped together, which is the moment Prism became operationally stable enough to warrant curated release notes.
Last modified on May 18, 2026