@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,161 @@
1
+ #!/usr/bin/env bash
2
+ # Start the graph visualizer server and output connection info
3
+ # Usage: start-visualizer.sh [--project-dir <path>] [--host <bind-host>] [--url-host <display-host>] [--foreground] [--background]
4
+ #
5
+ # Starts server on a random high port, outputs JSON with URL.
6
+ # Each session gets its own directory to avoid conflicts.
7
+ #
8
+ # Options:
9
+ # --project-dir <path> Store session files under <path>/.sia/visualize/
10
+ # instead of /tmp. Files persist after server stops.
11
+ # --host <bind-host> Host/interface to bind (default: 127.0.0.1).
12
+ # Use 0.0.0.0 in remote/containerized environments.
13
+ # --url-host <host> Hostname shown in returned URL JSON.
14
+ # --foreground Run server in the current terminal (no backgrounding).
15
+ # --background Force background mode (overrides Codex auto-foreground).
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
18
+
19
+ # Parse arguments
20
+ PROJECT_DIR=""
21
+ FOREGROUND="false"
22
+ FORCE_BACKGROUND="false"
23
+ BIND_HOST="127.0.0.1"
24
+ URL_HOST=""
25
+ while [[ $# -gt 0 ]]; do
26
+ case "$1" in
27
+ --project-dir)
28
+ PROJECT_DIR="$2"
29
+ shift 2
30
+ ;;
31
+ --host)
32
+ BIND_HOST="$2"
33
+ shift 2
34
+ ;;
35
+ --url-host)
36
+ URL_HOST="$2"
37
+ shift 2
38
+ ;;
39
+ --foreground|--no-daemon)
40
+ FOREGROUND="true"
41
+ shift
42
+ ;;
43
+ --background|--daemon)
44
+ FORCE_BACKGROUND="true"
45
+ shift
46
+ ;;
47
+ *)
48
+ echo "{\"error\": \"Unknown argument: $1\"}"
49
+ exit 1
50
+ ;;
51
+ esac
52
+ done
53
+
54
+ if [[ -z "$URL_HOST" ]]; then
55
+ if [[ "$BIND_HOST" == "127.0.0.1" || "$BIND_HOST" == "localhost" ]]; then
56
+ URL_HOST="localhost"
57
+ else
58
+ URL_HOST="$BIND_HOST"
59
+ fi
60
+ fi
61
+
62
+ # Some environments reap detached/background processes. Auto-foreground when detected.
63
+ if [[ -n "${CODEX_CI:-}" && "$FOREGROUND" != "true" && "$FORCE_BACKGROUND" != "true" ]]; then
64
+ FOREGROUND="true"
65
+ fi
66
+
67
+ # Windows/Git Bash reaps nohup background processes. Auto-foreground when detected.
68
+ if [[ "$FOREGROUND" != "true" && "$FORCE_BACKGROUND" != "true" ]]; then
69
+ case "${OSTYPE:-}" in
70
+ msys*|cygwin*|mingw*) FOREGROUND="true" ;;
71
+ esac
72
+ if [[ -n "${MSYSTEM:-}" ]]; then
73
+ FOREGROUND="true"
74
+ fi
75
+ fi
76
+
77
+ # Generate unique session directory
78
+ SESSION_ID="$$-$(date +%s)"
79
+
80
+ if [[ -n "$PROJECT_DIR" ]]; then
81
+ SCREEN_DIR="${PROJECT_DIR}/.sia/visualize/${SESSION_ID}"
82
+ else
83
+ SCREEN_DIR="/tmp/visualize-${SESSION_ID}"
84
+ fi
85
+
86
+ PID_FILE="${SCREEN_DIR}/.server.pid"
87
+ LOG_FILE="${SCREEN_DIR}/.server.log"
88
+
89
+ # Create fresh session directory
90
+ mkdir -p "$SCREEN_DIR"
91
+
92
+ # Generate graph data before starting server
93
+ if [[ -n "$PROJECT_DIR" ]]; then
94
+ GRAPH_FILE="${SCREEN_DIR}/graph.json"
95
+ if command -v sia &>/dev/null; then
96
+ sia export --format json > "$GRAPH_FILE" 2>/dev/null || echo '{"nodes":[],"edges":[]}' > "$GRAPH_FILE"
97
+ elif command -v bun &>/dev/null && [[ -f "${PROJECT_DIR}/src/cli/index.ts" ]]; then
98
+ bun run "${PROJECT_DIR}/src/cli/index.ts" export --format json > "$GRAPH_FILE" 2>/dev/null || echo '{"nodes":[],"edges":[]}' > "$GRAPH_FILE"
99
+ else
100
+ echo '{"nodes":[],"edges":[]}' > "$GRAPH_FILE"
101
+ fi
102
+ fi
103
+
104
+ # Kill any existing server
105
+ if [[ -f "$PID_FILE" ]]; then
106
+ old_pid=$(cat "$PID_FILE")
107
+ kill "$old_pid" 2>/dev/null
108
+ rm -f "$PID_FILE"
109
+ fi
110
+
111
+ cd "$SCRIPT_DIR"
112
+
113
+ # Resolve the harness PID (grandparent of this script).
114
+ OWNER_PID="$(ps -o ppid= -p "$PPID" 2>/dev/null | tr -d ' ')"
115
+ if [[ -z "$OWNER_PID" || "$OWNER_PID" == "1" ]]; then
116
+ OWNER_PID="$PPID"
117
+ fi
118
+
119
+ # On Windows/MSYS2, the MSYS2 PID namespace is invisible to Node.js.
120
+ case "${OSTYPE:-}" in
121
+ msys*|cygwin*|mingw*) OWNER_PID="" ;;
122
+ esac
123
+
124
+ # Foreground mode for environments that reap detached/background processes.
125
+ if [[ "$FOREGROUND" == "true" ]]; then
126
+ echo "$$" > "$PID_FILE"
127
+ env VISUALIZER_DIR="$SCREEN_DIR" VISUALIZER_HOST="$BIND_HOST" VISUALIZER_URL_HOST="$URL_HOST" VISUALIZER_OWNER_PID="$OWNER_PID" GRAPH_DATA_FILE="${GRAPH_FILE:-${SCREEN_DIR}/graph.json}" node visualizer-server.cjs
128
+ exit $?
129
+ fi
130
+
131
+ # Start server, capturing output to log file
132
+ nohup env VISUALIZER_DIR="$SCREEN_DIR" VISUALIZER_HOST="$BIND_HOST" VISUALIZER_URL_HOST="$URL_HOST" VISUALIZER_OWNER_PID="$OWNER_PID" GRAPH_DATA_FILE="${GRAPH_FILE:-${SCREEN_DIR}/graph.json}" node visualizer-server.cjs > "$LOG_FILE" 2>&1 &
133
+ SERVER_PID=$!
134
+ disown "$SERVER_PID" 2>/dev/null
135
+ echo "$SERVER_PID" > "$PID_FILE"
136
+
137
+ # Wait for server-started message (check log file)
138
+ for i in {1..50}; do
139
+ if grep -q "server-started" "$LOG_FILE" 2>/dev/null; then
140
+ # Verify server is still alive after a short window (catches process reapers)
141
+ alive="true"
142
+ for _ in {1..20}; do
143
+ if ! kill -0 "$SERVER_PID" 2>/dev/null; then
144
+ alive="false"
145
+ break
146
+ fi
147
+ sleep 0.1
148
+ done
149
+ if [[ "$alive" != "true" ]]; then
150
+ echo "{\"error\": \"Server started but was killed. Retry in a persistent terminal with: $SCRIPT_DIR/start-visualizer.sh${PROJECT_DIR:+ --project-dir $PROJECT_DIR} --host $BIND_HOST --url-host $URL_HOST --foreground\"}"
151
+ exit 1
152
+ fi
153
+ grep "server-started" "$LOG_FILE" | head -1
154
+ exit 0
155
+ fi
156
+ sleep 0.1
157
+ done
158
+
159
+ # Timeout - server didn't start
160
+ echo '{"error": "Server failed to start within 5 seconds"}'
161
+ exit 1
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+ # Stop the visualizer server and clean up
3
+ # Usage: stop-visualizer.sh <screen_dir>
4
+ #
5
+ # Kills the server process. Only deletes session directory if it's
6
+ # under /tmp (ephemeral). Persistent directories (.sia/) are
7
+ # kept so graph snapshots can be reviewed later.
8
+
9
+ SCREEN_DIR="$1"
10
+
11
+ if [[ -z "$SCREEN_DIR" ]]; then
12
+ echo '{"error": "Usage: stop-visualizer.sh <screen_dir>"}'
13
+ exit 1
14
+ fi
15
+
16
+ PID_FILE="${SCREEN_DIR}/.server.pid"
17
+
18
+ if [[ -f "$PID_FILE" ]]; then
19
+ pid=$(cat "$PID_FILE")
20
+
21
+ # Try to stop gracefully, fallback to force if still alive
22
+ kill "$pid" 2>/dev/null || true
23
+
24
+ # Wait for graceful shutdown (up to ~2s)
25
+ for i in {1..20}; do
26
+ if ! kill -0 "$pid" 2>/dev/null; then
27
+ break
28
+ fi
29
+ sleep 0.1
30
+ done
31
+
32
+ # If still running, escalate to SIGKILL
33
+ if kill -0 "$pid" 2>/dev/null; then
34
+ kill -9 "$pid" 2>/dev/null || true
35
+
36
+ # Give SIGKILL a moment to take effect
37
+ sleep 0.1
38
+ fi
39
+
40
+ if kill -0 "$pid" 2>/dev/null; then
41
+ echo '{"status": "failed", "error": "process still running"}'
42
+ exit 1
43
+ fi
44
+
45
+ rm -f "$PID_FILE" "${SCREEN_DIR}/.server.log"
46
+
47
+ # Only delete ephemeral /tmp directories
48
+ if [[ "$SCREEN_DIR" == /tmp/* ]]; then
49
+ rm -rf "$SCREEN_DIR"
50
+ fi
51
+
52
+ echo '{"status": "stopped"}'
53
+ else
54
+ echo '{"status": "not_running"}'
55
+ fi
@@ -0,0 +1,264 @@
1
+ const crypto = require('crypto');
2
+ const http = require('http');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ // ========== WebSocket Protocol (RFC 6455) ==========
7
+
8
+ const OPCODES = { TEXT: 0x01, CLOSE: 0x08, PING: 0x09, PONG: 0x0A };
9
+ const WS_MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
10
+
11
+ function computeAcceptKey(clientKey) {
12
+ return crypto.createHash('sha1').update(clientKey + WS_MAGIC).digest('base64');
13
+ }
14
+
15
+ function encodeFrame(opcode, payload) {
16
+ const fin = 0x80;
17
+ const len = payload.length;
18
+ let header;
19
+
20
+ if (len < 126) {
21
+ header = Buffer.alloc(2);
22
+ header[0] = fin | opcode;
23
+ header[1] = len;
24
+ } else if (len < 65536) {
25
+ header = Buffer.alloc(4);
26
+ header[0] = fin | opcode;
27
+ header[1] = 126;
28
+ header.writeUInt16BE(len, 2);
29
+ } else {
30
+ header = Buffer.alloc(10);
31
+ header[0] = fin | opcode;
32
+ header[1] = 127;
33
+ header.writeBigUInt64BE(BigInt(len), 2);
34
+ }
35
+
36
+ return Buffer.concat([header, payload]);
37
+ }
38
+
39
+ function decodeFrame(buffer) {
40
+ if (buffer.length < 2) return null;
41
+
42
+ const secondByte = buffer[1];
43
+ const opcode = buffer[0] & 0x0F;
44
+ const masked = (secondByte & 0x80) !== 0;
45
+ let payloadLen = secondByte & 0x7F;
46
+ let offset = 2;
47
+
48
+ if (!masked) throw new Error('Client frames must be masked');
49
+
50
+ if (payloadLen === 126) {
51
+ if (buffer.length < 4) return null;
52
+ payloadLen = buffer.readUInt16BE(2);
53
+ offset = 4;
54
+ } else if (payloadLen === 127) {
55
+ if (buffer.length < 10) return null;
56
+ payloadLen = Number(buffer.readBigUInt64BE(2));
57
+ offset = 10;
58
+ }
59
+
60
+ const maskOffset = offset;
61
+ const dataOffset = offset + 4;
62
+ const totalLen = dataOffset + payloadLen;
63
+ if (buffer.length < totalLen) return null;
64
+
65
+ const mask = buffer.slice(maskOffset, dataOffset);
66
+ const data = Buffer.alloc(payloadLen);
67
+ for (let i = 0; i < payloadLen; i++) {
68
+ data[i] = buffer[dataOffset + i] ^ mask[i % 4];
69
+ }
70
+
71
+ return { opcode, payload: data, bytesConsumed: totalLen };
72
+ }
73
+
74
+ // ========== Configuration ==========
75
+
76
+ const PORT = process.env.VISUALIZER_PORT || (49152 + Math.floor(Math.random() * 16383));
77
+ const HOST = process.env.VISUALIZER_HOST || '127.0.0.1';
78
+ const URL_HOST = process.env.VISUALIZER_URL_HOST || (HOST === '127.0.0.1' ? 'localhost' : HOST);
79
+ const SCREEN_DIR = process.env.VISUALIZER_DIR || '/tmp/visualize';
80
+ const OWNER_PID = process.env.VISUALIZER_OWNER_PID ? Number(process.env.VISUALIZER_OWNER_PID) : null;
81
+ const GRAPH_DATA_FILE = process.env.GRAPH_DATA_FILE || path.join(SCREEN_DIR, 'graph.json');
82
+
83
+ // ========== Template and Graph Data ==========
84
+
85
+ const graphTemplate = fs.readFileSync(path.join(__dirname, 'graph-template.html'), 'utf-8');
86
+
87
+ function loadGraphData() {
88
+ if (fs.existsSync(GRAPH_DATA_FILE)) {
89
+ try {
90
+ return fs.readFileSync(GRAPH_DATA_FILE, 'utf-8');
91
+ } catch (e) {
92
+ console.error('Failed to read graph data:', e.message);
93
+ }
94
+ }
95
+ return JSON.stringify({ nodes: [], edges: [] });
96
+ }
97
+
98
+ function buildPage() {
99
+ const graphJson = loadGraphData();
100
+ return graphTemplate.replace('/* GRAPH_DATA */', graphJson);
101
+ }
102
+
103
+ // ========== HTTP Request Handler ==========
104
+
105
+ function handleRequest(req, res) {
106
+ touchActivity();
107
+ if (req.method === 'GET' && req.url === '/') {
108
+ const html = buildPage();
109
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
110
+ res.end(html);
111
+ } else {
112
+ res.writeHead(404);
113
+ res.end('Not found');
114
+ }
115
+ }
116
+
117
+ // ========== WebSocket Connection Handling ==========
118
+
119
+ const clients = new Set();
120
+
121
+ function handleUpgrade(req, socket) {
122
+ const key = req.headers['sec-websocket-key'];
123
+ if (!key) { socket.destroy(); return; }
124
+
125
+ const accept = computeAcceptKey(key);
126
+ socket.write(
127
+ 'HTTP/1.1 101 Switching Protocols\r\n' +
128
+ 'Upgrade: websocket\r\n' +
129
+ 'Connection: Upgrade\r\n' +
130
+ 'Sec-WebSocket-Accept: ' + accept + '\r\n\r\n'
131
+ );
132
+
133
+ let buffer = Buffer.alloc(0);
134
+ clients.add(socket);
135
+
136
+ socket.on('data', (chunk) => {
137
+ buffer = Buffer.concat([buffer, chunk]);
138
+ while (buffer.length > 0) {
139
+ let result;
140
+ try {
141
+ result = decodeFrame(buffer);
142
+ } catch (e) {
143
+ socket.end(encodeFrame(OPCODES.CLOSE, Buffer.alloc(0)));
144
+ clients.delete(socket);
145
+ return;
146
+ }
147
+ if (!result) break;
148
+ buffer = buffer.slice(result.bytesConsumed);
149
+
150
+ switch (result.opcode) {
151
+ case OPCODES.TEXT:
152
+ touchActivity();
153
+ break;
154
+ case OPCODES.CLOSE:
155
+ socket.end(encodeFrame(OPCODES.CLOSE, Buffer.alloc(0)));
156
+ clients.delete(socket);
157
+ return;
158
+ case OPCODES.PING:
159
+ socket.write(encodeFrame(OPCODES.PONG, result.payload));
160
+ break;
161
+ case OPCODES.PONG:
162
+ break;
163
+ default: {
164
+ const closeBuf = Buffer.alloc(2);
165
+ closeBuf.writeUInt16BE(1003);
166
+ socket.end(encodeFrame(OPCODES.CLOSE, closeBuf));
167
+ clients.delete(socket);
168
+ return;
169
+ }
170
+ }
171
+ }
172
+ });
173
+
174
+ socket.on('close', () => clients.delete(socket));
175
+ socket.on('error', () => clients.delete(socket));
176
+ }
177
+
178
+ function broadcast(msg) {
179
+ const frame = encodeFrame(OPCODES.TEXT, Buffer.from(JSON.stringify(msg)));
180
+ for (const socket of clients) {
181
+ try { socket.write(frame); } catch (e) { clients.delete(socket); }
182
+ }
183
+ }
184
+
185
+ // ========== Activity Tracking ==========
186
+
187
+ const IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
188
+ let lastActivity = Date.now();
189
+
190
+ function touchActivity() {
191
+ lastActivity = Date.now();
192
+ }
193
+
194
+ // ========== Server Startup ==========
195
+
196
+ function startServer() {
197
+ if (!fs.existsSync(SCREEN_DIR)) fs.mkdirSync(SCREEN_DIR, { recursive: true });
198
+
199
+ const server = http.createServer(handleRequest);
200
+ server.on('upgrade', handleUpgrade);
201
+
202
+ // Watch for graph data file changes and push reloads
203
+ const debounceTimers = new Map();
204
+
205
+ if (fs.existsSync(path.dirname(GRAPH_DATA_FILE))) {
206
+ try {
207
+ const watcher = fs.watch(path.dirname(GRAPH_DATA_FILE), (eventType, filename) => {
208
+ if (!filename || filename !== path.basename(GRAPH_DATA_FILE)) return;
209
+
210
+ if (debounceTimers.has(filename)) clearTimeout(debounceTimers.get(filename));
211
+ debounceTimers.set(filename, setTimeout(() => {
212
+ debounceTimers.delete(filename);
213
+ if (!fs.existsSync(GRAPH_DATA_FILE)) return;
214
+ touchActivity();
215
+ console.log(JSON.stringify({ type: 'graph-updated', file: GRAPH_DATA_FILE }));
216
+ broadcast({ type: 'reload' });
217
+ }, 100));
218
+ });
219
+ watcher.on('error', (err) => console.error('fs.watch error:', err.message));
220
+ } catch (e) {
221
+ console.error('Could not watch graph data directory:', e.message);
222
+ }
223
+ }
224
+
225
+ function shutdown(reason) {
226
+ console.log(JSON.stringify({ type: 'server-stopped', reason }));
227
+ const infoFile = path.join(SCREEN_DIR, '.server-info');
228
+ if (fs.existsSync(infoFile)) fs.unlinkSync(infoFile);
229
+ fs.writeFileSync(
230
+ path.join(SCREEN_DIR, '.server-stopped'),
231
+ JSON.stringify({ reason, timestamp: Date.now() }) + '\n'
232
+ );
233
+ clearInterval(lifecycleCheck);
234
+ server.close(() => process.exit(0));
235
+ }
236
+
237
+ function ownerAlive() {
238
+ if (!OWNER_PID) return true;
239
+ try { process.kill(OWNER_PID, 0); return true; } catch (e) { return false; }
240
+ }
241
+
242
+ // Check every 60s: exit if owner process died or idle for 30 minutes
243
+ const lifecycleCheck = setInterval(() => {
244
+ if (!ownerAlive()) shutdown('owner process exited');
245
+ else if (Date.now() - lastActivity > IDLE_TIMEOUT_MS) shutdown('idle timeout');
246
+ }, 60 * 1000);
247
+ lifecycleCheck.unref();
248
+
249
+ server.listen(PORT, HOST, () => {
250
+ const info = JSON.stringify({
251
+ type: 'server-started', port: Number(PORT), host: HOST,
252
+ url_host: URL_HOST, url: 'http://' + URL_HOST + ':' + PORT,
253
+ screen_dir: SCREEN_DIR
254
+ });
255
+ console.log(info);
256
+ fs.writeFileSync(path.join(SCREEN_DIR, '.server-info'), info + '\n');
257
+ });
258
+ }
259
+
260
+ if (require.main === module) {
261
+ startServer();
262
+ }
263
+
264
+ module.exports = { computeAcceptKey, encodeFrame, decodeFrame, OPCODES };
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: sia-workspace
3
+ description: Manages SIA workspaces for cross-repo knowledge sharing — creating workspaces, adding repos, and detecting API contracts. Use when working across multiple repositories or setting up shared knowledge.
4
+ ---
5
+
6
+ # SIA Workspace
7
+
8
+ Manage workspaces that enable cross-repo knowledge sharing.
9
+
10
+ ## What Are Workspaces?
11
+
12
+ Workspaces group multiple repositories together so SIA can:
13
+ - Share knowledge across repos via bridge edges
14
+ - Detect API contracts between services
15
+ - Enable cross-repo search with `sia_search({ workspace: true })`
16
+
17
+ ## Commands
18
+
19
+ ### Create a workspace
20
+
21
+ ```bash
22
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/workspace.ts create "my-workspace"
23
+ ```
24
+
25
+ ### List workspaces
26
+
27
+ ```bash
28
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/workspace.ts list
29
+ ```
30
+
31
+ ### Add a repo to a workspace
32
+
33
+ ```bash
34
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/workspace.ts add "my-workspace" /path/to/repo
35
+ ```
36
+
37
+ ### Remove a repo from a workspace
38
+
39
+ ```bash
40
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/workspace.ts remove "my-workspace" /path/to/repo
41
+ ```
42
+
43
+ ### Show workspace details
44
+
45
+ ```bash
46
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/workspace.ts show "my-workspace"
47
+ ```
48
+
49
+ ## Related: Team Sync
50
+
51
+ For team-based knowledge sharing (requires a sync server):
52
+
53
+ ```bash
54
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/team.ts join <server-url>
55
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/team.ts status
56
+ bun run ${CLAUDE_PLUGIN_ROOT}/src/cli/commands/team.ts leave
57
+ ```