@rkarim08/sia 1.0.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 (355) hide show
  1. package/.claude-plugin/marketplace.json +35 -0
  2. package/.claude-plugin/plugin.json +27 -0
  3. package/.mcp.json +13 -0
  4. package/CLAUDE.md +226 -0
  5. package/LICENSE +202 -0
  6. package/PLUGIN_README.md +253 -0
  7. package/README.md +1013 -0
  8. package/agents/sia-changelog-writer.md +89 -0
  9. package/agents/sia-code-reviewer.md +86 -0
  10. package/agents/sia-conflict-resolver.md +100 -0
  11. package/agents/sia-convention-enforcer.md +69 -0
  12. package/agents/sia-debug.md +106 -0
  13. package/agents/sia-decision-reviewer.md +101 -0
  14. package/agents/sia-dependency-tracker.md +80 -0
  15. package/agents/sia-explain.md +126 -0
  16. package/agents/sia-feature.md +116 -0
  17. package/agents/sia-knowledge-capture.md +117 -0
  18. package/agents/sia-lead-architecture-advisor.md +93 -0
  19. package/agents/sia-lead-team-health.md +107 -0
  20. package/agents/sia-migration.md +100 -0
  21. package/agents/sia-onboarding.md +115 -0
  22. package/agents/sia-orientation.md +99 -0
  23. package/agents/sia-pm-briefing.md +106 -0
  24. package/agents/sia-pm-risk-advisor.md +82 -0
  25. package/agents/sia-qa-analyst.md +116 -0
  26. package/agents/sia-qa-regression-map.md +94 -0
  27. package/agents/sia-refactor.md +115 -0
  28. package/agents/sia-regression.md +112 -0
  29. package/agents/sia-security-audit.md +125 -0
  30. package/agents/sia-test-advisor.md +91 -0
  31. package/hooks/hooks.json +98 -0
  32. package/migrations/bridge/001_initial.sql +34 -0
  33. package/migrations/episodic/001_initial.sql +35 -0
  34. package/migrations/meta/001_initial.sql +68 -0
  35. package/migrations/semantic/001_initial.sql +292 -0
  36. package/migrations/semantic/002_ontology.sql +89 -0
  37. package/migrations/semantic/003_freshness.sql +63 -0
  38. package/migrations/semantic/004_v5_unified_schema.sql +194 -0
  39. package/migrations/semantic/005_backfill_event_kinds.sql +8 -0
  40. package/migrations/semantic/006_tree_sitter.sql +6 -0
  41. package/migrations/semantic/007_branch_snapshots.sql +22 -0
  42. package/package.json +110 -0
  43. package/scripts/branch-switch.sh +13 -0
  44. package/scripts/build-wasm-grammars.sh +81 -0
  45. package/scripts/post-compact.sh +8 -0
  46. package/scripts/post-tool-use.sh +10 -0
  47. package/scripts/pre-compact.sh +8 -0
  48. package/scripts/session-end.sh +8 -0
  49. package/scripts/session-start.sh +8 -0
  50. package/scripts/start-mcp.ts +45 -0
  51. package/scripts/stop-hook.sh +8 -0
  52. package/scripts/user-prompt-submit.sh +8 -0
  53. package/scripts/viz-server.ts +152 -0
  54. package/skills/sia-brainstorm/SKILL.md +156 -0
  55. package/skills/sia-brainstorm/scripts/frame-template.html +214 -0
  56. package/skills/sia-brainstorm/scripts/helper.js +95 -0
  57. package/skills/sia-brainstorm/scripts/server.cjs +338 -0
  58. package/skills/sia-brainstorm/scripts/start-server.sh +153 -0
  59. package/skills/sia-brainstorm/scripts/stop-server.sh +55 -0
  60. package/skills/sia-brainstorm/spec-document-reviewer-prompt.md +49 -0
  61. package/skills/sia-brainstorm/visual-companion.md +286 -0
  62. package/skills/sia-capture/SKILL.md +64 -0
  63. package/skills/sia-compare/SKILL.md +33 -0
  64. package/skills/sia-conflicts/SKILL.md +38 -0
  65. package/skills/sia-debug-workflow/SKILL.md +120 -0
  66. package/skills/sia-debug-workflow/root-cause-tracing.md +70 -0
  67. package/skills/sia-debug-workflow/scripts/find-polluter.sh +64 -0
  68. package/skills/sia-debug-workflow/temporal-investigation.md +72 -0
  69. package/skills/sia-digest/SKILL.md +23 -0
  70. package/skills/sia-dispatch/SKILL.md +69 -0
  71. package/skills/sia-dispatch/agent-task-template.md +99 -0
  72. package/skills/sia-doctor/SKILL.md +39 -0
  73. package/skills/sia-execute/SKILL.md +70 -0
  74. package/skills/sia-execute-plan/SKILL.md +85 -0
  75. package/skills/sia-export-import/SKILL.md +49 -0
  76. package/skills/sia-export-knowledge/SKILL.md +46 -0
  77. package/skills/sia-finish/SKILL.md +100 -0
  78. package/skills/sia-finish/pr-summary-template.md +54 -0
  79. package/skills/sia-freshness/SKILL.md +38 -0
  80. package/skills/sia-history/SKILL.md +42 -0
  81. package/skills/sia-impact/SKILL.md +70 -0
  82. package/skills/sia-index/SKILL.md +54 -0
  83. package/skills/sia-install/SKILL.md +39 -0
  84. package/skills/sia-lead-compliance/SKILL.md +16 -0
  85. package/skills/sia-lead-drift-report/SKILL.md +16 -0
  86. package/skills/sia-lead-knowledge-map/SKILL.md +16 -0
  87. package/skills/sia-learn/SKILL.md +58 -0
  88. package/skills/sia-plan/SKILL.md +68 -0
  89. package/skills/sia-plan/plan-reviewer-prompt.md +63 -0
  90. package/skills/sia-playbooks/SKILL.md +29 -0
  91. package/skills/sia-playbooks/reference-feature.md +100 -0
  92. package/skills/sia-playbooks/reference-flagging.md +50 -0
  93. package/skills/sia-playbooks/reference-orientation.md +92 -0
  94. package/skills/sia-playbooks/reference-regression.md +115 -0
  95. package/skills/sia-playbooks/reference-review.md +64 -0
  96. package/skills/sia-playbooks/reference-tools.md +239 -0
  97. package/skills/sia-pm-decision-log/SKILL.md +28 -0
  98. package/skills/sia-pm-risk-dashboard/SKILL.md +24 -0
  99. package/skills/sia-pm-sprint-summary/SKILL.md +27 -0
  100. package/skills/sia-prune/SKILL.md +45 -0
  101. package/skills/sia-qa-coverage/SKILL.md +28 -0
  102. package/skills/sia-qa-flaky/SKILL.md +20 -0
  103. package/skills/sia-qa-report/SKILL.md +26 -0
  104. package/skills/sia-reindex/SKILL.md +30 -0
  105. package/skills/sia-review-respond/SKILL.md +88 -0
  106. package/skills/sia-review-respond/pushback-patterns.md +90 -0
  107. package/skills/sia-search/SKILL.md +47 -0
  108. package/skills/sia-setup/SKILL.md +82 -0
  109. package/skills/sia-setup/setup-checklist.md +97 -0
  110. package/skills/sia-stats/SKILL.md +36 -0
  111. package/skills/sia-status/SKILL.md +44 -0
  112. package/skills/sia-sync/SKILL.md +46 -0
  113. package/skills/sia-team/SKILL.md +64 -0
  114. package/skills/sia-test/SKILL.md +92 -0
  115. package/skills/sia-test/testing-anti-patterns.md +104 -0
  116. package/skills/sia-tour/SKILL.md +29 -0
  117. package/skills/sia-upgrade/SKILL.md +43 -0
  118. package/skills/sia-verify/SKILL.md +81 -0
  119. package/skills/sia-visualize/SKILL.md +28 -0
  120. package/skills/sia-visualize-live/SKILL.md +55 -0
  121. package/skills/sia-visualize-live/scripts/graph-template.html +389 -0
  122. package/skills/sia-visualize-live/scripts/start-visualizer.sh +161 -0
  123. package/skills/sia-visualize-live/scripts/stop-visualizer.sh +55 -0
  124. package/skills/sia-visualize-live/scripts/visualizer-server.cjs +264 -0
  125. package/skills/sia-workspace/SKILL.md +57 -0
  126. package/src/agent/claude-md-template-flagging.md +219 -0
  127. package/src/agent/claude-md-template.md +213 -0
  128. package/src/agent/modules/sia-feature.md +100 -0
  129. package/src/agent/modules/sia-flagging.md +50 -0
  130. package/src/agent/modules/sia-orientation.md +92 -0
  131. package/src/agent/modules/sia-regression.md +115 -0
  132. package/src/agent/modules/sia-review.md +64 -0
  133. package/src/agent/modules/sia-tools.md +239 -0
  134. package/src/ast/extractors/c-include.ts +189 -0
  135. package/src/ast/extractors/csharp-project.ts +260 -0
  136. package/src/ast/extractors/prisma-schema.ts +44 -0
  137. package/src/ast/extractors/project-manifest.ts +111 -0
  138. package/src/ast/extractors/sql-schema.ts +67 -0
  139. package/src/ast/extractors/tier-a.ts +423 -0
  140. package/src/ast/extractors/tier-b.ts +289 -0
  141. package/src/ast/extractors/tier-dispatch.ts +247 -0
  142. package/src/ast/index-worker.ts +108 -0
  143. package/src/ast/indexer.ts +484 -0
  144. package/src/ast/languages.ts +408 -0
  145. package/src/ast/pagerank-builder.ts +125 -0
  146. package/src/ast/path-utils.ts +137 -0
  147. package/src/ast/tree-sitter/backends/native.ts +57 -0
  148. package/src/ast/tree-sitter/backends/wasm.ts +39 -0
  149. package/src/ast/tree-sitter/call-walker.ts +44 -0
  150. package/src/ast/tree-sitter/edit-computer.ts +55 -0
  151. package/src/ast/tree-sitter/query-runner.ts +46 -0
  152. package/src/ast/tree-sitter/service.ts +174 -0
  153. package/src/ast/tree-sitter/tree-cache.ts +39 -0
  154. package/src/ast/tree-sitter/types.ts +79 -0
  155. package/src/ast/watcher.ts +322 -0
  156. package/src/capture/chunker.ts +169 -0
  157. package/src/capture/consolidate.ts +127 -0
  158. package/src/capture/edge-inferrer.ts +161 -0
  159. package/src/capture/embedder.ts +166 -0
  160. package/src/capture/embedding-cache.ts +73 -0
  161. package/src/capture/flag-processor.ts +64 -0
  162. package/src/capture/hook.ts +67 -0
  163. package/src/capture/pipeline.ts +450 -0
  164. package/src/capture/prompts/consolidate.ts +25 -0
  165. package/src/capture/prompts/edge-infer.ts +29 -0
  166. package/src/capture/prompts/extract-flagged.ts +36 -0
  167. package/src/capture/prompts/extract.ts +42 -0
  168. package/src/capture/tokenizer.ts +147 -0
  169. package/src/capture/track-a-ast.ts +93 -0
  170. package/src/capture/track-b-llm.ts +149 -0
  171. package/src/capture/types.ts +64 -0
  172. package/src/cli/commands/community.ts +137 -0
  173. package/src/cli/commands/compare.ts +123 -0
  174. package/src/cli/commands/conflicts.ts +41 -0
  175. package/src/cli/commands/digest.ts +197 -0
  176. package/src/cli/commands/disable-flagging.ts +34 -0
  177. package/src/cli/commands/doctor.ts +240 -0
  178. package/src/cli/commands/download-model.ts +161 -0
  179. package/src/cli/commands/enable-flagging.ts +34 -0
  180. package/src/cli/commands/export-knowledge.ts +208 -0
  181. package/src/cli/commands/export.ts +85 -0
  182. package/src/cli/commands/freshness.ts +164 -0
  183. package/src/cli/commands/graph.ts +51 -0
  184. package/src/cli/commands/history.ts +139 -0
  185. package/src/cli/commands/import.ts +335 -0
  186. package/src/cli/commands/install.ts +156 -0
  187. package/src/cli/commands/lead-report.ts +241 -0
  188. package/src/cli/commands/learn.ts +321 -0
  189. package/src/cli/commands/pm-report.ts +413 -0
  190. package/src/cli/commands/prune.ts +75 -0
  191. package/src/cli/commands/qa-report.ts +278 -0
  192. package/src/cli/commands/reindex.ts +104 -0
  193. package/src/cli/commands/rollback.ts +70 -0
  194. package/src/cli/commands/search.ts +103 -0
  195. package/src/cli/commands/server.ts +91 -0
  196. package/src/cli/commands/share.ts +33 -0
  197. package/src/cli/commands/stats.ts +79 -0
  198. package/src/cli/commands/status.ts +176 -0
  199. package/src/cli/commands/sync.ts +96 -0
  200. package/src/cli/commands/team.ts +118 -0
  201. package/src/cli/commands/tour.ts +157 -0
  202. package/src/cli/commands/visualize-live.ts +162 -0
  203. package/src/cli/commands/workspace.ts +117 -0
  204. package/src/cli/index.ts +424 -0
  205. package/src/cli/learn-progress.ts +87 -0
  206. package/src/community/detection-bridge.ts +344 -0
  207. package/src/community/leiden.ts +462 -0
  208. package/src/community/raptor.ts +210 -0
  209. package/src/community/scheduler.ts +74 -0
  210. package/src/community/summarize.ts +115 -0
  211. package/src/decay/archiver.ts +73 -0
  212. package/src/decay/bridge-orphan-cleanup.ts +212 -0
  213. package/src/decay/consolidation-sweep.ts +112 -0
  214. package/src/decay/decay.ts +116 -0
  215. package/src/decay/deep-validator.ts +62 -0
  216. package/src/decay/episodic-promoter.ts +132 -0
  217. package/src/decay/maintenance-scheduler.ts +326 -0
  218. package/src/decay/scheduler.ts +6 -0
  219. package/src/decay/session-sweeper.ts +79 -0
  220. package/src/decay/types.ts +17 -0
  221. package/src/freshness/confidence-decay.ts +122 -0
  222. package/src/freshness/cuckoo-filter.ts +176 -0
  223. package/src/freshness/deep-validation.ts +345 -0
  224. package/src/freshness/dirty-tracker.ts +237 -0
  225. package/src/freshness/file-watcher-layer.ts +119 -0
  226. package/src/freshness/firewall.ts +64 -0
  227. package/src/freshness/git-reconcile-layer.ts +161 -0
  228. package/src/freshness/inverted-index.ts +158 -0
  229. package/src/freshness/stale-read-layer.ts +222 -0
  230. package/src/graph/audit.ts +69 -0
  231. package/src/graph/bridge-db.ts +141 -0
  232. package/src/graph/communities.ts +195 -0
  233. package/src/graph/db-interface.ts +259 -0
  234. package/src/graph/edges.ts +163 -0
  235. package/src/graph/entities.ts +327 -0
  236. package/src/graph/episodic-db.ts +113 -0
  237. package/src/graph/flags.ts +31 -0
  238. package/src/graph/meta-db.ts +200 -0
  239. package/src/graph/semantic-db.ts +101 -0
  240. package/src/graph/session-resume.ts +56 -0
  241. package/src/graph/snapshots.ts +342 -0
  242. package/src/graph/staging.ts +151 -0
  243. package/src/graph/types.ts +128 -0
  244. package/src/hooks/adapters/claude-code.ts +21 -0
  245. package/src/hooks/adapters/cline.ts +43 -0
  246. package/src/hooks/adapters/cursor.ts +65 -0
  247. package/src/hooks/adapters/generic.ts +12 -0
  248. package/src/hooks/agent-detect.ts +34 -0
  249. package/src/hooks/claude-md-directives.ts +32 -0
  250. package/src/hooks/event-router.ts +182 -0
  251. package/src/hooks/extractors/pattern-detector.ts +111 -0
  252. package/src/hooks/handlers/post-compact.ts +30 -0
  253. package/src/hooks/handlers/post-tool-use.ts +403 -0
  254. package/src/hooks/handlers/pre-compact.ts +100 -0
  255. package/src/hooks/handlers/session-end.ts +47 -0
  256. package/src/hooks/handlers/session-start.ts +154 -0
  257. package/src/hooks/handlers/stop.ts +128 -0
  258. package/src/hooks/handlers/user-prompt-submit.ts +68 -0
  259. package/src/hooks/plugin-branch-switch.ts +68 -0
  260. package/src/hooks/plugin-common.ts +47 -0
  261. package/src/hooks/plugin-post-compact.ts +28 -0
  262. package/src/hooks/plugin-post-tool-use.ts +38 -0
  263. package/src/hooks/plugin-pre-compact.ts +37 -0
  264. package/src/hooks/plugin-session-end.ts +37 -0
  265. package/src/hooks/plugin-session-start.ts +75 -0
  266. package/src/hooks/plugin-stop.ts +61 -0
  267. package/src/hooks/plugin-user-prompt-submit.ts +47 -0
  268. package/src/hooks/types.ts +43 -0
  269. package/src/knowledge/discovery.ts +238 -0
  270. package/src/knowledge/external-refs.ts +98 -0
  271. package/src/knowledge/freshness.ts +221 -0
  272. package/src/knowledge/ingest.ts +330 -0
  273. package/src/knowledge/markdown-export.ts +229 -0
  274. package/src/knowledge/markdown-import.ts +359 -0
  275. package/src/knowledge/patterns.ts +74 -0
  276. package/src/knowledge/templates.ts +307 -0
  277. package/src/llm/ai-sdk-adapter.ts +46 -0
  278. package/src/llm/config.ts +88 -0
  279. package/src/llm/cost-tracker.ts +110 -0
  280. package/src/llm/prompts/extraction.ts +55 -0
  281. package/src/llm/prompts/summarization.ts +36 -0
  282. package/src/llm/prompts/validation.ts +37 -0
  283. package/src/llm/provider-registry.ts +68 -0
  284. package/src/llm/reliability.ts +179 -0
  285. package/src/llm/schemas.ts +52 -0
  286. package/src/mcp/freshness-annotator.ts +69 -0
  287. package/src/mcp/server.ts +949 -0
  288. package/src/mcp/tools/sia-ast-query.ts +225 -0
  289. package/src/mcp/tools/sia-at-time.ts +151 -0
  290. package/src/mcp/tools/sia-backlinks.ts +87 -0
  291. package/src/mcp/tools/sia-batch-execute.ts +169 -0
  292. package/src/mcp/tools/sia-by-file.ts +89 -0
  293. package/src/mcp/tools/sia-community.ts +113 -0
  294. package/src/mcp/tools/sia-doctor.ts +73 -0
  295. package/src/mcp/tools/sia-execute-file.ts +122 -0
  296. package/src/mcp/tools/sia-execute.ts +104 -0
  297. package/src/mcp/tools/sia-expand.ts +158 -0
  298. package/src/mcp/tools/sia-fetch-and-index.ts +241 -0
  299. package/src/mcp/tools/sia-flag.ts +65 -0
  300. package/src/mcp/tools/sia-index.ts +111 -0
  301. package/src/mcp/tools/sia-note.ts +134 -0
  302. package/src/mcp/tools/sia-search.ts +105 -0
  303. package/src/mcp/tools/sia-stats.ts +63 -0
  304. package/src/mcp/tools/sia-sync-status.ts +44 -0
  305. package/src/mcp/tools/sia-upgrade.ts +247 -0
  306. package/src/mcp/truncate.ts +231 -0
  307. package/src/native/bridge.ts +167 -0
  308. package/src/native/fallback-ast-diff.ts +144 -0
  309. package/src/native/fallback-graph.ts +325 -0
  310. package/src/ontology/constraints.ts +56 -0
  311. package/src/ontology/errors.ts +8 -0
  312. package/src/ontology/middleware.ts +266 -0
  313. package/src/retrieval/bm25-search.ts +151 -0
  314. package/src/retrieval/context-assembly.ts +76 -0
  315. package/src/retrieval/graph-traversal.ts +168 -0
  316. package/src/retrieval/pagerank.ts +40 -0
  317. package/src/retrieval/query-classifier.ts +106 -0
  318. package/src/retrieval/reranker.ts +156 -0
  319. package/src/retrieval/search.ts +236 -0
  320. package/src/retrieval/throttle.ts +102 -0
  321. package/src/retrieval/vector-search.ts +203 -0
  322. package/src/retrieval/workspace-search.ts +130 -0
  323. package/src/sandbox/context-mode.ts +285 -0
  324. package/src/sandbox/credential-pass.ts +55 -0
  325. package/src/sandbox/executor.ts +235 -0
  326. package/src/security/pattern-detector.ts +127 -0
  327. package/src/security/rule-of-two.ts +50 -0
  328. package/src/security/sanitize.ts +46 -0
  329. package/src/security/semantic-consistency.ts +93 -0
  330. package/src/security/staging-promoter.ts +154 -0
  331. package/src/shared/config.ts +302 -0
  332. package/src/shared/diagnostics.ts +210 -0
  333. package/src/shared/errors.ts +48 -0
  334. package/src/shared/git-utils.ts +143 -0
  335. package/src/shared/llm-client.ts +120 -0
  336. package/src/shared/logger.ts +99 -0
  337. package/src/shared/types.ts +79 -0
  338. package/src/sync/client.ts +43 -0
  339. package/src/sync/conflict.ts +106 -0
  340. package/src/sync/dedup.ts +183 -0
  341. package/src/sync/hlc.ts +117 -0
  342. package/src/sync/keychain.ts +144 -0
  343. package/src/sync/pull.ts +232 -0
  344. package/src/sync/push.ts +131 -0
  345. package/src/types/chokidar.d.ts +23 -0
  346. package/src/visualization/graph-renderer.ts +312 -0
  347. package/src/visualization/subgraph-extract.ts +208 -0
  348. package/src/visualization/views/community-clusters.ts +246 -0
  349. package/src/visualization/views/dependency-map.ts +189 -0
  350. package/src/visualization/views/graph-explorer.ts +364 -0
  351. package/src/visualization/views/timeline.ts +247 -0
  352. package/src/workspace/api-contracts.ts +226 -0
  353. package/src/workspace/cross-repo.ts +61 -0
  354. package/src/workspace/detector.ts +190 -0
  355. package/src/workspace/manifest.ts +141 -0
