maestro-flow 0.5.2 → 0.5.3

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 (485) hide show
  1. package/.agents/skills/insight-challenge/SKILL.md +228 -0
  2. package/.agents/skills/insight-challenge/specs/challenge-protocol.md +154 -0
  3. package/.agents/skills/insight-challenge/specs/verdict-schema.md +239 -0
  4. package/.agents/skills/maestro/SKILL.md +6 -6
  5. package/.agents/skills/maestro-help/SKILL.md +1 -1
  6. package/.agents/skills/maestro-help/index/catalog.json +3 -2
  7. package/.agents/skills/maestro-ralph/SKILL.md +11 -10
  8. package/.agents/skills/maestro-ralph-beta/SKILL.md +11 -10
  9. package/.agents/skills/odyssey-debug/SKILL.md +475 -0
  10. package/.agents/skills/odyssey-improve/SKILL.md +507 -0
  11. package/.agents/skills/odyssey-planex/SKILL.md +603 -0
  12. package/.agents/skills/odyssey-review-test-fix/SKILL.md +429 -0
  13. package/.agents/skills/odyssey-ui/SKILL.md +464 -0
  14. package/.agy/skills/insight-challenge/SKILL.md +230 -0
  15. package/.agy/skills/insight-challenge/specs/challenge-protocol.md +154 -0
  16. package/.agy/skills/insight-challenge/specs/verdict-schema.md +239 -0
  17. package/.agy/skills/maestro/SKILL.md +6 -6
  18. package/.agy/skills/maestro-help/SKILL.md +1 -1
  19. package/.agy/skills/maestro-help/index/catalog.json +3 -2
  20. package/.agy/skills/maestro-ralph/SKILL.md +11 -10
  21. package/.agy/skills/maestro-ralph-beta/SKILL.md +11 -10
  22. package/.agy/skills/odyssey-debug/SKILL.md +475 -0
  23. package/.agy/skills/odyssey-improve/SKILL.md +507 -0
  24. package/.agy/skills/odyssey-planex/SKILL.md +603 -0
  25. package/.agy/skills/odyssey-review-test-fix/SKILL.md +429 -0
  26. package/.agy/skills/odyssey-ui/SKILL.md +464 -0
  27. package/.claude/commands/maestro-ralph-beta.md +11 -10
  28. package/.claude/commands/maestro-ralph.md +11 -10
  29. package/.claude/commands/maestro.md +6 -6
  30. package/.claude/commands/odyssey-debug.md +473 -0
  31. package/.claude/commands/odyssey-improve.md +505 -0
  32. package/.claude/commands/odyssey-planex.md +601 -0
  33. package/.claude/commands/odyssey-review-test-fix.md +427 -0
  34. package/.claude/commands/odyssey-ui.md +462 -0
  35. package/.claude/skills/insight-challenge/SKILL.md +226 -0
  36. package/.claude/skills/insight-challenge/specs/challenge-protocol.md +154 -0
  37. package/.claude/skills/insight-challenge/specs/verdict-schema.md +239 -0
  38. package/.claude/skills/maestro-help/SKILL.md +1 -1
  39. package/.claude/skills/maestro-help/index/catalog.json +3 -2
  40. package/.codex/skills/codify-to-knowhow/SKILL.md +1 -1
  41. package/.codex/skills/maestro-companion/SKILL.md +1 -1
  42. package/.codex/skills/maestro-help/SKILL.md +1 -1
  43. package/.codex/skills/maestro-impeccable/SKILL.md +1 -1
  44. package/.codex/skills/maestro-next/SKILL.md +1 -1
  45. package/.codex/skills/maestro-ralph-beta/SKILL.md +1 -1
  46. package/.codex/skills/odyssey-debug/SKILL.md +456 -0
  47. package/.codex/skills/odyssey-improve/SKILL.md +466 -0
  48. package/.codex/skills/odyssey-planex/SKILL.md +409 -0
  49. package/.codex/skills/odyssey-review-test-fix/SKILL.md +377 -0
  50. package/.codex/skills/odyssey-ui/SKILL.md +411 -0
  51. package/dashboard/dist/assets/{ArtifactsPage-BLvAqQlQ.js → ArtifactsPage-B6z23DfG.js} +2 -2
  52. package/dashboard/dist/assets/{ChatInput-DU9YGZKX.js → ChatInput-tBtGKV2i.js} +1 -1
  53. package/dashboard/dist/assets/{ChatPage-DYHfheXC.js → ChatPage-CcggDVs4.js} +2 -2
  54. package/dashboard/dist/assets/{CollabPage-CSlmvEa-.js → CollabPage-FaZeqqeS.js} +1 -1
  55. package/dashboard/dist/assets/{ExecutionPanel-RYWf0dYC.js → ExecutionPanel-DNRwYDXp.js} +1 -1
  56. package/dashboard/dist/assets/{KanbanPage-N55Iv0-X.js → KanbanPage-B2xh2s_N.js} +1 -1
  57. package/dashboard/dist/assets/{MaestroCoordinatePage-BxwZ6yy5.js → MaestroCoordinatePage-DCMGHDAL.js} +1 -1
  58. package/dashboard/dist/assets/{MarkdownRenderer-ZGtOY7Ti.js → MarkdownRenderer-C3FvTqVe.js} +1 -1
  59. package/dashboard/dist/assets/McpPage-HKaJ8cQP.js +16 -0
  60. package/dashboard/dist/assets/{MeetingRoomPage-CxHRn1xx.js → MeetingRoomPage-DGN5oUXH.js} +1 -1
  61. package/dashboard/dist/assets/{OutputPanel-DaL8c1i5.js → OutputPanel-BiCteH5k.js} +1 -1
  62. package/dashboard/dist/assets/{ProblemsPanel-BQTd5812.js → ProblemsPanel-Dk4v9tol.js} +1 -1
  63. package/dashboard/dist/assets/{RequirementBoardPage-22y9u1qh.js → RequirementBoardPage-D10A26gi.js} +1 -1
  64. package/dashboard/dist/assets/{RequirementPage-_mO743Xm.js → RequirementPage-Cs-2omLz.js} +1 -1
  65. package/dashboard/dist/assets/{RoomsPage-CExTbOGr.js → RoomsPage-tKQQhw1W.js} +1 -1
  66. package/dashboard/dist/assets/SpecsPage-LK1QCtcg.js +36 -0
  67. package/dashboard/dist/assets/{TeamsPage-BxEXLb5g.js → TeamsPage-C-bEwB8E.js} +1 -1
  68. package/dashboard/dist/assets/{TreeBrowser-CVtPF5C9.js → TreeBrowser-1YP-DfTY.js} +2 -2
  69. package/dashboard/dist/assets/{WorkflowPage-BoN18Lhs.js → WorkflowPage-dGHPsDDr.js} +2 -2
  70. package/dashboard/dist/assets/{arrow-left-C5ROg97G.js → arrow-left-BPFSEpfO.js} +1 -1
  71. package/dashboard/dist/assets/{check-Bs8PM0tQ.js → check-D5hOViiQ.js} +1 -1
  72. package/dashboard/dist/assets/{chevron-right-SmErd_1F.js → chevron-right-D9BsXrIg.js} +1 -1
  73. package/dashboard/dist/assets/{circle-CjpslL_D.js → circle-Cn5fNpmp.js} +1 -1
  74. package/dashboard/dist/assets/{circle-alert-CuzAg2fd.js → circle-alert-CZvK3B1K.js} +1 -1
  75. package/dashboard/dist/assets/{circle-check-BIkDU5D5.js → circle-check-DApOBP0J.js} +1 -1
  76. package/dashboard/dist/assets/{circle-check-big-CYctV8bK.js → circle-check-big-Cd9ztJpl.js} +1 -1
  77. package/dashboard/dist/assets/{code-DoB7rfxt.js → code-C3TuHjMs.js} +1 -1
  78. package/dashboard/dist/assets/{columns-3-Ch5KIyRa.js → columns-3-CO2SvNJb.js} +1 -1
  79. package/dashboard/dist/assets/{download-DadtG2Nr.js → download-BuKGI7KX.js} +1 -1
  80. package/dashboard/dist/assets/{en-2h6fD0j8.js → en-BmpYsIfb.js} +1 -1
  81. package/dashboard/dist/assets/folder-Chwj_P4A.js +11 -0
  82. package/dashboard/dist/assets/folder-open-S72FbKvn.js +6 -0
  83. package/dashboard/dist/assets/{index-BL4h1OKY.js → index-CN0YdC9M.js} +1 -1
  84. package/dashboard/dist/assets/{index-DQIlX2w_.js → index-Cbs79erW.js} +5 -5
  85. package/dashboard/dist/assets/{index-DaFwSmVJ.js → index-CdT1WNND.js} +1 -1
  86. package/dashboard/dist/assets/index-DEvP8cgc.css +1 -0
  87. package/dashboard/dist/assets/{list-CI-XIPZh.js → list-Dg_ojUpi.js} +1 -1
  88. package/dashboard/dist/assets/{loader-DpdMoQvh.js → loader-CMcc73C_.js} +1 -1
  89. package/dashboard/dist/assets/{minus-BVbfXGrC.js → minus-KxmVOIB7.js} +1 -1
  90. package/dashboard/dist/assets/pen-line-D1YTNDPw.js +11 -0
  91. package/dashboard/dist/assets/{pencil-I7GE0y29.js → pencil-BAjxSHuh.js} +1 -1
  92. package/dashboard/dist/assets/{proxy-CcYyZZWI.js → proxy-BewnIei6.js} +1 -1
  93. package/dashboard/dist/assets/{refresh-cw-BG9V_T4R.js → refresh-cw-Chc0RcRY.js} +1 -1
  94. package/dashboard/dist/assets/{rows-2-DP6NjQFk.js → rows-2-DWJuw8OM.js} +1 -1
  95. package/dashboard/dist/assets/{search-b78eLlw2.js → search-CPGb2sEw.js} +1 -1
  96. package/dashboard/dist/assets/{shallow-CJEesgtu.js → shallow-Dy0-7n5s.js} +1 -1
  97. package/dashboard/dist/assets/{table-B_lk-a1d.js → table-VI5scWpO.js} +1 -1
  98. package/dashboard/dist/assets/{team-types-Se7f9LfJ.js → team-types-Cu8zCPN3.js} +1 -1
  99. package/dashboard/dist/assets/{terminal-DXx4tvzq.js → terminal-Bqt5c6Ny.js} +1 -1
  100. package/dashboard/dist/assets/{trash-2-CVh9mnRj.js → trash-2-BcTVifbw.js} +1 -1
  101. package/dashboard/dist/assets/{users-Da9zGME5.js → users-BhFAHz4H.js} +1 -1
  102. package/dashboard/dist/assets/{zap-C0zaC7gJ.js → zap-BWbLhgr6.js} +1 -1
  103. package/dashboard/dist/assets/{zh-CN-r3AvxxOL.js → zh-CN-BIRiTdAD.js} +1 -1
  104. package/dashboard/dist/index.html +2 -2
  105. package/dashboard/dist-server/dashboard/src/server/routes/wiki.js +1 -0
  106. package/dashboard/dist-server/dashboard/src/server/routes/wiki.js.map +1 -1
  107. package/dashboard/dist-server/dashboard/src/server/wiki/search.d.ts +14 -14
  108. package/dashboard/dist-server/dashboard/src/server/wiki/search.js +188 -56
  109. package/dashboard/dist-server/dashboard/src/server/wiki/search.js.map +1 -1
  110. package/dashboard/dist-server/dashboard/src/server/wiki/stress.test.js +1 -0
  111. package/dashboard/dist-server/dashboard/src/server/wiki/stress.test.js.map +1 -1
  112. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.d.ts +37 -0
  113. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js +560 -22
  114. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js.map +1 -1
  115. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-types.d.ts +6 -2
  116. package/dashboard/dist-server/src/types/index.d.ts +9 -0
  117. package/dist/src/cli.js +3 -0
  118. package/dist/src/cli.js.map +1 -1
  119. package/dist/src/commands/delegate.d.ts.map +1 -1
  120. package/dist/src/commands/delegate.js +50 -8
  121. package/dist/src/commands/delegate.js.map +1 -1
  122. package/dist/src/commands/domain.d.ts +9 -0
  123. package/dist/src/commands/domain.d.ts.map +1 -0
  124. package/dist/src/commands/domain.js +445 -0
  125. package/dist/src/commands/domain.js.map +1 -0
  126. package/dist/src/commands/hooks.d.ts +10 -0
  127. package/dist/src/commands/hooks.d.ts.map +1 -1
  128. package/dist/src/commands/hooks.js +132 -22
  129. package/dist/src/commands/hooks.js.map +1 -1
  130. package/dist/src/commands/install.d.ts.map +1 -1
  131. package/dist/src/commands/install.js +82 -204
  132. package/dist/src/commands/install.js.map +1 -1
  133. package/dist/src/commands/kg.d.ts.map +1 -1
  134. package/dist/src/commands/kg.js +183 -90
  135. package/dist/src/commands/kg.js.map +1 -1
  136. package/dist/src/commands/search.d.ts +15 -8
  137. package/dist/src/commands/search.d.ts.map +1 -1
  138. package/dist/src/commands/search.js +205 -59
  139. package/dist/src/commands/search.js.map +1 -1
  140. package/dist/src/commands/spec.d.ts.map +1 -1
  141. package/dist/src/commands/spec.js +9 -1
  142. package/dist/src/commands/spec.js.map +1 -1
  143. package/dist/src/commands/update.d.ts.map +1 -1
  144. package/dist/src/commands/update.js +0 -7
  145. package/dist/src/commands/update.js.map +1 -1
  146. package/dist/src/commands/wiki.d.ts.map +1 -1
  147. package/dist/src/commands/wiki.js +8 -1
  148. package/dist/src/commands/wiki.js.map +1 -1
  149. package/dist/src/commands/workspace.d.ts +12 -0
  150. package/dist/src/commands/workspace.d.ts.map +1 -0
  151. package/dist/src/commands/workspace.js +230 -0
  152. package/dist/src/commands/workspace.js.map +1 -0
  153. package/dist/src/config/cli-tools-config.d.ts +5 -0
  154. package/dist/src/config/cli-tools-config.d.ts.map +1 -1
  155. package/dist/src/config/cli-tools-config.js +31 -0
  156. package/dist/src/config/cli-tools-config.js.map +1 -1
  157. package/dist/src/config/index.d.ts +9 -1
  158. package/dist/src/config/index.d.ts.map +1 -1
  159. package/dist/src/config/index.js +35 -1
  160. package/dist/src/config/index.js.map +1 -1
  161. package/dist/src/core/install-executor.d.ts +31 -0
  162. package/dist/src/core/install-executor.d.ts.map +1 -0
  163. package/dist/src/core/install-executor.js +231 -0
  164. package/dist/src/core/install-executor.js.map +1 -0
  165. package/dist/src/core/install-profile.d.ts +103 -0
  166. package/dist/src/core/install-profile.d.ts.map +1 -0
  167. package/dist/src/core/install-profile.js +225 -0
  168. package/dist/src/core/install-profile.js.map +1 -0
  169. package/dist/src/graph/kg/credibility.d.ts +37 -0
  170. package/dist/src/graph/kg/credibility.d.ts.map +1 -0
  171. package/dist/src/graph/kg/credibility.js +141 -0
  172. package/dist/src/graph/kg/credibility.js.map +1 -0
  173. package/dist/src/graph/kg/db/connection.d.ts +28 -0
  174. package/dist/src/graph/kg/db/connection.d.ts.map +1 -0
  175. package/dist/src/graph/kg/db/connection.js +142 -0
  176. package/dist/src/graph/kg/db/connection.js.map +1 -0
  177. package/dist/src/graph/kg/db/index.d.ts +5 -0
  178. package/dist/src/graph/kg/db/index.d.ts.map +1 -0
  179. package/dist/src/graph/kg/db/index.js +6 -0
  180. package/dist/src/graph/kg/db/index.js.map +1 -0
  181. package/dist/src/graph/kg/db/migrations.d.ts +8 -0
  182. package/dist/src/graph/kg/db/migrations.d.ts.map +1 -0
  183. package/dist/src/graph/kg/db/migrations.js +88 -0
  184. package/dist/src/graph/kg/db/migrations.js.map +1 -0
  185. package/dist/src/graph/kg/db/queries.d.ts +84 -0
  186. package/dist/src/graph/kg/db/queries.d.ts.map +1 -0
  187. package/dist/src/graph/kg/db/queries.js +471 -0
  188. package/dist/src/graph/kg/db/queries.js.map +1 -0
  189. package/dist/src/graph/kg/db/types.d.ts +123 -0
  190. package/dist/src/graph/kg/db/types.d.ts.map +1 -0
  191. package/dist/src/graph/kg/db/types.js +75 -0
  192. package/dist/src/graph/kg/db/types.js.map +1 -0
  193. package/dist/src/graph/kg/engine.d.ts +87 -0
  194. package/dist/src/graph/kg/engine.d.ts.map +1 -0
  195. package/dist/src/graph/kg/engine.js +247 -0
  196. package/dist/src/graph/kg/engine.js.map +1 -0
  197. package/dist/src/graph/kg/extraction/code/code-extractor.d.ts +40 -0
  198. package/dist/src/graph/kg/extraction/code/code-extractor.d.ts.map +1 -0
  199. package/dist/src/graph/kg/extraction/code/code-extractor.js +296 -0
  200. package/dist/src/graph/kg/extraction/code/code-extractor.js.map +1 -0
  201. package/dist/src/graph/kg/extraction/code/dfm-extractor.d.ts +3 -0
  202. package/dist/src/graph/kg/extraction/code/dfm-extractor.d.ts.map +1 -0
  203. package/dist/src/graph/kg/extraction/code/dfm-extractor.js +122 -0
  204. package/dist/src/graph/kg/extraction/code/dfm-extractor.js.map +1 -0
  205. package/dist/src/graph/kg/extraction/code/generated-detection.d.ts +14 -0
  206. package/dist/src/graph/kg/extraction/code/generated-detection.d.ts.map +1 -0
  207. package/dist/src/graph/kg/extraction/code/generated-detection.js +65 -0
  208. package/dist/src/graph/kg/extraction/code/generated-detection.js.map +1 -0
  209. package/dist/src/graph/kg/extraction/code/languages/index.d.ts +9 -0
  210. package/dist/src/graph/kg/extraction/code/languages/index.d.ts.map +1 -0
  211. package/dist/src/graph/kg/extraction/code/languages/index.js +2119 -0
  212. package/dist/src/graph/kg/extraction/code/languages/index.js.map +1 -0
  213. package/dist/src/graph/kg/extraction/code/languages/typescript.d.ts +5 -0
  214. package/dist/src/graph/kg/extraction/code/languages/typescript.d.ts.map +1 -0
  215. package/dist/src/graph/kg/extraction/code/languages/typescript.js +191 -0
  216. package/dist/src/graph/kg/extraction/code/languages/typescript.js.map +1 -0
  217. package/dist/src/graph/kg/extraction/code/liquid-extractor.d.ts +3 -0
  218. package/dist/src/graph/kg/extraction/code/liquid-extractor.d.ts.map +1 -0
  219. package/dist/src/graph/kg/extraction/code/liquid-extractor.js +117 -0
  220. package/dist/src/graph/kg/extraction/code/liquid-extractor.js.map +1 -0
  221. package/dist/src/graph/kg/extraction/code/mybatis-extractor.d.ts +3 -0
  222. package/dist/src/graph/kg/extraction/code/mybatis-extractor.d.ts.map +1 -0
  223. package/dist/src/graph/kg/extraction/code/mybatis-extractor.js +84 -0
  224. package/dist/src/graph/kg/extraction/code/mybatis-extractor.js.map +1 -0
  225. package/dist/src/graph/kg/extraction/code/svelte-extractor.d.ts +3 -0
  226. package/dist/src/graph/kg/extraction/code/svelte-extractor.d.ts.map +1 -0
  227. package/dist/src/graph/kg/extraction/code/svelte-extractor.js +92 -0
  228. package/dist/src/graph/kg/extraction/code/svelte-extractor.js.map +1 -0
  229. package/dist/src/graph/kg/extraction/code/tree-sitter-types.d.ts +61 -0
  230. package/dist/src/graph/kg/extraction/code/tree-sitter-types.d.ts.map +1 -0
  231. package/dist/src/graph/kg/extraction/code/tree-sitter-types.js +53 -0
  232. package/dist/src/graph/kg/extraction/code/tree-sitter-types.js.map +1 -0
  233. package/dist/src/graph/kg/extraction/code/tree-sitter.d.ts +55 -0
  234. package/dist/src/graph/kg/extraction/code/tree-sitter.d.ts.map +1 -0
  235. package/dist/src/graph/kg/extraction/code/tree-sitter.js +227 -0
  236. package/dist/src/graph/kg/extraction/code/tree-sitter.js.map +1 -0
  237. package/dist/src/graph/kg/extraction/code/vue-extractor.d.ts +6 -0
  238. package/dist/src/graph/kg/extraction/code/vue-extractor.d.ts.map +1 -0
  239. package/dist/src/graph/kg/extraction/code/vue-extractor.js +109 -0
  240. package/dist/src/graph/kg/extraction/code/vue-extractor.js.map +1 -0
  241. package/dist/src/graph/kg/extraction/code/wasm-stability.d.ts +44 -0
  242. package/dist/src/graph/kg/extraction/code/wasm-stability.d.ts.map +1 -0
  243. package/dist/src/graph/kg/extraction/code/wasm-stability.js +140 -0
  244. package/dist/src/graph/kg/extraction/code/wasm-stability.js.map +1 -0
  245. package/dist/src/graph/kg/extraction/knowledge/codebase-extractor.d.ts +3 -0
  246. package/dist/src/graph/kg/extraction/knowledge/codebase-extractor.d.ts.map +1 -0
  247. package/dist/src/graph/kg/extraction/knowledge/codebase-extractor.js +149 -0
  248. package/dist/src/graph/kg/extraction/knowledge/codebase-extractor.js.map +1 -0
  249. package/dist/src/graph/kg/extraction/knowledge/domain-extractor.d.ts +4 -0
  250. package/dist/src/graph/kg/extraction/knowledge/domain-extractor.d.ts.map +1 -0
  251. package/dist/src/graph/kg/extraction/knowledge/domain-extractor.js +114 -0
  252. package/dist/src/graph/kg/extraction/knowledge/domain-extractor.js.map +1 -0
  253. package/dist/src/graph/kg/extraction/knowledge/issue-extractor.d.ts +3 -0
  254. package/dist/src/graph/kg/extraction/knowledge/issue-extractor.d.ts.map +1 -0
  255. package/dist/src/graph/kg/extraction/knowledge/issue-extractor.js +84 -0
  256. package/dist/src/graph/kg/extraction/knowledge/issue-extractor.js.map +1 -0
  257. package/dist/src/graph/kg/extraction/knowledge/spec-extractor.d.ts +3 -0
  258. package/dist/src/graph/kg/extraction/knowledge/spec-extractor.d.ts.map +1 -0
  259. package/dist/src/graph/kg/extraction/knowledge/spec-extractor.js +173 -0
  260. package/dist/src/graph/kg/extraction/knowledge/spec-extractor.js.map +1 -0
  261. package/dist/src/graph/kg/extraction/knowledge/wiki-extractor.d.ts +3 -0
  262. package/dist/src/graph/kg/extraction/knowledge/wiki-extractor.d.ts.map +1 -0
  263. package/dist/src/graph/kg/extraction/knowledge/wiki-extractor.js +165 -0
  264. package/dist/src/graph/kg/extraction/knowledge/wiki-extractor.js.map +1 -0
  265. package/dist/src/graph/kg/extraction/orchestrator.d.ts +6 -0
  266. package/dist/src/graph/kg/extraction/orchestrator.d.ts.map +1 -0
  267. package/dist/src/graph/kg/extraction/orchestrator.js +208 -0
  268. package/dist/src/graph/kg/extraction/orchestrator.js.map +1 -0
  269. package/dist/src/graph/kg/index.d.ts +29 -0
  270. package/dist/src/graph/kg/index.d.ts.map +1 -0
  271. package/dist/src/graph/kg/index.js +35 -0
  272. package/dist/src/graph/kg/index.js.map +1 -0
  273. package/dist/src/graph/kg/query/context-builder.d.ts +38 -0
  274. package/dist/src/graph/kg/query/context-builder.d.ts.map +1 -0
  275. package/dist/src/graph/kg/query/context-builder.js +184 -0
  276. package/dist/src/graph/kg/query/context-builder.js.map +1 -0
  277. package/dist/src/graph/kg/query/index.d.ts +8 -0
  278. package/dist/src/graph/kg/query/index.d.ts.map +1 -0
  279. package/dist/src/graph/kg/query/index.js +6 -0
  280. package/dist/src/graph/kg/query/index.js.map +1 -0
  281. package/dist/src/graph/kg/query/scoring.d.ts +19 -0
  282. package/dist/src/graph/kg/query/scoring.d.ts.map +1 -0
  283. package/dist/src/graph/kg/query/scoring.js +158 -0
  284. package/dist/src/graph/kg/query/scoring.js.map +1 -0
  285. package/dist/src/graph/kg/query/search.d.ts +59 -0
  286. package/dist/src/graph/kg/query/search.d.ts.map +1 -0
  287. package/dist/src/graph/kg/query/search.js +158 -0
  288. package/dist/src/graph/kg/query/search.js.map +1 -0
  289. package/dist/src/graph/kg/query/traversal.d.ts +75 -0
  290. package/dist/src/graph/kg/query/traversal.d.ts.map +1 -0
  291. package/dist/src/graph/kg/query/traversal.js +420 -0
  292. package/dist/src/graph/kg/query/traversal.js.map +1 -0
  293. package/dist/src/graph/kg/resolution/callback-synthesizer.d.ts +41 -0
  294. package/dist/src/graph/kg/resolution/callback-synthesizer.d.ts.map +1 -0
  295. package/dist/src/graph/kg/resolution/callback-synthesizer.js +450 -0
  296. package/dist/src/graph/kg/resolution/callback-synthesizer.js.map +1 -0
  297. package/dist/src/graph/kg/resolution/frameworks/index.d.ts +18 -0
  298. package/dist/src/graph/kg/resolution/frameworks/index.d.ts.map +1 -0
  299. package/dist/src/graph/kg/resolution/frameworks/index.js +632 -0
  300. package/dist/src/graph/kg/resolution/frameworks/index.js.map +1 -0
  301. package/dist/src/graph/kg/resolution/import-resolver.d.ts +73 -0
  302. package/dist/src/graph/kg/resolution/import-resolver.d.ts.map +1 -0
  303. package/dist/src/graph/kg/resolution/import-resolver.js +257 -0
  304. package/dist/src/graph/kg/resolution/import-resolver.js.map +1 -0
  305. package/dist/src/graph/kg/resolution/index.d.ts +11 -0
  306. package/dist/src/graph/kg/resolution/index.d.ts.map +1 -0
  307. package/dist/src/graph/kg/resolution/index.js +7 -0
  308. package/dist/src/graph/kg/resolution/index.js.map +1 -0
  309. package/dist/src/graph/kg/resolution/knowledge-resolver.d.ts +22 -0
  310. package/dist/src/graph/kg/resolution/knowledge-resolver.d.ts.map +1 -0
  311. package/dist/src/graph/kg/resolution/knowledge-resolver.js +288 -0
  312. package/dist/src/graph/kg/resolution/knowledge-resolver.js.map +1 -0
  313. package/dist/src/graph/kg/resolution/name-matcher.d.ts +25 -0
  314. package/dist/src/graph/kg/resolution/name-matcher.d.ts.map +1 -0
  315. package/dist/src/graph/kg/resolution/name-matcher.js +162 -0
  316. package/dist/src/graph/kg/resolution/name-matcher.js.map +1 -0
  317. package/dist/src/graph/kg/schema.sql +210 -0
  318. package/dist/src/graph/kg/surface/cli.d.ts +3 -0
  319. package/dist/src/graph/kg/surface/cli.d.ts.map +1 -0
  320. package/dist/src/graph/kg/surface/cli.js +500 -0
  321. package/dist/src/graph/kg/surface/cli.js.map +1 -0
  322. package/dist/src/graph/kg/surface/hook-injector.d.ts +33 -0
  323. package/dist/src/graph/kg/surface/hook-injector.d.ts.map +1 -0
  324. package/dist/src/graph/kg/surface/hook-injector.js +172 -0
  325. package/dist/src/graph/kg/surface/hook-injector.js.map +1 -0
  326. package/dist/src/graph/kg/surface/index.d.ts +6 -0
  327. package/dist/src/graph/kg/surface/index.d.ts.map +1 -0
  328. package/dist/src/graph/kg/surface/index.js +5 -0
  329. package/dist/src/graph/kg/surface/index.js.map +1 -0
  330. package/dist/src/graph/kg/surface/mcp-tools.d.ts +20 -0
  331. package/dist/src/graph/kg/surface/mcp-tools.d.ts.map +1 -0
  332. package/dist/src/graph/kg/surface/mcp-tools.js +253 -0
  333. package/dist/src/graph/kg/surface/mcp-tools.js.map +1 -0
  334. package/dist/src/graph/kg/sync/incremental-sync.d.ts +24 -0
  335. package/dist/src/graph/kg/sync/incremental-sync.d.ts.map +1 -0
  336. package/dist/src/graph/kg/sync/incremental-sync.js +71 -0
  337. package/dist/src/graph/kg/sync/incremental-sync.js.map +1 -0
  338. package/dist/src/graph/kg/sync/index.d.ts +5 -0
  339. package/dist/src/graph/kg/sync/index.d.ts.map +1 -0
  340. package/dist/src/graph/kg/sync/index.js +4 -0
  341. package/dist/src/graph/kg/sync/index.js.map +1 -0
  342. package/dist/src/graph/kg/sync/watch-policy.d.ts +33 -0
  343. package/dist/src/graph/kg/sync/watch-policy.d.ts.map +1 -0
  344. package/dist/src/graph/kg/sync/watch-policy.js +90 -0
  345. package/dist/src/graph/kg/sync/watch-policy.js.map +1 -0
  346. package/dist/src/hooks/constants.d.ts +0 -2
  347. package/dist/src/hooks/constants.d.ts.map +1 -1
  348. package/dist/src/hooks/constants.js +0 -2
  349. package/dist/src/hooks/constants.js.map +1 -1
  350. package/dist/src/hooks/keyword-spec-injector.d.ts +6 -0
  351. package/dist/src/hooks/keyword-spec-injector.d.ts.map +1 -1
  352. package/dist/src/hooks/keyword-spec-injector.js +157 -81
  353. package/dist/src/hooks/keyword-spec-injector.js.map +1 -1
  354. package/dist/src/hooks/kg-auto-init.d.ts +13 -0
  355. package/dist/src/hooks/kg-auto-init.d.ts.map +1 -0
  356. package/dist/src/hooks/kg-auto-init.js +38 -0
  357. package/dist/src/hooks/kg-auto-init.js.map +1 -0
  358. package/dist/src/hooks/kg-context-injector.d.ts +1 -3
  359. package/dist/src/hooks/kg-context-injector.d.ts.map +1 -1
  360. package/dist/src/hooks/kg-context-injector.js +12 -17
  361. package/dist/src/hooks/kg-context-injector.js.map +1 -1
  362. package/dist/src/hooks/kg-sync-hook.d.ts +1 -9
  363. package/dist/src/hooks/kg-sync-hook.d.ts.map +1 -1
  364. package/dist/src/hooks/kg-sync-hook.js +21 -90
  365. package/dist/src/hooks/kg-sync-hook.js.map +1 -1
  366. package/dist/src/hooks/spec-analytics.d.ts +1 -0
  367. package/dist/src/hooks/spec-analytics.d.ts.map +1 -1
  368. package/dist/src/hooks/spec-analytics.js +1 -3
  369. package/dist/src/hooks/spec-analytics.js.map +1 -1
  370. package/dist/src/hooks/spec-injector.d.ts.map +1 -1
  371. package/dist/src/hooks/spec-injector.js +65 -1
  372. package/dist/src/hooks/spec-injector.js.map +1 -1
  373. package/dist/src/i18n/locales/en.d.ts.map +1 -1
  374. package/dist/src/i18n/locales/en.js +52 -9
  375. package/dist/src/i18n/locales/en.js.map +1 -1
  376. package/dist/src/i18n/locales/zh.d.ts.map +1 -1
  377. package/dist/src/i18n/locales/zh.js +52 -9
  378. package/dist/src/i18n/locales/zh.js.map +1 -1
  379. package/dist/src/i18n/types.d.ts +40 -4
  380. package/dist/src/i18n/types.d.ts.map +1 -1
  381. package/dist/src/tools/__tests__/domain-search-debug.d.ts +2 -0
  382. package/dist/src/tools/__tests__/domain-search-debug.d.ts.map +1 -0
  383. package/dist/src/tools/__tests__/domain-search-debug.js +32 -0
  384. package/dist/src/tools/__tests__/domain-search-debug.js.map +1 -0
  385. package/dist/src/tools/domain-loader.d.ts +63 -0
  386. package/dist/src/tools/domain-loader.d.ts.map +1 -0
  387. package/dist/src/tools/domain-loader.js +295 -0
  388. package/dist/src/tools/domain-loader.js.map +1 -0
  389. package/dist/src/tools/domain-matcher.d.ts +24 -0
  390. package/dist/src/tools/domain-matcher.d.ts.map +1 -0
  391. package/dist/src/tools/domain-matcher.js +117 -0
  392. package/dist/src/tools/domain-matcher.js.map +1 -0
  393. package/dist/src/tools/domain-scanner.d.ts +32 -0
  394. package/dist/src/tools/domain-scanner.d.ts.map +1 -0
  395. package/dist/src/tools/domain-scanner.js +263 -0
  396. package/dist/src/tools/domain-scanner.js.map +1 -0
  397. package/dist/src/tools/domain-schema.d.ts +18 -0
  398. package/dist/src/tools/domain-schema.d.ts.map +1 -0
  399. package/dist/src/tools/domain-schema.js +104 -0
  400. package/dist/src/tools/domain-schema.js.map +1 -0
  401. package/dist/src/tools/spec-entry-parser.d.ts +1 -0
  402. package/dist/src/tools/spec-entry-parser.d.ts.map +1 -1
  403. package/dist/src/tools/spec-entry-parser.js +1 -0
  404. package/dist/src/tools/spec-entry-parser.js.map +1 -1
  405. package/dist/src/tools/spec-loader.d.ts +5 -0
  406. package/dist/src/tools/spec-loader.d.ts.map +1 -1
  407. package/dist/src/tools/spec-loader.js +10 -2
  408. package/dist/src/tools/spec-loader.js.map +1 -1
  409. package/dist/src/tui/install-ui/ConfigPanel.d.ts.map +1 -1
  410. package/dist/src/tui/install-ui/ConfigPanel.js +9 -1
  411. package/dist/src/tui/install-ui/ConfigPanel.js.map +1 -1
  412. package/dist/src/tui/install-ui/GroupedHub.d.ts +55 -0
  413. package/dist/src/tui/install-ui/GroupedHub.d.ts.map +1 -0
  414. package/dist/src/tui/install-ui/GroupedHub.js +210 -0
  415. package/dist/src/tui/install-ui/GroupedHub.js.map +1 -0
  416. package/dist/src/tui/install-ui/HooksConfig.d.ts +10 -5
  417. package/dist/src/tui/install-ui/HooksConfig.d.ts.map +1 -1
  418. package/dist/src/tui/install-ui/HooksConfig.js +83 -18
  419. package/dist/src/tui/install-ui/HooksConfig.js.map +1 -1
  420. package/dist/src/tui/install-ui/InstallConfirm.d.ts +1 -30
  421. package/dist/src/tui/install-ui/InstallConfirm.d.ts.map +1 -1
  422. package/dist/src/tui/install-ui/InstallConfirm.js +72 -12
  423. package/dist/src/tui/install-ui/InstallConfirm.js.map +1 -1
  424. package/dist/src/tui/install-ui/InstallExecution.d.ts +4 -21
  425. package/dist/src/tui/install-ui/InstallExecution.d.ts.map +1 -1
  426. package/dist/src/tui/install-ui/InstallExecution.js +89 -260
  427. package/dist/src/tui/install-ui/InstallExecution.js.map +1 -1
  428. package/dist/src/tui/install-ui/InstallFlow.d.ts +3 -7
  429. package/dist/src/tui/install-ui/InstallFlow.d.ts.map +1 -1
  430. package/dist/src/tui/install-ui/InstallFlow.js +45 -267
  431. package/dist/src/tui/install-ui/InstallFlow.js.map +1 -1
  432. package/dist/src/tui/install-ui/InstallHub.d.ts.map +1 -1
  433. package/dist/src/tui/install-ui/InstallHub.js +2 -4
  434. package/dist/src/tui/install-ui/InstallHub.js.map +1 -1
  435. package/dist/src/tui/install-ui/InstallResult.d.ts.map +1 -1
  436. package/dist/src/tui/install-ui/InstallResult.js +1 -5
  437. package/dist/src/tui/install-ui/InstallResult.js.map +1 -1
  438. package/dist/src/tui/install-ui/index.d.ts +5 -1
  439. package/dist/src/tui/install-ui/index.d.ts.map +1 -1
  440. package/dist/src/tui/install-ui/index.js +1 -0
  441. package/dist/src/tui/install-ui/index.js.map +1 -1
  442. package/dist/src/tui/install-ui/types.d.ts +39 -0
  443. package/dist/src/tui/install-ui/types.d.ts.map +1 -1
  444. package/dist/src/tui/install-ui/types.js +1 -1
  445. package/dist/src/tui/install-ui/types.js.map +1 -1
  446. package/dist/src/tui/install-ui/useInstallFlowState.d.ts +69 -0
  447. package/dist/src/tui/install-ui/useInstallFlowState.d.ts.map +1 -0
  448. package/dist/src/tui/install-ui/useInstallFlowState.js +288 -0
  449. package/dist/src/tui/install-ui/useInstallFlowState.js.map +1 -0
  450. package/dist/src/tui/shared/components.d.ts +4 -0
  451. package/dist/src/tui/shared/components.d.ts.map +1 -1
  452. package/dist/src/tui/shared/components.js +4 -0
  453. package/dist/src/tui/shared/components.js.map +1 -1
  454. package/dist/src/tui/shared/index.d.ts +1 -1
  455. package/dist/src/tui/shared/index.d.ts.map +1 -1
  456. package/dist/src/tui/shared/index.js +1 -1
  457. package/dist/src/tui/shared/index.js.map +1 -1
  458. package/dist/src/tui/shared/tokens.d.ts +5 -5
  459. package/dist/src/tui/shared/tokens.js +5 -5
  460. package/dist/src/tui/shared/tokens.js.map +1 -1
  461. package/dist/src/types/index.d.ts +9 -0
  462. package/dist/src/types/index.d.ts.map +1 -1
  463. package/dist/src/utils/cli-format.d.ts +2 -1
  464. package/dist/src/utils/cli-format.d.ts.map +1 -1
  465. package/dist/src/utils/cli-format.js +14 -3
  466. package/dist/src/utils/cli-format.js.map +1 -1
  467. package/dist/src/utils/cooldown-guard.d.ts +17 -0
  468. package/dist/src/utils/cooldown-guard.d.ts.map +1 -0
  469. package/dist/src/utils/cooldown-guard.js +59 -0
  470. package/dist/src/utils/cooldown-guard.js.map +1 -0
  471. package/dist/src/utils/jsonl-log.d.ts.map +1 -1
  472. package/dist/src/utils/jsonl-log.js +2 -1
  473. package/dist/src/utils/jsonl-log.js.map +1 -1
  474. package/dist/src/utils/update-notices.js +17 -4
  475. package/dist/src/utils/update-notices.js.map +1 -1
  476. package/package.json +4 -5
  477. package/workflows/claude-instructions.md +23 -0
  478. package/workflows/codex-instructions.md +22 -0
  479. package/workflows/finish-work.md +25 -0
  480. package/workflows/updates/update-v3-setup.md +7 -15
  481. package/dashboard/dist/assets/McpPage-Im6s4pGR.js +0 -21
  482. package/dashboard/dist/assets/SpecsPage-gr4KX51-.js +0 -36
  483. package/dashboard/dist/assets/folder-B8ODoZfb.js +0 -16
  484. package/dashboard/dist/assets/index-6-yE5Yl9.css +0 -1
  485. package/dashboard/dist/assets/pen-line-CR8GaHt-.js +0 -6
