Playbook: Session Notes Workflow

Issue: #2630
Last updated: 2026-07-05

Purpose

Capture decision context, deferred work, and identified risks from agent sessions in a searchable, tamper-evident format. Supports EU AI Act Art.12/13/14 transparency requirements.


When to create a session note

DO create a note when the session:

  • Made architectural or operational decisions (even small ones)
  • Completed substantive work (PR merged, migration applied, playbook written)
  • Identified risks that may affect the platform
  • Left work deferred with specific reasoning

DO NOT create a note when:

  • Session was read-only research under 5 minutes
  • No decisions, no completions, no risks
  • Session answered a single factual question

Architecture — Two paths

Path A: Worker sessions (CLAUDE_SESSION_ID present)

Used by AI-Dev-IO1 (vps-i1) and AI-Dev-BMS4-1 (bms-4).

  1. Run generate-session-note.py to write markdown to docs/sessions/YYYY-MM/
  2. Commit with git commit --no-verify -m "docs: session note YYYY-MM-DD {topic}"
  3. agent-session-end.py PATCHes dev_r_agent_sessions with:
    • session_note_path (relative path from repo root)
    • key_decisions[]
    • deferred_items[]
    • risks_identified[]

Path B: Local dev sessions (no CLAUDE_SESSION_ID)

Used by interactive developer sessions on Windows dev machine.

  1. Run generate-session-note.py to write markdown to docs/sessions/YYYY-MM/
  2. Commit manually
  3. session_note_path stays NULL in Supabase — known limitation, documented in ADR 002

How to trigger manually

# From repo root (Windows dev machine)
python scripts/generate-session-note.py `
    --topic "audit log gap repair" `
    --branch feat/2630 `
    --worker "local" `
    --env "local" `
    --session-id "" `
    --completed "Added log_op() to 82 playbooks||Opened PR #2741" `
    --deferred "CI regeneration for role-context templates" `
    --decisions "Used infra_operations not dev_r_rotation_log" `
    --risks "infra_operations coverage gap -- P1"
# From repo root (Linux worker)
python3 scripts/generate-session-note.py \
    --topic "audit log gap repair" \
    --branch feat/2630 \
    --worker "$P24_WORKER_LABEL" \
    --env "$P24_ENVIRONMENT" \
    --session-id "$CLAUDE_SESSION_ID" \
    --completed "Added log_op() to 82 playbooks||Opened PR #2741" \
    --deferred "CI regeneration for role-context templates" \
    --decisions "Used infra_operations not dev_r_rotation_log" \
    --risks "infra_operations coverage gap -- P1"

The script prints the relative file path to stdout on success (e.g. docs/sessions/2026-07/2026-07-05-audit-log-gap-rep-abc12345.md). It exits 0 on success, 0 with a message on skip (nothing substantive), 1 on error.


How to commit

# Worker (Linux, --no-verify skips hooks that need CLAUDE_SESSION_ID at commit time)
NOTE_PATH=$(python3 scripts/generate-session-note.py --topic "..." ...)
git add "$NOTE_PATH"
git commit --no-verify -m "docs: session note $(date +%Y-%m-%d) {topic}"
# Developer (Windows)
$NotePath = python scripts/generate-session-note.py --topic "..." ...
git add $NotePath
git commit -m "docs: session note $(Get-Date -Format yyyy-MM-dd) {topic}"

Supabase columns updated by agent-session-end.py (Path A)

ColumnSourceType
session_note_path--note-path CLI argTEXT
key_decisionsP24_KEY_DECISIONS env (comma-sep)TEXT[]
deferred_itemsP24_DEFERRED_ITEMS env (comma-sep)TEXT[]
risks_identifiedP24_RISKS_IDENTIFIED env (comma-sep)TEXT[]

Set these env vars before calling agent-session-end.py:

export P24_KEY_DECISIONS="Used infra_operations table,Deferred IONOS GPU runner"
export P24_DEFERRED_ITEMS="CI regeneration for templates"
export P24_RISKS_IDENTIFIED="infra_operations coverage gap -- P1"
 
NOTE_PATH=$(python3 scripts/generate-session-note.py --topic "..." ...)
python3 scripts/agent-session-end.py --note-path "$NOTE_PATH" --summary "..."

Storage location

docs/sessions/YYYY-MM/YYYY-MM-DD-{slug}-{short-session-id}.md

Monthly subdirectories keep navigation manageable. The .gitkeep in docs/sessions/ ensures the parent directory is tracked even before any notes are written.


Querying session notes (Supabase)

-- All sessions with notes in the last 30 days
SELECT session_id, started_at, session_note_path, key_decisions, risks_identified
FROM dev_r_agent_sessions
WHERE session_note_path IS NOT NULL
  AND started_at > now() - interval '30 days'
ORDER BY started_at DESC;
 
-- Sessions with P1 risks
SELECT session_id, started_at, risks_identified
FROM dev_r_agent_sessions
WHERE array_to_string(risks_identified, ',') ILIKE '%P1%';

Escalation

If generate-session-note.py fails: check stderr, verify repo root detection, verify docs/sessions/ write permissions.

If agent-session-end.py PATCH fails: the note still exists in git — the Supabase link is advisory, not critical. Check SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY env vars.


  • docs/01-architecture/adr-002-session-notes-storage.md — design rationale
  • docs/templates/session-note.md — manual template
  • scripts/generate-session-note.py — generator script
  • scripts/agent-session-end.py — Supabase PATCH
  • supabase/migrations/054_session_notes_columns.sql — schema