Skip to content

I0804 — Close a session into an envelope derived from the ledger

Implement `session close`: read the active record, derive the episode's references from the ledger between its start and now, write an immutable closed record with computed end-state git facts and an optional authored summary body, remove the active record, and append the close event to the ledger.

DONE wave 2 · p1 · deep-work profile · runs alone

Part of M003 — A session is a durable envelope, and knowledge is compiled from what is already canonical.

Objective

Implement `session close`: read the active record, derive the episode's references from the ledger between its start and now, write an immutable closed record with computed end-state git facts and an optional authored summary body, remove the active record, and append the close event to the ledger.

Why

This is the mechanism that makes the session an envelope rather than a narrative. Nothing accumulates references during the episode, so no command outside session pays for them; and because the ledger is append-only and machine-written, the envelope is a derivation of existing evidence rather than a second account of it.

Current state

The ledger records task, checkpoint, handover, finish, decision, question, plan and maintenance events, each with a timestamp, a branch and a head. Nothing reads a time range out of it.

Desired state

A closed record under .majordomus/state/sessions/ carries the computed identity, started_at and closed_at, start and end head and working tree, the outcome, and reference lists of task ids, issue ids, milestone ids, checkpoint paths, handover paths, decision entries and question ids observed in the ledger window. It copies no body. An authored summary on stdin is optional and is stored as the record body, subject to the identity-field refusal every other record uses.

Scope

  • lib/session.sh
  • test/cases/60_session_lifecycle.sh
  • test/cases/61_session_envelope.sh

Out of scope

  • Reading a closed record back, which is its own issue
  • Retention and archiving
  • Any copying of a checkpoint, handover or decision body into the session file

Dependencies

What waits on this

Acceptance criteria

  • Closing writes an immutable record, removes the active record, and appends one ledger event
  • The reference lists match the events the ledger holds in the window, and nothing outside the window appears
  • An episode that spans two tasks names both; a task that spans two sessions is named by both
  • No body of any referenced record appears in the session file, and a case asserts that
  • An authored summary containing an identity field is refused, as it is for a checkpoint

Validation

  • bash test/run.sh 60_session_lifecycle
  • bash test/run.sh 61_session_envelope

Evidence required

  • session_closes
  • envelope_is_references

Evidence

coverstypecommandresultat commit
session_closestesttest/run.sh 61_session_envelope1 passed. Closing writes an immutable record, removes the open one and appends exactly one session.closed event; closing with nothing open exits 12; a summary carrying an identity field exits 10 and leaves the open record in place; a second close writes a new file and leaves the earlier record byte-identical; every record is mode 06007ca51d2
envelope_is_referencestesttest/run.sh 61_session_envelope1 passed, and the mutation back to a time window fails it. The case proves the record names checkpoint, handover and decision references and carries none of their bodies, that every referenced state path resolves, that an episode across two tasks names both while a task across two sessions is named by both, and that an event stamped by another session or by none is excluded. The first live run of the time-window implementation collected the other worker's records into my envelope; selection is now by the session stamp each ledger line carries7ca51d2

Risk

The ledger window is bounded by timestamps with second resolution, so two episodes that abut within one second could each claim an event. The ledger's line order is the existing tiebreak for exactly this and has to be used rather than the timestamps alone.

Timeline

started
2026-09-04T17:26:46Z
verified
completed
2026-09-04T17:38:33Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I0804.yaml. Read it back with majordomus plan show I0804.