@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,68 @@
1
+ import type { AiSdkAdapter } from "@/llm/ai-sdk-adapter";
2
+
3
+ /** Roles an LLM provider can fulfil within the Sia pipeline. */
4
+ export type OperationRole = "extract" | "consolidate" | "summarize" | "validate";
5
+
6
+ /** How raw knowledge enters the graph. */
7
+ export type CaptureMode = "hooks" | "api" | "hybrid";
8
+
9
+ /** Provider + model pair for a specific role. */
10
+ export interface ProviderConfig {
11
+ provider: string; // "anthropic" | "openai" | "google" | "ollama"
12
+ model: string;
13
+ }
14
+
15
+ /**
16
+ * Registry that maps each OperationRole to a ProviderConfig.
17
+ * Determines which roles are active based on the current CaptureMode.
18
+ */
19
+ export class ProviderRegistry {
20
+ private configs = new Map<OperationRole, ProviderConfig>();
21
+ private captureMode: CaptureMode = "hooks";
22
+
23
+ setCaptureMode(mode: CaptureMode): void {
24
+ this.captureMode = mode;
25
+ }
26
+
27
+ getCaptureMode(): CaptureMode {
28
+ return this.captureMode;
29
+ }
30
+
31
+ setProvider(role: OperationRole, config: ProviderConfig): void {
32
+ this.configs.set(role, config);
33
+ }
34
+
35
+ getProvider(role: OperationRole): ProviderConfig | undefined {
36
+ return this.configs.get(role);
37
+ }
38
+
39
+ /**
40
+ * Whether a role is active given the current capture mode.
41
+ * In hooks mode, extract and consolidate are dormant (handled by the host agent).
42
+ * In api or hybrid mode, all roles are active.
43
+ */
44
+ isRoleActive(role: OperationRole): boolean {
45
+ if (this.captureMode === "api") return true;
46
+ if (this.captureMode === "hooks") {
47
+ return role === "summarize" || role === "validate";
48
+ }
49
+ // hybrid: all active
50
+ return true;
51
+ }
52
+
53
+ /** Get all configured providers for diagnostics. */
54
+ getAll(): Map<OperationRole, ProviderConfig> {
55
+ return new Map(this.configs);
56
+ }
57
+
58
+ /**
59
+ * Resolve an AiSdkAdapter for the given role, or null if no provider is
60
+ * configured for that role or the provider is unsupported by the AI SDK.
61
+ */
62
+ async adapt(role: OperationRole): Promise<AiSdkAdapter | null> {
63
+ const config = this.getProvider(role);
64
+ if (!config) return null;
65
+ const { createAdapter } = await import("@/llm/ai-sdk-adapter");
66
+ return createAdapter(config);
67
+ }
68
+ }
@@ -0,0 +1,179 @@
1
+ /** Configuration for the reliability wrapper. */
2
+ export interface ReliabilityConfig {
3
+ maxRetries: number;
4
+ fallbackChain: string[];
5
+ circuitBreakerThreshold: number;
6
+ circuitBreakerWindowMs: number;
7
+ }
8
+
9
+ export interface CircuitBreakerOptions {
10
+ /** Failure ratio (0-1) that triggers the circuit to open. Default 0.5. */
11
+ threshold?: number;
12
+ /** Window in ms for tracking failures. Default 60000. */
13
+ windowMs?: number;
14
+ /** Minimum number of operations before the breaker can trip. Default 3. */
15
+ minSamples?: number;
16
+ }
17
+
18
+ /**
19
+ * Circuit breaker that tracks success/failure ratios and opens
20
+ * the circuit when the failure rate exceeds the configured threshold.
21
+ */
22
+ export class CircuitBreaker {
23
+ private failures = 0;
24
+ private successes = 0;
25
+ private state: "closed" | "open" | "half-open" = "closed";
26
+ private lastFailureTime = 0;
27
+ private readonly threshold: number;
28
+ private readonly windowMs: number;
29
+ private readonly minSamples: number;
30
+
31
+ constructor(options?: CircuitBreakerOptions) {
32
+ this.threshold = options?.threshold ?? 0.5;
33
+ this.windowMs = options?.windowMs ?? 60000;
34
+ this.minSamples = options?.minSamples ?? 3;
35
+ }
36
+
37
+ /** Whether the circuit is open (rejecting calls). */
38
+ isOpen(): boolean {
39
+ if (this.state === "open") {
40
+ // Check if the window has expired — transition to half-open
41
+ if (Date.now() - this.lastFailureTime > this.windowMs) {
42
+ this.state = "half-open";
43
+ return false;
44
+ }
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+
50
+ /** Record a successful operation. Closes the circuit if half-open. */
51
+ recordSuccess(): void {
52
+ this.successes++;
53
+ if (this.state === "half-open") {
54
+ this.state = "closed";
55
+ }
56
+ }
57
+
58
+ /** Record a failed operation. Opens the circuit if threshold exceeded and minimum samples met. */
59
+ recordFailure(): void {
60
+ this.failures++;
61
+ this.lastFailureTime = Date.now();
62
+ const total = this.failures + this.successes;
63
+ if (total >= this.minSamples && this.failures / total >= this.threshold) {
64
+ this.state = "open";
65
+ }
66
+ }
67
+
68
+ /** Reset all counters and close the circuit. */
69
+ reset(): void {
70
+ this.failures = 0;
71
+ this.successes = 0;
72
+ this.state = "closed";
73
+ this.lastFailureTime = 0;
74
+ }
75
+
76
+ /** Get diagnostic stats. */
77
+ getStats(): { state: string; failures: number; successes: number } {
78
+ // Refresh state check (window may have expired)
79
+ if (this.state === "open" && Date.now() - this.lastFailureTime > this.windowMs) {
80
+ this.state = "half-open";
81
+ }
82
+ return {
83
+ state: this.state,
84
+ failures: this.failures,
85
+ successes: this.successes,
86
+ };
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Attempt to repair malformed JSON from LLM responses.
92
+ *
93
+ * LLMs sometimes produce JSON with:
94
+ * - Trailing commas in arrays/objects
95
+ * - Single quotes instead of double quotes
96
+ * - Unquoted property names
97
+ * - Missing closing brackets
98
+ * - Markdown code fences wrapping the JSON
99
+ *
100
+ * This handles the most common cases (~30% of malformed responses)
101
+ * without requiring a retry, saving both latency and cost.
102
+ */
103
+ export function repairJson(text: string): string {
104
+ let s = text.trim();
105
+
106
+ // Strip markdown code fences: ```json ... ``` or ``` ... ```
107
+ s = s.replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/, "");
108
+
109
+ // Strip leading/trailing whitespace again after fence removal
110
+ s = s.trim();
111
+
112
+ // Replace single quotes around keys/values with double quotes
113
+ // (only when they look like JSON — not inside string values)
114
+ s = s.replace(/(?<=[{[,:\s])'/g, '"').replace(/'(?=[}\],:\s])/g, '"');
115
+
116
+ // Remove trailing commas before } or ]
117
+ s = s.replace(/,\s*([}\]])/g, "$1");
118
+
119
+ // Try to close unclosed brackets (count openers vs closers)
120
+ const opens = (s.match(/\{/g) || []).length;
121
+ const closes = (s.match(/\}/g) || []).length;
122
+ for (let i = 0; i < opens - closes; i++) {
123
+ s += "}";
124
+ }
125
+ const openBrackets = (s.match(/\[/g) || []).length;
126
+ const closeBrackets = (s.match(/\]/g) || []).length;
127
+ for (let i = 0; i < openBrackets - closeBrackets; i++) {
128
+ s += "]";
129
+ }
130
+
131
+ return s;
132
+ }
133
+
134
+ /**
135
+ * Parse JSON with repair fallback. First tries JSON.parse directly.
136
+ * On failure, runs repairJson and retries. Returns parsed object or throws.
137
+ */
138
+ export function parseJsonWithRepair<T>(text: string): T {
139
+ try {
140
+ return JSON.parse(text) as T;
141
+ } catch {
142
+ const repaired = repairJson(text);
143
+ return JSON.parse(repaired) as T;
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Wrap an async operation with retry + circuit breaker.
149
+ * Returns the result or throws after all retries are exhausted.
150
+ */
151
+ export async function withReliability<T>(
152
+ operation: () => Promise<T>,
153
+ breaker: CircuitBreaker,
154
+ maxRetries = 3,
155
+ ): Promise<T> {
156
+ if (breaker.isOpen()) {
157
+ throw new Error("Circuit breaker is open — request rejected");
158
+ }
159
+
160
+ let lastError: Error | undefined;
161
+
162
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
163
+ try {
164
+ const result = await operation();
165
+ breaker.recordSuccess();
166
+ return result;
167
+ } catch (err) {
168
+ lastError = err instanceof Error ? err : new Error(String(err));
169
+ breaker.recordFailure();
170
+
171
+ // If the circuit just opened, stop retrying
172
+ if (breaker.isOpen()) {
173
+ break;
174
+ }
175
+ }
176
+ }
177
+
178
+ throw lastError ?? new Error("withReliability: all retries exhausted");
179
+ }
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Unified extraction result schema.
5
+ * Used by BOTH hooks extractors AND LLM provider — same shape regardless of source.
6
+ */
7
+ export const SiaExtractionResult = z.object({
8
+ entities: z.array(
9
+ z.object({
10
+ kind: z.enum(["Decision", "Convention", "Bug", "Solution", "Concept"]),
11
+ name: z.string().min(3).max(200),
12
+ content: z.string().min(10).max(2000),
13
+ confidence: z.number().min(0).max(1),
14
+ tags: z.array(z.string()).max(5),
15
+ relates_to: z.array(z.string()),
16
+ }),
17
+ ),
18
+ _meta: z
19
+ .object({
20
+ source: z.enum(["hook", "llm", "claude-directive"]),
21
+ input_tokens: z.number().optional(),
22
+ output_tokens: z.number().optional(),
23
+ })
24
+ .optional(),
25
+ });
26
+
27
+ /** Consolidation decision for incoming vs existing entities. */
28
+ export const SiaConsolidationResult = z.object({
29
+ decision: z.enum(["ADD", "UPDATE", "INVALIDATE", "NOOP"]),
30
+ target_id: z.string().nullable(),
31
+ reasoning: z.string().optional(),
32
+ });
33
+
34
+ /** Community or cluster summary result. */
35
+ export const SiaSummaryResult = z.object({
36
+ summary: z.string().min(10).max(2000),
37
+ key_entities: z.array(z.string()).max(10),
38
+ confidence: z.number().min(0).max(1),
39
+ });
40
+
41
+ /** Fact validation result for freshness/correctness checks. */
42
+ export const SiaValidationResult = z.object({
43
+ is_valid: z.boolean(),
44
+ confidence: z.number().min(0).max(1),
45
+ reasoning: z.string(),
46
+ action: z.enum(["confirm", "invalidate", "flag_for_review"]),
47
+ });
48
+
49
+ export type SiaExtractionResultType = z.infer<typeof SiaExtractionResult>;
50
+ export type SiaConsolidationResultType = z.infer<typeof SiaConsolidationResult>;
51
+ export type SiaSummaryResultType = z.infer<typeof SiaSummaryResult>;
52
+ export type SiaValidationResultType = z.infer<typeof SiaValidationResult>;
@@ -0,0 +1,69 @@
1
+ // Module: freshness-annotator — Adds freshness state to MCP tool results.
2
+ //
3
+ // Wraps entity results with a freshness annotation so Claude knows
4
+ // whether the source file has changed since the knowledge was captured.
5
+
6
+ import type { SiaDb } from "@/graph/db-interface";
7
+
8
+ export interface FreshnessAnnotatedEntity {
9
+ [key: string]: unknown;
10
+ freshness: "fresh" | "stale" | "rotten" | "unknown";
11
+ freshness_note?: string;
12
+ }
13
+
14
+ /**
15
+ * Annotate an array of entity results with freshness state.
16
+ *
17
+ * For each entity with file_paths, checks if the source file's mtime
18
+ * is newer than the entity's updated_at timestamp. This is a lightweight
19
+ * check — not the full DirtyTracker pipeline.
20
+ */
21
+ export async function annotateFreshness(
22
+ entities: Array<Record<string, unknown>>,
23
+ db: SiaDb | null,
24
+ ): Promise<FreshnessAnnotatedEntity[]> {
25
+ if (!db) {
26
+ return entities.map((e) => ({ ...e, freshness: "unknown" as const }));
27
+ }
28
+
29
+ const { statSync } = await import("node:fs");
30
+ const { resolve } = await import("node:path");
31
+
32
+ return entities.map((entity) => {
33
+ const filePaths = entity.file_paths as string | null;
34
+ if (!filePaths) {
35
+ return { ...entity, freshness: "unknown" as const };
36
+ }
37
+
38
+ try {
39
+ const paths = JSON.parse(filePaths) as string[];
40
+ if (paths.length === 0) {
41
+ return { ...entity, freshness: "unknown" as const };
42
+ }
43
+
44
+ const absPath = resolve(process.cwd(), paths[0]);
45
+ const fileMtime = statSync(absPath).mtimeMs;
46
+ const entityUpdated = (entity.updated_at as number) ?? (entity.created_at as number) ?? 0;
47
+
48
+ if (fileMtime <= entityUpdated) {
49
+ return { ...entity, freshness: "fresh" as const };
50
+ }
51
+
52
+ const staleDays = (fileMtime - entityUpdated) / (1000 * 60 * 60 * 24);
53
+ if (staleDays > 30) {
54
+ return {
55
+ ...entity,
56
+ freshness: "rotten" as const,
57
+ freshness_note: `Source file changed ${Math.round(staleDays)} days after capture — verify before using`,
58
+ };
59
+ }
60
+ return {
61
+ ...entity,
62
+ freshness: "stale" as const,
63
+ freshness_note: "Source file changed since capture — may need verification",
64
+ };
65
+ } catch {
66
+ return { ...entity, freshness: "unknown" as const };
67
+ }
68
+ });
69
+ }