mirror of
https://github.com/codician-team/growmos.git
synced 2026-08-18 06:47:17 +02:00
157 lines
41 KiB
HTML
157 lines
41 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>growmos · growmos</title>
|
||
<style>
|
||
:root { --bg:#0b0f17; --panel:#111827; --line:#1f2937; --text:#e5e7eb; --muted:#9ca3af; --accent:#7dd3fc; }
|
||
* { box-sizing:border-box; }
|
||
html,body { margin:0; height:100%; background:var(--bg); color:var(--text); font:14px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Inter,sans-serif; }
|
||
#top { position:fixed; top:0; left:0; right:0; height:52px; display:flex; align-items:center; gap:12px; padding:0 16px; background:linear-gradient(180deg,rgba(11,15,23,.98),rgba(11,15,23,.85)); border-bottom:1px solid var(--line); z-index:5; }
|
||
#top h1 { font-size:15px; font-weight:600; margin:0; letter-spacing:.2px; white-space:nowrap; }
|
||
#top h1 span { color:var(--muted); font-weight:400; }
|
||
#search { flex:0 0 260px; background:var(--panel); border:1px solid var(--line); color:var(--text); border-radius:8px; padding:7px 10px; outline:none; }
|
||
#search:focus { border-color:var(--accent); }
|
||
#stats { color:var(--muted); font-size:12px; margin-left:auto; white-space:nowrap; }
|
||
#legend { display:flex; gap:6px; flex-wrap:nowrap; overflow-x:auto; max-width:45vw; scrollbar-width:none; }
|
||
.chip { display:inline-flex; align-items:center; gap:6px; padding:3px 9px; border-radius:999px; border:1px solid var(--line); background:var(--panel); font-size:11px; cursor:pointer; user-select:none; }
|
||
.chip i { width:9px; height:9px; border-radius:50%; display:inline-block; }
|
||
.chip.off { opacity:.35; }
|
||
canvas { position:fixed; inset:0; top:52px; cursor:grab; }
|
||
canvas.grabbing { cursor:grabbing; }
|
||
#card { position:fixed; top:64px; right:16px; width:380px; max-height:calc(100% - 80px); overflow:auto; background:var(--panel); border:1px solid var(--line); border-radius:12px; padding:14px 16px; display:none; z-index:6; box-shadow:0 20px 50px rgba(0,0,0,.5); }
|
||
#card h2 { margin:0 0 2px; font-size:16px; }
|
||
#card .type { color:var(--muted); font-size:12px; margin-bottom:8px; }
|
||
#card p { margin:6px 0; }
|
||
#card h3 { font-size:12px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); margin:14px 0 6px; }
|
||
#card ul { margin:0; padding-left:16px; }
|
||
#card li { margin:3px 0; }
|
||
#card .prov { color:var(--muted); font-size:11px; }
|
||
#card a.node { color:var(--accent); cursor:pointer; text-decoration:none; }
|
||
#card .close { position:absolute; top:8px; right:12px; color:var(--muted); cursor:pointer; font-size:18px; }
|
||
#hint { position:fixed; left:16px; bottom:12px; color:var(--muted); font-size:11px; }
|
||
#card .stale { color:#fbbf24; font-size:11px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="top">
|
||
<h1>growmos <span>· growmos</span></h1>
|
||
<input id="search" placeholder="search entities… (enter to focus)" autocomplete="off">
|
||
<div id="legend"></div>
|
||
<div id="stats"></div>
|
||
</div>
|
||
<canvas id="c"></canvas>
|
||
<div id="card"><span class="close" onclick="closeCard()">×</span><div id="cardbody"></div></div>
|
||
<div id="hint">drag to pan · wheel to zoom · drag nodes · click a node for its card · double-click background to reset</div>
|
||
<script id="data" type="application/json">{"entities": [{"id": "artifact/aliases-jsonl", "name": "aliases.jsonl", "type": "ARTIFACT", "description": "Alias-to-entity map.", "sources": ["src_3fd317a2cb2b"], "provisional": false}, {"id": "artifact/entities-jsonl", "name": "entities.jsonl", "type": "ARTIFACT", "description": "Canonical nodes with stable type/slug ids, description, sources, mentions and provisional flag.", "sources": ["src_3fd317a2cb2b"], "provisional": false}, {"id": "artifact/gold-set", "name": "Gold set", "type": "ARTIFACT", "description": "Hand-corrected per-document JSON of expected entities and (source,target) relation pairs under .growmos/eval/gold/.", "sources": ["src_15e0af4a3dd5"], "provisional": false}, {"id": "artifact/mentions-jsonl", "name": "mentions.jsonl", "type": "ARTIFACT", "description": "Append-only raw per-document extraction output; provenance.", "sources": ["src_3fd317a2cb2b"], "provisional": false}, {"id": "artifact/relations-jsonl", "name": "relations.jsonl", "type": "ARTIFACT", "description": "Edges with predicate, sources, confidence (= corroborating sources) and optional when range.", "sources": ["src_3fd317a2cb2b"], "provisional": false}, {"id": "artifact/schema-json", "name": "schema.json", "type": "ARTIFACT", "description": "Versioned entity types and predicate hints with history.", "sources": ["src_3fd317a2cb2b"], "provisional": false}, {"id": "artifact/scorer-alias-map", "name": "Scorer alias map", "type": "ARTIFACT", "description": ".growmos/eval/aliases.json mapping canonical forms to gold names so scoring artifacts don't count as misses.", "sources": ["src_15e0af4a3dd5"], "provisional": false}, {"id": "artifact/sources-jsonl", "name": "sources.jsonl", "type": "ARTIFACT", "description": "Every document eaten with ref, kind, sha256 and status (pending, extracted, note, missing).", "sources": ["src_3fd317a2cb2b"], "provisional": false}, {"id": "component/ci-workflow", "name": "CI workflow", "type": "COMPONENT", "description": ".github/workflows/growmos.yml running status, doctor and eval on PRs.", "sources": ["src_a384388adcb2"], "provisional": false}, {"id": "component/evaluation-harness", "name": "Evaluation harness", "type": "COMPONENT", "description": "Gold sets, growmos eval P/R/F1, the ten-item growmos doctor checklist and growmos sample.", "sources": ["src_b33563055168", "src_15e0af4a3dd5"], "provisional": false}, {"id": "component/git-hooks", "name": "Git hooks", "type": "COMPONENT", "description": "post-commit, post-merge, post-checkout hooks that run growmos scan --quiet to queue changed docs.", "sources": ["src_a384388adcb2"], "provisional": false}, {"id": "component/graph-engine-graph-py", "name": "Graph engine (graph.py)", "type": "COMPONENT", "description": "Adjacency, k-hop traversal, triple serialization with provenance, diagnostics, seed finding, deterministic claim checking, sampling.", "sources": ["src_7a4afa70f300"], "provisional": false}, {"id": "component/graphstore-store-py", "name": "GraphStore (store.py)", "type": "COMPONENT", "description": "Python module implementing the .growmos store: load/save JSONL tables, register sources, apply extraction/resolution, merge entities, remember/link/journal.", "sources": ["src_7a4afa70f300"], "provisional": false}, {"id": "component/growmos-store", "name": ".growmos store", "type": "COMPONENT", "description": "Plain JSONL store: sources, mentions, entities, aliases, relations, profiles, prompts, eval, journal — committed with the code.", "sources": ["src_b33563055168", "src_3fd317a2cb2b"], "provisional": false}, {"id": "component/mcp-server", "name": "MCP server", "type": "COMPONENT", "description": "growmos mcp: a zero-dependency MCP stdio server exposing growmos_query, growmos_remember, growmos_link and other tools.", "sources": ["src_b33563055168"], "provisional": false}, {"id": "component/packet-builder-prompts-py", "name": "Packet builder (prompts.py)", "type": "COMPONENT", "description": "Builds extraction/resolution/profile/query/check task packets from editable prompt templates; chunks long docs at section boundaries with overlap.", "sources": ["src_7a4afa70f300"], "provisional": false}, {"id": "concept/agent-protocol", "name": "Agent protocol", "type": "CONCEPT", "description": "Six-step loop agents follow: context at start, query for cross-cutting questions, remember/link/journal, next→apply, check before asserting, journal at end.", "sources": ["src_a384388adcb2"], "provisional": false}, {"id": "concept/anthropic-knowledge-graph-playbook", "name": "Anthropic Knowledge Graph Playbook", "type": "CONCEPT", "description": "The four-stage extraction→resolution→assembly→querying methodology with an evaluation loop that growmos implements.", "sources": ["src_b33563055168", "src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/assembly", "name": "Assembly", "type": "CONCEPT", "description": "Deterministic stage: multi-digraph assembly with diagnostics (components, degree, density, compression) and hub profiles.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/evaluation-loop", "name": "Evaluation loop", "type": "CONCEPT", "description": "Gold set plus scorer alias map; change prompt, rerun scorer, watch F1 move.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/evaluator-optimizer-pattern", "name": "Evaluator-optimizer pattern", "type": "CONCEPT", "description": "Agent pattern where the graph is the grounding layer: the evaluator checks claims against edges with provenance.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/extraction", "name": "Extraction", "type": "CONCEPT", "description": "Judgment stage: per-chunk prompt extracting central entities with grounded descriptions and short-verb-phrase relations; fast model.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/living-knowledge-graph-methodology", "name": "Living Knowledge Graph methodology", "type": "CONCEPT", "description": "Tool-agnostic method for a repository knowledge graph that eats new material, grows, resolves itself, answers with citations, measures its health and never forgets.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/model-split", "name": "Model split", "type": "CONCEPT", "description": "Fast cheap model for extraction, stronger reasoning model for resolution, summarization and answering (playbook Table IV).", "sources": ["src_644a9dc71c36"], "provisional": false}, {"id": "concept/orchestrator-workers-pattern", "name": "Orchestrator-workers pattern", "type": "CONCEPT", "description": "Agent pattern where the graph is the shared memory workers read and write so the orchestrator's window stays clean.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/provisional-entity", "name": "Provisional entity", "type": "CONCEPT", "description": "An unmatched extracted name kept as a single-element cluster until resolution — nothing is silently lost.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/querying", "name": "Querying", "type": "CONCEPT", "description": "Judgment stage: seed entities, k-hop subgraph serialized as triples with edge ids and provenance, answer only from it.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/readiness-checklist", "name": "Readiness checklist", "type": "CONCEPT", "description": "Ten items: gold set, alias map, schema version, extraction cap, resolution fallback, provenance, incremental update, connectivity monitor, summarization trigger, human sample.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/resolution", "name": "Resolution", "type": "CONCEPT", "description": "Judgment stage: cluster provisional surface forms per entity type using descriptions after cheap token blocking; reasoning model.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "concept/task-packet", "name": "Task packet", "type": "CONCEPT", "description": "Unit of judgment work growmos hands to an agent: prompt, JSON shape and the exact growmos apply command.", "sources": ["src_b33563055168"], "provisional": false}, {"id": "concept/write-path", "name": "Write path", "type": "CONCEPT", "description": "remember/link/journal commands by which agents record durable knowledge with session provenance while developing.", "sources": ["src_5dd15b5b20d6"], "provisional": false}, {"id": "decision/provenance-rule", "name": "Provenance rule", "type": "DECISION", "description": "No feature may create an edge without a source.", "sources": ["src_eca12c0a30e2"], "provisional": false}, {"id": "decision/zero-dependency-rule", "name": "Zero-dependency rule", "type": "DECISION", "description": "The core must remain stdlib-only so growmos drops into any repo; optional integrations degrade gracefully.", "sources": ["src_eca12c0a30e2"], "provisional": false}, {"id": "dependency/anthropic-api", "name": "Anthropic API", "type": "DEPENDENCY", "description": "Provider used with ANTHROPIC_API_KEY; structured outputs via output_config json_schema.", "sources": ["src_644a9dc71c36"], "provisional": false}, {"id": "dependency/openai-compatible-api", "name": "OpenAI-compatible API", "type": "DEPENDENCY", "description": "Provider used with OPENAI_API_KEY or GROWMOS_BASE_URL; response_format json_schema.", "sources": ["src_644a9dc71c36"], "provisional": false}, {"id": "dependency/xai-api", "name": "xAI API", "type": "DEPENDENCY", "description": "Grok provider used with XAI_API_KEY.", "sources": ["src_644a9dc71c36"], "provisional": false}, {"id": "feature/growmos-view-view-html", "name": "growmos view (view.html)", "type": "FEATURE", "description": "Self-contained interactive HTML explorer of the graph: force layout, search, type filters, node cards with profile, edges and provenance; growmos view opens it, export --format html writes it.", "sources": ["src_a384388adcb2"], "provisional": true}, {"id": "feature/headless-mode", "name": "Headless mode", "type": "FEATURE", "description": "growmos ingest calls Anthropic, OpenAI-compatible or xAI APIs directly for cron and CI, following the playbook's fast-vs-reasoning model split.", "sources": ["src_b33563055168", "src_644a9dc71c36"], "provisional": false}, {"id": "feature/presets", "name": "Presets", "type": "FEATURE", "description": "software, general, research and business entity-type vocabularies sharing the same prompts.", "sources": ["src_b33563055168"], "provisional": false}, {"id": "organization/codician", "name": "Codician", "type": "ORGANIZATION", "description": "Company (codician.com) that builds and maintains growmos under the MIT license.", "sources": ["src_b33563055168", "src_eca12c0a30e2"], "provisional": false}, {"id": "tool/claude-code", "name": "Claude Code", "type": "TOOL", "description": "Agent CLI integrated via CLAUDE.md block, a growmos skill, SessionStart/Stop hooks and .mcp.json.", "sources": ["src_b33563055168", "src_a384388adcb2"], "provisional": false}, {"id": "tool/codex-cli", "name": "Codex CLI", "type": "TOOL", "description": "Agent CLI integrated via an AGENTS.md block and optional MCP server.", "sources": ["src_b33563055168", "src_a384388adcb2"], "provisional": false}, {"id": "tool/cursor", "name": "Cursor", "type": "TOOL", "description": "Editor integrated via .cursor/rules/growmos.mdc (alwaysApply).", "sources": ["src_b33563055168", "src_a384388adcb2"], "provisional": false}, {"id": "tool/gemini-cli", "name": "Gemini CLI", "type": "TOOL", "description": "Agent CLI integrated via a GEMINI.md block.", "sources": ["src_b33563055168", "src_a384388adcb2"], "provisional": false}, {"id": "tool/grok-cli", "name": "Grok CLI", "type": "TOOL", "description": "Agent CLI integrated via AGENTS.md and .mcp.json.", "sources": ["src_b33563055168", "src_a384388adcb2"], "provisional": false}, {"id": "tool/growmos", "name": "growmos", "type": "TOOL", "description": "A zero-dependency CLI and .growmos/ store that keeps a living, provenance-carrying knowledge graph inside a repository for humans and AI agents.", "sources": ["src_b33563055168", "src_5dd15b5b20d6", "src_a384388adcb2", "src_eca12c0a30e2"], "provisional": false}, {"id": "tool/growmos-eval", "name": "growmos eval", "type": "TOOL", "description": "Command scoring raw and resolved entities and relation pairs against the gold set.", "sources": ["src_15e0af4a3dd5"], "provisional": false}, {"id": "tool/growmos-sample", "name": "growmos sample", "type": "TOOL", "description": "Command printing a random degree-weighted node for the human comprehension check; doctor warns after 7 days.", "sources": ["src_15e0af4a3dd5"], "provisional": false}], "relations": [{"id": "r_0212ea0a625b", "source": "concept/write-path", "target": "concept/living-knowledge-graph-methodology", "predicate": "part of", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_10c9e8a2efd1", "source": "artifact/aliases-jsonl", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_3fd317a2cb2b"], "confidence": 1}, {"id": "r_11f3b0667ec2", "source": "component/ci-workflow", "target": "tool/growmos", "predicate": "part of", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_13713794321b", "source": "concept/resolution", "target": "concept/living-knowledge-graph-methodology", "predicate": "part of", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_14150a04bf37", "source": "tool/growmos", "target": "tool/codex-cli", "predicate": "integrates with", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_1ec2ab741f21", "source": "feature/presets", "target": "tool/growmos", "predicate": "part of", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_22bfcd0aa8b2", "source": "tool/growmos", "target": "decision/provenance-rule", "predicate": "governed by", "sources": ["src_eca12c0a30e2"], "confidence": 1}, {"id": "r_27697452cc8d", "source": "artifact/relations-jsonl", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_3fd317a2cb2b"], "confidence": 1}, {"id": "r_2843334f8415", "source": "feature/headless-mode", "target": "dependency/anthropic-api", "predicate": "calls", "sources": ["src_644a9dc71c36"], "confidence": 1}, {"id": "r_2fb7afc62a09", "source": "concept/evaluation-loop", "target": "concept/extraction", "predicate": "tunes", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_308dac5cb53b", "source": "artifact/schema-json", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_3fd317a2cb2b"], "confidence": 1}, {"id": "r_32f6545238ee", "source": "tool/growmos", "target": "tool/cursor", "predicate": "integrates with", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_346861c0544a", "source": "concept/living-knowledge-graph-methodology", "target": "concept/anthropic-knowledge-graph-playbook", "predicate": "synthesizes", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_38bd3a66194d", "source": "tool/gemini-cli", "target": "concept/agent-protocol", "predicate": "follows", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_3b6d37efba09", "source": "component/graph-engine-graph-py", "target": "component/graphstore-store-py", "predicate": "depends on", "sources": ["src_7a4afa70f300"], "confidence": 1}, {"id": "r_3c068163c973", "source": "component/packet-builder-prompts-py", "target": "component/graphstore-store-py", "predicate": "depends on", "sources": ["src_7a4afa70f300"], "confidence": 1}, {"id": "r_3e6b5ce7ae5d", "source": "tool/growmos-sample", "target": "component/evaluation-harness", "predicate": "part of", "sources": ["src_15e0af4a3dd5"], "confidence": 1}, {"id": "r_455737c6171f", "source": "feature/growmos-view-view-html", "target": "tool/growmos", "predicate": "part of", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_5160f89fa514", "source": "tool/growmos", "target": "concept/anthropic-knowledge-graph-playbook", "predicate": "implements", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_51b0f6496aa6", "source": "component/mcp-server", "target": "tool/growmos", "predicate": "calls", "sources": ["src_7a4afa70f300"], "confidence": 1}, {"id": "r_56711eca826a", "source": "tool/growmos-eval", "target": "artifact/scorer-alias-map", "predicate": "uses", "sources": ["src_15e0af4a3dd5"], "confidence": 1}, {"id": "r_5b9d2bb8f0bb", "source": "feature/headless-mode", "target": "dependency/openai-compatible-api", "predicate": "calls", "sources": ["src_644a9dc71c36"], "confidence": 1}, {"id": "r_5f163f8172ca", "source": "artifact/scorer-alias-map", "target": "component/evaluation-harness", "predicate": "part of", "sources": ["src_15e0af4a3dd5"], "confidence": 1}, {"id": "r_650d34b53709", "source": "tool/cursor", "target": "concept/agent-protocol", "predicate": "follows", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_65259ee2955c", "source": "tool/claude-code", "target": "concept/agent-protocol", "predicate": "follows", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_652a04bd6d17", "source": "tool/growmos", "target": "decision/zero-dependency-rule", "predicate": "governed by", "sources": ["src_eca12c0a30e2"], "confidence": 1}, {"id": "r_68da442e5cf3", "source": "concept/extraction", "target": "concept/provisional-entity", "predicate": "produces", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_6ea967cb4180", "source": "tool/growmos", "target": "concept/task-packet", "predicate": "hands out", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_722dbdb73aeb", "source": "artifact/entities-jsonl", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_3fd317a2cb2b"], "confidence": 1}, {"id": "r_78156d988b02", "source": "concept/querying", "target": "concept/living-knowledge-graph-methodology", "predicate": "part of", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_7901f7de4616", "source": "concept/readiness-checklist", "target": "concept/evaluation-loop", "predicate": "part of", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_81cd10733e5a", "source": "artifact/sources-jsonl", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_3fd317a2cb2b"], "confidence": 1}, {"id": "r_92fff4079589", "source": "tool/growmos", "target": "tool/gemini-cli", "predicate": "integrates with", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_947da8670cc2", "source": "tool/growmos", "target": "tool/claude-code", "predicate": "integrates with", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_9c69704588e7", "source": "organization/codician", "target": "tool/growmos", "predicate": "maintains", "sources": ["src_eca12c0a30e2"], "confidence": 1}, {"id": "r_9e1a93e68a4f", "source": "tool/growmos", "target": "tool/grok-cli", "predicate": "integrates with", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_a0e9c85f311d", "source": "tool/codex-cli", "target": "concept/agent-protocol", "predicate": "follows", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_a2f221212adc", "source": "concept/extraction", "target": "concept/living-knowledge-graph-methodology", "predicate": "part of", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_b1bf090bc23e", "source": "artifact/gold-set", "target": "component/evaluation-harness", "predicate": "part of", "sources": ["src_15e0af4a3dd5"], "confidence": 1}, {"id": "r_bbb063019ebe", "source": "component/git-hooks", "target": "tool/growmos", "predicate": "part of", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_bddb08312708", "source": "artifact/mentions-jsonl", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_3fd317a2cb2b"], "confidence": 1}, {"id": "r_c0964ad848b5", "source": "tool/growmos-eval", "target": "artifact/gold-set", "predicate": "scores against", "sources": ["src_15e0af4a3dd5"], "confidence": 1}, {"id": "r_c288f1aabccc", "source": "concept/living-knowledge-graph-methodology", "target": "concept/orchestrator-workers-pattern", "predicate": "serves as shared memory in", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_c6d4e8696844", "source": "component/graphstore-store-py", "target": "component/growmos-store", "predicate": "part of", "sources": ["src_7a4afa70f300"], "confidence": 1}, {"id": "r_d242f3144a3e", "source": "tool/grok-cli", "target": "concept/agent-protocol", "predicate": "follows", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_d358d74e8947", "source": "organization/codician", "target": "tool/growmos", "predicate": "develops", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_e033d480e42a", "source": "component/evaluation-harness", "target": "tool/growmos", "predicate": "part of", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_e0c717508446", "source": "component/growmos-store", "target": "tool/growmos", "predicate": "part of", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_e25a6915810a", "source": "tool/growmos", "target": "concept/agent-protocol", "predicate": "defines", "sources": ["src_a384388adcb2"], "confidence": 1}, {"id": "r_e6128f133ed7", "source": "feature/headless-mode", "target": "tool/growmos", "predicate": "part of", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_e733dd798448", "source": "component/mcp-server", "target": "tool/growmos", "predicate": "part of", "sources": ["src_b33563055168"], "confidence": 1}, {"id": "r_e787550d8d8a", "source": "concept/living-knowledge-graph-methodology", "target": "concept/evaluator-optimizer-pattern", "predicate": "serves as grounding layer in", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_ec624e478cf1", "source": "tool/growmos", "target": "concept/living-knowledge-graph-methodology", "predicate": "implements", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_f1c709004713", "source": "feature/headless-mode", "target": "concept/model-split", "predicate": "follows", "sources": ["src_644a9dc71c36"], "confidence": 1}, {"id": "r_f6e21b56bb95", "source": "concept/resolution", "target": "concept/provisional-entity", "predicate": "clusters", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_f97713872e12", "source": "concept/assembly", "target": "concept/living-knowledge-graph-methodology", "predicate": "part of", "sources": ["src_5dd15b5b20d6"], "confidence": 1}, {"id": "r_fc49eddc6240", "source": "feature/headless-mode", "target": "dependency/xai-api", "predicate": "calls", "sources": ["src_644a9dc71c36"], "confidence": 1}], "profiles": {"concept/living-knowledge-graph-methodology": {"entity": "concept/living-knowledge-graph-methodology", "key_facts": ["Four stages: extraction, resolution, assembly, querying (METHODOLOGY.md)", "Unmatched names become provisional single-element clusters — nothing is silently lost (METHODOLOGY.md)", "The write path (remember, link, journal) records agent knowledge with session provenance (METHODOLOGY.md)", "The evaluation loop and the ten-item readiness checklist provide homeostasis (METHODOLOGY.md)", "Serves as shared memory in orchestrator–workers and grounding layer in evaluator–optimizer patterns (METHODOLOGY.md)"], "sources_hash": "f77f8bc4e015", "summary": "The Living Knowledge Graph methodology is the tool-agnostic method growmos implements: a repository knowledge graph that eats new material, grows by accretion, resolves its own surface forms, answers with edge citations, measures its health and never forgets. It synthesizes the Anthropic playbook's four stages and agent patterns and adds what a living graph in a developing repository needs.\n\nIts stages are extraction (fast model, central entities with grounded descriptions), resolution (reasoning model clustering provisional entities after cheap blocking), deterministic assembly with diagnostics and hub profiles, and grounded querying over k-hop subgraphs. The write path (remember/link/journal) lets agents record durable knowledge with session provenance while developing, and the evaluation loop plus the ten-item readiness checklist keep it honest. In agent architectures the graph acts as shared memory for orchestrator–workers and as the grounding layer for evaluator–optimizer loops.", "time_range": {"end": "ongoing", "start": "2026"}, "ts": "2026-08-17T11:51:11Z", "stale": false}, "tool/growmos": {"entity": "tool/growmos", "key_facts": ["Developed by Codician under the MIT license (README.md, CONTRIBUTING.md)", "Implements the Anthropic Knowledge Graph Playbook and the Living Knowledge Graph methodology (README.md, METHODOLOGY.md)", "Hands judgment work to agents as task packets; no API key needed in agent-native mode (README.md, docs/agents.md)", "Integrates with Claude Code, Codex CLI, Grok CLI, Cursor and Gemini CLI, plus git hooks, CI and an MCP server (docs/agents.md)", "Governed by the zero-dependency rule and the provenance rule (CONTRIBUTING.md)"], "sources_hash": "9a409667a528", "summary": "growmos is a zero-dependency Python CLI plus a plain-JSONL `.growmos/` store that keeps a living, provenance-carrying knowledge graph inside a repository. It is developed and maintained by Codician (codician.com) under the MIT license and implements the Anthropic knowledge-graph playbook's four stages — extraction, resolution, assembly, querying — with an evaluation loop closing the circle.\n\nIt is agent-native: the CLI performs the deterministic work (storage, hashing, blocking, assembly, traversal, diagnostics, scoring) and hands judgment work to whatever agent CLI the user runs as task packets (prompt + JSON shape + apply command). It integrates with Claude Code, Codex CLI, Grok CLI, Cursor and Gemini CLI through instruction-file blocks, a Claude skill and hooks, git hooks, a CI workflow, and a built-in MCP stdio server. Optional headless mode calls Anthropic, OpenAI-compatible or xAI APIs directly for cron and CI runs.\n\nTwo governing decisions shape it: the core stays stdlib-only, and no feature may create an edge without provenance.", "time_range": {"end": "ongoing", "start": "2026"}, "ts": "2026-08-17T11:51:11Z", "stale": false}}, "aliases": {"artifact/aliases-jsonl": ["aliases.jsonl"], "artifact/entities-jsonl": ["entities.jsonl"], "artifact/gold-set": ["Gold set"], "artifact/mentions-jsonl": ["mentions.jsonl"], "artifact/relations-jsonl": ["relations.jsonl"], "artifact/schema-json": ["schema.json"], "artifact/scorer-alias-map": ["Scorer alias map"], "artifact/sources-jsonl": ["sources.jsonl"], "component/ci-workflow": ["CI workflow"], "component/evaluation-harness": ["Evaluation harness"], "component/git-hooks": ["Git hooks"], "component/graph-engine-graph-py": ["Graph engine (graph.py)"], "component/graphstore-store-py": ["GraphStore (store.py)"], "component/growmos-store": [".growmos store"], "component/mcp-server": ["MCP server"], "component/packet-builder-prompts-py": ["Packet builder (prompts.py)"], "concept/agent-protocol": ["Agent protocol"], "concept/anthropic-knowledge-graph-playbook": ["Anthropic Knowledge Graph Playbook"], "concept/assembly": ["Assembly"], "concept/evaluation-loop": ["Evaluation loop"], "concept/evaluator-optimizer-pattern": ["Evaluator-optimizer pattern"], "concept/extraction": ["Extraction"], "concept/living-knowledge-graph-methodology": ["Living Knowledge Graph methodology"], "concept/model-split": ["Model split"], "concept/orchestrator-workers-pattern": ["Orchestrator-workers pattern"], "concept/provisional-entity": ["Provisional entity"], "concept/querying": ["Querying"], "concept/readiness-checklist": ["Readiness checklist"], "concept/resolution": ["Resolution"], "concept/task-packet": ["Task packet"], "concept/write-path": ["Write path"], "decision/provenance-rule": ["Provenance rule"], "decision/zero-dependency-rule": ["Zero-dependency rule"], "dependency/anthropic-api": ["Anthropic API"], "dependency/openai-compatible-api": ["OpenAI-compatible API"], "dependency/xai-api": ["xAI API"], "feature/growmos-view-view-html": ["growmos view (view.html)"], "feature/headless-mode": ["Headless mode"], "feature/presets": ["Presets"], "organization/codician": ["Codician"], "tool/claude-code": ["Claude Code"], "tool/codex-cli": ["Codex CLI"], "tool/cursor": ["Cursor"], "tool/gemini-cli": ["Gemini CLI"], "tool/grok-cli": ["Grok CLI"], "tool/growmos": ["growmos"], "tool/growmos-eval": ["growmos eval"], "tool/growmos-sample": ["growmos sample"]}, "sources": {"src_15e0af4a3dd5": "docs/evaluation.md", "src_17ed18489a95": "docs/configuration.md", "src_3fd317a2cb2b": "docs/file-format.md", "src_5dd15b5b20d6": "METHODOLOGY.md", "src_644a9dc71c36": "docs/headless.md", "src_7a4afa70f300": "session:2026-08-17 build", "src_a384388adcb2": "docs/agents.md", "src_b33563055168": "README.md", "src_eca12c0a30e2": "CONTRIBUTING.md"}, "meta": {"components": 1, "density": 1.19, "schema_version": 1, "generated": "2026-08-17 12:52", "focus": ""}}</script>
|
||
<script>
|
||
(function(){
|
||
const DATA = JSON.parse(document.getElementById('data').textContent);
|
||
const PALETTE = ['#7dd3fc','#f9a8d4','#86efac','#fcd34d','#c4b5fd','#fda4af','#5eead4','#fdba74','#a5b4fc','#bef264','#f0abfc','#67e8f9','#fca5a5','#d9f99d'];
|
||
const types = [...new Set(DATA.entities.map(e=>e.type))].sort();
|
||
const color = Object.fromEntries(types.map((t,i)=>[t,PALETTE[i%PALETTE.length]]));
|
||
const hidden = new Set();
|
||
|
||
// ---- graph model
|
||
const nodes = DATA.entities.map(e=>({...e, x:0,y:0,vx:0,vy:0, deg:0}));
|
||
const byId = Object.fromEntries(nodes.map(n=>[n.id,n]));
|
||
const links = DATA.relations.filter(r=>byId[r.source]&&byId[r.target]).map(r=>({...r, s:byId[r.source], t:byId[r.target]}));
|
||
links.forEach(l=>{l.s.deg++; l.t.deg++;});
|
||
const maxDeg = Math.max(1,...nodes.map(n=>n.deg));
|
||
const R = n => 6 + 18*Math.sqrt(n.deg/maxDeg);
|
||
// initial layout: hubs near center, radial by degree
|
||
nodes.forEach((n,i)=>{ const a=i*2.399963, r=80+ (1-n.deg/maxDeg)*Math.min(innerWidth,innerHeight)*0.35; n.x=Math.cos(a)*r; n.y=Math.sin(a)*r; });
|
||
|
||
// ---- canvas + camera
|
||
const cv=document.getElementById('c'), ctx=cv.getContext('2d');
|
||
let W,H,dpr; const cam={x:0,y:0,k:1};
|
||
function resize(){ dpr=devicePixelRatio||1; W=innerWidth; H=innerHeight-52; cv.width=W*dpr; cv.height=H*dpr; cv.style.width=W+'px'; cv.style.height=H+'px'; }
|
||
addEventListener('resize',resize); resize();
|
||
const toScreen=(x,y)=>[(x-cam.x)*cam.k+W/2,(y-cam.y)*cam.k+H/2];
|
||
const toWorld=(sx,sy)=>[(sx-W/2)/cam.k+cam.x,(sy-H/2)/cam.k+cam.y];
|
||
|
||
// ---- force simulation (simple, good enough for a few thousand edges)
|
||
let alpha=1, hover=null, selected=null, dragging=null;
|
||
function step(){
|
||
const vis = nodes.filter(n=>!hidden.has(n.type));
|
||
const n=vis.length; if(!n) return;
|
||
// repulsion (O(n^2) with cutoff; fine up to ~1500 nodes)
|
||
for(let i=0;i<n;i++){ const a=vis[i]; for(let j=i+1;j<n;j++){ const b=vis[j]; let dx=b.x-a.x, dy=b.y-a.y; let d2=dx*dx+dy*dy+0.01; if(d2>250000) continue; const f=900/d2; dx*=f; dy*=f; a.vx-=dx; a.vy-=dy; b.vx+=dx; b.vy+=dy; } }
|
||
// springs
|
||
for(const l of links){ if(hidden.has(l.s.type)||hidden.has(l.t.type)) continue; const dx=l.t.x-l.s.x, dy=l.t.y-l.s.y, d=Math.sqrt(dx*dx+dy*dy)+0.01; const want=60+R(l.s)+R(l.t); const f=(d-want)*0.02; const fx=dx/d*f, fy=dy/d*f; l.s.vx+=fx; l.s.vy+=fy; l.t.vx-=fx; l.t.vy-=fy; }
|
||
// gravity + integrate
|
||
for(const a of vis){ if(a===dragging) {a.vx=a.vy=0; continue;} a.vx+=-a.x*0.006; a.vy+=-a.y*0.006; a.vx*=0.82; a.vy*=0.82; a.x+=a.vx*alpha; a.y+=a.vy*alpha; }
|
||
alpha=Math.max(0.05, alpha*0.995);
|
||
}
|
||
|
||
// ---- drawing
|
||
function draw(){
|
||
ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,W,H);
|
||
const focus = selected||hover; const nb = new Set(); if(focus){ nb.add(focus.id); links.forEach(l=>{ if(l.s===focus) nb.add(l.t.id); if(l.t===focus) nb.add(l.s.id); }); }
|
||
// edges
|
||
for(const l of links){ if(hidden.has(l.s.type)||hidden.has(l.t.type)) continue;
|
||
const [x1,y1]=toScreen(l.s.x,l.s.y), [x2,y2]=toScreen(l.t.x,l.t.y);
|
||
const lit = focus && (l.s===focus||l.t===focus);
|
||
ctx.strokeStyle = lit ? 'rgba(125,211,252,.9)' : (focus ? 'rgba(148,163,184,.08)' : 'rgba(148,163,184,.25)');
|
||
ctx.lineWidth = lit ? 1.6 : (0.6 + Math.min(l.confidence||1,4)*0.35);
|
||
ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke();
|
||
// arrow head
|
||
const ang=Math.atan2(y2-y1,x2-x1), rt=R(l.t)*cam.k+2, ax=x2-Math.cos(ang)*rt, ay=y2-Math.sin(ang)*rt;
|
||
ctx.fillStyle=ctx.strokeStyle; ctx.beginPath(); ctx.moveTo(ax,ay); ctx.lineTo(ax-Math.cos(ang-0.5)*7, ay-Math.sin(ang-0.5)*7); ctx.lineTo(ax-Math.cos(ang+0.5)*7, ay-Math.sin(ang+0.5)*7); ctx.closePath(); ctx.fill();
|
||
if(lit && cam.k>0.6){ ctx.fillStyle='rgba(229,231,235,.9)'; ctx.font='11px sans-serif'; ctx.fillText(l.predicate,(x1+x2)/2+4,(y1+y2)/2-4); }
|
||
}
|
||
// nodes
|
||
const q=(document.getElementById('search').value||'').toLowerCase();
|
||
for(const n of nodes){ if(hidden.has(n.type)) continue;
|
||
const [x,y]=toScreen(n.x,n.y), r=R(n)*cam.k;
|
||
const dim = (focus && !nb.has(n.id)) || (q && !n.name.toLowerCase().includes(q));
|
||
ctx.globalAlpha = dim ? 0.18 : 1;
|
||
ctx.fillStyle=color[n.type]; ctx.beginPath(); ctx.arc(x,y,r,0,Math.PI*2); ctx.fill();
|
||
if(n===selected){ ctx.strokeStyle='#fff'; ctx.lineWidth=2; ctx.stroke(); }
|
||
if(r>5 || (n.deg>=2 && cam.k>0.45) || n===focus || nb.has(n.id) || (q&&!dim)){ ctx.fillStyle='rgba(229,231,235,.95)'; ctx.font=(n.deg>=maxDeg*0.5?'600 ':'')+Math.max(10,Math.min(14,10+r/2))+'px sans-serif'; ctx.fillText(n.name, x+r+4, y+4); }
|
||
ctx.globalAlpha=1;
|
||
}
|
||
}
|
||
function fit(pad){ const vis=nodes.filter(n=>!hidden.has(n.type)); if(!vis.length) return; let x0=1e9,y0=1e9,x1=-1e9,y1=-1e9; for(const n of vis){ x0=Math.min(x0,n.x); y0=Math.min(y0,n.y); x1=Math.max(x1,n.x); y1=Math.max(y1,n.y); } cam.x=(x0+x1)/2; cam.y=(y0+y1)/2; cam.k=Math.min(2.5, Math.max(0.2, Math.min(W/((x1-x0)+2*(pad||60)), H/((y1-y0)+2*(pad||60))))); }
|
||
let frame=0; function loop(){ step(); if(frame<420 && frame%30===0) fit(); frame++; draw(); requestAnimationFrame(loop); } loop();
|
||
window.fitView=fit;
|
||
|
||
// ---- interaction
|
||
let panStart=null, moved=false;
|
||
function nodeAt(sx,sy){ let best=null,bd=1e9; for(const n of nodes){ if(hidden.has(n.type)) continue; const [x,y]=toScreen(n.x,n.y); const d=Math.hypot(sx-x,sy-y); if(d<R(n)*cam.k+4 && d<bd){best=n;bd=d;} } return best; }
|
||
cv.addEventListener('mousedown',e=>{ const n=nodeAt(e.offsetX,e.offsetY); moved=false; if(n){dragging=n; alpha=0.6;} else {panStart={x:e.offsetX,y:e.offsetY,cx:cam.x,cy:cam.y}; cv.classList.add('grabbing');} });
|
||
addEventListener('mousemove',e=>{ const rect=cv.getBoundingClientRect(); const sx=e.clientX-rect.left, sy=e.clientY-rect.top; if(dragging){ const [wx,wy]=toWorld(sx,sy); dragging.x=wx; dragging.y=wy; moved=true; } else if(panStart){ cam.x=panStart.cx-(sx-panStart.x)/cam.k; cam.y=panStart.cy-(sy-panStart.y)/cam.k; moved=true; } else { hover=nodeAt(sx,sy); cv.style.cursor=hover?'pointer':'grab'; } });
|
||
addEventListener('mouseup',e=>{ if(dragging && !moved) select(dragging); dragging=null; panStart=null; cv.classList.remove('grabbing'); });
|
||
cv.addEventListener('click',e=>{ if(!moved && !nodeAt(e.offsetX,e.offsetY)) { selected=null; closeCard(); } });
|
||
cv.addEventListener('dblclick',()=>{ alpha=0.8; fit(); });
|
||
cv.addEventListener('wheel',e=>{ e.preventDefault(); const [wx,wy]=toWorld(e.offsetX,e.offsetY); cam.k=Math.min(6,Math.max(0.15,cam.k*(e.deltaY<0?1.12:0.89))); const [nx,ny]=toWorld(e.offsetX,e.offsetY); cam.x+=wx-nx; cam.y+=wy-ny; },{passive:false});
|
||
document.getElementById('search').addEventListener('keydown',e=>{ if(e.key==='Enter'){ const q=e.target.value.toLowerCase(); const n=nodes.find(n=>n.name.toLowerCase()===q)||nodes.filter(n=>n.name.toLowerCase().includes(q)).sort((a,b)=>b.deg-a.deg)[0]; if(n){ select(n); cam.x=n.x; cam.y=n.y; } } });
|
||
|
||
// ---- legend
|
||
const legend=document.getElementById('legend');
|
||
types.forEach(t=>{ const c=document.createElement('span'); c.className='chip'; c.innerHTML=`<i style="background:${color[t]}"></i>${t} <span style="color:var(--muted)">${nodes.filter(n=>n.type===t).length}</span>`; c.onclick=()=>{ hidden.has(t)?hidden.delete(t):hidden.add(t); c.classList.toggle('off'); alpha=0.6; }; legend.appendChild(c); });
|
||
document.getElementById('stats').textContent = `${nodes.length} nodes · ${links.length} edges · ${DATA.meta.components} component(s) · density ${DATA.meta.density} · schema v${DATA.meta.schema_version} · ${DATA.meta.generated}`;
|
||
|
||
// ---- card
|
||
const esc=s=>String(s??'').replace(/[&<>]/g,c=>({'&':'&','<':'<','>':'>'}[c]));
|
||
window.closeCard=()=>{ document.getElementById('card').style.display='none'; };
|
||
window.selectId=id=>{ const n=byId[id]; if(n){ select(n); cam.x=n.x; cam.y=n.y; } };
|
||
function select(n){ selected=n; const card=document.getElementById('card'), b=document.getElementById('cardbody');
|
||
const out=links.filter(l=>l.s===n), inc=links.filter(l=>l.t===n);
|
||
const prof=DATA.profiles[n.id];
|
||
let h=`<h2>${esc(n.name)}</h2><div class="type"><i class="chip" style="padding:1px 7px;border-color:${color[n.type]}">${n.type}</i> · degree ${n.deg} · ${(n.sources||[]).length} source(s)${n.provisional?' · <span class="stale">provisional</span>':''}</div>`;
|
||
if(n.description) h+=`<p>${esc(n.description)}</p>`;
|
||
if(prof){ h+=`<h3>Profile</h3>`; prof.summary.split(/\n\n+/).forEach(p=>h+=`<p>${esc(p)}</p>`); if(prof.key_facts?.length){ h+=`<ul>`+prof.key_facts.map(f=>`<li>${esc(f)}</li>`).join('')+`</ul>`; } if(prof.time_range) h+=`<p class="prov">${esc(prof.time_range.start)} → ${esc(prof.time_range.end)}</p>`; if(prof.stale) h+=`<p class="stale">profile is stale (source set changed)</p>`; }
|
||
const edge=(l,dir)=>`<li>${dir==='out'?'→':'←'} <b>${esc(l.predicate)}</b> <a class="node" onclick="selectId('${dir==='out'?l.t.id:l.s.id}')">${esc(dir==='out'?l.t.name:l.s.name)}</a><div class="prov">${esc(l.id)} · ×${l.confidence||1} · ${(l.sources||[]).map(s=>esc(DATA.sources[s]||s)).join(', ')}</div></li>`;
|
||
if(out.length){ h+=`<h3>Outgoing (${out.length})</h3><ul>`+out.map(l=>edge(l,'out')).join('')+`</ul>`; }
|
||
if(inc.length){ h+=`<h3>Incoming (${inc.length})</h3><ul>`+inc.map(l=>edge(l,'in')).join('')+`</ul>`; }
|
||
if((n.sources||[]).length){ h+=`<h3>Sources</h3><ul>`+n.sources.map(s=>`<li class="prov">${esc(DATA.sources[s]||s)}</li>`).join('')+`</ul>`; }
|
||
if(DATA.aliases[n.id]?.length>1){ h+=`<h3>Aliases</h3><p class="prov">${DATA.aliases[n.id].map(esc).join(', ')}</p>`; }
|
||
b.innerHTML=h; card.style.display='block'; }
|
||
const qp=new URLSearchParams(location.search); const f0=qp.get('focus')||DATA.meta.focus; if(f0 && byId[f0]) setTimeout(()=>{ select(byId[f0]); },qp.has('focus')?2500:0);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|