Audit — R93 B5 Document session_id Binding in Audit-Proof Workflow

Round: R93 debug-sweep (fix #5 of 6, doc-only) Branch: feature/r93-b5-session-id-binding-docs Base SHA: fbc8808a β task: c4aba667-892c-4c99-94fb-1ae25050331d Closes parked R89 investigation: 6f309f3a-7d22-4e2c-a02d-3a62fc46c834 (merkle_finalize ERR_NO_RECORDS root cause).

§1. Goal

The R88 calling pattern that produced merkle_finalize ERR_NO_RECORDS even with task-bound thought_record rows was caused by missing session_id on the thought_record calls. Document the requirement so the next executor working a proof-grade slice doesn’t repeat the mistake.

§2. Code reality

§2.1. merkle_finalize binding

src/tools/merkle.ts:296-300:

const hashesStmt = db.prepare<[string], { hash: string }>(
  `SELECT hash FROM thought_records
     WHERE session_id = ?
     ORDER BY rowid ASC`,
);

The query is WHERE session_id = ?. The binding key is thought_records.session_id, not task_id.

§2.2. thought_record schema

src/domains/trail/repository.ts:139-145:

const CreateThoughtRecordInputSchema = z.object({
  type: z.enum(THOUGHT_TYPES),
  task_id: z.string().min(1),
  agent_id: z.string().min(1),
  content: z.string().min(1, 'thought content must be non-empty'),
  session_id: z.string().min(1).optional(),
});

session_id is optional. When omitted, repository.ts:252 stores NULL:

const sessionId = parsed.session_id ?? null;

This is correct — non-proof-grade work writes thought records without a session. But the moment a caller opens audit_session_start, every subsequent thought_record in that proof chain MUST pass the returned session_id, otherwise merkle_finalize (whose WHERE session_id = ? query excludes NULL-bound rows) returns ERR_NO_RECORDS.

§3. Existing documentation gaps

§3.1. .agents/skills/colibri-audit-proof/SKILL.md

  • §”The load-bearing ordering rule” lifecycle diagram (lines 28-40) mentions the ordering of calls but not the session_id propagation requirement.
  • All thought_record example JSON blocks (lines 82-106) use thought_type (wrong; the actual field is type) and pass session_id but omit the required task_id + agent_id. The examples will fail Zod validation if pasted verbatim into an MCP call.
  • §”Operating rules” rule 4 says “Carry forward session_id from the initial call to every subsequent call in the chain” but isn’t load-bearing enough to surface the failure mode.

§3.2. docs/agents/writeback-protocol.md

  • §1.2 thought_record example uses thought_type (wrong; should be type) and omits task_id + agent_id.
  • §3.1 audit_session_start example uses name=<task-slug>, scope="task" — neither field exists in the actual schema. Real fields are intent, task_id?, session_id?.
  • §3.3 audit_verify_chain example uses session_id=<from start> — but audit_verify_chain accepts only task_id?, not session_id.
  • §10 “Proof-grade example” reproduces all three errors.
  • No explicit anti-pattern entry for “writing thought_record without session_id between audit_session_start and merkle_finalize”.

§3.3. .claude/skills/colibri-audit-proof/SKILL.md

R77.C mirror of .agents/skills/colibri-audit-proof/SKILL.md. Must be kept byte-clean.

§4. Constraints on the fix

  • MUST NOT modify any source code or any handler behaviour.
  • MUST update the audit-proof skill (canonical + mirror) and the writeback protocol document to make session_id propagation explicit.
  • MUST fix the example field shapes to match the live Zod schemas so the docs stop teaching the wrong calling pattern.
  • MAY fix the audit_session_start + audit_verify_chain example shapes while in the neighbourhood (adjacent to the session_id story).
  • MUST NOT touch CLAUDE.md §7 in this slice (separate concern, broader review scope).
  • After PR merges, the parked R89 task 6f309f3a-7d22-4e2c-a02d-3a62fc46c834 should be marked DONE — but that’s a separate β writeback after merge, not part of this slice.

§5. Path forward

Three doc edits + one mirror sync:

  1. .agents/skills/colibri-audit-proof/SKILL.md — fix examples + add session_id callout.
  2. docs/agents/writeback-protocol.md — fix audit_session_start, audit_verify_chain, thought_record examples + add session_id anti-pattern.
  3. .claude/skills/colibri-audit-proof/SKILL.md — mirror sync.

Proceeding to contract + packet (combined for XS scope).


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.