rig-constellation 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +201 -0
  2. package/LICENSE-CODEGRAPH.txt +27 -0
  3. package/NOTICE +15 -0
  4. package/README.md +121 -0
  5. package/dist/chunk-8sqjbsgt.js +42 -0
  6. package/dist/chunk-9754b9t6.js +70 -0
  7. package/dist/chunk-arpj39jd.js +10 -0
  8. package/dist/chunk-bnz0drs2.js +10 -0
  9. package/dist/chunk-hk4h7yej.js +71 -0
  10. package/dist/rig.js +11708 -0
  11. package/generated/.manifest +57 -0
  12. package/generated/core/anchors-registry.ts +70 -0
  13. package/generated/core/migrations.ts +79 -0
  14. package/generated/core/schema.sql +241 -0
  15. package/generated/installer/claude.instructions.md +345 -0
  16. package/generated/installer/claude.permissions.json +44 -0
  17. package/generated/installer/codex.instructions.md +345 -0
  18. package/generated/installer/codex.permissions.json +44 -0
  19. package/generated/installer/cursor.instructions.md +345 -0
  20. package/generated/installer/cursor.permissions.json +44 -0
  21. package/generated/installer/opencode.instructions.md +345 -0
  22. package/generated/installer/opencode.permissions.json +44 -0
  23. package/generated/installer/openrouter.instructions.md +345 -0
  24. package/generated/installer/openrouter.permissions.json +44 -0
  25. package/generated/mcp/handlers/rig_add_alias.handler.ts +34 -0
  26. package/generated/mcp/handlers/rig_add_node.handler.ts +34 -0
  27. package/generated/mcp/handlers/rig_aliases.handler.ts +25 -0
  28. package/generated/mcp/handlers/rig_annotate.handler.ts +34 -0
  29. package/generated/mcp/handlers/rig_callees.handler.ts +25 -0
  30. package/generated/mcp/handlers/rig_callers.handler.ts +25 -0
  31. package/generated/mcp/handlers/rig_chain.handler.ts +25 -0
  32. package/generated/mcp/handlers/rig_cluster.handler.ts +34 -0
  33. package/generated/mcp/handlers/rig_cold.handler.ts +25 -0
  34. package/generated/mcp/handlers/rig_context.handler.ts +29 -0
  35. package/generated/mcp/handlers/rig_critical_path.handler.ts +25 -0
  36. package/generated/mcp/handlers/rig_dep_conflicts.handler.ts +25 -0
  37. package/generated/mcp/handlers/rig_deps.handler.ts +25 -0
  38. package/generated/mcp/handlers/rig_drill.handler.ts +25 -0
  39. package/generated/mcp/handlers/rig_drop_waypoint.handler.ts +34 -0
  40. package/generated/mcp/handlers/rig_explore.handler.ts +29 -0
  41. package/generated/mcp/handlers/rig_files.handler.ts +25 -0
  42. package/generated/mcp/handlers/rig_focus.handler.ts +29 -0
  43. package/generated/mcp/handlers/rig_hotspots.handler.ts +25 -0
  44. package/generated/mcp/handlers/rig_hub_of.handler.ts +25 -0
  45. package/generated/mcp/handlers/rig_hubs.handler.ts +25 -0
  46. package/generated/mcp/handlers/rig_impact.handler.ts +25 -0
  47. package/generated/mcp/handlers/rig_neighbors.handler.ts +25 -0
  48. package/generated/mcp/handlers/rig_node.handler.ts +25 -0
  49. package/generated/mcp/handlers/rig_phantom_imports.handler.ts +25 -0
  50. package/generated/mcp/handlers/rig_promote.handler.ts +34 -0
  51. package/generated/mcp/handlers/rig_propose_edge.handler.ts +34 -0
  52. package/generated/mcp/handlers/rig_pull.handler.ts +25 -0
  53. package/generated/mcp/handlers/rig_relevant_skills.handler.ts +25 -0
  54. package/generated/mcp/handlers/rig_search.handler.ts +25 -0
  55. package/generated/mcp/handlers/rig_session_token.handler.ts +25 -0
  56. package/generated/mcp/handlers/rig_status.handler.ts +25 -0
  57. package/generated/mcp/handlers/rig_subscribe.handler.ts +25 -0
  58. package/generated/mcp/handlers/rig_undo.handler.ts +29 -0
  59. package/generated/mcp/handlers/rig_unused_deps.handler.ts +25 -0
  60. package/generated/mcp/handlers/rig_waypoints.handler.ts +25 -0
  61. package/generated/mcp/handlers-index.ts +40 -0
  62. package/generated/mcp/tools-manifest.json +2958 -0
  63. package/generated/web/ws-events.ts +237 -0
  64. package/package.json +77 -0
  65. package/packages/web/dist/assets/index-VRO-sxc2.js +54 -0
  66. package/packages/web/dist/index.html +35 -0
