@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,79 @@
1
+ // Module: stats — graph statistics
2
+
3
+ import type { SiaDb } from "@/graph/db-interface";
4
+
5
+ export interface GraphStats {
6
+ totalEntitiesByType: Record<string, number>;
7
+ archivedCount: number;
8
+ invalidatedCount: number;
9
+ activeEdgesByType: Record<string, number>;
10
+ communityCount: number;
11
+ episodeCount: number;
12
+ pendingConflicts: number;
13
+ }
14
+
15
+ /**
16
+ * Gather aggregate statistics from the graph, episodic, and meta databases.
17
+ */
18
+ export async function getStats(
19
+ graphDb: SiaDb,
20
+ episodicDb?: SiaDb,
21
+ _metaDb?: SiaDb,
22
+ ): Promise<GraphStats> {
23
+ // --- Active entities by type ---
24
+ const totalEntitiesByType: Record<string, number> = {};
25
+ const { rows: entityTypeRows } = await graphDb.execute(
26
+ "SELECT type, COUNT(*) AS cnt FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL GROUP BY type",
27
+ );
28
+ for (const row of entityTypeRows) {
29
+ totalEntitiesByType[row.type as string] = row.cnt as number;
30
+ }
31
+
32
+ // --- Archived count ---
33
+ const { rows: archivedRows } = await graphDb.execute(
34
+ "SELECT COUNT(*) AS cnt FROM graph_nodes WHERE archived_at IS NOT NULL",
35
+ );
36
+ const archivedCount = (archivedRows[0]?.cnt as number) ?? 0;
37
+
38
+ // --- Invalidated count ---
39
+ const { rows: invalidatedRows } = await graphDb.execute(
40
+ "SELECT COUNT(*) AS cnt FROM graph_nodes WHERE t_valid_until IS NOT NULL",
41
+ );
42
+ const invalidatedCount = (invalidatedRows[0]?.cnt as number) ?? 0;
43
+
44
+ // --- Active edges by type ---
45
+ const activeEdgesByType: Record<string, number> = {};
46
+ const { rows: edgeTypeRows } = await graphDb.execute(
47
+ "SELECT type, COUNT(*) AS cnt FROM graph_edges WHERE t_valid_until IS NULL GROUP BY type",
48
+ );
49
+ for (const row of edgeTypeRows) {
50
+ activeEdgesByType[row.type as string] = row.cnt as number;
51
+ }
52
+
53
+ // --- Community count ---
54
+ const { rows: communityRows } = await graphDb.execute("SELECT COUNT(*) AS cnt FROM communities");
55
+ const communityCount = (communityRows[0]?.cnt as number) ?? 0;
56
+
57
+ // --- Episode count (from episodicDb if provided) ---
58
+ let episodeCount = 0;
59
+ if (episodicDb) {
60
+ const { rows: episodeRows } = await episodicDb.execute("SELECT COUNT(*) AS cnt FROM episodes");
61
+ episodeCount = (episodeRows[0]?.cnt as number) ?? 0;
62
+ }
63
+
64
+ // --- Pending conflicts ---
65
+ const { rows: conflictRows } = await graphDb.execute(
66
+ "SELECT COUNT(DISTINCT conflict_group_id) AS cnt FROM graph_nodes WHERE conflict_group_id IS NOT NULL AND t_valid_until IS NULL",
67
+ );
68
+ const pendingConflicts = (conflictRows[0]?.cnt as number) ?? 0;
69
+
70
+ return {
71
+ totalEntitiesByType,
72
+ archivedCount,
73
+ invalidatedCount,
74
+ activeEdgesByType,
75
+ communityCount,
76
+ episodeCount,
77
+ pendingConflicts,
78
+ };
79
+ }
@@ -0,0 +1,176 @@
1
+ // Module: status — knowledge graph health dashboard
2
+
3
+ import type { SiaDb } from "@/graph/db-interface";
4
+
5
+ export interface GraphHealth {
6
+ totalEntities: number;
7
+ totalEdges: number;
8
+ totalCommunities: number;
9
+ byType: Record<string, number>;
10
+ byTier: Record<number, number>;
11
+ byKind: Record<string, number>;
12
+ conflictGroups: number;
13
+ archivedEntities: number;
14
+ recentEntities24h: number;
15
+ oldestEntity: string | null;
16
+ newestEntity: string | null;
17
+ }
18
+
19
+ const TIER_LABELS: Record<number, string> = {
20
+ 1: "User-Direct ",
21
+ 2: "Code-Analysis",
22
+ 3: "LLM-Inferred ",
23
+ 4: "External ",
24
+ };
25
+
26
+ /**
27
+ * Gather health metrics from the knowledge graph.
28
+ */
29
+ export async function getGraphHealth(db: SiaDb): Promise<GraphHealth> {
30
+ // Active entities total
31
+ const { rows: totalRows } = await db.execute(
32
+ "SELECT COUNT(*) AS cnt FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL",
33
+ );
34
+ const totalEntities = (totalRows[0]?.cnt as number) ?? 0;
35
+
36
+ // By type
37
+ const byType: Record<string, number> = {};
38
+ const { rows: typeRows } = await db.execute(
39
+ "SELECT type, COUNT(*) AS cnt FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL GROUP BY type",
40
+ );
41
+ for (const row of typeRows) {
42
+ byType[row.type as string] = row.cnt as number;
43
+ }
44
+
45
+ // By trust tier
46
+ const byTier: Record<number, number> = {};
47
+ const { rows: tierRows } = await db.execute(
48
+ "SELECT trust_tier, COUNT(*) AS cnt FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL GROUP BY trust_tier",
49
+ );
50
+ for (const row of tierRows) {
51
+ byTier[row.trust_tier as number] = row.cnt as number;
52
+ }
53
+
54
+ // By kind
55
+ const byKind: Record<string, number> = {};
56
+ const { rows: kindRows } = await db.execute(
57
+ "SELECT kind, COUNT(*) AS cnt FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL AND kind IS NOT NULL GROUP BY kind",
58
+ );
59
+ for (const row of kindRows) {
60
+ byKind[row.kind as string] = row.cnt as number;
61
+ }
62
+
63
+ // Total edges
64
+ const { rows: edgeRows } = await db.execute(
65
+ "SELECT COUNT(*) AS cnt FROM graph_edges WHERE t_valid_until IS NULL",
66
+ );
67
+ const totalEdges = (edgeRows[0]?.cnt as number) ?? 0;
68
+
69
+ // Communities
70
+ const { rows: communityRows } = await db.execute("SELECT COUNT(*) AS cnt FROM communities");
71
+ const totalCommunities = (communityRows[0]?.cnt as number) ?? 0;
72
+
73
+ // Conflict groups
74
+ const { rows: conflictRows } = await db.execute(
75
+ "SELECT COUNT(DISTINCT conflict_group_id) AS cnt FROM graph_nodes WHERE conflict_group_id IS NOT NULL AND t_valid_until IS NULL",
76
+ );
77
+ const conflictGroups = (conflictRows[0]?.cnt as number) ?? 0;
78
+
79
+ // Archived
80
+ const { rows: archivedRows } = await db.execute(
81
+ "SELECT COUNT(*) AS cnt FROM graph_nodes WHERE archived_at IS NOT NULL",
82
+ );
83
+ const archivedEntities = (archivedRows[0]?.cnt as number) ?? 0;
84
+
85
+ // Recent (24h)
86
+ const oneDayAgo = Date.now() - 86_400_000;
87
+ const { rows: recentRows } = await db.execute(
88
+ "SELECT COUNT(*) AS cnt FROM graph_nodes WHERE created_at > ? AND t_valid_until IS NULL AND archived_at IS NULL",
89
+ [oneDayAgo],
90
+ );
91
+ const recentEntities24h = (recentRows[0]?.cnt as number) ?? 0;
92
+
93
+ // Oldest / newest
94
+ const { rows: oldestRows } = await db.execute(
95
+ "SELECT MIN(created_at) AS ts FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL",
96
+ );
97
+ const oldestTs = oldestRows[0]?.ts as number | null;
98
+ const oldestEntity = oldestTs ? new Date(oldestTs).toISOString() : null;
99
+
100
+ const { rows: newestRows } = await db.execute(
101
+ "SELECT MAX(created_at) AS ts FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL",
102
+ );
103
+ const newestTs = newestRows[0]?.ts as number | null;
104
+ const newestEntity = newestTs ? new Date(newestTs).toISOString() : null;
105
+
106
+ return {
107
+ totalEntities,
108
+ totalEdges,
109
+ totalCommunities,
110
+ byType,
111
+ byTier,
112
+ byKind,
113
+ conflictGroups,
114
+ archivedEntities,
115
+ recentEntities24h,
116
+ oldestEntity,
117
+ newestEntity,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Format GraphHealth as a human-friendly terminal string.
123
+ */
124
+ export function formatHealth(health: GraphHealth): string {
125
+ const lines: string[] = [];
126
+
127
+ lines.push("=== SIA Knowledge Graph Health ===");
128
+ lines.push(`Total entities: ${health.totalEntities}`);
129
+ lines.push(`Total edges: ${health.totalEdges}`);
130
+ lines.push(`Communities: ${health.totalCommunities}`);
131
+ lines.push(
132
+ `Conflicts: ${health.conflictGroups} group${health.conflictGroups !== 1 ? "s" : ""}`,
133
+ );
134
+ lines.push(`Archived: ${health.archivedEntities}`);
135
+ lines.push(`Recent (24h): ${health.recentEntities24h}`);
136
+
137
+ if (health.oldestEntity && health.newestEntity) {
138
+ const oldestDate = new Date(health.oldestEntity);
139
+ const newestDate = new Date(health.newestEntity);
140
+ const ageDays = Math.round((newestDate.getTime() - oldestDate.getTime()) / 86_400_000);
141
+ lines.push(`Graph age: ${ageDays} day${ageDays !== 1 ? "s" : ""}`);
142
+ }
143
+
144
+ // By type
145
+ const typeEntries = Object.entries(health.byType).sort((a, b) => b[1] - a[1]);
146
+ if (typeEntries.length > 0) {
147
+ lines.push("");
148
+ lines.push("--- By Type ---");
149
+ for (const [type, count] of typeEntries) {
150
+ lines.push(` ${type.padEnd(21)}${count}`);
151
+ }
152
+ }
153
+
154
+ // By tier
155
+ const tierEntries = Object.entries(health.byTier)
156
+ .map(([tier, count]) => [Number(tier), count] as [number, number])
157
+ .sort((a, b) => a[0] - b[0]);
158
+ if (tierEntries.length > 0) {
159
+ lines.push("");
160
+ lines.push("--- By Trust Tier ---");
161
+ for (const [tier, count] of tierEntries) {
162
+ const label = TIER_LABELS[tier] ?? `Tier ${tier} `;
163
+ lines.push(` Tier ${tier} (${label}) ${count}`);
164
+ }
165
+ }
166
+
167
+ return lines.join("\n");
168
+ }
169
+
170
+ /**
171
+ * CLI entry point for `sia status`.
172
+ */
173
+ export async function runStatus(db: SiaDb): Promise<void> {
174
+ const health = await getGraphHealth(db);
175
+ console.log(formatHealth(health));
176
+ }
@@ -0,0 +1,96 @@
1
+ // Module: sync — CLI command for manual team sync push/pull
2
+ //
3
+ // Usage:
4
+ // sia sync — push then pull
5
+ // sia sync push — push local knowledge to server
6
+ // sia sync pull — pull team knowledge from server
7
+
8
+ import { resolveRepoHash } from "@/capture/hook";
9
+ import type { SiaDb } from "@/graph/db-interface";
10
+ import { getConfig, resolveSiaHome } from "@/shared/config";
11
+
12
+ function printUsage(): void {
13
+ console.log(`Usage: sia sync [push|pull]
14
+
15
+ sia sync Push then pull (default)
16
+ sia sync push Push local knowledge to team server
17
+ sia sync pull Pull team knowledge from server
18
+ `);
19
+ }
20
+
21
+ export async function runSync(args: string[]): Promise<void> {
22
+ const subcommand = args[0] ?? "both";
23
+
24
+ if (subcommand === "--help" || subcommand === "-h") {
25
+ printUsage();
26
+ return;
27
+ }
28
+
29
+ const validSubcommands = ["push", "pull", "both"];
30
+ if (!validSubcommands.includes(subcommand)) {
31
+ console.error(`Unknown subcommand: ${subcommand}`);
32
+ printUsage();
33
+ process.exit(1);
34
+ }
35
+
36
+ const siaHome = resolveSiaHome();
37
+ const config = getConfig(siaHome);
38
+
39
+ if (!config.sync.enabled || !config.sync.serverUrl) {
40
+ console.error("Sync not configured. Run 'sia team join <url> <token>' first.");
41
+ process.exit(1);
42
+ }
43
+
44
+ const cwd = process.cwd();
45
+ const repoHash = resolveRepoHash(cwd);
46
+
47
+ let syncDb: SiaDb | undefined;
48
+ let bridgeDb: SiaDb | undefined;
49
+ let metaDb: SiaDb | undefined;
50
+
51
+ try {
52
+ const { createSiaDb } = await import("@/sync/client");
53
+ const { openBridgeDb } = await import("@/graph/bridge-db");
54
+ const { openMetaDb } = await import("@/graph/meta-db");
55
+
56
+ syncDb = await createSiaDb(repoHash, config.sync, { siaHome });
57
+ bridgeDb = openBridgeDb(siaHome);
58
+ metaDb = openMetaDb(siaHome);
59
+
60
+ if (subcommand === "push" || subcommand === "both") {
61
+ const { pushChanges } = await import("@/sync/push");
62
+ const result = await pushChanges(syncDb, config.sync, bridgeDb, repoHash, siaHome);
63
+ process.stdout.write(
64
+ `Push: ${result.entitiesPushed} entities, ${result.edgesPushed} edges, ${result.bridgeEdgesPushed} bridge edges\n`,
65
+ );
66
+ }
67
+
68
+ if (subcommand === "pull" || subcommand === "both") {
69
+ const { pullChanges } = await import("@/sync/pull");
70
+ const result = await pullChanges(syncDb, bridgeDb, config.sync, repoHash, siaHome, metaDb);
71
+ process.stdout.write(
72
+ `Pull: ${result.entitiesReceived} entities, ${result.edgesReceived} edges, ${result.vssRefreshed} VSS refreshed\n`,
73
+ );
74
+ }
75
+ } catch (err) {
76
+ const msg = err instanceof Error ? err.message : String(err);
77
+ console.error(`Sync failed: ${msg}`);
78
+ process.exit(1);
79
+ } finally {
80
+ try {
81
+ await syncDb?.close();
82
+ } catch (e) {
83
+ console.error("[sia] warning: failed to close sync db:", e);
84
+ }
85
+ try {
86
+ await bridgeDb?.close();
87
+ } catch (e) {
88
+ console.error("[sia] warning: failed to close bridge db:", e);
89
+ }
90
+ try {
91
+ await metaDb?.close();
92
+ } catch (e) {
93
+ console.error("[sia] warning: failed to close meta db:", e);
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,118 @@
1
+ // Module: team — team sync CLI helpers
2
+
3
+ import { randomUUID } from "node:crypto";
4
+ import type { SiaDb } from "@/graph/db-interface";
5
+ import { getConfig, type SiaConfig, writeConfig } from "@/shared/config";
6
+ import { deleteToken, storeToken } from "@/sync/keychain";
7
+ import { pullChanges } from "@/sync/pull";
8
+
9
+ export interface TeamStatus {
10
+ enabled: boolean;
11
+ serverUrl: string | null;
12
+ developerId: string | null;
13
+ syncInterval: number;
14
+ peerCount: number;
15
+ pendingConflicts: number;
16
+ lastSyncAt: number | null;
17
+ }
18
+
19
+ function ensureDeveloperId(config: SiaConfig): string {
20
+ if (config.sync.developerId) return config.sync.developerId;
21
+ const id = randomUUID();
22
+ writeConfig({
23
+ sync: {
24
+ developerId: id,
25
+ enabled: false,
26
+ serverUrl: null,
27
+ syncInterval: 0,
28
+ },
29
+ });
30
+ return id;
31
+ }
32
+
33
+ export async function teamJoin(
34
+ serverUrl: string,
35
+ token: string,
36
+ opts: {
37
+ syncInterval?: number;
38
+ siaHome?: string;
39
+ repoHash?: string;
40
+ db?: SiaDb;
41
+ bridgeDb?: SiaDb;
42
+ } = {},
43
+ ): Promise<void> {
44
+ await storeToken(serverUrl, token);
45
+
46
+ const config = getConfig(opts.siaHome);
47
+ const developerId = ensureDeveloperId(config);
48
+
49
+ writeConfig(
50
+ {
51
+ sync: {
52
+ enabled: true,
53
+ serverUrl,
54
+ developerId,
55
+ syncInterval: opts.syncInterval ?? config.sync.syncInterval,
56
+ },
57
+ },
58
+ opts.siaHome,
59
+ );
60
+
61
+ if (opts.db && opts.bridgeDb) {
62
+ await pullChanges(opts.db, opts.bridgeDb, {
63
+ enabled: true,
64
+ serverUrl,
65
+ developerId,
66
+ syncInterval: opts.syncInterval ?? config.sync.syncInterval,
67
+ });
68
+ }
69
+ }
70
+
71
+ export async function teamLeave(opts: { siaHome?: string; db?: SiaDb } = {}): Promise<void> {
72
+ const config = getConfig(opts.siaHome);
73
+ if (config.sync.serverUrl) {
74
+ await deleteToken(config.sync.serverUrl);
75
+ }
76
+
77
+ writeConfig(
78
+ {
79
+ sync: {
80
+ enabled: false,
81
+ serverUrl: null,
82
+ developerId: config.sync.developerId,
83
+ syncInterval: config.sync.syncInterval,
84
+ },
85
+ },
86
+ opts.siaHome,
87
+ );
88
+
89
+ if (opts.db) {
90
+ await opts.db.execute(
91
+ "UPDATE graph_nodes SET visibility = 'private', workspace_scope = NULL, synced_at = NULL",
92
+ );
93
+ }
94
+ }
95
+
96
+ export async function teamStatus(opts: { siaHome?: string; db?: SiaDb } = {}): Promise<TeamStatus> {
97
+ const config = getConfig(opts.siaHome);
98
+ const peerCount = 0;
99
+ let pendingConflicts = 0;
100
+ const lastSyncAt: number | null = null;
101
+
102
+ if (opts.db) {
103
+ const conflicts = await opts.db.execute(
104
+ "SELECT COUNT(DISTINCT conflict_group_id) as cnt FROM graph_nodes WHERE conflict_group_id IS NOT NULL AND t_valid_until IS NULL",
105
+ );
106
+ pendingConflicts = (conflicts.rows[0]?.cnt as number) ?? 0;
107
+ }
108
+
109
+ return {
110
+ enabled: config.sync.enabled,
111
+ serverUrl: config.sync.serverUrl,
112
+ developerId: config.sync.developerId,
113
+ syncInterval: config.sync.syncInterval,
114
+ peerCount,
115
+ pendingConflicts,
116
+ lastSyncAt,
117
+ };
118
+ }
@@ -0,0 +1,157 @@
1
+ // Module: tour — Interactive guided walkthrough of the knowledge graph
2
+
3
+ import type { SiaDb } from "@/graph/db-interface";
4
+
5
+ export interface TourSection {
6
+ title: string;
7
+ content: string;
8
+ entityCount: number;
9
+ }
10
+
11
+ export interface TourResult {
12
+ totalEntities: number;
13
+ totalEdges: number;
14
+ sections: TourSection[];
15
+ }
16
+
17
+ export async function generateTour(db: SiaDb): Promise<TourResult> {
18
+ // Count totals
19
+ const entityCount = await db.execute(
20
+ "SELECT COUNT(*) as cnt FROM graph_nodes WHERE t_valid_until IS NULL AND archived_at IS NULL",
21
+ );
22
+ const edgeCount = await db.execute(
23
+ "SELECT COUNT(*) as cnt FROM graph_edges WHERE t_valid_until IS NULL",
24
+ );
25
+
26
+ const totalEntities = (entityCount.rows[0] as any).cnt;
27
+ const totalEdges = (edgeCount.rows[0] as any).cnt;
28
+
29
+ const sections: TourSection[] = [];
30
+
31
+ // Section 1: Architecture Overview (from communities)
32
+ const communities = await db.execute(
33
+ "SELECT id, summary, member_count FROM communities WHERE level = 2 ORDER BY member_count DESC LIMIT 5",
34
+ );
35
+ if ((communities.rows as any[]).length > 0) {
36
+ const content = (communities.rows as any[])
37
+ .map(
38
+ (c) =>
39
+ `- **${c.summary?.slice(0, 100) || "Unnamed community"}** (${c.member_count} members)`,
40
+ )
41
+ .join("\n");
42
+ sections.push({
43
+ title: "Architecture Overview",
44
+ content: `Your codebase has ${(communities.rows as any[]).length} major modules:\n\n${content}`,
45
+ entityCount: (communities.rows as any[]).length,
46
+ });
47
+ }
48
+
49
+ // Section 2: Key Decisions
50
+ const decisions = await db.execute(
51
+ `SELECT name, summary FROM graph_nodes
52
+ WHERE type = 'Decision' AND t_valid_until IS NULL AND archived_at IS NULL
53
+ ORDER BY importance DESC LIMIT 5`,
54
+ );
55
+ if ((decisions.rows as any[]).length > 0) {
56
+ const content = (decisions.rows as any[])
57
+ .map((d) => `- **${d.name}**: ${d.summary?.slice(0, 120) || "no summary"}`)
58
+ .join("\n");
59
+ sections.push({
60
+ title: "Key Decisions",
61
+ content: `${(decisions.rows as any[]).length} architectural decisions captured:\n\n${content}`,
62
+ entityCount: (decisions.rows as any[]).length,
63
+ });
64
+ }
65
+
66
+ // Section 3: Active Conventions
67
+ const conventions = await db.execute(
68
+ `SELECT name, summary FROM graph_nodes
69
+ WHERE type = 'Convention' AND t_valid_until IS NULL AND archived_at IS NULL
70
+ ORDER BY importance DESC LIMIT 10`,
71
+ );
72
+ if ((conventions.rows as any[]).length > 0) {
73
+ const content = (conventions.rows as any[])
74
+ .map((c) => `- **${c.name}**: ${c.summary?.slice(0, 120) || "no summary"}`)
75
+ .join("\n");
76
+ sections.push({
77
+ title: "Coding Conventions",
78
+ content: `${(conventions.rows as any[]).length} conventions to follow:\n\n${content}`,
79
+ entityCount: (conventions.rows as any[]).length,
80
+ });
81
+ }
82
+
83
+ // Section 4: Known Issues
84
+ const bugs = await db.execute(
85
+ `SELECT name, summary FROM graph_nodes
86
+ WHERE type = 'Bug' AND t_valid_until IS NULL AND archived_at IS NULL
87
+ ORDER BY created_at DESC LIMIT 5`,
88
+ );
89
+ if ((bugs.rows as any[]).length > 0) {
90
+ const content = (bugs.rows as any[])
91
+ .map((b) => `- **${b.name}**: ${b.summary?.slice(0, 120) || "no summary"}`)
92
+ .join("\n");
93
+ sections.push({
94
+ title: "Known Issues",
95
+ content: `${(bugs.rows as any[]).length} known bugs to be aware of:\n\n${content}`,
96
+ entityCount: (bugs.rows as any[]).length,
97
+ });
98
+ }
99
+
100
+ // Section 5: Documentation
101
+ const docs = await db.execute(
102
+ `SELECT name, summary FROM graph_nodes
103
+ WHERE type = 'FileNode' AND tags LIKE '%project-docs%' AND t_valid_until IS NULL
104
+ ORDER BY importance DESC LIMIT 10`,
105
+ );
106
+ if ((docs.rows as any[]).length > 0) {
107
+ const content = (docs.rows as any[]).map((d) => `- ${d.name}`).join("\n");
108
+ sections.push({
109
+ title: "Ingested Documentation",
110
+ content: `${(docs.rows as any[]).length} docs in the knowledge graph:\n\n${content}`,
111
+ entityCount: (docs.rows as any[]).length,
112
+ });
113
+ }
114
+
115
+ return { totalEntities, totalEdges, sections };
116
+ }
117
+
118
+ export function formatTour(tour: TourResult): string {
119
+ const lines: string[] = [];
120
+ lines.push("=== SIA Knowledge Graph Tour ===\n");
121
+ lines.push(`Total: ${tour.totalEntities} entities, ${tour.totalEdges} edges\n`);
122
+
123
+ for (const section of tour.sections) {
124
+ lines.push(`--- ${section.title} ---`);
125
+ lines.push(section.content);
126
+ lines.push("");
127
+ }
128
+
129
+ if (tour.sections.length === 0) {
130
+ lines.push("The knowledge graph is empty. Run /sia-learn to populate it.");
131
+ }
132
+
133
+ lines.push("--- Next Steps ---");
134
+ lines.push("- Ask any question — SIA tools activate automatically");
135
+ lines.push("- /sia-search — search the knowledge graph");
136
+ lines.push("- /sia-status — detailed graph health");
137
+ lines.push("- /sia-visualize-live — interactive browser visualization");
138
+
139
+ return lines.join("\n");
140
+ }
141
+
142
+ export async function runTour(_args: string[]): Promise<void> {
143
+ const { resolveRepoHash } = await import("@/capture/hook");
144
+ const { openGraphDb } = await import("@/graph/semantic-db");
145
+ const { resolveSiaHome } = await import("@/shared/config");
146
+
147
+ const repoHash = resolveRepoHash(process.cwd());
148
+ const siaHome = resolveSiaHome();
149
+ const db = openGraphDb(repoHash, siaHome);
150
+
151
+ try {
152
+ const tour = await generateTour(db);
153
+ console.log(formatTour(tour));
154
+ } finally {
155
+ await db.close();
156
+ }
157
+ }