A render-function CLI and web SPA for exploring cognitive and structural patterns (atoms and molecules) with deterministic filtering, ranking, and visualization. Includes hook integration for Claude Code, benchmark evaluation, and multi-view catalog browsing (list, pivot, graph, reading order, document trace).
Lexicon is a specialized research/knowledge-management tool with 24 domain-specific commands, not a general-purpose agent toolkit. Tool definitions lack rigor: most descriptions are terse (10-50 chars), parameter schemas are minimal or absent, and output structures are undocumented. No input validation guidance, no error recovery hints, and no structured output schemas. The codebase shows these are CLI commands (render/cmd/lexicon/main.go) retrofitted as MCP tools, not designed for LLM consumption. Example: 'render' has a 50-char description and 4 params with minimal type info; 'gate' has a 150-char description but no output schema; 'log' and 'mark-fire' are write operations with no confirmation or dry-run pattern. Naming is inconsistent (verb_noun for some, noun-only for others). No tool follows the 50-200 char description baseline for LLM optimization.
Export the elements as an Anki-importable TSV deck. Two cards per atom, not one — the minimum-information principle (Wozniak's 20 rules) is explicit that a card testing more than one fact is a card nobody reviews consistently.
V16: enumerate (n−1)-subsets of every molecule's decomposes-into and emit a markdown table of candidate failure-modes. Delivers composition-operations.md §"Why bonds matter".
V54: derive embedding-gate threshold from held-out POS/NEG probe corpus. Prints distributions, sweep table, recommended LEXICON_GATE_THRESHOLD. Builtin corpus in render/internal/embedgate/probe.go; override with LEXICON_CALIB_CORPUS=/path.json.
V16: weighted molecular distance = w_atom·Jaccard(atoms) + w_assembly·TED + w_type·type-mismatch. Zhang-Shasha tree-edit distance over parsed assembly trees. The chess-opening-tree analog.
V13: observability snapshot. Reads ~/.claude/lexicon/{metrics,fires}.jsonl + hook.log; reports file growth, hook latency p50/p95, outcome distribution, estimated API spend, and alerts that catch silent degradation.
2026-09-06: walk each document in the manifest paragraph by paragraph, matching corp.ScoreRaw per paragraph, and emit an ORDERED trace of atom hits — a sequence across a whole document, not a single top-K snapshot like read/what-if. Build-time precompute for the web/ SPA's Trace tab; never called live from the browser.
Output schemas completely undocumented. No tool declares what fields it returns, forcing LLMs to guess structure and parse unstructured text. Example: 'export-graph' returns 'raw JSON' but no schema; 'doctor' returns 'observability snapshot' with no field list.
Descriptions are too terse (10-50 chars for most tools). Baseline for LLM optimization is 50-200 chars. Example: 'hook' = 15 chars, 'matrix' = 35 chars. LLMs cannot determine when/why to select these tools.
Write operations (log, mark-fire, shell, matrix, pivot, want) lack confirmation/dry-run patterns. No guidance on irreversibility or recovery. Agents could accidentally modify state without safeguards.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 33 | 2026-07-28+ | v2 |
2026-08-20: emit viz.Graph as raw JSON — nodes, edges, clusters, precomputed 3D layouts. Same data every HTML renderer inlines at build time; consumed by the web/ frontend's build step.
V96: Tier 1 self-gap-detection — atoms with empty critical-questions, atoms with status: under-review, and unminted candidate sections aggregated across mining-pass docs. Roadmap #13 Tier 1.
Run the deterministic filter+rank against the elements. V13: lens applies when --context is set; --no-lens forces pure lexical re-rank on the full pool, the pre-V13 behavior.
Claude Code UserPromptSubmit hook. Reads JSON from stdin, emits to stdout.
V16: type-check assembly: fields against elements' typed primitives. Surfaces type-mismatches in sequential/parallel/choice, unresolvable atoms (forcing function for next mining pass), and decomposes-into ↔ assembly consistency.
Unified cross-reference linter. One pass over elements + every tracked MD: flags stale lex-NNNN refs, concept-mismatch when cited name disagrees with actual atom name, and unreciprocated related[] edges. Replaces the older check-reciprocation.py + audit-stale-refs.py scripts. Exits non-zero on any error.
Append one per-session vibe entry to session-log.jsonl.
Tag a specific hook fire (by hook_event_id from fires.jsonl) as useful / mixed / not-useful / autonomous.
Standalone single-view page for matrix visualization. Keeps working as stable legacy URL. Canvas2D view has no SPA equivalent yet.
Standalone single-view page for pivot visualization. Keeps working as stable legacy URL. Pivot's own rendering is superseded by the SPA's Pivot tab.
V16: composition-recovery rate + per-entry χ² discriminativity + pairwise firing-pattern redundancy. Replaces the IB framing per round-2 review.
Render one entry in a chosen mode.
V54.2: replay last N V13 fires from ~/.claude/lexicon/fires.jsonl through the V14 embedding gate. Real-world validation — reports silence-rate vs fire-rate, V14 vs V13 agreement on top-atom, V13-pick rank in V14 top-K.
Emit the legacy composed matrix+pivot HTML view. 2026-08-20: legacy view, superseded as the landing page by the web/ SPA — kept for its matrix Canvas2D tab, which the SPA doesn't have yet. Emits matrix + pivot as tabs + persistent detail pane. Mobile-responsive.
Pick N entries at random and render each.
V13: explicit oblique-provocation draw. Pure random N primitives from elements, framed as Eno cards. Hook auto-fires this same shape inline when lens detects stuck-signals; this is the manual override for when you want to draw regardless of signal.
V117 n: verify wanted-materials.md TOP block items against lexicon/refs/, plus any dirs in LEXICON_SIBLING_REFS_DIRS (optional, colon-separated). Author surname required for PRESENT verdict; year-only matches → AMBIGUOUS.
V25: fetch Wikipedia article via local gozimhttpd, pipe through pandoc for verbatim staking. Assumes gozimhttpd is running on the given port; start manually with 'gozimhttpd -path <zim> -port N'.
Parameter descriptions are minimal or missing type constraints. Example: 'mode' param in render/shuffle has no enum values; 'filter' in shuffle has no format spec; 'seed' in tarot has no range. LLMs will hallucinate invalid values.
No error handling guidance. Tools return success/failure with no recovery hints. Example: 'gate' filters results but no guidance on empty results; 'zim-fetch' requires external gozimhttpd but no error message if port is unreachable.