@@ -0,0 +1,57 @@
1
+ {
2
+ "version": 1,
3
+ "files": {
4
+ "core/anchors-registry.ts": "beb53c35680dc34b",
5
+ "core/migrations.ts": "314120cca2471a13",
6
+ "core/schema.sql": "52ebe9156c8a633a",
7
+ "installer/claude.instructions.md": "b3dba5ffef028fbc",
8
+ "installer/claude.permissions.json": "3b9a29a1fc774419",
9
+ "installer/codex.instructions.md": "85f4bcec18733e6f",
10
+ "installer/codex.permissions.json": "3b9a29a1fc774419",
11
+ "installer/cursor.instructions.md": "550ff29bf8608ce3",
12
+ "installer/cursor.permissions.json": "3b9a29a1fc774419",
13
+ "installer/opencode.instructions.md": "a7298c966bbcbe7a",
14
+ "installer/opencode.permissions.json": "3b9a29a1fc774419",
15
+ "installer/openrouter.instructions.md": "54b3cccb03080c78",
16
+ "installer/openrouter.permissions.json": "3b9a29a1fc774419",
17
+ "mcp/handlers-index.ts": "8aa59ae4f775091f",
18
+ "mcp/handlers/rig_add_alias.handler.ts": "f416a8a5c90f1ca7",
19
+ "mcp/handlers/rig_add_node.handler.ts": "c002f1cdb5230a2f",
20
+ "mcp/handlers/rig_aliases.handler.ts": "c4838d5742f03c4a",
21
+ "mcp/handlers/rig_annotate.handler.ts": "bfd7d8611cb0106e",
22
+ "mcp/handlers/rig_callees.handler.ts": "41945f900c2a4718",
23
+ "mcp/handlers/rig_callers.handler.ts": "9d932f214b57fc15",
24
+ "mcp/handlers/rig_chain.handler.ts": "768d2fc35319d4e5",
25
+ "mcp/handlers/rig_cluster.handler.ts": "c3aee5953d2db840",
26
+ "mcp/handlers/rig_cold.handler.ts": "ca376ea14df0b3af",
27
+ "mcp/handlers/rig_context.handler.ts": "53dad4af1fcda2ab",
28
+ "mcp/handlers/rig_critical_path.handler.ts": "51888df0e863b044",
29
+ "mcp/handlers/rig_dep_conflicts.handler.ts": "40470cd696f6a140",
30
+ "mcp/handlers/rig_deps.handler.ts": "29828a670d3468c0",
31
+ "mcp/handlers/rig_drill.handler.ts": "a61c46a4d0249b45",
32
+ "mcp/handlers/rig_drop_waypoint.handler.ts": "d4e35fe8c8bca709",
33
+ "mcp/handlers/rig_explore.handler.ts": "5fad1a5e7b4b40ef",
34
+ "mcp/handlers/rig_files.handler.ts": "d8db41d00f84be60",
35
+ "mcp/handlers/rig_focus.handler.ts": "902ecccf8e5e4fcf",
36
+ "mcp/handlers/rig_hotspots.handler.ts": "d4addbb2c46a3ef0",
37
+ "mcp/handlers/rig_hub_of.handler.ts": "b3c4fbaf118765f0",
38
+ "mcp/handlers/rig_hubs.handler.ts": "28c66afae61993c1",
39
+ "mcp/handlers/rig_impact.handler.ts": "6294509669d3b4e4",
40
+ "mcp/handlers/rig_neighbors.handler.ts": "e0fbefc0c732850f",
41
+ "mcp/handlers/rig_node.handler.ts": "061d2328c65ddad1",
42
+ "mcp/handlers/rig_phantom_imports.handler.ts": "6396c7b6e250f627",
43
+ "mcp/handlers/rig_promote.handler.ts": "7fcd3cad0ec86f95",
44
+ "mcp/handlers/rig_propose_edge.handler.ts": "1c57558cafcc96b4",
45
+ "mcp/handlers/rig_pull.handler.ts": "cf008f36c6ab829b",
46
+ "mcp/handlers/rig_relevant_skills.handler.ts": "78d3a69c4e735ab1",
47
+ "mcp/handlers/rig_search.handler.ts": "ca32b0de149f8a73",
48
+ "mcp/handlers/rig_session_token.handler.ts": "14d7e8c940ccffa8",
49
+ "mcp/handlers/rig_status.handler.ts": "ddf2754733594794",
50
+ "mcp/handlers/rig_subscribe.handler.ts": "92746a3928399606",
51
+ "mcp/handlers/rig_undo.handler.ts": "2addb3a0315adb0d",
52
+ "mcp/handlers/rig_unused_deps.handler.ts": "79d099728b1a2de6",
53
+ "mcp/handlers/rig_waypoints.handler.ts": "29f87f767a3b27e2",
54
+ "mcp/tools-manifest.json": "3196cbb161d16e2d",
55
+ "web/ws-events.ts": "e974a13abab1e2c2"
56
+ }
57
+ }
@@ -0,0 +1,70 @@
1
+ // GENERATED FILE — DO NOT EDIT.
2
+ // Source: .contracts/anchors/cluster.contract.ts, .contracts/anchors/code-symbol.contract.ts, .contracts/anchors/conversation-waypoint.contract.ts, .contracts/anchors/declared-dependency.contract.ts, .contracts/anchors/markdown-section.contract.ts, .contracts/anchors/skill.contract.ts
3
+ // Edit the .contract.ts file(s), then run `bun run gen`.
4
+
5
+ export interface AnchorTypeMeta {
6
+ type: string;
7
+ description: string;
8
+ extractor: 'tree-sitter' | 'custom' | 'manual';
9
+ ui: { icon: string; color: string; label_field: string; detail_fields?: string[] };
10
+ allowed_edges: { outgoing?: string[]; incoming?: string[] };
11
+ embeddable: boolean;
12
+ embedding_text: string[];
13
+ }
14
+
15
+ export const ANCHOR_REGISTRY: Record<string, AnchorTypeMeta> = {
16
+ 'cluster': {
17
+ type: 'cluster',
18
+ description: "AI-curated grouping of related anchors; created by rig_cluster",
19
+ extractor: 'manual',
20
+ ui: {"icon":"layers","color":"c-violet","label_field":"name","detail_fields":["rationale","members"]},
21
+ allowed_edges: {"outgoing":["contains"],"incoming":["references"]},
22
+ embeddable: true,
23
+ embedding_text: ["name","rationale"],
24
+ },
25
+ 'code-symbol': {
26
+ type: 'code-symbol',
27
+ description: "A function, class, method, or other code-level identifier",
28
+ extractor: 'tree-sitter',
29
+ ui: {"icon":"function","color":"c-teal","label_field":"name","detail_fields":["qualified_name","file_path","signature"]},
30
+ allowed_edges: {"outgoing":["calls","imports","extends","implements","contains","references"],"incoming":["calls","extends","implements","contains","references"]},
31
+ embeddable: true,
32
+ embedding_text: ["name","qualified_name","docstring","signature"],
33
+ },
34
+ 'conversation-waypoint': {
35
+ type: 'conversation-waypoint',
36
+ description: "A discrete decision/observation/constraint/open-question/principle marker dropped by the AI during a session. Carries an analogy + summary + refs into the graph so future sessions can rehydrate the reasoning thread.",
37
+ extractor: 'manual',
38
+ ui: {"icon":"flag","color":"c-cyan","label_field":"title","detail_fields":["type","summary","analogy","key_terms"]},
39
+ allowed_edges: {"outgoing":["waypoint_succeeds","waypoint_references"],"incoming":["waypoint_succeeds"]},
40
+ embeddable: true,
41
+ embedding_text: ["title","summary","analogy","key_terms"],
42
+ },
43
+ 'declared-dependency': {
44
+ type: 'declared-dependency',
45
+ description: "A dependency declared in a package-manifest file (package.json, requirements.txt, pyproject.toml, etc.). Carries its version spec + dev/runtime classification on the node.",
46
+ extractor: 'custom',
47
+ ui: {"icon":"package","color":"c-violet","label_field":"name","detail_fields":["spec","manifest_path","source"]},
48
+ allowed_edges: {"outgoing":["resolves_to"],"incoming":["manifest_declares","imports_package"]},
49
+ embeddable: false,
50
+ embedding_text: [],
51
+ },
52
+ 'markdown-section': {
53
+ type: 'markdown-section',
54
+ description: "A heading inside a markdown document; nests by ATX heading level",
55
+ extractor: 'custom',
56
+ ui: {"icon":"heading","color":"c-amber","label_field":"name","detail_fields":["heading_path","file_path","level"]},
57
+ allowed_edges: {"outgoing":["contains","references"],"incoming":["contains","references"]},
58
+ embeddable: true,
59
+ embedding_text: ["name","heading_path"],
60
+ },
61
+ 'skill': {
62
+ type: 'skill',
63
+ description: "An AI-callable tool exposed by the MCP server (e.g. rig_pull, rig_search). Seeded from the tools-manifest at session startup.",
64
+ extractor: 'manual',
65
+ ui: {"icon":"wrench","color":"c-fuchsia","label_field":"name","detail_fields":["tier","summary"]},
66
+ allowed_edges: {"outgoing":["references"],"incoming":["references","invoked_in_session"]},
67
+ embeddable: true,
68
+ embedding_text: ["name","description","summary"],
69
+ },
70
+ };
@@ -0,0 +1,79 @@
1
+ // GENERATED FILE — DO NOT EDIT.
2
+ // Source: .contracts/migrations/v1.contract.ts, .contracts/migrations/v2.contract.ts, .contracts/migrations/v3.contract.ts, .contracts/migrations/v4.contract.ts, .contracts/migrations/v5.contract.ts, .contracts/migrations/v6.contract.ts, .contracts/migrations/v7.contract.ts, .contracts/migrations/v8.contract.ts, .contracts/migrations/v9.contract.ts, .contracts/migrations/v10.contract.ts, .contracts/migrations/v11.contract.ts
3
+ // Edit the .contract.ts file(s), then run `bun run gen`.
4
+
5
+ export interface Migration {
6
+ version: number;
7
+ description: string;
8
+ forward: string;
9
+ rollback: string;
10
+ }
11
+
12
+ export const MIGRATIONS: readonly Migration[] = [
13
+ {
14
+ version: 1,
15
+ description: "Initial Rig schema: nodes, structural + semantic edges, embeddings, activations, FTS5",
16
+ forward: "CREATE TABLE IF NOT EXISTS schema_versions (\n version INTEGER PRIMARY KEY,\n applied_at INTEGER NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL UNIQUE,\n mtime INTEGER NOT NULL,\n hash TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_files_path ON files(path);\n\nCREATE TABLE IF NOT EXISTS nodes (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL,\n name TEXT NOT NULL,\n data TEXT NOT NULL,\n pull_score REAL DEFAULT 0,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type);\nCREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name);\n\nCREATE TABLE IF NOT EXISTS edges (\n src TEXT NOT NULL,\n dst TEXT NOT NULL,\n kind TEXT NOT NULL,\n provenance TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (src, dst, kind),\n FOREIGN KEY (src) REFERENCES nodes(id) ON DELETE CASCADE,\n FOREIGN KEY (dst) REFERENCES nodes(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src);\nCREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst);\nCREATE INDEX IF NOT EXISTS idx_edges_provenance ON edges(provenance);\n\nCREATE TABLE IF NOT EXISTS edges_semantic (\n src TEXT NOT NULL,\n dst TEXT NOT NULL,\n weight REAL NOT NULL,\n provenance TEXT NOT NULL,\n rationale TEXT,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (src, dst, provenance),\n FOREIGN KEY (src) REFERENCES nodes(id) ON DELETE CASCADE,\n FOREIGN KEY (dst) REFERENCES nodes(id) ON DELETE CASCADE\n);\nCREATE INDEX IF NOT EXISTS idx_edges_semantic_src ON edges_semantic(src);\nCREATE INDEX IF NOT EXISTS idx_edges_semantic_dst ON edges_semantic(dst);\n\nCREATE TABLE IF NOT EXISTS embeddings (\n node_id TEXT PRIMARY KEY,\n model TEXT NOT NULL,\n dim INTEGER NOT NULL,\n vector BLOB NOT NULL,\n FOREIGN KEY (node_id) REFERENCES nodes(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS activations (\n node_id TEXT NOT NULL,\n ts INTEGER NOT NULL,\n source TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_activations_node_ts ON activations(node_id, ts);\n\nCREATE TABLE IF NOT EXISTS unresolved_refs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n src TEXT NOT NULL,\n target_name TEXT NOT NULL,\n file_path TEXT NOT NULL,\n line INTEGER NOT NULL\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS nodes_fts USING fts5(\n name, qualified_name, node_id UNINDEXED\n);\n\nCREATE TRIGGER IF NOT EXISTS nodes_after_insert AFTER INSERT ON nodes BEGIN\n INSERT INTO nodes_fts(name, qualified_name, node_id)\n VALUES (\n NEW.name,\n COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),\n NEW.id\n );\nEND;\n\nCREATE TRIGGER IF NOT EXISTS nodes_after_update AFTER UPDATE ON nodes BEGIN\n DELETE FROM nodes_fts WHERE node_id = OLD.id;\n INSERT INTO nodes_fts(name, qualified_name, node_id)\n VALUES (\n NEW.name,\n COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),\n NEW.id\n );\nEND;\n\nCREATE TRIGGER IF NOT EXISTS nodes_after_delete AFTER DELETE ON nodes BEGIN\n DELETE FROM nodes_fts WHERE node_id = OLD.id;\nEND;",
17
+ rollback: "DROP TRIGGER IF EXISTS nodes_after_delete;\nDROP TRIGGER IF EXISTS nodes_after_update;\nDROP TRIGGER IF EXISTS nodes_after_insert;\nDROP TABLE IF EXISTS nodes_fts;\nDROP TABLE IF EXISTS unresolved_refs;\nDROP TABLE IF EXISTS activations;\nDROP TABLE IF EXISTS embeddings;\nDROP TABLE IF EXISTS edges_semantic;\nDROP TABLE IF EXISTS edges;\nDROP TABLE IF EXISTS nodes;\nDROP TABLE IF EXISTS files;\nDROP TABLE IF EXISTS schema_versions;",
18
+ },
19
+ {
20
+ version: 2,
21
+ description: "Phase 3 read-write: pending_edges, mutation_log, provenance triggers",
22
+ forward: "CREATE TABLE IF NOT EXISTS pending_edges (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n src TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,\n dst TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,\n kind TEXT NOT NULL DEFAULT 'related',\n weight REAL NOT NULL DEFAULT 0.5,\n provenance TEXT NOT NULL,\n rationale TEXT NOT NULL,\n proposed_at INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n status TEXT NOT NULL CHECK(status IN ('pending','accepted','rejected'))\n);\nCREATE INDEX IF NOT EXISTS idx_pending_edges_status ON pending_edges(status);\nCREATE INDEX IF NOT EXISTS idx_pending_edges_session ON pending_edges(session_id);\n\nCREATE TABLE IF NOT EXISTS mutation_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n payload TEXT NOT NULL,\n actor TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_mutation_log_session_ts ON mutation_log(session_id, ts);\nCREATE INDEX IF NOT EXISTS idx_mutation_log_ts ON mutation_log(ts);\n\nCREATE TRIGGER IF NOT EXISTS edges_provenance_nonempty\n BEFORE INSERT ON edges\n WHEN NEW.provenance IS NULL OR NEW.provenance = ''\n BEGIN\n SELECT RAISE(ABORT, 'edges: provenance required');\n END;\n\nCREATE TRIGGER IF NOT EXISTS edges_semantic_provenance_nonempty\n BEFORE INSERT ON edges_semantic\n WHEN NEW.provenance IS NULL OR NEW.provenance = ''\n BEGIN\n SELECT RAISE(ABORT, 'edges_semantic: provenance required');\n END;\n\nCREATE TRIGGER IF NOT EXISTS pending_edges_provenance_nonempty\n BEFORE INSERT ON pending_edges\n WHEN NEW.provenance IS NULL OR NEW.provenance = ''\n BEGIN\n SELECT RAISE(ABORT, 'pending_edges: provenance required');\n END;\n\nCREATE TRIGGER IF NOT EXISTS pending_edges_rationale_nonempty\n BEFORE INSERT ON pending_edges\n WHEN NEW.rationale IS NULL OR NEW.rationale = ''\n BEGIN\n SELECT RAISE(ABORT, 'pending_edges: rationale required');\n END;",
23
+ rollback: "DROP TRIGGER IF EXISTS pending_edges_rationale_nonempty;\nDROP TRIGGER IF EXISTS pending_edges_provenance_nonempty;\nDROP TRIGGER IF EXISTS edges_semantic_provenance_nonempty;\nDROP TRIGGER IF EXISTS edges_provenance_nonempty;\nDROP TABLE IF EXISTS mutation_log;\nDROP TABLE IF EXISTS pending_edges;",
24
+ },
25
+ {
26
+ version: 3,
27
+ description: "Phase 3.5 A1: hub-and-spoke topology — is_hub + hubness on nodes",
28
+ forward: "ALTER TABLE nodes ADD COLUMN is_hub INTEGER NOT NULL DEFAULT 0;\nALTER TABLE nodes ADD COLUMN hubness REAL NOT NULL DEFAULT 0;\nALTER TABLE nodes ADD COLUMN hub_explicit INTEGER NOT NULL DEFAULT 0;\nCREATE INDEX IF NOT EXISTS idx_nodes_is_hub ON nodes(is_hub) WHERE is_hub = 1;\nCREATE INDEX IF NOT EXISTS idx_nodes_hubness ON nodes(hubness DESC);",
29
+ rollback: "DROP INDEX IF EXISTS idx_nodes_hubness;\nDROP INDEX IF EXISTS idx_nodes_is_hub;\n-- SQLite cannot DROP COLUMN before 3.35; rollback is destructive (table recreate).\n-- Left as a no-op for forward-only deployments.",
30
+ },
31
+ {
32
+ version: 4,
33
+ description: "Phase 3.5 A3: aliases table + FTS5 union for canonical-anchor resolution",
34
+ forward: "CREATE TABLE IF NOT EXISTS aliases (\n node_id TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,\n alias TEXT NOT NULL,\n provenance TEXT NOT NULL,\n rationale TEXT,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (node_id, alias)\n);\nCREATE INDEX IF NOT EXISTS idx_aliases_alias ON aliases(alias);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS aliases_fts USING fts5(\n alias, node_id UNINDEXED, tokenize = 'unicode61'\n);\n\nCREATE TRIGGER IF NOT EXISTS aliases_after_insert AFTER INSERT ON aliases BEGIN\n INSERT INTO aliases_fts(alias, node_id) VALUES (NEW.alias, NEW.node_id);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS aliases_after_delete AFTER DELETE ON aliases BEGIN\n DELETE FROM aliases_fts WHERE node_id = OLD.node_id AND alias = OLD.alias;\nEND;\n\nCREATE TRIGGER IF NOT EXISTS aliases_provenance_nonempty\n BEFORE INSERT ON aliases\n WHEN NEW.provenance IS NULL OR NEW.provenance = ''\n BEGIN\n SELECT RAISE(ABORT, 'aliases: provenance required');\n END;",
35
+ rollback: "DROP TRIGGER IF EXISTS aliases_provenance_nonempty;\nDROP TRIGGER IF EXISTS aliases_after_delete;\nDROP TRIGGER IF EXISTS aliases_after_insert;\nDROP TABLE IF EXISTS aliases_fts;\nDROP INDEX IF EXISTS idx_aliases_alias;\nDROP TABLE IF EXISTS aliases;",
36
+ },
37
+ {
38
+ version: 5,
39
+ description: "A3.5 perf: text_hash on embeddings lets re-index skip unchanged nodes",
40
+ forward: "ALTER TABLE embeddings ADD COLUMN text_hash TEXT NOT NULL DEFAULT '';",
41
+ rollback: "-- SQLite cannot DROP COLUMN before 3.35; intentional no-op.",
42
+ },
43
+ {
44
+ version: 6,
45
+ description: "A4-lite: community_id column on nodes for label-propagation clustering",
46
+ forward: "ALTER TABLE nodes ADD COLUMN community_id INTEGER NOT NULL DEFAULT 0;\nCREATE INDEX IF NOT EXISTS idx_nodes_community ON nodes(community_id);",
47
+ rollback: "DROP INDEX IF EXISTS idx_nodes_community;\n-- SQLite cannot DROP COLUMN before 3.35; intentional no-op.",
48
+ },
49
+ {
50
+ version: 7,
51
+ description: "Scope nodes_after_update FTS trigger to name + data columns",
52
+ forward: "DROP TRIGGER IF EXISTS nodes_after_update;\nCREATE TRIGGER nodes_after_update AFTER UPDATE OF name, data ON nodes BEGIN\n DELETE FROM nodes_fts WHERE node_id = OLD.id;\n INSERT INTO nodes_fts(name, qualified_name, node_id)\n VALUES (\n NEW.name,\n COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),\n NEW.id\n );\nEND;",
53
+ rollback: "DROP TRIGGER IF EXISTS nodes_after_update;\nCREATE TRIGGER nodes_after_update AFTER UPDATE ON nodes BEGIN\n DELETE FROM nodes_fts WHERE node_id = OLD.id;\n INSERT INTO nodes_fts(name, qualified_name, node_id)\n VALUES (\n NEW.name,\n COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),\n NEW.id\n );\nEND;",
54
+ },
55
+ {
56
+ version: 8,
57
+ description: "C1: session_id + query_hash columns on activations",
58
+ forward: "ALTER TABLE activations ADD COLUMN session_id TEXT;\nALTER TABLE activations ADD COLUMN query_hash TEXT;\nCREATE INDEX IF NOT EXISTS idx_activations_query_hash ON activations(query_hash);\nCREATE INDEX IF NOT EXISTS idx_activations_session ON activations(session_id);",
59
+ rollback: "DROP INDEX IF EXISTS idx_activations_session;\nDROP INDEX IF EXISTS idx_activations_query_hash;\n-- SQLite cannot DROP COLUMN before 3.35; intentional no-op for older runtimes.",
60
+ },
61
+ {
62
+ version: 9,
63
+ description: "B1: sessions table for waypoint provenance",
64
+ forward: "CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n started_at INTEGER NOT NULL,\n last_seen INTEGER NOT NULL,\n title TEXT,\n context_model TEXT\n);\nCREATE INDEX IF NOT EXISTS idx_sessions_last_seen ON sessions(last_seen DESC);",
65
+ rollback: "DROP INDEX IF EXISTS idx_sessions_last_seen;\nDROP TABLE IF EXISTS sessions;",
66
+ },
67
+ {
68
+ version: 10,
69
+ description: "A2 follow-up: kind column on unresolved_refs for phantom-import detection",
70
+ forward: "ALTER TABLE unresolved_refs ADD COLUMN kind TEXT;\nCREATE INDEX IF NOT EXISTS idx_unresolved_kind_target ON unresolved_refs(kind, target_name);",
71
+ rollback: "DROP INDEX IF EXISTS idx_unresolved_kind_target;\n-- SQLite cannot DROP COLUMN before 3.35; intentional no-op.",
72
+ },
73
+ {
74
+ version: 11,
75
+ description: "E1: source_urls JSON column on pending_edges",
76
+ forward: "ALTER TABLE pending_edges ADD COLUMN source_urls TEXT;",
77
+ rollback: "-- SQLite cannot DROP COLUMN before 3.35; intentional no-op.",
78
+ },
79
+ ];
@@ -0,0 +1,241 @@
1
+ -- GENERATED FILE — DO NOT EDIT.
2
+ -- Source: .contracts/migrations/v1.contract.ts, .contracts/migrations/v2.contract.ts, .contracts/migrations/v3.contract.ts, .contracts/migrations/v4.contract.ts, .contracts/migrations/v5.contract.ts, .contracts/migrations/v6.contract.ts, .contracts/migrations/v7.contract.ts, .contracts/migrations/v8.contract.ts, .contracts/migrations/v9.contract.ts, .contracts/migrations/v10.contract.ts, .contracts/migrations/v11.contract.ts
3
+ -- Edit the .contract.ts file(s), then run `bun run gen`.
4
+
5
+ -- v1: Initial Rig schema: nodes, structural + semantic edges, embeddings, activations, FTS5
6
+ CREATE TABLE IF NOT EXISTS schema_versions (
7
+ version INTEGER PRIMARY KEY,
8
+ applied_at INTEGER NOT NULL
9
+ );
10
+
11
+ CREATE TABLE IF NOT EXISTS files (
12
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
13
+ path TEXT NOT NULL UNIQUE,
14
+ mtime INTEGER NOT NULL,
15
+ hash TEXT NOT NULL
16
+ );
17
+ CREATE INDEX IF NOT EXISTS idx_files_path ON files(path);
18
+
19
+ CREATE TABLE IF NOT EXISTS nodes (
20
+ id TEXT PRIMARY KEY,
21
+ type TEXT NOT NULL,
22
+ name TEXT NOT NULL,
23
+ data TEXT NOT NULL,
24
+ pull_score REAL DEFAULT 0,
25
+ created_at INTEGER NOT NULL,
26
+ updated_at INTEGER NOT NULL
27
+ );
28
+ CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type);
29
+ CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name);
30
+
31
+ CREATE TABLE IF NOT EXISTS edges (
32
+ src TEXT NOT NULL,
33
+ dst TEXT NOT NULL,
34
+ kind TEXT NOT NULL,
35
+ provenance TEXT NOT NULL,
36
+ created_at INTEGER NOT NULL,
37
+ PRIMARY KEY (src, dst, kind),
38
+ FOREIGN KEY (src) REFERENCES nodes(id) ON DELETE CASCADE,
39
+ FOREIGN KEY (dst) REFERENCES nodes(id) ON DELETE CASCADE
40
+ );
41
+ CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src);
42
+ CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst);
43
+ CREATE INDEX IF NOT EXISTS idx_edges_provenance ON edges(provenance);
44
+
45
+ CREATE TABLE IF NOT EXISTS edges_semantic (
46
+ src TEXT NOT NULL,
47
+ dst TEXT NOT NULL,
48
+ weight REAL NOT NULL,
49
+ provenance TEXT NOT NULL,
50
+ rationale TEXT,
51
+ created_at INTEGER NOT NULL,
52
+ PRIMARY KEY (src, dst, provenance),
53
+ FOREIGN KEY (src) REFERENCES nodes(id) ON DELETE CASCADE,
54
+ FOREIGN KEY (dst) REFERENCES nodes(id) ON DELETE CASCADE
55
+ );
56
+ CREATE INDEX IF NOT EXISTS idx_edges_semantic_src ON edges_semantic(src);
57
+ CREATE INDEX IF NOT EXISTS idx_edges_semantic_dst ON edges_semantic(dst);
58
+
59
+ CREATE TABLE IF NOT EXISTS embeddings (
60
+ node_id TEXT PRIMARY KEY,
61
+ model TEXT NOT NULL,
62
+ dim INTEGER NOT NULL,
63
+ vector BLOB NOT NULL,
64
+ FOREIGN KEY (node_id) REFERENCES nodes(id) ON DELETE CASCADE
65
+ );
66
+
67
+ CREATE TABLE IF NOT EXISTS activations (
68
+ node_id TEXT NOT NULL,
69
+ ts INTEGER NOT NULL,
70
+ source TEXT NOT NULL
71
+ );
72
+ CREATE INDEX IF NOT EXISTS idx_activations_node_ts ON activations(node_id, ts);
73
+
74
+ CREATE TABLE IF NOT EXISTS unresolved_refs (
75
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
76
+ src TEXT NOT NULL,
77
+ target_name TEXT NOT NULL,
78
+ file_path TEXT NOT NULL,
79
+ line INTEGER NOT NULL
80
+ );
81
+
82
+ CREATE VIRTUAL TABLE IF NOT EXISTS nodes_fts USING fts5(
83
+ name, qualified_name, node_id UNINDEXED
84
+ );
85
+
86
+ CREATE TRIGGER IF NOT EXISTS nodes_after_insert AFTER INSERT ON nodes BEGIN
87
+ INSERT INTO nodes_fts(name, qualified_name, node_id)
88
+ VALUES (
89
+ NEW.name,
90
+ COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),
91
+ NEW.id
92
+ );
93
+ END;
94
+
95
+ CREATE TRIGGER IF NOT EXISTS nodes_after_update AFTER UPDATE ON nodes BEGIN
96
+ DELETE FROM nodes_fts WHERE node_id = OLD.id;
97
+ INSERT INTO nodes_fts(name, qualified_name, node_id)
98
+ VALUES (
99
+ NEW.name,
100
+ COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),
101
+ NEW.id
102
+ );
103
+ END;
104
+
105
+ CREATE TRIGGER IF NOT EXISTS nodes_after_delete AFTER DELETE ON nodes BEGIN
106
+ DELETE FROM nodes_fts WHERE node_id = OLD.id;
107
+ END;
108
+
109
+ -- v2: Phase 3 read-write: pending_edges, mutation_log, provenance triggers
110
+ CREATE TABLE IF NOT EXISTS pending_edges (
111
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
112
+ src TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
113
+ dst TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
114
+ kind TEXT NOT NULL DEFAULT 'related',
115
+ weight REAL NOT NULL DEFAULT 0.5,
116
+ provenance TEXT NOT NULL,
117
+ rationale TEXT NOT NULL,
118
+ proposed_at INTEGER NOT NULL,
119
+ session_id TEXT NOT NULL,
120
+ status TEXT NOT NULL CHECK(status IN ('pending','accepted','rejected'))
121
+ );
122
+ CREATE INDEX IF NOT EXISTS idx_pending_edges_status ON pending_edges(status);
123
+ CREATE INDEX IF NOT EXISTS idx_pending_edges_session ON pending_edges(session_id);
124
+
125
+ CREATE TABLE IF NOT EXISTS mutation_log (
126
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
127
+ ts INTEGER NOT NULL,
128
+ session_id TEXT NOT NULL,
129
+ kind TEXT NOT NULL,
130
+ payload TEXT NOT NULL,
131
+ actor TEXT NOT NULL
132
+ );
133
+ CREATE INDEX IF NOT EXISTS idx_mutation_log_session_ts ON mutation_log(session_id, ts);
134
+ CREATE INDEX IF NOT EXISTS idx_mutation_log_ts ON mutation_log(ts);
135
+
136
+ CREATE TRIGGER IF NOT EXISTS edges_provenance_nonempty
137
+ BEFORE INSERT ON edges
138
+ WHEN NEW.provenance IS NULL OR NEW.provenance = ''
139
+ BEGIN
140
+ SELECT RAISE(ABORT, 'edges: provenance required');
141
+ END;
142
+
143
+ CREATE TRIGGER IF NOT EXISTS edges_semantic_provenance_nonempty
144
+ BEFORE INSERT ON edges_semantic
145
+ WHEN NEW.provenance IS NULL OR NEW.provenance = ''
146
+ BEGIN
147
+ SELECT RAISE(ABORT, 'edges_semantic: provenance required');
148
+ END;
149
+
150
+ CREATE TRIGGER IF NOT EXISTS pending_edges_provenance_nonempty
151
+ BEFORE INSERT ON pending_edges
152
+ WHEN NEW.provenance IS NULL OR NEW.provenance = ''
153
+ BEGIN
154
+ SELECT RAISE(ABORT, 'pending_edges: provenance required');
155
+ END;
156
+
157
+ CREATE TRIGGER IF NOT EXISTS pending_edges_rationale_nonempty
158
+ BEFORE INSERT ON pending_edges
159
+ WHEN NEW.rationale IS NULL OR NEW.rationale = ''
160
+ BEGIN
161
+ SELECT RAISE(ABORT, 'pending_edges: rationale required');
162
+ END;
163
+
164
+ -- v3: Phase 3.5 A1: hub-and-spoke topology — is_hub + hubness on nodes
165
+ ALTER TABLE nodes ADD COLUMN is_hub INTEGER NOT NULL DEFAULT 0;
166
+ ALTER TABLE nodes ADD COLUMN hubness REAL NOT NULL DEFAULT 0;
167
+ ALTER TABLE nodes ADD COLUMN hub_explicit INTEGER NOT NULL DEFAULT 0;
168
+ CREATE INDEX IF NOT EXISTS idx_nodes_is_hub ON nodes(is_hub) WHERE is_hub = 1;
169
+ CREATE INDEX IF NOT EXISTS idx_nodes_hubness ON nodes(hubness DESC);
170
+
171
+ -- v4: Phase 3.5 A3: aliases table + FTS5 union for canonical-anchor resolution
172
+ CREATE TABLE IF NOT EXISTS aliases (
173
+ node_id TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
174
+ alias TEXT NOT NULL,
175
+ provenance TEXT NOT NULL,
176
+ rationale TEXT,
177
+ created_at INTEGER NOT NULL,
178
+ PRIMARY KEY (node_id, alias)
179
+ );
180
+ CREATE INDEX IF NOT EXISTS idx_aliases_alias ON aliases(alias);
181
+
182
+ CREATE VIRTUAL TABLE IF NOT EXISTS aliases_fts USING fts5(
183
+ alias, node_id UNINDEXED, tokenize = 'unicode61'
184
+ );
185
+
186
+ CREATE TRIGGER IF NOT EXISTS aliases_after_insert AFTER INSERT ON aliases BEGIN
187
+ INSERT INTO aliases_fts(alias, node_id) VALUES (NEW.alias, NEW.node_id);
188
+ END;
189
+
190
+ CREATE TRIGGER IF NOT EXISTS aliases_after_delete AFTER DELETE ON aliases BEGIN
191
+ DELETE FROM aliases_fts WHERE node_id = OLD.node_id AND alias = OLD.alias;
192
+ END;
193
+
194
+ CREATE TRIGGER IF NOT EXISTS aliases_provenance_nonempty
195
+ BEFORE INSERT ON aliases
196
+ WHEN NEW.provenance IS NULL OR NEW.provenance = ''
197
+ BEGIN
198
+ SELECT RAISE(ABORT, 'aliases: provenance required');
199
+ END;
200
+
201
+ -- v5: A3.5 perf: text_hash on embeddings lets re-index skip unchanged nodes
202
+ ALTER TABLE embeddings ADD COLUMN text_hash TEXT NOT NULL DEFAULT '';
203
+
204
+ -- v6: A4-lite: community_id column on nodes for label-propagation clustering
205
+ ALTER TABLE nodes ADD COLUMN community_id INTEGER NOT NULL DEFAULT 0;
206
+ CREATE INDEX IF NOT EXISTS idx_nodes_community ON nodes(community_id);
207
+
208
+ -- v7: Scope nodes_after_update FTS trigger to name + data columns
209
+ DROP TRIGGER IF EXISTS nodes_after_update;
210
+ CREATE TRIGGER nodes_after_update AFTER UPDATE OF name, data ON nodes BEGIN
211
+ DELETE FROM nodes_fts WHERE node_id = OLD.id;
212
+ INSERT INTO nodes_fts(name, qualified_name, node_id)
213
+ VALUES (
214
+ NEW.name,
215
+ COALESCE(json_extract(NEW.data, '$.qualifiedName'), NEW.name),
216
+ NEW.id
217
+ );
218
+ END;
219
+
220
+ -- v8: C1: session_id + query_hash columns on activations
221
+ ALTER TABLE activations ADD COLUMN session_id TEXT;
222
+ ALTER TABLE activations ADD COLUMN query_hash TEXT;
223
+ CREATE INDEX IF NOT EXISTS idx_activations_query_hash ON activations(query_hash);
224
+ CREATE INDEX IF NOT EXISTS idx_activations_session ON activations(session_id);
225
+
226
+ -- v9: B1: sessions table for waypoint provenance
227
+ CREATE TABLE IF NOT EXISTS sessions (
228
+ id TEXT PRIMARY KEY,
229
+ started_at INTEGER NOT NULL,
230
+ last_seen INTEGER NOT NULL,
231
+ title TEXT,
232
+ context_model TEXT
233
+ );
234
+ CREATE INDEX IF NOT EXISTS idx_sessions_last_seen ON sessions(last_seen DESC);
235
+
236
+ -- v10: A2 follow-up: kind column on unresolved_refs for phantom-import detection
237
+ ALTER TABLE unresolved_refs ADD COLUMN kind TEXT;
238
+ CREATE INDEX IF NOT EXISTS idx_unresolved_kind_target ON unresolved_refs(kind, target_name);
239
+
240
+ -- v11: E1: source_urls JSON column on pending_edges
241
+ ALTER TABLE pending_edges ADD COLUMN source_urls TEXT;