studiograph 1.1.2 → 1.2.0-beta.1

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 (349) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +301 -10
  3. package/dist/agent/orchestrator.d.ts +17 -9
  4. package/dist/agent/orchestrator.js +142 -97
  5. package/dist/agent/orchestrator.js.map +1 -1
  6. package/dist/agent/prompts/system.md +186 -0
  7. package/dist/agent/skill-loader.d.ts +48 -0
  8. package/dist/agent/skill-loader.js +166 -0
  9. package/dist/agent/skill-loader.js.map +1 -0
  10. package/dist/agent/skills/enrich-entities.md +136 -0
  11. package/dist/agent/skills/entity-schema.md +502 -0
  12. package/dist/agent/skills/gather-context.md +46 -0
  13. package/dist/agent/skills/obsidian-source-setup.md +246 -0
  14. package/dist/agent/skills/skill-loader.d.ts +48 -0
  15. package/dist/agent/skills/skill-loader.js +166 -0
  16. package/dist/agent/skills/skill-loader.js.map +1 -0
  17. package/dist/agent/skills/sync-configuration.md +144 -0
  18. package/dist/agent/skills/sync-setup.md +68 -0
  19. package/dist/agent/tools/connector-tools.d.ts +37 -0
  20. package/dist/agent/tools/connector-tools.js +132 -0
  21. package/dist/agent/tools/connector-tools.js.map +1 -0
  22. package/dist/agent/tools/fs-tools.d.ts +39 -0
  23. package/dist/agent/tools/fs-tools.js +106 -0
  24. package/dist/agent/tools/fs-tools.js.map +1 -0
  25. package/dist/agent/tools/graph-tools.d.ts +30 -2
  26. package/dist/agent/tools/graph-tools.js +154 -37
  27. package/dist/agent/tools/graph-tools.js.map +1 -1
  28. package/dist/agent/tools/load-skill.d.ts +42 -0
  29. package/dist/agent/tools/load-skill.js +45 -0
  30. package/dist/agent/tools/load-skill.js.map +1 -0
  31. package/dist/agent/tools/sync-tools.d.ts +25 -0
  32. package/dist/agent/tools/sync-tools.js +691 -0
  33. package/dist/agent/tools/sync-tools.js.map +1 -0
  34. package/dist/agent/tools/tool-loader.d.ts +25 -0
  35. package/dist/agent/tools/tool-loader.js +73 -0
  36. package/dist/agent/tools/tool-loader.js.map +1 -0
  37. package/dist/auth/github.d.ts +11 -8
  38. package/dist/auth/github.js +56 -75
  39. package/dist/auth/github.js.map +1 -1
  40. package/dist/cli/colors.d.ts +54 -0
  41. package/dist/cli/colors.js +133 -0
  42. package/dist/cli/colors.js.map +1 -0
  43. package/dist/cli/commands/app.d.ts +7 -0
  44. package/dist/cli/commands/app.js +167 -0
  45. package/dist/cli/commands/app.js.map +1 -0
  46. package/dist/cli/commands/auth.d.ts +1 -1
  47. package/dist/cli/commands/auth.js +26 -10
  48. package/dist/cli/commands/auth.js.map +1 -1
  49. package/dist/cli/commands/clone.d.ts +9 -0
  50. package/dist/cli/commands/clone.js +167 -0
  51. package/dist/cli/commands/clone.js.map +1 -0
  52. package/dist/cli/commands/commit.d.ts +8 -0
  53. package/dist/cli/commands/commit.js +43 -0
  54. package/dist/cli/commands/commit.js.map +1 -0
  55. package/dist/cli/commands/config.d.ts +13 -0
  56. package/dist/cli/commands/config.js +276 -0
  57. package/dist/cli/commands/config.js.map +1 -0
  58. package/dist/cli/commands/connector.d.ts +33 -0
  59. package/dist/cli/commands/connector.js +178 -0
  60. package/dist/cli/commands/connector.js.map +1 -0
  61. package/dist/cli/commands/deploy.d.ts +11 -0
  62. package/dist/cli/commands/deploy.js +153 -0
  63. package/dist/cli/commands/deploy.js.map +1 -0
  64. package/dist/cli/commands/enrich.d.ts +11 -0
  65. package/dist/cli/commands/enrich.js +135 -0
  66. package/dist/cli/commands/enrich.js.map +1 -0
  67. package/dist/cli/commands/graphrag.d.ts +12 -0
  68. package/dist/cli/commands/graphrag.js +122 -0
  69. package/dist/cli/commands/graphrag.js.map +1 -0
  70. package/dist/cli/commands/index.d.ts +15 -0
  71. package/dist/cli/commands/index.js +117 -0
  72. package/dist/cli/commands/index.js.map +1 -0
  73. package/dist/cli/commands/init.js +110 -210
  74. package/dist/cli/commands/init.js.map +1 -1
  75. package/dist/cli/commands/join.js +89 -24
  76. package/dist/cli/commands/join.js.map +1 -1
  77. package/dist/cli/commands/lint.d.ts +8 -0
  78. package/dist/cli/commands/lint.js +70 -0
  79. package/dist/cli/commands/lint.js.map +1 -0
  80. package/dist/cli/commands/mcp.d.ts +27 -0
  81. package/dist/cli/commands/mcp.js +56 -0
  82. package/dist/cli/commands/mcp.js.map +1 -0
  83. package/dist/cli/commands/orphans.d.ts +8 -0
  84. package/dist/cli/commands/orphans.js +125 -0
  85. package/dist/cli/commands/orphans.js.map +1 -0
  86. package/dist/cli/commands/provision.d.ts +8 -0
  87. package/dist/cli/commands/provision.js +116 -0
  88. package/dist/cli/commands/provision.js.map +1 -0
  89. package/dist/cli/commands/r2.d.ts +2 -0
  90. package/dist/cli/commands/r2.js +87 -6
  91. package/dist/cli/commands/r2.js.map +1 -1
  92. package/dist/cli/commands/reset.d.ts +12 -0
  93. package/dist/cli/commands/reset.js +137 -0
  94. package/dist/cli/commands/reset.js.map +1 -0
  95. package/dist/cli/commands/review.d.ts +19 -0
  96. package/dist/cli/commands/review.js +128 -0
  97. package/dist/cli/commands/review.js.map +1 -0
  98. package/dist/cli/commands/serve.js +47 -2
  99. package/dist/cli/commands/serve.js.map +1 -1
  100. package/dist/cli/commands/source.d.ts +16 -0
  101. package/dist/cli/commands/source.js +159 -0
  102. package/dist/cli/commands/source.js.map +1 -0
  103. package/dist/cli/commands/start.js +472 -103
  104. package/dist/cli/commands/start.js.map +1 -1
  105. package/dist/cli/commands/sync-entities.d.ts +13 -0
  106. package/dist/cli/commands/sync-entities.js +242 -0
  107. package/dist/cli/commands/sync-entities.js.map +1 -0
  108. package/dist/cli/commands/sync.js +40 -9
  109. package/dist/cli/commands/sync.js.map +1 -1
  110. package/dist/cli/commands/update.d.ts +8 -0
  111. package/dist/cli/commands/update.js +155 -0
  112. package/dist/cli/commands/update.js.map +1 -0
  113. package/dist/cli/index.js +114 -3
  114. package/dist/cli/index.js.map +1 -1
  115. package/dist/cli/scaffolding.d.ts +10 -0
  116. package/dist/cli/scaffolding.js +302 -0
  117. package/dist/cli/scaffolding.js.map +1 -0
  118. package/dist/cli/setup-wizard.d.ts +30 -0
  119. package/dist/cli/setup-wizard.js +244 -0
  120. package/dist/cli/setup-wizard.js.map +1 -0
  121. package/dist/cli/sync-review-interactive.d.ts +31 -0
  122. package/dist/cli/sync-review-interactive.js +393 -0
  123. package/dist/cli/sync-review-interactive.js.map +1 -0
  124. package/dist/cli/theme.d.ts +31 -0
  125. package/dist/cli/theme.js +116 -0
  126. package/dist/cli/theme.js.map +1 -0
  127. package/dist/core/graph.d.ts +16 -9
  128. package/dist/core/graph.js +263 -145
  129. package/dist/core/graph.js.map +1 -1
  130. package/dist/core/migration-runner.d.ts +42 -0
  131. package/dist/core/migration-runner.js +232 -0
  132. package/dist/core/migration-runner.js.map +1 -0
  133. package/dist/core/migration-types.d.ts +101 -0
  134. package/dist/core/migration-types.js +21 -0
  135. package/dist/core/migration-types.js.map +1 -0
  136. package/dist/core/migrations/20260219-formalize-memory-location.d.ts +2 -0
  137. package/dist/core/migrations/20260219-formalize-memory-location.js +35 -0
  138. package/dist/core/migrations/20260219-formalize-memory-location.js.map +1 -0
  139. package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +12 -0
  140. package/dist/core/migrations/20260220-add-workspace-metadata.js +65 -0
  141. package/dist/core/migrations/20260220-add-workspace-metadata.js.map +1 -0
  142. package/dist/core/migrations/20260220-add-workspace-readme.d.ts +11 -0
  143. package/dist/core/migrations/20260220-add-workspace-readme.js +82 -0
  144. package/dist/core/migrations/20260220-add-workspace-readme.js.map +1 -0
  145. package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +9 -0
  146. package/dist/core/migrations/20260220-migrate-yaml-to-json.js +64 -0
  147. package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +1 -0
  148. package/dist/core/migrations/index.d.ts +11 -0
  149. package/dist/core/migrations/index.js +23 -0
  150. package/dist/core/migrations/index.js.map +1 -0
  151. package/dist/core/schema-registry.d.ts +36 -0
  152. package/dist/core/schema-registry.js +161 -0
  153. package/dist/core/schema-registry.js.map +1 -0
  154. package/dist/core/types.d.ts +242 -3
  155. package/dist/core/types.js +21 -2
  156. package/dist/core/types.js.map +1 -1
  157. package/dist/core/user-config.d.ts +16 -0
  158. package/dist/core/user-config.js +8 -0
  159. package/dist/core/user-config.js.map +1 -1
  160. package/dist/core/validation.d.ts +973 -32
  161. package/dist/core/validation.js +163 -4
  162. package/dist/core/validation.js.map +1 -1
  163. package/dist/core/workspace-manager.d.ts +26 -2
  164. package/dist/core/workspace-manager.js +113 -15
  165. package/dist/core/workspace-manager.js.map +1 -1
  166. package/dist/core/workspace.d.ts +20 -11
  167. package/dist/core/workspace.js +123 -34
  168. package/dist/core/workspace.js.map +1 -1
  169. package/dist/mcp/connector-manager.d.ts +65 -0
  170. package/dist/mcp/connector-manager.js +223 -0
  171. package/dist/mcp/connector-manager.js.map +1 -0
  172. package/dist/mcp/connectors/asana.d.ts +2 -0
  173. package/dist/mcp/connectors/asana.js +20 -0
  174. package/dist/mcp/connectors/asana.js.map +1 -0
  175. package/dist/mcp/connectors/definitions.d.ts +45 -0
  176. package/dist/mcp/connectors/definitions.js +32 -0
  177. package/dist/mcp/connectors/definitions.js.map +1 -0
  178. package/dist/mcp/connectors/figma.d.ts +5 -0
  179. package/dist/mcp/connectors/figma.js +21 -0
  180. package/dist/mcp/connectors/figma.js.map +1 -0
  181. package/dist/mcp/connectors/gdrive.d.ts +2 -0
  182. package/dist/mcp/connectors/gdrive.js +20 -0
  183. package/dist/mcp/connectors/gdrive.js.map +1 -0
  184. package/dist/mcp/connectors/granola.d.ts +2 -0
  185. package/dist/mcp/connectors/granola.js +12 -0
  186. package/dist/mcp/connectors/granola.js.map +1 -0
  187. package/dist/mcp/connectors/linear.d.ts +2 -0
  188. package/dist/mcp/connectors/linear.js +19 -0
  189. package/dist/mcp/connectors/linear.js.map +1 -0
  190. package/dist/mcp/connectors/obsidian.d.ts +2 -0
  191. package/dist/mcp/connectors/obsidian.js +19 -0
  192. package/dist/mcp/connectors/obsidian.js.map +1 -0
  193. package/dist/mcp/connectors/pipedrive.d.ts +2 -0
  194. package/dist/mcp/connectors/pipedrive.js +20 -0
  195. package/dist/mcp/connectors/pipedrive.js.map +1 -0
  196. package/dist/mcp/connectors/slack.d.ts +2 -0
  197. package/dist/mcp/connectors/slack.js +21 -0
  198. package/dist/mcp/connectors/slack.js.map +1 -0
  199. package/dist/mcp/oauth-provider.d.ts +41 -0
  200. package/dist/mcp/oauth-provider.js +160 -0
  201. package/dist/mcp/oauth-provider.js.map +1 -0
  202. package/dist/mcp/server.d.ts +11 -0
  203. package/dist/mcp/server.js +28 -0
  204. package/dist/mcp/server.js.map +1 -0
  205. package/dist/mcp/tools.d.ts +14 -0
  206. package/dist/mcp/tools.js +172 -0
  207. package/dist/mcp/tools.js.map +1 -0
  208. package/dist/server/index.js +17 -4
  209. package/dist/server/index.js.map +1 -1
  210. package/dist/server/plugin-loader.d.ts +15 -0
  211. package/dist/server/plugin-loader.js +68 -2
  212. package/dist/server/plugin-loader.js.map +1 -1
  213. package/dist/server/routes/graph-api.js +1 -1
  214. package/dist/server/routes/graph-api.js.map +1 -1
  215. package/dist/server/routes/webhook.js +33 -0
  216. package/dist/server/routes/webhook.js.map +1 -1
  217. package/dist/services/github-provisioner.d.ts +9 -3
  218. package/dist/services/github-provisioner.js +46 -8
  219. package/dist/services/github-provisioner.js.map +1 -1
  220. package/dist/services/lint-service.d.ts +27 -0
  221. package/dist/services/lint-service.js +83 -0
  222. package/dist/services/lint-service.js.map +1 -0
  223. package/dist/services/markdown.d.ts +9 -0
  224. package/dist/services/markdown.js +26 -5
  225. package/dist/services/markdown.js.map +1 -1
  226. package/dist/services/memory-service.d.ts +1 -2
  227. package/dist/services/memory-service.js +5 -4
  228. package/dist/services/memory-service.js.map +1 -1
  229. package/dist/services/orphan-service.d.ts +31 -0
  230. package/dist/services/orphan-service.js +100 -0
  231. package/dist/services/orphan-service.js.map +1 -0
  232. package/dist/services/sync/commit.d.ts +58 -0
  233. package/dist/services/sync/commit.js +350 -0
  234. package/dist/services/sync/commit.js.map +1 -0
  235. package/dist/services/sync/context-index.d.ts +69 -0
  236. package/dist/services/sync/context-index.js +280 -0
  237. package/dist/services/sync/context-index.js.map +1 -0
  238. package/dist/services/sync/derive.d.ts +34 -0
  239. package/dist/services/sync/derive.js +164 -0
  240. package/dist/services/sync/derive.js.map +1 -0
  241. package/dist/services/sync/enrichment-state.d.ts +31 -0
  242. package/dist/services/sync/enrichment-state.js +63 -0
  243. package/dist/services/sync/enrichment-state.js.map +1 -0
  244. package/dist/services/sync/enrichment.d.ts +25 -0
  245. package/dist/services/sync/enrichment.js +121 -0
  246. package/dist/services/sync/enrichment.js.map +1 -0
  247. package/dist/services/sync/frontmatter-extractor.d.ts +40 -0
  248. package/dist/services/sync/frontmatter-extractor.js +273 -0
  249. package/dist/services/sync/frontmatter-extractor.js.map +1 -0
  250. package/dist/services/sync/graph-match-state.d.ts +33 -0
  251. package/dist/services/sync/graph-match-state.js +61 -0
  252. package/dist/services/sync/graph-match-state.js.map +1 -0
  253. package/dist/services/sync/graph-match.d.ts +53 -0
  254. package/dist/services/sync/graph-match.js +316 -0
  255. package/dist/services/sync/graph-match.js.map +1 -0
  256. package/dist/services/sync/graphrag-client.d.ts +43 -0
  257. package/dist/services/sync/graphrag-client.js +94 -0
  258. package/dist/services/sync/graphrag-client.js.map +1 -0
  259. package/dist/services/sync/graphrag-config.d.ts +16 -0
  260. package/dist/services/sync/graphrag-config.js +39 -0
  261. package/dist/services/sync/graphrag-config.js.map +1 -0
  262. package/dist/services/sync/graphrag-context.d.ts +14 -0
  263. package/dist/services/sync/graphrag-context.js +109 -0
  264. package/dist/services/sync/graphrag-context.js.map +1 -0
  265. package/dist/services/sync/graphrag-indexer.d.ts +30 -0
  266. package/dist/services/sync/graphrag-indexer.js +358 -0
  267. package/dist/services/sync/graphrag-indexer.js.map +1 -0
  268. package/dist/services/sync/llm.d.ts +32 -0
  269. package/dist/services/sync/llm.js +115 -0
  270. package/dist/services/sync/llm.js.map +1 -0
  271. package/dist/services/sync/mcp-client.d.ts +59 -0
  272. package/dist/services/sync/mcp-client.js +285 -0
  273. package/dist/services/sync/mcp-client.js.map +1 -0
  274. package/dist/services/sync/model-factory.d.ts +10 -0
  275. package/dist/services/sync/model-factory.js +24 -0
  276. package/dist/services/sync/model-factory.js.map +1 -0
  277. package/dist/services/sync/name-quality.d.ts +31 -0
  278. package/dist/services/sync/name-quality.js +60 -0
  279. package/dist/services/sync/name-quality.js.map +1 -0
  280. package/dist/services/sync/output-schemas.d.ts +92 -0
  281. package/dist/services/sync/output-schemas.js +43 -0
  282. package/dist/services/sync/output-schemas.js.map +1 -0
  283. package/dist/services/sync/prompts.d.ts +19 -0
  284. package/dist/services/sync/prompts.js +128 -0
  285. package/dist/services/sync/prompts.js.map +1 -0
  286. package/dist/services/sync/reconciler.d.ts +48 -0
  287. package/dist/services/sync/reconciler.js +295 -0
  288. package/dist/services/sync/reconciler.js.map +1 -0
  289. package/dist/services/sync/source-config.d.ts +45 -0
  290. package/dist/services/sync/source-config.js +208 -0
  291. package/dist/services/sync/source-config.js.map +1 -0
  292. package/dist/services/sync/source-definitions/asana.d.ts +15 -0
  293. package/dist/services/sync/source-definitions/asana.js +48 -0
  294. package/dist/services/sync/source-definitions/asana.js.map +1 -0
  295. package/dist/services/sync/source-definitions/definitions.d.ts +21 -0
  296. package/dist/services/sync/source-definitions/definitions.js +26 -0
  297. package/dist/services/sync/source-definitions/definitions.js.map +1 -0
  298. package/dist/services/sync/source-definitions/gdrive.d.ts +16 -0
  299. package/dist/services/sync/source-definitions/gdrive.js +68 -0
  300. package/dist/services/sync/source-definitions/gdrive.js.map +1 -0
  301. package/dist/services/sync/source-definitions/granola.d.ts +2 -0
  302. package/dist/services/sync/source-definitions/granola.js +28 -0
  303. package/dist/services/sync/source-definitions/granola.js.map +1 -0
  304. package/dist/services/sync/source-definitions/linear.d.ts +2 -0
  305. package/dist/services/sync/source-definitions/linear.js +60 -0
  306. package/dist/services/sync/source-definitions/linear.js.map +1 -0
  307. package/dist/services/sync/source-definitions/obsidian.d.ts +2 -0
  308. package/dist/services/sync/source-definitions/obsidian.js +55 -0
  309. package/dist/services/sync/source-definitions/obsidian.js.map +1 -0
  310. package/dist/services/sync/source-definitions/pipedrive.d.ts +2 -0
  311. package/dist/services/sync/source-definitions/pipedrive.js +52 -0
  312. package/dist/services/sync/source-definitions/pipedrive.js.map +1 -0
  313. package/dist/services/sync/staging.d.ts +53 -0
  314. package/dist/services/sync/staging.js +131 -0
  315. package/dist/services/sync/staging.js.map +1 -0
  316. package/dist/services/sync/structured-extractor.d.ts +49 -0
  317. package/dist/services/sync/structured-extractor.js +344 -0
  318. package/dist/services/sync/structured-extractor.js.map +1 -0
  319. package/dist/services/sync/sync-runner.d.ts +32 -0
  320. package/dist/services/sync/sync-runner.js +195 -0
  321. package/dist/services/sync/sync-runner.js.map +1 -0
  322. package/dist/services/sync/sync-state.d.ts +43 -0
  323. package/dist/services/sync/sync-state.js +154 -0
  324. package/dist/services/sync/sync-state.js.map +1 -0
  325. package/dist/services/sync/types.d.ts +203 -0
  326. package/dist/services/sync/types.js +8 -0
  327. package/dist/services/sync/types.js.map +1 -0
  328. package/dist/services/sync/unstructured-extractor.d.ts +29 -0
  329. package/dist/services/sync/unstructured-extractor.js +197 -0
  330. package/dist/services/sync/unstructured-extractor.js.map +1 -0
  331. package/dist/services/vector-service.d.ts +88 -0
  332. package/dist/services/vector-service.js +322 -0
  333. package/dist/services/vector-service.js.map +1 -0
  334. package/dist/utils/git.d.ts +26 -4
  335. package/dist/utils/git.js +55 -7
  336. package/dist/utils/git.js.map +1 -1
  337. package/dist/utils/merge-resolver.d.ts +34 -0
  338. package/dist/utils/merge-resolver.js +201 -0
  339. package/dist/utils/merge-resolver.js.map +1 -0
  340. package/dist/utils/preflight.d.ts +2 -1
  341. package/dist/utils/preflight.js +8 -1
  342. package/dist/utils/preflight.js.map +1 -1
  343. package/dist/utils/version-checker.d.ts +23 -0
  344. package/dist/utils/version-checker.js +116 -0
  345. package/dist/utils/version-checker.js.map +1 -0
  346. package/dist/utils/workspace-config.d.ts +8 -0
  347. package/dist/utils/workspace-config.js +22 -0
  348. package/dist/utils/workspace-config.js.map +1 -0
  349. package/package.json +24 -11
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Orphan Entity Detection Service
3
+ *
4
+ * Finds entities with zero inbound wikilink references across the entire graph.
5
+ * These are "orphans" — they exist but nothing points to them.
6
+ *
7
+ * Supports filtering by entity type, minimum age, and actions like
8
+ * tombstoning (sync-state) or deletion.
9
+ */
10
+ import { MarkdownService, slugifyWikilink } from './markdown.js';
11
+ /**
12
+ * Build a set of all entity IDs that are referenced by at least one wikilink
13
+ * anywhere in the graph. An entity NOT in this set is an orphan.
14
+ */
15
+ function buildReferencedSet(manager, markdown) {
16
+ const referenced = new Set();
17
+ const allRepos = manager.getAllRepoConfigs();
18
+ for (const repoConfig of allRepos) {
19
+ let graph;
20
+ try {
21
+ graph = manager.getGraph(repoConfig.name);
22
+ }
23
+ catch {
24
+ continue;
25
+ }
26
+ const entities = graph.list();
27
+ for (const entity of entities) {
28
+ // Collect all wikilinks from this entity's content + frontmatter
29
+ for (const link of entity.document.wikilinks) {
30
+ // Normalize: strip repo prefix if present, then slugify
31
+ const cleanLink = link.split('/').pop() || link;
32
+ referenced.add(cleanLink);
33
+ referenced.add(slugifyWikilink(cleanLink));
34
+ }
35
+ }
36
+ }
37
+ return referenced;
38
+ }
39
+ /**
40
+ * Find all orphan entities — entities with zero inbound wikilink references.
41
+ */
42
+ export function findOrphans(manager, filters) {
43
+ const markdown = new MarkdownService();
44
+ const referenced = buildReferencedSet(manager, markdown);
45
+ const allRepos = manager.getAllRepoConfigs();
46
+ const repos = filters?.repos
47
+ ? allRepos.filter(r => filters.repos.includes(r.name))
48
+ : allRepos;
49
+ const entityTypeFilter = filters?.entityTypes
50
+ ? new Set(filters.entityTypes)
51
+ : null;
52
+ const now = Date.now();
53
+ const minAgeMs = (filters?.minAgeDays ?? 0) * 86_400_000;
54
+ const orphans = [];
55
+ let totalScanned = 0;
56
+ for (const repoConfig of repos) {
57
+ let graph;
58
+ try {
59
+ graph = manager.getGraph(repoConfig.name);
60
+ }
61
+ catch {
62
+ continue;
63
+ }
64
+ const entities = graph.list();
65
+ for (const entity of entities) {
66
+ const entityType = entity.data.entity_type;
67
+ // Filter by entity type
68
+ if (entityTypeFilter && !entityTypeFilter.has(entityType))
69
+ continue;
70
+ totalScanned++;
71
+ // Check if this entity is referenced anywhere
72
+ const id = entity.id;
73
+ if (referenced.has(id) || referenced.has(slugifyWikilink(id))) {
74
+ continue;
75
+ }
76
+ // Check minimum age
77
+ if (minAgeMs > 0) {
78
+ const createdStr = entity.data.created_at;
79
+ if (createdStr) {
80
+ const createdMs = new Date(createdStr).getTime();
81
+ if (now - createdMs < minAgeMs)
82
+ continue;
83
+ }
84
+ }
85
+ orphans.push({
86
+ repo: repoConfig.name,
87
+ entityType,
88
+ entityId: id,
89
+ createdAt: entity.data.created_at,
90
+ name: entity.data.name,
91
+ });
92
+ }
93
+ }
94
+ return {
95
+ orphans,
96
+ totalScanned,
97
+ totalOrphans: orphans.length,
98
+ };
99
+ }
100
+ //# sourceMappingURL=orphan-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-service.js","sourceRoot":"","sources":["../../src/services/orphan-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Commit staging files to the graph.
3
+ *
4
+ * Reads staging files, filters out _action: skip, strips _* metadata,
5
+ * and uses MarkdownService to write to repos. Persists provenance to
6
+ * SyncState before stripping. Records explicit skips as tombstones.
7
+ *
8
+ * For updates, performs field-level merge: sync only overwrites fields
9
+ * it owns (tracked via field_origins). User-added fields are preserved.
10
+ *
11
+ * Exports:
12
+ * applyStaging() — write staging → entity files (no git)
13
+ * commitRepos() — git commit across workspace repos
14
+ * commitStaging() — backwards-compatible wrapper (apply + git)
15
+ */
16
+ export interface CommitResult {
17
+ created: number;
18
+ updated: number;
19
+ skipped: number;
20
+ }
21
+ export interface ApplyResult extends CommitResult {
22
+ /** Per-repo stats for building git commit messages. */
23
+ perRepo: Map<string, {
24
+ created: number;
25
+ updated: number;
26
+ sources: Set<string>;
27
+ }>;
28
+ }
29
+ export interface CommitOptions {
30
+ force?: boolean;
31
+ noGit?: boolean;
32
+ }
33
+ export interface CommitReposOptions {
34
+ /** Prefix for the commit message (e.g. "sync", "enrich"). Default: "sync" */
35
+ messagePrefix?: string;
36
+ /** Per-repo stats from applyStaging() — used to build detailed commit messages. */
37
+ perRepo?: Map<string, {
38
+ created: number;
39
+ updated: number;
40
+ sources: Set<string>;
41
+ }>;
42
+ }
43
+ /**
44
+ * Write staging files to entity files on disk. Does NOT touch git.
45
+ * Handles: dirty tree check, staging read, field-level merge, entity file
46
+ * writes, staging clear, and sync state update.
47
+ */
48
+ export declare function applyStaging(workspacePath: string, onProgress?: (msg: string) => void, options?: Pick<CommitOptions, 'force'>): Promise<ApplyResult>;
49
+ /**
50
+ * Git commit uncommitted changes across workspace repos.
51
+ * Works after applyStaging(), enrich, or any manual edits.
52
+ */
53
+ export declare function commitRepos(workspacePath: string, onProgress?: (msg: string) => void, options?: CommitReposOptions): Promise<void>;
54
+ /**
55
+ * Write staging files to the graph and optionally git-commit.
56
+ * Backwards-compatible wrapper around applyStaging() + commitRepos().
57
+ */
58
+ export declare function commitStaging(workspacePath: string, onProgress?: (msg: string) => void, options?: CommitOptions): Promise<CommitResult>;
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Commit staging files to the graph.
3
+ *
4
+ * Reads staging files, filters out _action: skip, strips _* metadata,
5
+ * and uses MarkdownService to write to repos. Persists provenance to
6
+ * SyncState before stripping. Records explicit skips as tombstones.
7
+ *
8
+ * For updates, performs field-level merge: sync only overwrites fields
9
+ * it owns (tracked via field_origins). User-added fields are preserved.
10
+ *
11
+ * Exports:
12
+ * applyStaging() — write staging → entity files (no git)
13
+ * commitRepos() — git commit across workspace repos
14
+ * commitStaging() — backwards-compatible wrapper (apply + git)
15
+ */
16
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
17
+ import { join } from 'path';
18
+ import { spawnSync } from 'child_process';
19
+ import { MarkdownService } from '../../services/markdown.js';
20
+ import { StagingManager } from './staging.js';
21
+ import { SyncStateManager } from './sync-state.js';
22
+ import { gitHasUncommittedChanges, isGitRepo } from '../../utils/git.js';
23
+ import { loadWorkspaceConfig } from '../../utils/workspace-config.js';
24
+ import { Workspace } from '../../core/workspace.js';
25
+ import { RepoType } from '../../core/types.js';
26
+ import { reindexWorkspace } from '../vector-service.js';
27
+ /** Base entity fields that sync always controls. */
28
+ const BASE_FIELDS = new Set([
29
+ 'entity_type', 'entity_id', 'updated_at', 'updated_by',
30
+ ]);
31
+ // ── applyStaging ──────────────────────────────────────────────────────────────
32
+ /**
33
+ * Write staging files to entity files on disk. Does NOT touch git.
34
+ * Handles: dirty tree check, staging read, field-level merge, entity file
35
+ * writes, staging clear, and sync state update.
36
+ */
37
+ export async function applyStaging(workspacePath, onProgress, options) {
38
+ const log = onProgress ?? (() => { });
39
+ const staging = new StagingManager(workspacePath);
40
+ const syncState = new SyncStateManager(workspacePath);
41
+ const markdown = new MarkdownService();
42
+ const files = staging.readStaging();
43
+ if (files.length === 0) {
44
+ log('No staging files to apply.');
45
+ return { created: 0, updated: 0, skipped: 0, perRepo: new Map() };
46
+ }
47
+ // Load workspace config for repo paths
48
+ const config = loadWorkspaceConfig(workspacePath);
49
+ let repos = config?.repos ?? [];
50
+ // ── Auto-register unknown repos ───────────────────────────────────────
51
+ if (config) {
52
+ const targetRepoNames = new Set(files.filter(f => f.frontmatter._action !== 'skip').map(f => f.repo));
53
+ for (const repoName of targetRepoNames) {
54
+ if (!repos.find((r) => r.name === repoName)) {
55
+ log(` Auto-registering repo: ${repoName}`);
56
+ const workspace = new Workspace(workspacePath);
57
+ await workspace.registerRepo({ name: repoName, type: RepoType.PROJECT });
58
+ // Reload config to pick up new repo
59
+ const updatedConfig = loadWorkspaceConfig(workspacePath);
60
+ repos = updatedConfig?.repos ?? [];
61
+ }
62
+ }
63
+ }
64
+ // ── Dirty working tree check (per-repo) ─────────────────────────────────
65
+ if (!options?.force) {
66
+ const targetRepoPaths = new Set();
67
+ for (const file of files) {
68
+ if (file.frontmatter._action === 'skip')
69
+ continue;
70
+ const repo = repos.find((r) => r.name === file.repo);
71
+ const repoPath = repo ? join(workspacePath, repo.path) : join(workspacePath, file.repo);
72
+ targetRepoPaths.add(repoPath);
73
+ }
74
+ for (const repoPath of targetRepoPaths) {
75
+ if (existsSync(repoPath) && isGitRepo(repoPath) && gitHasUncommittedChanges(repoPath)) {
76
+ const msg = `Uncommitted changes in ${repoPath}. Commit or stash changes first, or use --force.`;
77
+ log(msg);
78
+ throw new Error(msg);
79
+ }
80
+ }
81
+ }
82
+ const result = { created: 0, updated: 0, skipped: 0, perRepo: new Map() };
83
+ for (const file of files) {
84
+ const action = file.frontmatter._action;
85
+ const fieldSources = (file.frontmatter._field_sources ?? {});
86
+ // Save provenance before stripping
87
+ const sources = file.frontmatter._sources;
88
+ if (sources && sources.length > 0) {
89
+ for (const sourceRef of sources) {
90
+ const sourceName = sourceRef.split(':')[0] ?? sourceRef.split('/')[0] ?? 'unknown';
91
+ syncState.setEntityMapping(sourceName, file.entity_id, sourceRef);
92
+ }
93
+ }
94
+ if (action === 'skip') {
95
+ // Track as tombstone if user explicitly changed from create to skip
96
+ syncState.addTombstone(file.entity_id);
97
+ result.skipped++;
98
+ log(` Skipped: ${file.entity_type}/${file.entity_id}`);
99
+ continue;
100
+ }
101
+ // Strip staging metadata fields
102
+ const stagedFrontmatter = { ...file.frontmatter };
103
+ const coLocate = stagedFrontmatter._co_locate;
104
+ const writeMode = stagedFrontmatter._write_mode;
105
+ delete stagedFrontmatter._action;
106
+ delete stagedFrontmatter._confidence;
107
+ delete stagedFrontmatter._sources;
108
+ delete stagedFrontmatter._notes;
109
+ delete stagedFrontmatter._field_sources;
110
+ delete stagedFrontmatter._co_locate;
111
+ delete stagedFrontmatter._write_mode;
112
+ // Determine target path
113
+ const repo = repos.find((r) => r.name === file.repo);
114
+ const repoPath = repo ? join(workspacePath, repo.path) : join(workspacePath, file.repo);
115
+ // Git-init new repo directories immediately so they're protected from
116
+ // manual resets or git clean even if workspace_commit isn't called later.
117
+ if (!existsSync(repoPath)) {
118
+ mkdirSync(repoPath, { recursive: true });
119
+ }
120
+ if (!isGitRepo(repoPath)) {
121
+ spawnSync('git', ['init'], { cwd: repoPath, encoding: 'utf-8' });
122
+ const ignorePath = join(repoPath, '.gitignore');
123
+ if (!existsSync(ignorePath)) {
124
+ writeFileSync(ignorePath, '.DS_Store\n*.tmp\n*.log\n', 'utf-8');
125
+ }
126
+ }
127
+ let entityPath;
128
+ if (coLocate) {
129
+ // Co-located sub-content: {repo}/{parentId}/{subfolder}/{entityId}.md
130
+ const parentRef = stagedFrontmatter[coLocate.parent_field];
131
+ if (!parentRef) {
132
+ result.skipped++;
133
+ log(` Skipped: ${file.entity_type}/${file.entity_id} (no ${coLocate.parent_field} assigned)`);
134
+ continue;
135
+ }
136
+ const parentId = parentRef.replace(/^\[\[/, '').replace(/\]\]$/, '');
137
+ const subDir = join(repoPath, parentId, coLocate.subfolder);
138
+ mkdirSync(subDir, { recursive: true });
139
+ entityPath = join(subDir, `${file.entity_id}.md`);
140
+ }
141
+ else if (writeMode === 'collection') {
142
+ // Collection mode: {repo}/{entityId}.md (loose file, no subfolder)
143
+ mkdirSync(repoPath, { recursive: true });
144
+ entityPath = join(repoPath, `${file.entity_id}.md`);
145
+ }
146
+ else {
147
+ // Standard entity: {repo}/{entityId}/main.md
148
+ const entityDir = join(repoPath, file.entity_id);
149
+ mkdirSync(entityDir, { recursive: true });
150
+ entityPath = join(entityDir, 'main.md');
151
+ }
152
+ const now = new Date().toISOString();
153
+ let finalFrontmatter;
154
+ if (action === 'update' && existsSync(entityPath)) {
155
+ // ── Field-level merge ─────────────────────────────────────────────
156
+ const existing = markdown.parseFile(entityPath);
157
+ finalFrontmatter = { ...existing.frontmatter };
158
+ // Overwrite source-owned fields and base fields
159
+ for (const [key, value] of Object.entries(stagedFrontmatter)) {
160
+ if (BASE_FIELDS.has(key) || fieldSources[key]) {
161
+ finalFrontmatter[key] = value;
162
+ }
163
+ else if (finalFrontmatter[key] === undefined) {
164
+ // New field from sync that wasn't on disk — add it
165
+ finalFrontmatter[key] = value;
166
+ }
167
+ // else: field exists on disk and sync doesn't own it → preserve user value
168
+ }
169
+ // Preserve created_at/created_by from existing
170
+ if (existing.frontmatter.created_at)
171
+ finalFrontmatter.created_at = existing.frontmatter.created_at;
172
+ if (existing.frontmatter.created_by)
173
+ finalFrontmatter.created_by = existing.frontmatter.created_by;
174
+ // Always update timestamps
175
+ finalFrontmatter.updated_at = now;
176
+ finalFrontmatter.updated_by = 'sync';
177
+ }
178
+ else {
179
+ // ── Create (or update with no existing file) ──────────────────────
180
+ finalFrontmatter = stagedFrontmatter;
181
+ // Add base entity fields if missing
182
+ if (!finalFrontmatter.entity_type)
183
+ finalFrontmatter.entity_type = file.entity_type;
184
+ if (!finalFrontmatter.entity_id)
185
+ finalFrontmatter.entity_id = file.entity_id;
186
+ if (!finalFrontmatter.created_at)
187
+ finalFrontmatter.created_at = now;
188
+ if (!finalFrontmatter.updated_at)
189
+ finalFrontmatter.updated_at = now;
190
+ if (!finalFrontmatter.created_by)
191
+ finalFrontmatter.created_by = 'sync';
192
+ if (!finalFrontmatter.updated_by)
193
+ finalFrontmatter.updated_by = 'sync';
194
+ }
195
+ markdown.writeFile(entityPath, {
196
+ frontmatter: finalFrontmatter,
197
+ content: file.content,
198
+ wikilinks: [],
199
+ });
200
+ // Track per-repo stats for git commit messages
201
+ if (!result.perRepo.has(repoPath)) {
202
+ result.perRepo.set(repoPath, { created: 0, updated: 0, sources: new Set() });
203
+ }
204
+ const repoStats = result.perRepo.get(repoPath);
205
+ const sourceRefs = file.frontmatter._sources;
206
+ if (sourceRefs) {
207
+ for (const ref of sourceRefs) {
208
+ const name = ref.split('/')[0];
209
+ if (name)
210
+ repoStats.sources.add(name);
211
+ }
212
+ }
213
+ // Persist field origins to sync state
214
+ if (Object.keys(fieldSources).length > 0) {
215
+ // Group field_sources by source name
216
+ const bySource = new Map();
217
+ for (const [field, source] of Object.entries(fieldSources)) {
218
+ if (!bySource.has(source))
219
+ bySource.set(source, {});
220
+ bySource.get(source)[field] = source;
221
+ }
222
+ for (const [sourceName, fields] of bySource) {
223
+ syncState.setFieldOrigins(sourceName, file.entity_id, fields);
224
+ }
225
+ }
226
+ if (action === 'update') {
227
+ result.updated++;
228
+ repoStats.updated++;
229
+ log(` Updated: ${file.entity_type}/${file.entity_id}`);
230
+ }
231
+ else {
232
+ result.created++;
233
+ repoStats.created++;
234
+ log(` Created: ${file.entity_type}/${file.entity_id}`);
235
+ }
236
+ }
237
+ // Clear staging after successful apply
238
+ staging.clear();
239
+ log(`\nApply complete: ${result.created} created, ${result.updated} updated, ${result.skipped} skipped`);
240
+ return result;
241
+ }
242
+ // ── commitRepos ───────────────────────────────────────────────────────────────
243
+ /**
244
+ * Git commit uncommitted changes across workspace repos.
245
+ * Works after applyStaging(), enrich, or any manual edits.
246
+ */
247
+ export async function commitRepos(workspacePath, onProgress, options) {
248
+ const log = onProgress ?? (() => { });
249
+ const prefix = options?.messagePrefix ?? 'sync';
250
+ const perRepo = options?.perRepo;
251
+ // ── Reconcile workspace.json with filesystem ────────────────────────
252
+ const workspace = new Workspace(workspacePath);
253
+ if (workspace.isWorkspace()) {
254
+ const { added, removed } = await workspace.reconcileRepos();
255
+ for (const name of added)
256
+ log(` Registered repo: ${name}`);
257
+ for (const name of removed)
258
+ log(` Removed stale repo: ${name}`);
259
+ // Commit .studiograph/ if workspace.json changed
260
+ if (added.length > 0 || removed.length > 0) {
261
+ const sgDir = join(workspacePath, '.studiograph');
262
+ if (isGitRepo(workspacePath) && gitHasUncommittedChanges(workspacePath)) {
263
+ spawnSync('git', ['add', sgDir], { cwd: workspacePath, encoding: 'utf-8' });
264
+ const parts = [];
265
+ if (added.length > 0)
266
+ parts.push(`add ${added.join(', ')}`);
267
+ if (removed.length > 0)
268
+ parts.push(`remove ${removed.join(', ')}`);
269
+ const msg = `workspace: reconcile repos (${parts.join('; ')})`;
270
+ spawnSync('git', ['commit', '-m', msg], { cwd: workspacePath, encoding: 'utf-8' });
271
+ log(` Committed workspace.json update`);
272
+ }
273
+ }
274
+ }
275
+ const config = loadWorkspaceConfig(workspacePath);
276
+ const repos = config?.repos ?? [];
277
+ for (const repo of repos) {
278
+ const repoPath = join(workspacePath, repo.path);
279
+ if (!existsSync(repoPath))
280
+ continue;
281
+ // Initialize git repo if it doesn't exist yet
282
+ if (!isGitRepo(repoPath)) {
283
+ const init = spawnSync('git', ['init'], { cwd: repoPath, encoding: 'utf-8' });
284
+ if (init.status !== 0) {
285
+ log(` Warning: git init failed in ${repoPath}: ${init.stderr?.trim()}`);
286
+ continue;
287
+ }
288
+ const ignorePath = join(repoPath, '.gitignore');
289
+ if (!existsSync(ignorePath)) {
290
+ writeFileSync(ignorePath, '.DS_Store\n*.tmp\n*.log\n', 'utf-8');
291
+ }
292
+ log(` Git init: ${repo.name}`);
293
+ }
294
+ if (!gitHasUncommittedChanges(repoPath))
295
+ continue;
296
+ // Build commit message
297
+ let commitMsg;
298
+ const stats = perRepo?.get(repoPath);
299
+ if (stats) {
300
+ const parts = [];
301
+ if (stats.created > 0)
302
+ parts.push(`${stats.created} created`);
303
+ if (stats.updated > 0)
304
+ parts.push(`${stats.updated} updated`);
305
+ const from = stats.sources.size > 0 ? ` from ${[...stats.sources].join(', ')}` : '';
306
+ commitMsg = `${prefix}: ${parts.join(', ')}${from}`;
307
+ }
308
+ else {
309
+ // Generic message — count changed files from git status
310
+ const status = spawnSync('git', ['status', '--porcelain'], { cwd: repoPath, encoding: 'utf-8' });
311
+ const changedFiles = (status.stdout?.trim().split('\n').filter(Boolean) ?? []).length;
312
+ commitMsg = `${prefix}: ${changedFiles} file${changedFiles === 1 ? '' : 's'} changed`;
313
+ }
314
+ // Stage all changes within this repo directory (relies on .gitignore for exclusions)
315
+ const add = spawnSync('git', ['add', '.'], { cwd: repoPath, encoding: 'utf-8' });
316
+ if (add.status !== 0) {
317
+ log(` Warning: git add failed in ${repoPath}: ${add.stderr?.trim()}`);
318
+ continue;
319
+ }
320
+ const commit = spawnSync('git', ['commit', '-m', commitMsg], { cwd: repoPath, encoding: 'utf-8' });
321
+ if (commit.status === 0) {
322
+ log(` Git commit: ${repo.name}`);
323
+ }
324
+ else {
325
+ log(` Warning: git commit failed in ${repoPath}: ${commit.stderr?.trim()}`);
326
+ }
327
+ }
328
+ // Reindex search after commit (non-fatal)
329
+ try {
330
+ const indexed = await reindexWorkspace(workspacePath, repos, log);
331
+ if (indexed > 0)
332
+ log(` Search index updated (${indexed} entities)`);
333
+ }
334
+ catch {
335
+ // Non-fatal — search may be stale until next manual reindex
336
+ }
337
+ }
338
+ // ── commitStaging (backwards-compatible wrapper) ──────────────────────────────
339
+ /**
340
+ * Write staging files to the graph and optionally git-commit.
341
+ * Backwards-compatible wrapper around applyStaging() + commitRepos().
342
+ */
343
+ export async function commitStaging(workspacePath, onProgress, options) {
344
+ const applyResult = await applyStaging(workspacePath, onProgress, { force: options?.force });
345
+ if (!options?.noGit) {
346
+ await commitRepos(workspacePath, onProgress, { perRepo: applyResult.perRepo });
347
+ }
348
+ return { created: applyResult.created, updated: applyResult.updated, skipped: applyResult.skipped };
349
+ }
350
+ //# sourceMappingURL=commit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../../src/services/sync/commit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * ContextIndex
3
+ *
4
+ * Cross-source context index for enrichment. Scans all repos for entity
5
+ * references using schema relationship fields and wikilinks.
6
+ *
7
+ * Ranks references by recency, enforces a max_tokens budget, and truncates
8
+ * excess context before the LLM call.
9
+ */
10
+ import type { SchemaRegistry } from '../../core/schema-registry.js';
11
+ export interface ContextReference {
12
+ entity_id: string;
13
+ entity_type: string;
14
+ field: string;
15
+ repo: string;
16
+ /** ISO date for recency ranking */
17
+ date?: string;
18
+ /** Short summary snippet */
19
+ snippet: string;
20
+ }
21
+ export interface EnrichableEntity {
22
+ entity_id: string;
23
+ entity_type: string;
24
+ repo: string;
25
+ path: string;
26
+ frontmatter: Record<string, any>;
27
+ completeness: number;
28
+ refCount: number;
29
+ }
30
+ export declare class ContextIndex {
31
+ private workspacePath;
32
+ private schemaRegistry;
33
+ private markdownService;
34
+ private references;
35
+ private built;
36
+ constructor(workspacePath: string, schemaRegistry: SchemaRegistry);
37
+ /**
38
+ * Scan all repos for entity references.
39
+ */
40
+ build(): void;
41
+ /**
42
+ * Get all context references for one entity.
43
+ */
44
+ getReferences(entityId: string): ContextReference[];
45
+ /**
46
+ * Calculate field completeness (0–1) for an entity.
47
+ */
48
+ getCompleteness(entityType: string, frontmatter: Record<string, any>): number;
49
+ /**
50
+ * Filter to entities worth enriching (low completeness + high context).
51
+ */
52
+ getEnrichable(minRefs?: number, maxCompleteness?: number): EnrichableEntity[];
53
+ /**
54
+ * Assemble LLM context bundle for one entity.
55
+ * Ranks references by recency, enforces max_tokens budget.
56
+ */
57
+ assembleContextBundle(entityId: string, entityName: string, maxTokens?: number): string;
58
+ private scanRepo;
59
+ private addReference;
60
+ /**
61
+ * Get relationship fields for an entity type by inspecting schema descriptions.
62
+ */
63
+ private getRelationshipFields;
64
+ private getDescription;
65
+ private extractEntityId;
66
+ private makeSnippet;
67
+ private findRepoDirs;
68
+ private listSubDirs;
69
+ }