@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,359 @@
1
+ // Module: markdown-import — Import markdown vault into knowledge graph
2
+
3
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
4
+ import { basename, join } from "node:path";
5
+ import type { SiaDb } from "@/graph/db-interface";
6
+ import { insertEdge } from "@/graph/edges";
7
+ import { insertEntity } from "@/graph/entities";
8
+
9
+ export interface MarkdownImportResult {
10
+ entitiesImported: number;
11
+ edgesCreated: number;
12
+ errors: string[];
13
+ }
14
+
15
+ /** Parsed markdown file with metadata and content. */
16
+ interface ParsedMarkdownFile {
17
+ filePath: string;
18
+ slug: string;
19
+ frontmatter: Record<string, unknown>;
20
+ body: string;
21
+ heading: string | null;
22
+ wikilinks: string[];
23
+ }
24
+
25
+ /**
26
+ * Parse YAML frontmatter from a markdown string.
27
+ * Expects content to start with `---` delimiter followed by YAML key-value
28
+ * pairs and closed with another `---`.
29
+ *
30
+ * Returns the parsed frontmatter object and the remaining body.
31
+ * If no frontmatter is found, returns an empty object and the full content as body.
32
+ */
33
+ function parseFrontmatter(content: string): { frontmatter: Record<string, unknown>; body: string } {
34
+ const trimmed = content.trimStart();
35
+ if (!trimmed.startsWith("---")) {
36
+ return { frontmatter: {}, body: content };
37
+ }
38
+
39
+ // Find the closing `---` (must be on its own line after the opening)
40
+ const afterOpening = trimmed.slice(3);
41
+ const closingIdx = afterOpening.indexOf("\n---");
42
+ if (closingIdx === -1) {
43
+ return { frontmatter: {}, body: content };
44
+ }
45
+
46
+ const yamlBlock = afterOpening.slice(0, closingIdx).trim();
47
+ const body = afterOpening.slice(closingIdx + 4).trim();
48
+
49
+ const frontmatter: Record<string, unknown> = {};
50
+
51
+ for (const line of yamlBlock.split("\n")) {
52
+ const colonIdx = line.indexOf(":");
53
+ if (colonIdx === -1) continue;
54
+
55
+ const key = line.slice(0, colonIdx).trim();
56
+ let value: unknown = line.slice(colonIdx + 1).trim();
57
+
58
+ if (key === "" || value === "") continue;
59
+
60
+ const strValue = value as string;
61
+
62
+ // Parse YAML arrays: [a, b, c]
63
+ if (strValue.startsWith("[") && strValue.endsWith("]")) {
64
+ const inner = strValue.slice(1, -1);
65
+ if (inner.trim() === "") {
66
+ value = [];
67
+ } else {
68
+ value = inner.split(",").map((item) => parseYamlScalar(item.trim()));
69
+ }
70
+ } else {
71
+ value = parseYamlScalar(strValue);
72
+ }
73
+
74
+ frontmatter[key] = value;
75
+ }
76
+
77
+ return { frontmatter, body };
78
+ }
79
+
80
+ /**
81
+ * Parse a YAML scalar value into a JS primitive.
82
+ * Handles numbers, booleans, null, and quoted strings.
83
+ */
84
+ function parseYamlScalar(raw: string): string | number | boolean | null {
85
+ // Unquote double-quoted strings
86
+ if (raw.startsWith('"') && raw.endsWith('"')) {
87
+ return raw.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
88
+ }
89
+ // Unquote single-quoted strings
90
+ if (raw.startsWith("'") && raw.endsWith("'")) {
91
+ return raw.slice(1, -1);
92
+ }
93
+ // null / ~
94
+ if (raw === "null" || raw === "~") return null;
95
+ // booleans
96
+ if (raw === "true") return true;
97
+ if (raw === "false") return false;
98
+ // numbers
99
+ const num = Number(raw);
100
+ if (!Number.isNaN(num) && raw !== "") return num;
101
+ // fallback to string
102
+ return raw;
103
+ }
104
+
105
+ /**
106
+ * Extract wikilinks from markdown content.
107
+ * Matches `[[path/slug]]` patterns and returns the link targets.
108
+ */
109
+ function extractWikilinks(content: string): string[] {
110
+ const regex = /\[\[([^\]]+)\]\]/g;
111
+ const links: string[] = [];
112
+ let match: RegExpExecArray | null;
113
+ match = regex.exec(content);
114
+ while (match !== null) {
115
+ if (match[1] !== undefined) {
116
+ links.push(match[1]);
117
+ }
118
+ match = regex.exec(content);
119
+ }
120
+ return links;
121
+ }
122
+
123
+ /**
124
+ * Extract the first H1 heading from a markdown body.
125
+ * Returns null if no heading is found.
126
+ */
127
+ function extractHeading(body: string): string | null {
128
+ const match = /^#\s+(.+)$/m.exec(body);
129
+ return match ? (match[1]?.trim() ?? null) : null;
130
+ }
131
+
132
+ /**
133
+ * Strip the "## Related" section from the body content so it doesn't
134
+ * pollute the entity content.
135
+ */
136
+ function stripRelatedSection(body: string): string {
137
+ const relatedIdx = body.indexOf("\n## Related");
138
+ if (relatedIdx === -1) return body;
139
+ return body.slice(0, relatedIdx).trimEnd();
140
+ }
141
+
142
+ /**
143
+ * Derive the entity type from the directory name of the file.
144
+ * "decisions" -> "Decision", "bugs" -> "Bug", etc.
145
+ * Falls back to "Concept" if the directory doesn't map to a known type.
146
+ */
147
+ function dirToType(dirName: string): string {
148
+ const mapping: Record<string, string> = {
149
+ decisions: "Decision",
150
+ conventions: "Convention",
151
+ bugs: "Bug",
152
+ solutions: "Solution",
153
+ concepts: "Concept",
154
+ code: "CodeEntity",
155
+ files: "FileNode",
156
+ };
157
+ return mapping[dirName] ?? "Concept";
158
+ }
159
+
160
+ /**
161
+ * Extract the slug portion from a wikilink target.
162
+ * "decisions/use-jwt-rs256" -> "use-jwt-rs256"
163
+ * "use-jwt-rs256" -> "use-jwt-rs256"
164
+ */
165
+ function slugFromLink(link: string): string {
166
+ const parts = link.split("/");
167
+ return parts[parts.length - 1] ?? link;
168
+ }
169
+
170
+ /**
171
+ * Walk a directory recursively, collecting all .md file paths.
172
+ * Skips index.md at any level.
173
+ */
174
+ function walkMarkdownFiles(dir: string): string[] {
175
+ const results: string[] = [];
176
+
177
+ if (!existsSync(dir)) return results;
178
+
179
+ let names: string[];
180
+ try {
181
+ names = readdirSync(dir);
182
+ } catch {
183
+ return results;
184
+ }
185
+
186
+ for (const name of names) {
187
+ const fullPath = join(dir, name);
188
+ let stat: ReturnType<typeof statSync>;
189
+ try {
190
+ stat = statSync(fullPath);
191
+ } catch {
192
+ continue;
193
+ }
194
+ if (stat.isDirectory()) {
195
+ results.push(...walkMarkdownFiles(fullPath));
196
+ } else if (stat.isFile() && name.endsWith(".md") && name !== "index.md") {
197
+ results.push(fullPath);
198
+ }
199
+ }
200
+
201
+ return results;
202
+ }
203
+
204
+ /**
205
+ * Import markdown files from a vault directory into the knowledge graph.
206
+ * Parses YAML frontmatter for metadata, markdown body for content.
207
+ * Resolves [[wikilinks]] to graph edges.
208
+ */
209
+ export async function importFromMarkdown(
210
+ db: SiaDb,
211
+ inputDir: string,
212
+ ): Promise<MarkdownImportResult> {
213
+ const errors: string[] = [];
214
+ let entitiesImported = 0;
215
+ let edgesCreated = 0;
216
+
217
+ // Phase 1: Discover and parse all markdown files
218
+ const filePaths = walkMarkdownFiles(inputDir);
219
+ const parsed: ParsedMarkdownFile[] = [];
220
+
221
+ for (const filePath of filePaths) {
222
+ try {
223
+ const raw = readFileSync(filePath, "utf-8");
224
+ const { frontmatter, body } = parseFrontmatter(raw);
225
+
226
+ // Determine heading: prefer extracted H1, then fall back to filename
227
+ const heading = extractHeading(body);
228
+ const fallbackName = basename(filePath, ".md")
229
+ .replace(/-/g, " ")
230
+ .replace(/\b\w/g, (c) => c.toUpperCase());
231
+
232
+ // Determine slug from filename (without extension)
233
+ const slug = basename(filePath, ".md");
234
+
235
+ // Extract wikilinks from the body
236
+ const wikilinks = extractWikilinks(body);
237
+
238
+ parsed.push({
239
+ filePath,
240
+ slug,
241
+ frontmatter,
242
+ body,
243
+ heading: heading ?? fallbackName,
244
+ wikilinks,
245
+ });
246
+ } catch (err) {
247
+ const msg = err instanceof Error ? err.message : String(err);
248
+ errors.push(`Failed to parse ${filePath}: ${msg}`);
249
+ }
250
+ }
251
+
252
+ // Phase 2: Insert entities
253
+ // Map slug -> entity ID for edge resolution
254
+ const slugToId = new Map<string, string>();
255
+
256
+ for (const file of parsed) {
257
+ try {
258
+ const fm = file.frontmatter;
259
+
260
+ // Determine type from frontmatter.kind or from the parent directory name
261
+ let type = "Concept";
262
+ if (typeof fm.kind === "string" && fm.kind !== "") {
263
+ type = fm.kind;
264
+ } else {
265
+ // Infer from parent directory
266
+ const parentDir = basename(join(file.filePath, ".."));
267
+ type = dirToType(parentDir);
268
+ }
269
+
270
+ // Clean body: strip the heading line and the related section
271
+ let content = stripRelatedSection(file.body);
272
+ // Remove the leading H1 heading from content since we store name separately
273
+ content = content.replace(/^#\s+.+\n*/, "").trim();
274
+
275
+ // Build tags
276
+ let tags = "[]";
277
+ if (Array.isArray(fm.tags)) {
278
+ tags = JSON.stringify(fm.tags.map(String));
279
+ } else if (typeof fm.tags === "string") {
280
+ tags = fm.tags;
281
+ }
282
+
283
+ // Resolve trust_tier
284
+ const trustTier = typeof fm.trust_tier === "number" ? fm.trust_tier : 1;
285
+
286
+ // Resolve importance
287
+ const importance = typeof fm.importance === "number" ? fm.importance : 0.5;
288
+
289
+ // Build summary: first 150 characters of content
290
+ const summary = content.length > 150 ? `${content.slice(0, 147)}...` : content;
291
+
292
+ const entity = await insertEntity(db, {
293
+ type,
294
+ name: file.heading ?? file.slug,
295
+ content,
296
+ summary,
297
+ tags,
298
+ trust_tier: trustTier,
299
+ importance,
300
+ extraction_method: "markdown-import",
301
+ });
302
+
303
+ slugToId.set(file.slug, entity.id);
304
+ entitiesImported++;
305
+ } catch (err) {
306
+ const msg = err instanceof Error ? err.message : String(err);
307
+ errors.push(`Failed to import ${file.filePath}: ${msg}`);
308
+ }
309
+ }
310
+
311
+ // Phase 3: Resolve wikilinks to edges
312
+ for (const file of parsed) {
313
+ const sourceId = slugToId.get(file.slug);
314
+ if (!sourceId) continue;
315
+
316
+ for (const link of file.wikilinks) {
317
+ try {
318
+ const targetSlug = slugFromLink(link);
319
+ const targetId = slugToId.get(targetSlug);
320
+ if (!targetId) continue;
321
+ if (targetId === sourceId) continue;
322
+
323
+ // Determine edge type from the wikilink context:
324
+ // Look for "- {edge_type}: [[link]]" pattern
325
+ const edgeType = resolveEdgeType(file.body, link);
326
+
327
+ await insertEdge(db, {
328
+ from_id: sourceId,
329
+ to_id: targetId,
330
+ type: edgeType,
331
+ extraction_method: "markdown-import",
332
+ });
333
+
334
+ edgesCreated++;
335
+ } catch (err) {
336
+ const msg = err instanceof Error ? err.message : String(err);
337
+ errors.push(`Failed to create edge from ${file.slug} -> ${link}: ${msg}`);
338
+ }
339
+ }
340
+ }
341
+
342
+ return { entitiesImported, edgesCreated, errors };
343
+ }
344
+
345
+ /**
346
+ * Attempt to resolve the edge type from the surrounding markdown context.
347
+ * Looks for the pattern `- {edge_type}: [[link]]` near the wikilink.
348
+ * Falls back to "relates_to" if no pattern is found.
349
+ */
350
+ function resolveEdgeType(body: string, link: string): string {
351
+ // Match "- some_edge_type: [[link]]"
352
+ const escapedLink = link.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
353
+ const pattern = new RegExp(`-\\s+([\\w_]+):\\s*\\[\\[${escapedLink}\\]\\]`);
354
+ const match = pattern.exec(body);
355
+ if (match && match[1] !== undefined) {
356
+ return match[1];
357
+ }
358
+ return "relates_to";
359
+ }
@@ -0,0 +1,74 @@
1
+ // Module: patterns — File patterns for documentation auto-discovery
2
+
3
+ export interface DiscoveryPattern {
4
+ glob: string;
5
+ priority: 1 | 2 | 3 | 4 | 5;
6
+ tag: string;
7
+ trustTier: 1 | 2;
8
+ }
9
+
10
+ // Priority 1 — AI context files (highest signal density)
11
+ // Priority 2 — Architecture documentation
12
+ // Priority 3 — Project documentation
13
+ // Priority 4 — API documentation
14
+ // Priority 5 — Change history
15
+
16
+ export const DISCOVERY_PATTERNS: DiscoveryPattern[] = [
17
+ // Priority 1 — AI context files
18
+ { glob: "AGENTS.md", priority: 1, tag: "ai-context", trustTier: 1 },
19
+ { glob: "CLAUDE.md", priority: 1, tag: "ai-context", trustTier: 1 },
20
+ { glob: ".claude/CLAUDE.md", priority: 1, tag: "ai-context", trustTier: 1 },
21
+ { glob: "GEMINI.md", priority: 1, tag: "ai-context", trustTier: 1 },
22
+ { glob: ".cursor/rules/*.mdc", priority: 1, tag: "ai-context", trustTier: 1 },
23
+ { glob: ".windsurf/rules/*.md", priority: 1, tag: "ai-context", trustTier: 1 },
24
+ { glob: ".clinerules/*.md", priority: 1, tag: "ai-context", trustTier: 1 },
25
+ { glob: ".github/copilot-instructions.md", priority: 1, tag: "ai-context", trustTier: 1 },
26
+ { glob: ".github/instructions/*.instructions.md", priority: 1, tag: "ai-context", trustTier: 1 },
27
+ { glob: ".amazonq/rules/*.md", priority: 1, tag: "ai-context", trustTier: 1 },
28
+ { glob: ".continue/rules/*.md", priority: 1, tag: "ai-context", trustTier: 1 },
29
+
30
+ // Priority 2 — Architecture documentation
31
+ { glob: "ARCHITECTURE.md", priority: 2, tag: "architecture", trustTier: 1 },
32
+ { glob: "DESIGN.md", priority: 2, tag: "architecture", trustTier: 1 },
33
+ { glob: "docs/adr/*.md", priority: 2, tag: "architecture", trustTier: 1 },
34
+ { glob: "docs/decisions/*.md", priority: 2, tag: "architecture", trustTier: 1 },
35
+ { glob: "docs/architecture/*.md", priority: 2, tag: "architecture", trustTier: 1 },
36
+
37
+ // Priority 3 — Project documentation
38
+ { glob: "README.md", priority: 3, tag: "project-docs", trustTier: 1 },
39
+ { glob: "CONTRIBUTING.md", priority: 3, tag: "project-docs", trustTier: 1 },
40
+ { glob: "CONVENTIONS.md", priority: 3, tag: "project-docs", trustTier: 1 },
41
+ { glob: "STANDARDS.md", priority: 3, tag: "project-docs", trustTier: 1 },
42
+ { glob: "CONTEXT.md", priority: 3, tag: "project-docs", trustTier: 1 },
43
+ { glob: "docs/*.md", priority: 3, tag: "project-docs", trustTier: 1 },
44
+
45
+ // Priority 4 — API documentation
46
+ { glob: "openapi.yaml", priority: 4, tag: "api-docs", trustTier: 2 },
47
+ { glob: "openapi.json", priority: 4, tag: "api-docs", trustTier: 2 },
48
+ { glob: "swagger.yaml", priority: 4, tag: "api-docs", trustTier: 2 },
49
+ { glob: "swagger.json", priority: 4, tag: "api-docs", trustTier: 2 },
50
+ { glob: "schema.graphql", priority: 4, tag: "api-docs", trustTier: 2 },
51
+ { glob: "API.md", priority: 4, tag: "api-docs", trustTier: 2 },
52
+ { glob: "docs/api/*.md", priority: 4, tag: "api-docs", trustTier: 2 },
53
+
54
+ // Priority 5 — Change history
55
+ { glob: "CHANGELOG.md", priority: 5, tag: "changelog", trustTier: 2 },
56
+ { glob: "HISTORY.md", priority: 5, tag: "changelog", trustTier: 2 },
57
+ { glob: "MIGRATION.md", priority: 5, tag: "changelog", trustTier: 2 },
58
+ { glob: "UPGRADING.md", priority: 5, tag: "changelog", trustTier: 2 },
59
+ ];
60
+
61
+ export const EXCLUDED_DIRS = new Set([
62
+ "node_modules",
63
+ "vendor",
64
+ ".git",
65
+ "dist",
66
+ "build",
67
+ ".next",
68
+ ".nuxt",
69
+ "__pycache__",
70
+ ".venv",
71
+ "target",
72
+ "coverage",
73
+ ".cache",
74
+ ]);