@@ -0,0 +1,335 @@
1
+ // Module: import — load graph from exported JSON (merge or replace mode)
2
+
3
+ import { readFileSync } from "node:fs";
4
+ import { consolidate } from "@/capture/consolidate";
5
+ import type { CandidateFact } from "@/capture/types";
6
+ import type { ExportData } from "@/cli/commands/export";
7
+ import { writeAuditEntry } from "@/graph/audit";
8
+ import type { SiaDb } from "@/graph/db-interface";
9
+
10
+ /** Aggregate counts returned after an import operation. */
11
+ export interface ImportResult {
12
+ entitiesImported: number;
13
+ edgesImported: number;
14
+ communitiesImported: number;
15
+ mode: "merge" | "replace";
16
+ }
17
+
18
+ /**
19
+ * Import graph data from an ExportData payload.
20
+ *
21
+ * Two modes:
22
+ * - **merge**: converts entities to CandidateFact[] and runs through the
23
+ * consolidation pipeline; edges are inserted only when both endpoints exist;
24
+ * communities use INSERT OR IGNORE.
25
+ * - **replace**: archives all active entities, then bulk-inserts everything
26
+ * from the export data directly.
27
+ */
28
+ export async function importGraph(
29
+ db: SiaDb,
30
+ data: ExportData,
31
+ mode: "merge" | "replace",
32
+ ): Promise<ImportResult> {
33
+ if (data.version !== 1) {
34
+ throw new Error(`Unsupported export version: ${data.version}. Expected version 1.`);
35
+ }
36
+
37
+ if (mode === "merge") {
38
+ return mergeImport(db, data);
39
+ }
40
+ return replaceImport(db, data);
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Merge mode
45
+ // ---------------------------------------------------------------------------
46
+
47
+ async function mergeImport(db: SiaDb, data: ExportData): Promise<ImportResult> {
48
+ const result: ImportResult = {
49
+ entitiesImported: 0,
50
+ edgesImported: 0,
51
+ communitiesImported: 0,
52
+ mode: "merge",
53
+ };
54
+
55
+ // 1. Convert entities to CandidateFact[] and consolidate
56
+ const candidates: CandidateFact[] = data.entities.map((e) => ({
57
+ type: (e.type as CandidateFact["type"]) ?? "Concept",
58
+ name: (e.name as string) ?? "",
59
+ content: (e.content as string) ?? "",
60
+ summary: (e.summary as string) ?? "",
61
+ tags: parseTags(e.tags),
62
+ file_paths: parseFilePaths(e.file_paths),
63
+ trust_tier: parseTrustTier(e.trust_tier),
64
+ confidence: typeof e.confidence === "number" ? e.confidence : 0.7,
65
+ extraction_method: (e.extraction_method as string) ?? undefined,
66
+ t_valid_from: typeof e.t_valid_from === "number" ? e.t_valid_from : undefined,
67
+ }));
68
+
69
+ const consolidationResult = await consolidate(db, candidates);
70
+ result.entitiesImported = consolidationResult.added + consolidationResult.updated;
71
+
72
+ // 2. Import edges — only if both endpoints exist in the graph
73
+ for (const edge of data.edges) {
74
+ const fromId = edge.from_id as string;
75
+ const toId = edge.to_id as string;
76
+ if (!fromId || !toId) continue;
77
+
78
+ const fromExists = await db.execute("SELECT 1 FROM graph_nodes WHERE id = ?", [fromId]);
79
+ const toExists = await db.execute("SELECT 1 FROM graph_nodes WHERE id = ?", [toId]);
80
+
81
+ if (fromExists.rows.length > 0 && toExists.rows.length > 0) {
82
+ await db.execute(
83
+ `INSERT INTO graph_edges (id, from_id, to_id, type, weight, confidence, trust_tier,
84
+ t_created, t_expired, t_valid_from, t_valid_until,
85
+ source_episode, extraction_method)
86
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
87
+ [
88
+ edge.id as string,
89
+ fromId,
90
+ toId,
91
+ (edge.type as string) ?? "RELATED_TO",
92
+ typeof edge.weight === "number" ? edge.weight : 1.0,
93
+ typeof edge.confidence === "number" ? edge.confidence : 0.7,
94
+ typeof edge.trust_tier === "number" ? edge.trust_tier : 3,
95
+ typeof edge.t_created === "number" ? edge.t_created : Date.now(),
96
+ edge.t_expired ?? null,
97
+ edge.t_valid_from ?? null,
98
+ edge.t_valid_until ?? null,
99
+ edge.source_episode ?? null,
100
+ edge.extraction_method ?? null,
101
+ ],
102
+ );
103
+ result.edgesImported++;
104
+ }
105
+ }
106
+
107
+ // 3. Import communities — INSERT OR IGNORE
108
+ for (const community of data.communities) {
109
+ await db.execute(
110
+ `INSERT OR IGNORE INTO communities (id, level, parent_id, summary, member_count, package_path, created_at, updated_at)
111
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
112
+ [
113
+ community.id ?? null,
114
+ community.level ?? 0,
115
+ community.parent_id ?? null,
116
+ community.summary ?? "",
117
+ community.member_count ?? 0,
118
+ community.package_path ?? null,
119
+ community.created_at ?? Date.now(),
120
+ community.updated_at ?? Date.now(),
121
+ ],
122
+ );
123
+ result.communitiesImported++;
124
+ }
125
+
126
+ // 4. Audit log
127
+ await writeAuditEntry(db, "ADD", {
128
+ extraction_method: `import:merge:${result.entitiesImported}e/${result.edgesImported}ed/${result.communitiesImported}c`,
129
+ });
130
+
131
+ return result;
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Replace mode
136
+ // ---------------------------------------------------------------------------
137
+
138
+ async function replaceImport(db: SiaDb, data: ExportData): Promise<ImportResult> {
139
+ const result: ImportResult = {
140
+ entitiesImported: 0,
141
+ edgesImported: 0,
142
+ communitiesImported: 0,
143
+ mode: "replace",
144
+ };
145
+
146
+ const now = Date.now();
147
+
148
+ await db.transaction(async (tx) => {
149
+ // 1. Archive all currently active entities
150
+ await tx.execute(
151
+ "UPDATE graph_nodes SET archived_at = ? WHERE t_valid_until IS NULL AND archived_at IS NULL",
152
+ [now],
153
+ );
154
+
155
+ // 2. Insert all entities from export data
156
+ for (const e of data.entities) {
157
+ await tx.execute(
158
+ `INSERT INTO graph_nodes (
159
+ id, type, name, content, summary,
160
+ package_path, tags, file_paths,
161
+ trust_tier, confidence, base_confidence,
162
+ importance, base_importance,
163
+ access_count, edge_count,
164
+ last_accessed, created_at,
165
+ t_created, t_expired, t_valid_from, t_valid_until,
166
+ visibility, created_by, workspace_scope,
167
+ hlc_created, hlc_modified, synced_at,
168
+ conflict_group_id,
169
+ source_episode, extraction_method, extraction_model,
170
+ embedding, archived_at
171
+ ) VALUES (
172
+ ?, ?, ?, ?, ?,
173
+ ?, ?, ?,
174
+ ?, ?, ?,
175
+ ?, ?,
176
+ ?, ?,
177
+ ?, ?,
178
+ ?, ?, ?, ?,
179
+ ?, ?, ?,
180
+ ?, ?, ?,
181
+ ?,
182
+ ?, ?, ?,
183
+ ?, ?
184
+ )`,
185
+ [
186
+ e.id as string,
187
+ e.type as string,
188
+ e.name as string,
189
+ e.content as string,
190
+ e.summary as string,
191
+ e.package_path ?? null,
192
+ typeof e.tags === "string" ? e.tags : JSON.stringify(e.tags ?? []),
193
+ typeof e.file_paths === "string" ? e.file_paths : JSON.stringify(e.file_paths ?? []),
194
+ typeof e.trust_tier === "number" ? e.trust_tier : 3,
195
+ typeof e.confidence === "number" ? e.confidence : 0.7,
196
+ typeof e.base_confidence === "number" ? e.base_confidence : 0.7,
197
+ typeof e.importance === "number" ? e.importance : 0.5,
198
+ typeof e.base_importance === "number" ? e.base_importance : 0.5,
199
+ typeof e.access_count === "number" ? e.access_count : 0,
200
+ typeof e.edge_count === "number" ? e.edge_count : 0,
201
+ typeof e.last_accessed === "number" ? e.last_accessed : now,
202
+ typeof e.created_at === "number" ? e.created_at : now,
203
+ typeof e.t_created === "number" ? e.t_created : now,
204
+ e.t_expired ?? null,
205
+ e.t_valid_from ?? null,
206
+ e.t_valid_until ?? null,
207
+ (e.visibility as string) ?? "private",
208
+ (e.created_by as string) ?? "local",
209
+ e.workspace_scope ?? null,
210
+ e.hlc_created ?? null,
211
+ e.hlc_modified ?? null,
212
+ e.synced_at ?? null,
213
+ e.conflict_group_id ?? null,
214
+ e.source_episode ?? null,
215
+ e.extraction_method ?? null,
216
+ e.extraction_model ?? null,
217
+ e.embedding ?? null,
218
+ e.archived_at ?? null,
219
+ ],
220
+ );
221
+ result.entitiesImported++;
222
+ }
223
+
224
+ // 3. Insert all edges from export data
225
+ for (const edge of data.edges) {
226
+ await tx.execute(
227
+ `INSERT INTO graph_edges (id, from_id, to_id, type, weight, confidence, trust_tier,
228
+ t_created, t_expired, t_valid_from, t_valid_until,
229
+ source_episode, extraction_method)
230
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
231
+ [
232
+ edge.id as string,
233
+ edge.from_id as string,
234
+ edge.to_id as string,
235
+ (edge.type as string) ?? "RELATED_TO",
236
+ typeof edge.weight === "number" ? edge.weight : 1.0,
237
+ typeof edge.confidence === "number" ? edge.confidence : 0.7,
238
+ typeof edge.trust_tier === "number" ? edge.trust_tier : 3,
239
+ typeof edge.t_created === "number" ? edge.t_created : now,
240
+ edge.t_expired ?? null,
241
+ edge.t_valid_from ?? null,
242
+ edge.t_valid_until ?? null,
243
+ edge.source_episode ?? null,
244
+ edge.extraction_method ?? null,
245
+ ],
246
+ );
247
+ result.edgesImported++;
248
+ }
249
+
250
+ // 4. Insert communities
251
+ for (const community of data.communities) {
252
+ await tx.execute(
253
+ `INSERT INTO communities (id, level, parent_id, summary, member_count, package_path, created_at, updated_at)
254
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
255
+ [
256
+ community.id ?? null,
257
+ community.level ?? 0,
258
+ community.parent_id ?? null,
259
+ community.summary ?? "",
260
+ community.member_count ?? 0,
261
+ community.package_path ?? null,
262
+ community.created_at ?? Date.now(),
263
+ community.updated_at ?? Date.now(),
264
+ ],
265
+ );
266
+ result.communitiesImported++;
267
+ }
268
+
269
+ // 5. Audit log
270
+ await writeAuditEntry(tx, "ADD", {
271
+ extraction_method: `import:replace:${result.entitiesImported}e/${result.edgesImported}ed/${result.communitiesImported}c`,
272
+ });
273
+ });
274
+
275
+ return result;
276
+ }
277
+
278
+ // ---------------------------------------------------------------------------
279
+ // File I/O
280
+ // ---------------------------------------------------------------------------
281
+
282
+ /**
283
+ * Import graph data from a JSON file on disk.
284
+ *
285
+ * Reads the file, parses it as ExportData, and delegates to importGraph.
286
+ */
287
+ export async function importFromFile(
288
+ db: SiaDb,
289
+ filePath: string,
290
+ mode: "merge" | "replace",
291
+ ): Promise<ImportResult> {
292
+ const raw = readFileSync(filePath, "utf-8");
293
+ const data = JSON.parse(raw) as ExportData;
294
+ return importGraph(db, data, mode);
295
+ }
296
+
297
+ // ---------------------------------------------------------------------------
298
+ // Helpers
299
+ // ---------------------------------------------------------------------------
300
+
301
+ /** Parse tags from an export row — handles both JSON strings and arrays. */
302
+ function parseTags(raw: unknown): string[] {
303
+ if (Array.isArray(raw)) return raw as string[];
304
+ if (typeof raw === "string") {
305
+ try {
306
+ const parsed = JSON.parse(raw);
307
+ return Array.isArray(parsed) ? parsed : [];
308
+ } catch {
309
+ return [];
310
+ }
311
+ }
312
+ return [];
313
+ }
314
+
315
+ /** Parse file_paths from an export row — handles both JSON strings and arrays. */
316
+ function parseFilePaths(raw: unknown): string[] {
317
+ if (Array.isArray(raw)) return raw as string[];
318
+ if (typeof raw === "string") {
319
+ try {
320
+ const parsed = JSON.parse(raw);
321
+ return Array.isArray(parsed) ? parsed : [];
322
+ } catch {
323
+ return [];
324
+ }
325
+ }
326
+ return [];
327
+ }
328
+
329
+ /** Parse trust_tier ensuring it falls within the 1-4 range. */
330
+ function parseTrustTier(raw: unknown): 1 | 2 | 3 | 4 {
331
+ if (typeof raw === "number" && raw >= 1 && raw <= 4) {
332
+ return raw as 1 | 2 | 3 | 4;
333
+ }
334
+ return 3;
335
+ }
@@ -0,0 +1,156 @@
1
+ // Module: install — sia install command implementation
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { basename, join, resolve } from "node:path";
5
+ import { openBridgeDb } from "@/graph/bridge-db";
6
+ import { openMetaDb, registerRepo } from "@/graph/meta-db";
7
+ import { openEpisodicDb, openGraphDb } from "@/graph/semantic-db";
8
+ import { SIA_HOME, writeConfig } from "@/shared/config";
9
+
10
+ /** Result returned by siaInstall on success. */
11
+ export interface SiaInstallResult {
12
+ repoHash: string;
13
+ siaHome: string;
14
+ dbsInitialized: boolean;
15
+ }
16
+
17
+ /**
18
+ * Walk up from `startDir` looking for a `.git` directory.
19
+ * Returns the directory containing `.git`, or null if none found.
20
+ */
21
+ function findRepoRoot(startDir: string): string | null {
22
+ let dir = resolve(startDir);
23
+ const root = resolve("/");
24
+ while (dir !== root) {
25
+ if (existsSync(join(dir, ".git"))) {
26
+ return dir;
27
+ }
28
+ const parent = resolve(dir, "..");
29
+ if (parent === dir) break;
30
+ dir = parent;
31
+ }
32
+ // Check root as well
33
+ if (existsSync(join(dir, ".git"))) {
34
+ return dir;
35
+ }
36
+ return null;
37
+ }
38
+
39
+ /**
40
+ * Install Sia for a repository.
41
+ *
42
+ * Detects the repo root, initializes all databases, registers the repo,
43
+ * writes default config, copies the CLAUDE.md template, and creates the
44
+ * ast-cache directory.
45
+ */
46
+ export async function siaInstall(opts?: {
47
+ cwd?: string;
48
+ siaHome?: string;
49
+ }): Promise<SiaInstallResult> {
50
+ const cwd = opts?.cwd ?? process.cwd();
51
+ const siaHome = opts?.siaHome ?? SIA_HOME;
52
+
53
+ // (a) Detect repo root
54
+ const repoRoot = findRepoRoot(cwd);
55
+ if (!repoRoot) {
56
+ throw new Error(`No .git directory found from ${cwd}`);
57
+ }
58
+
59
+ // (b) Compute repo hash
60
+ const resolvedPath = resolve(repoRoot);
61
+ const repoHash = createHash("sha256").update(resolvedPath).digest("hex");
62
+
63
+ // (c) Create repo directory
64
+ const repoDir = join(siaHome, "repos", repoHash);
65
+ mkdirSync(repoDir, { recursive: true });
66
+
67
+ // (d) Initialize all 4 databases, then close each
68
+ const graphDb = openGraphDb(repoHash, siaHome);
69
+ await graphDb.close();
70
+
71
+ const episodicDb = openEpisodicDb(repoHash, siaHome);
72
+ await episodicDb.close();
73
+
74
+ const metaDb = openMetaDb(siaHome);
75
+
76
+ // (e) Register repo in meta.db
77
+ await registerRepo(metaDb, resolvedPath);
78
+ await metaDb.close();
79
+
80
+ const bridgeDb = openBridgeDb(siaHome);
81
+ await bridgeDb.close();
82
+
83
+ // (f) Write default config if absent
84
+ const configPath = join(siaHome, "config.json");
85
+ if (!existsSync(configPath)) {
86
+ writeConfig({}, siaHome);
87
+ }
88
+
89
+ // (g) Copy CLAUDE.md template to project root
90
+ writeClaude(repoRoot, resolvedPath);
91
+
92
+ // (h) Create ast-cache directory
93
+ const astCacheDir = join(siaHome, "ast-cache", repoHash);
94
+ mkdirSync(astCacheDir, { recursive: true });
95
+
96
+ // (i) Print success message
97
+ console.log(`Sia installed successfully.`);
98
+ console.log(` Repo hash: ${repoHash}`);
99
+ console.log(` Sia home: ${siaHome}`);
100
+ console.log(` Repo path: ${resolvedPath}`);
101
+
102
+ // (j) Return result
103
+ return { repoHash, siaHome, dbsInitialized: true };
104
+ }
105
+
106
+ /** End-of-generated-block marker used in CLAUDE.md */
107
+ const END_MARKER = "<!-- END GENERATED BLOCK -->";
108
+
109
+ /**
110
+ * Read the CLAUDE.md template, substitute placeholders, and write to project root.
111
+ * - If CLAUDE.md does not exist: write the full file.
112
+ * - If CLAUDE.md exists and contains the END_MARKER: replace everything up to and
113
+ * including the marker, preserving user content after it.
114
+ * - If CLAUDE.md exists but has no END_MARKER: skip (do not overwrite).
115
+ */
116
+ function writeClaude(repoRoot: string, resolvedPath: string): void {
117
+ const templatePath = resolve(import.meta.dirname, "../../agent/claude-md-template.md");
118
+ if (!existsSync(templatePath)) {
119
+ return;
120
+ }
121
+
122
+ const template = readFileSync(templatePath, "utf-8");
123
+ const pkgPath = resolve(import.meta.dirname, "../../../package.json");
124
+ let version = "0.0.0";
125
+ if (existsSync(pkgPath)) {
126
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
127
+ version = pkg.version ?? version;
128
+ }
129
+
130
+ const repoName = basename(resolvedPath);
131
+ const rendered = template
132
+ .replace(/\{\{SIA_VERSION\}\}/g, version)
133
+ .replace(/\{\{GENERATED_AT\}\}/g, new Date().toISOString())
134
+ .replace(/\{\{WORKSPACE_NAME\}\}/g, repoName);
135
+
136
+ const claudePath = join(repoRoot, "CLAUDE.md");
137
+
138
+ if (!existsSync(claudePath)) {
139
+ // File does not exist — write fresh
140
+ writeFileSync(claudePath, rendered, "utf-8");
141
+ return;
142
+ }
143
+
144
+ // File exists — check for END_MARKER
145
+ const existing = readFileSync(claudePath, "utf-8");
146
+ const markerIdx = existing.indexOf(END_MARKER);
147
+
148
+ if (markerIdx === -1) {
149
+ // No marker found — skip to avoid overwriting user content
150
+ return;
151
+ }
152
+
153
+ // Replace everything up to and including the marker, keep user content after
154
+ const userContent = existing.slice(markerIdx + END_MARKER.length);
155
+ writeFileSync(claudePath, rendered + userContent, "utf-8");
156
+ }