Status: draft · Version 0.1 · Filed 2026-04-23
SPEC-031 v0.1 — Session Lifecycle Refinement
Status
draft
1. Summary
Two targeted enhancements to the Prism session lifecycle and controller
visibility surface:
-
prism_checkpoint — a new verb that performs all prism_wrap hygiene
(delta flush, journal, TODO status, session stats) without deregistering
the caller from the controller. Solves the observed flaw where Donna wraps
between build phases, vanishes from the controller, and must re-bootstrap
to resume collaborative work.
-
prism_status payload enhancements — enriches the existing read-only
status verb (SPEC-030 §6.3) with project identity, session context, pending
TODOs, pending nudges, and a structured agent registry so any surface can
answer “who’s connected, what’s open, and what needs attention” in one call.
Both changes are minor-version extensions to existing accepted architecture.
No new tables. No schema migrations. No breaking changes to existing verb
contracts.
2. Origin
2026-04-23 session (Frank + Lola). Frank observed that when Donna finishes
a discrete unit of work (e.g., shipping SPEC-030 Phase 4) and calls
prism_wrap, the wrap deregisters her from the controller_registrations
table. Frank, sitting as CD master, loses visibility of Donna as a peer. To
hand her the next task, she must re-bootstrap via prism_start — a full
context-load cycle just to stay in the conversation.
Frank: “I think I over-indexed on wrap — maybe we need an interim state
that does all hygiene activities which works perfectly but wants to stay
logged in for collaboration.”
Simultaneously, Frank identified that prism_status returns raw controller
registration data but lacks the operational context a human or agent needs:
project identity, current phase, pending work items, and a clean agent
roster.
3. Enhancement 1 — prism_checkpoint verb
3.1 Problem
prism_wrap is currently atomic: hygiene + deregistration. In a
collaborative multi-agent session, an agent may want to:
- Flush session deltas (preserve context for the next agent or future self)
- Record session stats and journal
- Update TODO statuses
- Remain registered and election-eligible
- Continue accepting work from the operator
Today, calling prism_wrap achieves the first three but kills the last two.
Not calling prism_wrap preserves registration but loses session hygiene —
the exact discipline gap SPEC-023 was designed to close.
3.2 Design
Split the current prism_wrap behavior into two verbs:
| Verb | Hygiene | Deregistration | Use when |
|---|
prism_checkpoint | Yes — full delta flush, journal, TODO, session stats | No — registration stays active, election unchanged | ”I’m saving my game” — between phases, between tasks |
prism_wrap | Yes — calls checkpoint internally first | Yes — sets released_at, vacates master if applicable | ”I’m leaving the table” — end of session, done for the day |
prism_wrap becomes: prism_checkpoint() + deregistration. The existing
prism_wrap contract is preserved — callers who already use prism_wrap
see identical behavior. The new verb is purely additive.
3.3 Signature
prism_checkpoint(
pid: str,
summary: str = "", # session delta summary (same as prism_wrap)
decisions: list[str] = [], # decisions made this segment
next_actions: list[str] = [],# what comes next
tags: list[str] = [], # optional tags for the delta
) -> {
"delta_id": str,
"session_id": str,
"delta_kind": "checkpoint", # new delta_kind enum value
"hygiene": {
"todos_completed": int,
"todos_added": int,
"journal_written": bool,
"decisions_recorded": int,
},
"registration_status": "active", # always "active" — that's the point
"controller_status": { ... }, # same shape as prism_start returns
"wrap_rate": { ... }, # updated stats
}
3.4 delta_kind extension
SPEC-023 §6.2 defines delta_kind as: wrap | note | remember | methodology | research | other. Add checkpoint to the enum.
Checkpoints count toward wrap discipline metrics the same way wraps do —
they represent a deliberate hygiene act. The wrap_rate computation
(SPEC-023 §7) should count checkpoints as wraps for rate purposes, since
the discipline goal is “don’t leave sessions unhygiened,” not “don’t leave
sessions registered.”
3.5 prism_wrap refactor
Internally:
prism_wrap(pid, summary, ...) =
checkpoint_result = prism_checkpoint(pid, summary, ...)
deregister(pid, session_id)
return { ...checkpoint_result, registration_status: "released" }
Existing prism_wrap callers see no change in external behavior. The
deregistration step is identical to current behavior (set released_at,
vacate master if applicable).
3.6 Agent convention update
BIOS templates (CLAUDE.md / AGENTS.md) gain guidance:
Checkpoint vs Wrap. Use prism_checkpoint between discrete work
units (shipping a spec phase, completing a build task, finishing a review)
when you expect to continue working in the same session or receive
follow-up tasks. Use prism_wrap only when the session is truly ending
— you’re done for the day, the operator is signing off, or you’re
switching to a different project.
3.7 Interaction with SPEC-029 nudges
When SPEC-029 ships, wrap_session nudge semantics need a minor update:
a prism_checkpoint with delta_kind=checkpoint should NOT auto-resolve
a wrap_session nudge — only a full prism_wrap (with deregistration)
resolves it. The nudge exists to ensure session closure, not just
hygiene. However, a checkpoint resets the staleness clock: the “last
activity” timestamp used for nudge urgency should reflect checkpoints.
4. Enhancement 2 — prism_status payload improvements
4.1 Problem
The current prism_status response (SPEC-030 §6.3, live implementation)
returns:
{
"pid": "PID-PGR01",
"project": "Prism",
"phase": "Phase 4",
"caller": null,
"master": { ...raw registration row... },
"peers": [],
"total_active": 1
}
This is structurally correct but operationally thin. An agent or human
reading this can’t answer:
- What’s the human-readable project context? (phase, status, rules state)
- What’s pending? (TODOs, nudges)
- Who’s connected and in what role? (need Agent:Project:Master triple, not raw DB rows)
4.2 Enhanced response shape
{
"project": {
"pid": "PID-PGR01",
"name": "Prism",
"phase": "Phase 4",
"status": "active",
"rules_reminders_count": 1,
"last_wrapped_at": "2026-04-23T03:40:20Z"
},
"session": {
"session_id": "125490c6-...",
"started_at": "2026-04-23T12:14:13Z",
"is_master": true,
"agent_identity": "Lola",
"agent_surface": "claude_desktop"
},
"agents": [
{
"agent_identity": "Lola",
"agent_surface": "claude_desktop",
"machine_id": "mini3.home.lan",
"is_master": true,
"project": "PID-PGR01",
"registered_at": "2026-04-23T12:14:13Z",
"last_heartbeat": "2026-04-23T12:33:52Z"
}
],
"pending_todos": [
{
"number": 90,
"text": "SPEC-030 Phase 3 runtime verification: deploy to server1...",
"tags": ["spec-030", "phase-3-runtime-verification", "server1"],
"status": "open"
},
{
"number": 91,
"text": "SPEC-030 §10 pre-flight: explicit-transaction audit...",
"tags": ["spec-030", "phase-4-followup", "audit"],
"status": "open"
},
{
"number": 92,
"text": "Frank wants to discuss the prism_wrap function...",
"tags": ["post-spec-030", "wrap-discussion"],
"status": "open"
}
],
"pending_nudges": [],
"total_agents": 1,
"status_line": "Prism PID-PGR01 · Phase 4 · active · rules_reminders: 1"
}
4.3 Field specifications
project — Project identity block. Always present.
pid: project identifier
name: human-readable project name. Use "General Chat Session" if no
project is set (covers the no-PID edge case in future general-purpose use).
phase, status: from project record
rules_reminders_count: count of active rules_reminders
last_wrapped_at: from SPEC-022’s last_wrapped_at column
session — Current caller’s session context. Null if the caller is not
registered on this PID (e.g., querying another project’s status).
session_id, started_at (= registered_at), is_master,
agent_identity, agent_surface
agents — Flat list of all active registrations. Each entry carries the
Agent:Project:Master triple Frank specified. Replaces the split
master + peers fields with a unified list where is_master is a
boolean on each entry. Simpler to consume, no structural difference
between master and peer rendering.
pending_todos — Top N (default 5) open TODOs, ordered by most recently
created first. Gives immediate visibility into pending work without a
separate prism_todo(action=list) call. Agent can use this to proactively
surface work items.
pending_nudges — Top N (default 5) open nudges (SPEC-029). Empty array
until SPEC-029 ships. When nudges land, this field provides the same
at-a-glance visibility without a separate prism_nudge(action=list) call.
total_agents — Count of active registrations.
status_line — Pre-formatted status card string matching the SPEC-021
Ring 0 format. Agents can emit this directly without composing it from
parts.
4.4 Backward compatibility
The current response fields (pid, project, phase, caller, master,
peers, total_active) are restructured. This is acceptable because:
prism_status is a new verb (SPEC-030 Phase 1, ~1 week old)
- No external consumers exist
- The verb is explicitly
v0 / draft status
- The enhancement improves every consumer’s experience
If backward compat were needed, a ?format=v1 query param could be added.
Not recommended — clean break while the verb is young.
4.5 No-project edge case
When prism_status is called without a resolved PID (possible in future
general-purpose use), the response uses:
"project": {
"pid": null,
"name": "General Chat Session",
"phase": null,
"status": "active",
"rules_reminders_count": 0,
"last_wrapped_at": null
}
This keeps the response shape consistent and gives a meaningful label for
sessions that aren’t project-bound.
5. Implementation
5.1 Sequencing — single PR
Both enhancements are small enough for one PR:
| Step | Scope | Estimate |
|---|
| 1 | delta_kind enum: add checkpoint | 15 min |
| 2 | MCP verb prism_checkpoint — extract hygiene logic from prism_wrap into shared helper, wire new verb | 2h |
| 3 | Refactor prism_wrap to call checkpoint + deregister | 30 min |
| 4 | prism_status enhanced response — backend service + router | 2h |
| 5 | prism_status fetch top-N TODOs + nudges (nudges: stub empty until SPEC-029) | 1h |
| 6 | BIOS template update (checkpoint vs wrap guidance) | 30 min |
| 7 | Smoke tests | 1h |
Total: ~7h, single-day PR.
5.2 Smoke tests
Checkpoint:
prism_start → prism_checkpoint → verify registration still active
prism_start → prism_checkpoint → prism_status → verify caller in agents list
prism_start → prism_checkpoint → prism_wrap → verify deregistered
- Checkpoint delta appears in
recent_deltas with delta_kind=checkpoint
- Checkpoint counts toward wrap_rate
Status enhancements:
- Single agent →
prism_status returns project block, session block, 1 agent
- Status line matches expected format
- pending_todos returns top 5 open TODOs
- pending_nudges returns empty array (pre-SPEC-029)
- No-project case returns “General Chat Session” name
6. Relationships
- Extends SPEC-030 — adds
prism_checkpoint alongside prism_wrap in
the session lifecycle; enriches prism_status response shape.
- Extends SPEC-023 —
checkpoint delta_kind added; checkpoint counts
toward wrap discipline metrics.
- Prepares for SPEC-029 —
pending_nudges field in status; checkpoint
staleness-clock interaction with nudge urgency.
- Uses SPEC-022 —
last_wrapped_at surfaced in project block.
7. Open Questions
- Q1: Should checkpoints have their own wrap_rate metric separate from
wraps? Lean: no — count them together. The goal is hygiene discipline, not
wrap-specifically discipline.
- Q2: Maximum
pending_todos / pending_nudges in status response?
Lean: 5 each. Configurable via query param in future if needed.
- Q3: Should
prism_status be callable cross-project (status of PID-B
from a session registered on PID-A)? Lean: yes, read-only is safe.
Caller’s session block would be null.
8. Acceptance Criteria
prism_checkpoint performs full hygiene without deregistering.
prism_wrap behavior unchanged for existing callers.
- Checkpoint delta has
delta_kind=checkpoint.
prism_status returns enhanced payload per §4.2.
- Agents list uses flat
Agent:Project:Master structure.
- Top-N pending TODOs included in status response.
pending_nudges returns empty array (ready for SPEC-029).
status_line field matches SPEC-021 format.
- “General Chat Session” used when no PID is set.
- All smoke tests per §5.2 pass.
Status: draft