ζ Decision Trail — Algorithm Extraction
⚠ HERITAGE EXTRACTION — donor AMS ζ Decision Trail (Wave 8 quarantine)
This file extracts the donor AMS thought-record hash-chain from
src/controllers/thought.jsandsrc/domains/thought/(deleted R53). The 7-thought-tool donor surface and the 9-tool donor audit family are donor accretion. Phase 0 Colibri ships exactly 6 ζ/η tools total (3 audit + 3 merkle per ADR-004 R74.5) targetingsrc/domains/thought/(P0.7). The hash-chain algorithm itself is preserved as canonical and forms the basis of the Phase 0 implementation. The Phase 0 truth lives in../../concepts/ζ-decision-trail.md.Read this file as donor genealogy for the algorithm; the tool surface is in
../mcp-tools-phase-0.md.
Algorithmic content extracted from AMS
src/controllers/thought.jsandsrc/domains/thought/for Colibri implementation reference.
Hash-Chain Algorithm
Each thought record is cryptographically linked to its parent. The chain is tamper-evident: modifying any record breaks all subsequent chain hashes.
For each new thought record:
content_hash = SHA256(record.content)
if record.parent_id == null:
parent_chain_hash = "0000...0000" (64-char zero hash)
else:
parent_chain_hash = parent_record.chain_hash
chain_hash = SHA256(content_hash + parent_chain_hash)
(string concatenation before hashing)
Implementation detail: The concatenation is string concatenation of two hex-encoded SHA-256 digests (128 hex chars total), then SHA-256 of that string. Both hashes are lowercase hex without separator.
4 Valid Record Types
Defined in src/controllers/thought.js as the accepted enum:
| Type | When to use | Example content |
|---|---|---|
plan |
Before starting work | “I will implement X by doing Y, then Z” |
analysis |
During work — examining facts, code, options | “The root cause is X because Y. Evidence: …” |
decision |
At a choice point | “Chose approach A over B because of performance constraint C” |
reflection |
After work — lessons, outcomes | “Completed successfully. Blocker was X, resolved by Y. Tests: green” |
Note: observation and hypothesis are NOT valid types in the current implementation. Use analysis for recording discovered facts during work.
Record Schema
Full schema for mcp_thought table:
{
id: string — UUID, unique record identifier
session_id: string — groups records belonging to same work session
parent_id: string | null — links to previous record's id (null = chain root)
type: enum — "plan" | "analysis" | "decision" | "reflection"
content: string — the actual thought text (the content that gets hashed)
content_hash: string — SHA-256 hex digest of content field
chain_hash: string — SHA-256 hex digest of (content_hash + parent.chain_hash)
metadata: JSON — { task_id, agent_id, tool_calls: [...], branch, commit_sha }
created_at: ISO 8601 — UTC timestamp of record creation
}
The metadata.tool_calls array lists the MCP tool names called during the work session up to this record, providing execution context alongside the thought content.
Verification Algorithm
thought_verify(session_id) — O(n) walk over all records in the session:
def verify_chain(session_id):
records = db.query(
"SELECT * FROM mcp_thought WHERE session_id = ? ORDER BY created_at ASC",
session_id
)
for record in records:
# Step 1: verify content hash
computed_content_hash = SHA256(record.content)
if computed_content_hash != record.content_hash:
return {
valid: False,
broken_at: record.id,
reason: "content_hash_mismatch",
expected: computed_content_hash,
actual: record.content_hash
}
# Step 2: verify chain hash
if record.parent_id is None:
parent_chain_hash = "0" * 64
else:
parent = records[record.parent_id]
parent_chain_hash = parent.chain_hash
computed_chain_hash = SHA256(record.content_hash + parent_chain_hash)
if computed_chain_hash != record.chain_hash:
return {
valid: False,
broken_at: record.id,
reason: "chain_hash_mismatch",
expected: computed_chain_hash,
actual: record.chain_hash
}
return { valid: True, records: len(records), chain_length: len(records) }
Time complexity: O(n) where n = number of records in session. Space complexity: O(n) to hold all records in memory during walk.
FTS5 Full-Text Search Integration
The mcp_thought table has a companion FTS5 virtual table for full-text search:
-- FTS5 virtual table (one of the 4 FTS5 tables in the schema)
CREATE VIRTUAL TABLE mcp_thought_fts USING fts5(
content,
metadata,
content=mcp_thought,
content_rowid=rowid
);
-- Trigger to keep FTS5 in sync
CREATE TRIGGER mcp_thought_ai AFTER INSERT ON mcp_thought BEGIN
INSERT INTO mcp_thought_fts(rowid, content, metadata)
VALUES (new.rowid, new.content, new.metadata);
END;
thought_search(query, session_id?, limit?) uses mcp_thought_fts MATCH ? with optional session filter. Results include BM25 relevance rank.
Branching: Thought Trees
Multiple records can share the same parent_id, creating a tree structure rather than a strict linear chain:
root (parent_id = null)
├── analysis_1 (parent_id = root.id)
│ ├── decision_A (parent_id = analysis_1.id)
│ └── decision_B (parent_id = analysis_1.id) ← branch
└── analysis_2 (parent_id = root.id) ← branch
thought_tree(session_id) returns the full tree as a nested JSON structure.
thought_trail(session_id, record_id) returns the linear path from root to the specified record (single ancestry branch).
Verification note: thought_verify walks all records but branches mean a record can have only one parent. The chain_hash for each record still ties it uniquely to its parent — divergent branches cannot be grafted onto each other without breaking the chain.
Tool Surface (src/controllers/thought.js)
| Tool | Parameters | Returns |
|---|---|---|
thought_record |
session_id, type, content, parent_id?, metadata? | New record with content_hash, chain_hash |
thought_get |
id | Single record |
thought_tree |
session_id | Nested tree JSON |
thought_trail |
session_id, record_id | Linear path from root to record |
thought_verify |
session_id | Verification result (valid/broken) |
thought_search |
query, session_id?, limit? | FTS5 matched records |
See Also
-
[[concepts/ζ-decision-trail ζ Decision Trail]] — concept overview -
[[extractions/eta-proof-store-extraction η Proof Store Extraction]] — Merkle tree that consumes thought chains -
[[extractions/beta-task-pipeline-extraction β Pipeline Extraction]] — writeback contract requires thought_record -
[[architecture/database Database Architecture]] — mcp_thought table schema -
[[guides/tutorials/merkle-audit Merkle Audit Tutorial]] — end-to-end thought + merkle workflow