Skip to main content
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:
  1. 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.
  2. 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:
VerbHygieneDeregistrationUse when
prism_checkpointYes — full delta flush, journal, TODO, session statsNo — registration stays active, election unchanged”I’m saving my game” — between phases, between tasks
prism_wrapYes — calls checkpoint internally firstYes — 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:
StepScopeEstimate
1delta_kind enum: add checkpoint15 min
2MCP verb prism_checkpoint — extract hygiene logic from prism_wrap into shared helper, wire new verb2h
3Refactor prism_wrap to call checkpoint + deregister30 min
4prism_status enhanced response — backend service + router2h
5prism_status fetch top-N TODOs + nudges (nudges: stub empty until SPEC-029)1h
6BIOS template update (checkpoint vs wrap guidance)30 min
7Smoke tests1h
Total: ~7h, single-day PR.

5.2 Smoke tests

Checkpoint:
  1. prism_startprism_checkpoint → verify registration still active
  2. prism_startprism_checkpointprism_status → verify caller in agents list
  3. prism_startprism_checkpointprism_wrap → verify deregistered
  4. Checkpoint delta appears in recent_deltas with delta_kind=checkpoint
  5. Checkpoint counts toward wrap_rate
Status enhancements:
  1. Single agent → prism_status returns project block, session block, 1 agent
  2. Status line matches expected format
  3. pending_todos returns top 5 open TODOs
  4. pending_nudges returns empty array (pre-SPEC-029)
  5. 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

  1. prism_checkpoint performs full hygiene without deregistering.
  2. prism_wrap behavior unchanged for existing callers.
  3. Checkpoint delta has delta_kind=checkpoint.
  4. prism_status returns enhanced payload per §4.2.
  5. Agents list uses flat Agent:Project:Master structure.
  6. Top-N pending TODOs included in status response.
  7. pending_nudges returns empty array (ready for SPEC-029).
  8. status_line field matches SPEC-021 format.
  9. “General Chat Session” used when no PID is set.
  10. All smoke tests per §5.2 pass.
Status: draft
Last modified on April 27, 2026