| Session start is idempotentC06 | UQ_build_sessions_active — a filtered unique index on (project, computer, branch, actor); 201 on create, 200 on resume; concurrent starts cannot mint two active sessions | shipped |
| Decisions cannot be edited or deletedC07 | tg_decision_log_entries_append_only rejects DELETE and every UPDATE except the two source links; a correction is a new entry with corrects_entry_id | shipped |
| Backlog terminal states are absorbingC14 | tg_backlog_items_terminal_absorbing; resolve requires a closing PR, commit or closing notes; dismiss requires a reason | shipped |
| A rule matches on every populated dimensionC09 | file globs · operations · code patterns · languages · project attributes, AND across the populated ones; retrieval_count and last_retrieved_at bumped on each hit | shipped |
| Rules derive only from enforced lessonsC12rules are advisory to the agent — enforcement stays in your CI | derive_rule refuses a lesson that is not enforced; CK_build_lessons_enforced_requires_prevention refuses enforced without a prevention mechanism; status triggers move forward only | shipped |
| Every lifecycle event is on the audit chainC19pings, usage reports and retrieval-count bumps are deliberately not audited | 38 of 123 event types, written into the workspace’s SHA-256 chain in the same transaction as the row they record | shipped |
| Usage is idempotent per transcript, in tokensC17 | UQ_build_session_usages_report on (build session, transcript); five token classes + turns; token counts, not dollars; self-reported by the agent or the hook | shipped |
| REST and MCP return the same bytesC05 | one serializer per session-state aggregate, pinned by nine byte-parity test classes | shipped |
| Search is a LIKE matchC62 | query_decisions, query_backlog and search_build_sessions match an escaped substring with SQL LIKE, newest first, capped at 50; query_lessons matches the same way but comes back in lifecycle order, least-advanced first — not full-text search | shipped |
| Paging style differs by surfaceC100 | list_decision_log and list_build_sessions are keyset-paged over an opaque signed cursor; list_backlog_items and query_lessons are offset-paged with a total; query_decisions, query_backlog and search_build_sessions take neither cursor nor offset — they return a capped top-N | shipped |
| Flow metrics are dashboard-onlyC18 | /flow reads the backlog as it stands: no transition history, so aging is since creation, dismissed items are excluded, and there is no REST or MCP surface | shipped |
| LLM assist is optional and off by defaultC13 | lesson-candidate detection and rule enrichment run only when your own Anthropic key is configured; they propose, and a person promotes | default-off |
| Import dedups by fingerprint over the raw blockC20 | SHA-256 of each entry’s source block; preview first (dry run), commit once; an edited entry re-imports as new | shipped |