@@ -21,41 +21,153 @@ import { buildInvertedIndex, searchBM25 } from './search.js';
21
21
  */
22
22
  export class WikiIndexer {
23
23
  workflowRoot;
24
+ linkedWorkspaces;
24
25
  cache = null;
25
26
  graphCache = null;
26
27
  searchCache = null;
27
28
  inflight = null;
29
+ mtimeSnapshot = new Map();
28
30
  constructor(config) {
29
31
  this.workflowRoot = resolve(config.workflowRoot);
32
+ this.linkedWorkspaces = (config.linkedWorkspaces ?? []).map(lw => ({
33
+ name: lw.name,
34
+ workflowRoot: resolve(lw.workflowRoot),
35
+ shareTypes: new Set(lw.shareTypes),
36
+ }));
30
37
  }
31
38
  getWorkflowRoot() {
32
39
  return this.workflowRoot;
33
40
  }
34
41
  async get() {
35
- if (this.cache)
36
- return this.cache;
42
+ if (this.cache) {
43
+ if (!await this.hasSourceChanges())
44
+ return this.cache;
45
+ this.cache = null;
46
+ this.graphCache = null;
47
+ this.searchCache = null;
48
+ }
37
49
  return this.rebuild();
38
50
  }
51
+ /**
52
+ * Quick mtime scan of known source directories. If any file's mtime
53
+ * changed since the last rebuild, the cache is stale.
54
+ */
55
+ async hasSourceChanges() {
56
+ if (this.mtimeSnapshot.size === 0)
57
+ return true;
58
+ const dirs = [
59
+ join(this.workflowRoot, 'specs'),
60
+ join(this.workflowRoot, 'knowhow'),
61
+ join(this.workflowRoot, 'issues'),
62
+ join(this.workflowRoot, 'domain'),
63
+ join(this.workflowRoot, 'scratch'),
64
+ ];
65
+ // Include linked workspace directories in staleness check
66
+ for (const lw of this.linkedWorkspaces) {
67
+ if (lw.shareTypes.has('spec'))
68
+ dirs.push(join(lw.workflowRoot, 'specs'));
69
+ if (lw.shareTypes.has('knowhow'))
70
+ dirs.push(join(lw.workflowRoot, 'knowhow'));
71
+ if (lw.shareTypes.has('domain'))
72
+ dirs.push(join(lw.workflowRoot, 'domain'));
73
+ if (lw.shareTypes.has('codebase'))
74
+ dirs.push(join(lw.workflowRoot, 'codebase'));
75
+ }
76
+ const singletons = ['project.md', 'roadmap.md'];
77
+ for (const s of singletons) {
78
+ const p = join(this.workflowRoot, s);
79
+ try {
80
+ const st = await stat(p);
81
+ const prev = this.mtimeSnapshot.get(p);
82
+ if (prev === undefined || st.mtimeMs !== prev)
83
+ return true;
84
+ }
85
+ catch {
86
+ if (this.mtimeSnapshot.has(p))
87
+ return true;
88
+ }
89
+ }
90
+ for (const dir of dirs) {
91
+ try {
92
+ const st = await stat(dir);
93
+ const prev = this.mtimeSnapshot.get(dir);
94
+ if (prev === undefined || st.mtimeMs !== prev)
95
+ return true;
96
+ }
97
+ catch {
98
+ if (this.mtimeSnapshot.has(dir))
99
+ return true;
100
+ }
101
+ }
102
+ return false;
103
+ }
104
+ async captureMtimeSnapshot() {
105
+ const snap = new Map();
106
+ const dirs = [
107
+ join(this.workflowRoot, 'specs'),
108
+ join(this.workflowRoot, 'knowhow'),
109
+ join(this.workflowRoot, 'issues'),
110
+ join(this.workflowRoot, 'domain'),
111
+ join(this.workflowRoot, 'scratch'),
112
+ ];
113
+ for (const lw of this.linkedWorkspaces) {
114
+ if (lw.shareTypes.has('spec'))
115
+ dirs.push(join(lw.workflowRoot, 'specs'));
116
+ if (lw.shareTypes.has('knowhow'))
117
+ dirs.push(join(lw.workflowRoot, 'knowhow'));
118
+ if (lw.shareTypes.has('domain'))
119
+ dirs.push(join(lw.workflowRoot, 'domain'));
120
+ if (lw.shareTypes.has('codebase'))
121
+ dirs.push(join(lw.workflowRoot, 'codebase'));
122
+ }
123
+ const singletons = ['project.md', 'roadmap.md'];
124
+ for (const s of singletons) {
125
+ const p = join(this.workflowRoot, s);
126
+ try {
127
+ snap.set(p, (await stat(p)).mtimeMs);
128
+ }
129
+ catch { /* missing is fine */ }
130
+ }
131
+ for (const dir of dirs) {
132
+ try {
133
+ snap.set(dir, (await stat(dir)).mtimeMs);
134
+ }
135
+ catch { /* missing */ }
136
+ }
137
+ return snap;
138
+ }
39
139
  async rebuild() {
40
140
  if (this.inflight)
41
141
  return this.inflight;
42
142
  this.inflight = (async () => {
43
143
  const fileEntries = await this.scanFiles();
44
144
  const virtualEntries = await this.scanVirtual();
45
- const entries = [...fileEntries, ...virtualEntries];
145
+ const linkedEntries = await this.scanLinkedWorkspaces();
146
+ const entries = [...fileEntries, ...virtualEntries, ...linkedEntries];
46
147
  // Stable collision suffix — use original id for counting so the
47
148
  // third duplicate becomes -3 (not another -2).
149
+ // Collisions are expected across multi-source JSONL files; warn only
150
+ // when MAESTRO_DEBUG is set to avoid polluting CLI search output.
48
151
  const seen = new Map();
152
+ const debugCollisions = process.env.MAESTRO_DEBUG === '1';
153
+ let collisionCount = 0;
49
154
  for (const d of entries) {
50
155
  const original = d.id;
51
156
  const n = seen.get(original) ?? 0;
52
157
  if (n > 0) {
53
- // eslint-disable-next-line no-console
54
- console.warn(`[wiki-indexer] id collision '${original}' — suffixing`);
158
+ if (debugCollisions) {
159
+ // eslint-disable-next-line no-console
160
+ console.warn(`[wiki-indexer] id collision '${original}' — suffixing to ${original}-${n + 1}`);
161
+ }
55
162
  d.id = `${original}-${n + 1}`;
163
+ collisionCount++;
56
164
  }
57
165
  seen.set(original, n + 1);
58
166
  }
167
+ if (collisionCount > 0 && debugCollisions) {
168
+ // eslint-disable-next-line no-console
169
+ console.warn(`[wiki-indexer] ${collisionCount} id collision(s) resolved by suffixing`);
170
+ }
59
171
  const byId = {};
60
172
  const byType = {
61
173
  project: [],
@@ -64,6 +176,7 @@ export class WikiIndexer {
64
176
  issue: [],
65
177
  knowhow: [],
66
178
  note: [],
179
+ domain: [],
67
180
  };
68
181
  for (const d of entries) {
69
182
  byId[d.id] = d;
@@ -80,6 +193,8 @@ export class WikiIndexer {
80
193
  this.cache = index;
81
194
  this.graphCache = null;
82
195
  this.searchCache = null;
196
+ // Snapshot mtimes of source directories for incremental staleness check
197
+ this.mtimeSnapshot = await this.captureMtimeSnapshot();
83
198
  // Persist lightweight index to disk (fire-and-forget).
84
199
  this.persistIndex(index).catch(() => { });
85
200
  return index;
@@ -122,6 +237,7 @@ export class WikiIndexer {
122
237
  issue: [],
123
238
  knowhow: [],
124
239
  note: [],
240
+ domain: [],
125
241
  };
126
242
  for (const d of source)
127
243
  out[d.type].push(d);
@@ -141,13 +257,20 @@ export class WikiIndexer {
141
257
  this.searchCache = buildInvertedIndex(index.entries);
142
258
  return this.searchCache;
143
259
  }
144
- async search(query, limit = 50) {
260
+ async searchWithScores(query, limit = 50) {
145
261
  const index = await this.get();
146
262
  const bm25 = await this.getSearchIndex();
147
263
  const ranked = searchBM25(bm25, query, limit);
148
- return ranked
149
- .map((r) => index.byId[r.docId])
150
- .filter((d) => Boolean(d));
264
+ const out = [];
265
+ for (const r of ranked) {
266
+ const entry = index.byId[r.docId];
267
+ if (entry)
268
+ out.push({ entry, score: r.score });
269
+ }
270
+ return out;
271
+ }
272
+ async search(query, limit = 50) {
273
+ return (await this.searchWithScores(query, limit)).map(r => r.entry);
151
274
  }
152
275
  // -------------------------------------------------------------------------
153
276
  // Walk
@@ -214,11 +337,9 @@ export class WikiIndexer {
214
337
  }
215
338
  }
216
339
  }
217
- // knowhow/*.md (KNW-→session, TIP-→tip, TPL-→template, RCP-→recipe, REF-→reference, DCS-→decision, DOC-→document)
218
- for (const name of await safeReaddir(join(this.workflowRoot, 'knowhow'))) {
219
- if (extname(name).toLowerCase() !== '.md')
220
- continue;
221
- const entry = await this.parseFileEntry(join(this.workflowRoot, 'knowhow', name), 'knowhow');
340
+ // knowhow/*.md recursive scan supports both flat and sub-folder layouts
341
+ const knowhowEntries = await this.scanKnowhowDir(join(this.workflowRoot, 'knowhow'));
342
+ for (const { name, absPath, entry } of knowhowEntries) {
222
343
  if (entry) {
223
344
  // Only derive category from file prefix if no frontmatter category
224
345
  if (!entry.category) {
@@ -278,8 +399,139 @@ export class WikiIndexer {
278
399
  }
279
400
  }
280
401
  }
402
+ // domain/glossary.json → domain WikiEntries
403
+ const domainEntries = await this.scanDomain();
404
+ out.push(...domainEntries);
405
+ // scratch/*/*.md — session working documents (lowest search priority via SCRATCH_FIELD_CONFIGS)
406
+ const scratchEntries = await this.scanScratchDocuments();
407
+ out.push(...scratchEntries);
408
+ return out;
409
+ }
410
+ /**
411
+ * Recursively scan knowhow directory (supports both flat and sub-folder layouts).
412
+ */
413
+ async scanKnowhowDir(dir) {
414
+ const results = [];
415
+ for (const name of await safeReaddir(dir)) {
416
+ const fullPath = join(dir, name);
417
+ let stats = null;
418
+ try {
419
+ stats = await stat(fullPath);
420
+ }
421
+ catch {
422
+ continue;
423
+ }
424
+ if (stats.isDirectory()) {
425
+ const nested = await this.scanKnowhowDir(fullPath);
426
+ results.push(...nested);
427
+ }
428
+ else if (stats.isFile() && extname(name).toLowerCase() === '.md') {
429
+ const entry = await this.parseFileEntry(fullPath, 'knowhow');
430
+ results.push({ name, absPath: fullPath, entry });
431
+ }
432
+ }
433
+ return results;
434
+ }
435
+ /**
436
+ * Scan .workflow/scratch session directories for .md working documents.
437
+ * These are indexed as 'note' type with ext.virtualKind='scratch-doc'
438
+ * so search.ts applies SCRATCH_FIELD_CONFIGS (lowest BM25 weight).
439
+ */
440
+ async scanScratchDocuments() {
441
+ const scratchRoot = join(this.workflowRoot, 'scratch');
442
+ if (!existsSync(scratchRoot))
443
+ return [];
444
+ const out = [];
445
+ for (const sessionName of await safeReaddir(scratchRoot)) {
446
+ const sessionDir = join(scratchRoot, sessionName);
447
+ let dirStat = null;
448
+ try {
449
+ dirStat = await stat(sessionDir);
450
+ }
451
+ catch {
452
+ continue;
453
+ }
454
+ if (!dirStat.isDirectory())
455
+ continue;
456
+ for (const fileName of await safeReaddir(sessionDir)) {
457
+ if (extname(fileName).toLowerCase() !== '.md')
458
+ continue;
459
+ const absPath = join(sessionDir, fileName);
460
+ const entry = await this.parseFileEntry(absPath, 'note');
461
+ if (!entry)
462
+ continue;
463
+ const stem = basename(fileName, extname(fileName));
464
+ entry.id = `scratch-${slugify(sessionName)}-${slugify(stem)}`;
465
+ entry.ext = { ...entry.ext, virtualKind: 'scratch-doc', sessionDir: sessionName };
466
+ entry.category = entry.category || 'scratch';
467
+ out.push(entry);
468
+ }
469
+ }
281
470
  return out;
282
471
  }
472
+ /**
473
+ * Scan .workflow/domain/glossary.json and produce WikiEntry[] for each term.
474
+ */
475
+ async scanDomain() {
476
+ const glossaryPath = join(this.workflowRoot, 'domain', 'glossary.json');
477
+ try {
478
+ const raw = await readFile(glossaryPath, 'utf-8');
479
+ const glossary = JSON.parse(raw);
480
+ if (!Array.isArray(glossary.terms))
481
+ return [];
482
+ const now = new Date().toISOString();
483
+ let glossaryStat;
484
+ try {
485
+ glossaryStat = await stat(glossaryPath);
486
+ }
487
+ catch {
488
+ return [];
489
+ }
490
+ const fileDate = new Date(glossaryStat.mtimeMs).toISOString();
491
+ return glossary.terms.map((term) => {
492
+ const id = term.id;
493
+ const canonical = term.canonical;
494
+ const definition = term.definition ?? '';
495
+ const aliases = term.aliases ?? [];
496
+ const keywords = term.keywords ?? [];
497
+ const relationships = term.relationships ?? [];
498
+ const status = (term.status ?? 'active') === 'active' ? 'active' : 'archived';
499
+ const bodyLines = [`# ${canonical}`, '', definition, ''];
500
+ if (aliases.length)
501
+ bodyLines.push(`Aliases: ${aliases.join(', ')}`);
502
+ if (relationships.length)
503
+ bodyLines.push(`Related: ${relationships.join(', ')}`);
504
+ if (keywords.length)
505
+ bodyLines.push(`Keywords: ${keywords.join(', ')}`);
506
+ return {
507
+ id: `domain-${id}`,
508
+ type: 'domain',
509
+ title: canonical,
510
+ summary: definition,
511
+ tags: [...aliases, ...keywords],
512
+ status: status,
513
+ created: fileDate,
514
+ updated: fileDate,
515
+ related: relationships.map(r => `domain-${r}`),
516
+ source: { kind: 'file', path: 'domain/glossary.json' },
517
+ body: bodyLines.join('\n'),
518
+ ext: {
519
+ tier: term.tier ?? 'core',
520
+ sourceKind: term.source?.kind ?? 'unknown',
521
+ },
522
+ scope: null,
523
+ category: 'domain',
524
+ specCategory: null,
525
+ createdBy: null,
526
+ sourceRef: null,
527
+ parent: null,
528
+ };
529
+ });
530
+ }
531
+ catch {
532
+ return [];
533
+ }
534
+ }
283
535
  /**
284
536
  * Resolve spec directories for all scopes that exist on disk.
285
537
  * Returns entries with scoped ID prefix and source path prefix.
@@ -341,6 +593,11 @@ export class WikiIndexer {
341
593
  }
342
594
  async scanVirtual() {
343
595
  const out = [];
596
+ // Issues: collect from all JSONL files, then deduplicate by ID keeping the
597
+ // entry with the most recent updated timestamp. This avoids collision
598
+ // warnings when the same issue ID appears across multiple JSONL sources
599
+ // (e.g. issues.jsonl and review-issues.jsonl).
600
+ const allIssues = [];
344
601
  for (const name of await safeReaddir(join(this.workflowRoot, 'issues'))) {
345
602
  if (extname(name).toLowerCase() !== '.jsonl')
346
603
  continue;
@@ -348,8 +605,16 @@ export class WikiIndexer {
348
605
  if (!this.isInsideRoot(abs))
349
606
  continue;
350
607
  const rel = toForwardSlash(relative(this.workflowRoot, abs));
351
- out.push(...(await loadVirtualEntries(abs, adaptIssueRow, rel)));
608
+ allIssues.push(...(await loadVirtualEntries(abs, adaptIssueRow, rel)));
352
609
  }
610
+ const issueBest = new Map();
611
+ for (const e of allIssues) {
612
+ const existing = issueBest.get(e.id);
613
+ if (!existing || e.updated > existing.updated) {
614
+ issueBest.set(e.id, e);
615
+ }
616
+ }
617
+ out.push(...issueBest.values());
353
618
  // Codebase: .workflow/codebase/doc-index.json → component/feature/req/ADR
354
619
  const codebaseIndex = join(this.workflowRoot, 'codebase', 'doc-index.json');
355
620
  if (existsSync(codebaseIndex) && this.isInsideRoot(codebaseIndex)) {
@@ -395,6 +660,279 @@ export class WikiIndexer {
395
660
  }
396
661
  return out;
397
662
  }
663
+ // -------------------------------------------------------------------------
664
+ // Linked workspace scanning
665
+ // -------------------------------------------------------------------------
666
+ async scanLinkedWorkspaces() {
667
+ const out = [];
668
+ for (const lw of this.linkedWorkspaces) {
669
+ if (!existsSync(lw.workflowRoot)) {
670
+ if (process.env.MAESTRO_DEBUG === '1') {
671
+ // eslint-disable-next-line no-console
672
+ console.warn(`[wiki-indexer] linked workspace "${lw.name}" not found: ${lw.workflowRoot}`);
673
+ }
674
+ continue;
675
+ }
676
+ const entries = await this.scanLinkedWorkspace(lw);
677
+ out.push(...entries);
678
+ }
679
+ return out;
680
+ }
681
+ async scanLinkedWorkspace(lw) {
682
+ const out = [];
683
+ const idPrefix = `ws:${lw.name}:`;
684
+ if (lw.shareTypes.has('spec')) {
685
+ const specsDir = join(lw.workflowRoot, 'specs');
686
+ for (const name of await safeReaddir(specsDir)) {
687
+ if (extname(name).toLowerCase() !== '.md')
688
+ continue;
689
+ const absPath = join(specsDir, name);
690
+ const entry = await this.parseLinkedFileEntry(absPath, 'spec', lw.name, lw.workflowRoot);
691
+ if (!entry)
692
+ continue;
693
+ const stem = basename(name, extname(name));
694
+ entry.id = `${idPrefix}spec:${slugify(stem)}`;
695
+ entry.scope = 'linked';
696
+ entry.source = { kind: 'file', path: `specs/${name}`, workspace: lw.name };
697
+ out.push(entry);
698
+ const specEntries = parseSpecEntries(entry.body, name, {
699
+ category: entry.category ?? undefined,
700
+ keywords: entry.tags,
701
+ });
702
+ for (const se of specEntries) {
703
+ out.push({
704
+ id: `${idPrefix}spec:${se.id}`,
705
+ type: 'spec',
706
+ title: se.title,
707
+ summary: se.description || se.content.slice(0, 240).replace(/\s+/g, ' '),
708
+ tags: se.keywords,
709
+ status: 'active',
710
+ created: entry.created,
711
+ updated: entry.updated,
712
+ related: [],
713
+ source: { kind: 'file', path: `specs/${name}`, workspace: lw.name },
714
+ body: se.content,
715
+ ext: { entryType: se.type, timestamp: se.timestamp },
716
+ scope: 'linked',
717
+ category: se.category || entry.category,
718
+ specCategory: entry.specCategory,
719
+ createdBy: entry.createdBy,
720
+ sourceRef: entry.sourceRef,
721
+ parent: entry.id,
722
+ });
723
+ }
724
+ }
725
+ }
726
+ if (lw.shareTypes.has('knowhow')) {
727
+ const knowhowDir = join(lw.workflowRoot, 'knowhow');
728
+ const knowhowFiles = await this.scanLinkedKnowhowDir(knowhowDir, lw.name, lw.workflowRoot);
729
+ for (const { entry } of knowhowFiles) {
730
+ if (!entry)
731
+ continue;
732
+ entry.id = `${idPrefix}${entry.id}`;
733
+ entry.scope = 'linked';
734
+ out.push(entry);
735
+ }
736
+ }
737
+ if (lw.shareTypes.has('domain')) {
738
+ const domainEntries = await this.scanLinkedDomain(lw.workflowRoot, lw.name);
739
+ for (const e of domainEntries) {
740
+ e.id = `${idPrefix}${e.id}`;
741
+ out.push(e);
742
+ }
743
+ }
744
+ if (lw.shareTypes.has('codebase')) {
745
+ const codebaseIndex = join(lw.workflowRoot, 'codebase', 'doc-index.json');
746
+ if (existsSync(codebaseIndex)) {
747
+ const rel = `codebase/doc-index.json`;
748
+ const entries = await loadVirtualJsonEntries(codebaseIndex, adaptCodebaseDocIndex, rel);
749
+ for (const e of entries) {
750
+ e.id = `${idPrefix}${e.id}`;
751
+ e.source = { ...e.source, workspace: lw.name };
752
+ e.scope = 'linked';
753
+ out.push(e);
754
+ }
755
+ }
756
+ const kgPath = join(lw.workflowRoot, 'codebase', 'knowledge-graph.json');
757
+ if (existsSync(kgPath)) {
758
+ const kgRel = `codebase/knowledge-graph.json`;
759
+ const kgEntries = await loadVirtualJsonEntries(kgPath, adaptKnowledgeGraph, kgRel);
760
+ for (const e of kgEntries) {
761
+ e.id = `${idPrefix}${e.id}`;
762
+ e.source = { ...e.source, workspace: lw.name };
763
+ e.scope = 'linked';
764
+ out.push(e);
765
+ }
766
+ }
767
+ }
768
+ return out;
769
+ }
770
+ async parseLinkedFileEntry(absPath, type, wsName, wsWorkflowRoot) {
771
+ const requested = resolve(absPath);
772
+ const root = resolve(wsWorkflowRoot);
773
+ if (!requested.startsWith(root + sep) && requested !== root)
774
+ return null;
775
+ try {
776
+ const ls = await lstat(absPath);
777
+ if (ls.isSymbolicLink() || !ls.isFile())
778
+ return null;
779
+ }
780
+ catch {
781
+ return null;
782
+ }
783
+ let raw;
784
+ let stats;
785
+ try {
786
+ raw = await readFile(absPath, 'utf-8');
787
+ stats = await stat(absPath);
788
+ }
789
+ catch {
790
+ return null;
791
+ }
792
+ const { data, content } = parseFrontmatter(raw);
793
+ const fileName = basename(absPath);
794
+ const stem = basename(fileName, extname(fileName));
795
+ const title = asString(data.title) || firstHeading(content) || stem;
796
+ const summary = asString(data.description) || asString(data.summary) || firstParagraph(content);
797
+ const tags = extractTags(data);
798
+ const status = asStatus(data.status) ?? inferStatus(type);
799
+ const related = normalizeRelated(data.related);
800
+ const ext = extractExt(data);
801
+ const category = asString(data.category) || null;
802
+ const specCategory = asString(data.specCategory) || null;
803
+ const createdBy = asString(data.createdBy) || null;
804
+ const sourceRef = asString(data.sourceRef) || null;
805
+ const parent = asString(data.parent) || null;
806
+ const rel = toForwardSlash(relative(wsWorkflowRoot, absPath));
807
+ const id = `${type}-${slugify(stem)}`;
808
+ return {
809
+ id,
810
+ type,
811
+ title,
812
+ summary,
813
+ tags,
814
+ status,
815
+ created: new Date(stats.birthtimeMs || stats.mtimeMs).toISOString(),
816
+ updated: new Date(stats.mtimeMs).toISOString(),
817
+ related,
818
+ source: { kind: 'file', path: rel, workspace: wsName },
819
+ body: content,
820
+ ext,
821
+ scope: 'linked',
822
+ category,
823
+ specCategory,
824
+ createdBy,
825
+ sourceRef,
826
+ parent,
827
+ };
828
+ }
829
+ async scanLinkedKnowhowDir(dir, wsName, wsWorkflowRoot) {
830
+ const results = [];
831
+ for (const name of await safeReaddir(dir)) {
832
+ const fullPath = join(dir, name);
833
+ let stats = null;
834
+ try {
835
+ stats = await stat(fullPath);
836
+ }
837
+ catch {
838
+ continue;
839
+ }
840
+ if (stats.isDirectory()) {
841
+ const nested = await this.scanLinkedKnowhowDir(fullPath, wsName, wsWorkflowRoot);
842
+ results.push(...nested);
843
+ }
844
+ else if (stats.isFile() && extname(name).toLowerCase() === '.md') {
845
+ const entry = await this.parseLinkedFileEntry(fullPath, 'knowhow', wsName, wsWorkflowRoot);
846
+ if (entry) {
847
+ if (!entry.category) {
848
+ const upper = name.toUpperCase();
849
+ if (upper.startsWith('KNW-'))
850
+ entry.category = 'session';
851
+ else if (upper.startsWith('TPL-'))
852
+ entry.category = 'template';
853
+ else if (upper.startsWith('RCP-'))
854
+ entry.category = 'recipe';
855
+ else if (upper.startsWith('REF-'))
856
+ entry.category = 'reference';
857
+ else if (upper.startsWith('DCS-'))
858
+ entry.category = 'decision';
859
+ else if (upper.startsWith('TIP-'))
860
+ entry.category = 'tip';
861
+ else if (upper.startsWith('AST-'))
862
+ entry.category = 'asset';
863
+ else if (upper.startsWith('BLP-'))
864
+ entry.category = 'blueprint';
865
+ else if (upper.startsWith('DOC-'))
866
+ entry.category = 'document';
867
+ }
868
+ }
869
+ results.push({ entry });
870
+ }
871
+ }
872
+ return results;
873
+ }
874
+ async scanLinkedDomain(wsWorkflowRoot, wsName) {
875
+ const glossaryPath = join(wsWorkflowRoot, 'domain', 'glossary.json');
876
+ try {
877
+ const raw = await readFile(glossaryPath, 'utf-8');
878
+ const glossary = JSON.parse(raw);
879
+ if (!Array.isArray(glossary.terms))
880
+ return [];
881
+ let glossaryStat;
882
+ try {
883
+ glossaryStat = await stat(glossaryPath);
884
+ }
885
+ catch {
886
+ return [];
887
+ }
888
+ const fileDate = new Date(glossaryStat.mtimeMs).toISOString();
889
+ return glossary.terms.map((term) => {
890
+ const id = term.id;
891
+ const canonical = term.canonical;
892
+ const definition = term.definition ?? '';
893
+ const aliases = term.aliases ?? [];
894
+ const keywords = term.keywords ?? [];
895
+ const relationships = term.relationships ?? [];
896
+ const status = (term.status ?? 'active') === 'active' ? 'active' : 'archived';
897
+ const bodyLines = [`# ${canonical}`, '', definition, ''];
898
+ if (aliases.length)
899
+ bodyLines.push(`Aliases: ${aliases.join(', ')}`);
900
+ if (relationships.length)
901
+ bodyLines.push(`Related: ${relationships.join(', ')}`);
902
+ if (keywords.length)
903
+ bodyLines.push(`Keywords: ${keywords.join(', ')}`);
904
+ return {
905
+ id: `domain-${id}`,
906
+ type: 'domain',
907
+ title: canonical,
908
+ summary: definition,
909
+ tags: [...aliases, ...keywords],
910
+ status: status,
911
+ created: fileDate,
912
+ updated: fileDate,
913
+ related: relationships.map(r => `domain-${r}`),
914
+ source: { kind: 'file', path: 'domain/glossary.json', workspace: wsName },
915
+ body: bodyLines.join('\n'),
916
+ ext: {
917
+ tier: term.tier ?? 'core',
918
+ sourceKind: term.source?.kind ?? 'unknown',
919
+ },
920
+ scope: 'linked',
921
+ category: 'domain',
922
+ specCategory: null,
923
+ createdBy: null,
924
+ sourceRef: null,
925
+ parent: null,
926
+ };
927
+ });
928
+ }
929
+ catch {
930
+ return [];
931
+ }
932
+ }
933
+ // -------------------------------------------------------------------------
934
+ // File parsing
935
+ // -------------------------------------------------------------------------
398
936
  async parseFileEntry(absPath, type) {
399
937
  if (!this.isInsideRoot(absPath))
400
938
  return null;
@@ -433,13 +971,11 @@ export class WikiIndexer {
433
971
  const sourceRef = asString(data.sourceRef) || null;
434
972
  const parent = asString(data.parent) || null;
435
973
  const rel = toForwardSlash(relative(this.workflowRoot, absPath));
436
- // Knowhow files live under knowhow/ with prefix-<slug>.md naming.
437
- // Strip the 4-char prefix (KNW-/TIP-/TPL-/RCP-/REF-/DCS-/AST-/BLP-) from the id-generating
438
- // stem so the id matches what WikiWriter produced at create time (`knowhow-<slug>`).
439
- let idStem = stem;
440
- if (/^(KNW|TIP|TPL|RCP|REF|DCS|AST|BLP|DOC)-/i.test(stem))
441
- idStem = stem.slice(4);
442
- const id = `${type}-${slugify(idStem)}`;
974
+ // Knowhow files use prefix-<slug>.md naming (KNW-, TIP-, TPL-, etc.).
975
+ // Keep the full stem (including prefix) to avoid collisions when multiple
976
+ // prefixed files share the same timestamp slug (e.g. KNW-20260427-1912 vs
977
+ // DCS-20260427-1912 both slugifying to the same value).
978
+ const id = `${type}-${slugify(stem)}`;
443
979
  return {
444
980
  id,
445
981
  type,
@@ -623,6 +1159,8 @@ export function filterEntries(entries, filters) {
623
1159
  return false;
624
1160
  if (filters.tool && d.ext?.tool !== true && d.ext?.tool !== 'true')
625
1161
  return false;
1162
+ if (filters.workspace && d.source.workspace !== filters.workspace)
1163
+ return false;
626
1164
  if (filters.q) {
627
1165
  const q = filters.q.toLowerCase();
628
1166
  if (!d.title.toLowerCase().includes(q) && !d.summary.toLowerCase().includes(q)) {