> ## Documentation Index
> Fetch the complete documentation index at: https://prism.ntecdev.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SPEC-031 v0.1: Session lifecycle refinement — checkpoint verb + prism_status payload enhancements

> Session lifecycle refinement — checkpoint verb + prism_status payload enhancements

<Info>**Status:** `draft` · **Version** `0.1` · Filed 2026-04-23</Info>

# 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:

| 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

```python theme={null}
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:

```json theme={null}
{
    "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

```json theme={null}
{
    "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:

```json theme={null}
"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:**

1. `prism_start` → `prism_checkpoint` → verify registration still active
2. `prism_start` → `prism_checkpoint` → `prism_status` → verify caller in agents list
3. `prism_start` → `prism_checkpoint` → `prism_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
