@inharness-ai/claude4spec 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (552) hide show
  1. package/.claude/skills/c4s-brief-implementer/SKILL.md +105 -0
  2. package/.claude/skills/c4s-spec-reader/SKILL.md +46 -0
  3. package/CHANGELOG.md +19 -0
  4. package/LICENSE +21 -0
  5. package/README.md +50 -0
  6. package/dist/bin/agent-md-template.d.ts +1 -0
  7. package/dist/bin/agent-md-template.js +76 -0
  8. package/dist/bin/agent-md-template.js.map +1 -0
  9. package/dist/bin/bootstrap-template.d.ts +1 -0
  10. package/dist/bin/bootstrap-template.js +12 -0
  11. package/dist/bin/bootstrap-template.js.map +1 -0
  12. package/dist/bin/c4s/args.d.ts +13 -0
  13. package/dist/bin/c4s/args.js +82 -0
  14. package/dist/bin/c4s/args.js.map +1 -0
  15. package/dist/bin/c4s/commands/_meta.d.ts +2 -0
  16. package/dist/bin/c4s/commands/_meta.js +13 -0
  17. package/dist/bin/c4s/commands/_meta.js.map +1 -0
  18. package/dist/bin/c4s/commands/catalog.d.ts +2 -0
  19. package/dist/bin/c4s/commands/catalog.js +38 -0
  20. package/dist/bin/c4s/commands/catalog.js.map +1 -0
  21. package/dist/bin/c4s/commands/detail.d.ts +2 -0
  22. package/dist/bin/c4s/commands/detail.js +22 -0
  23. package/dist/bin/c4s/commands/detail.js.map +1 -0
  24. package/dist/bin/c4s/commands/element-list.d.ts +2 -0
  25. package/dist/bin/c4s/commands/element-list.js +23 -0
  26. package/dist/bin/c4s/commands/element-list.js.map +1 -0
  27. package/dist/bin/c4s/commands/inline-mention.d.ts +2 -0
  28. package/dist/bin/c4s/commands/inline-mention.js +22 -0
  29. package/dist/bin/c4s/commands/inline-mention.js.map +1 -0
  30. package/dist/bin/c4s/commands/list-slugs.d.ts +2 -0
  31. package/dist/bin/c4s/commands/list-slugs.js +16 -0
  32. package/dist/bin/c4s/commands/list-slugs.js.map +1 -0
  33. package/dist/bin/c4s/commands/list-tags.d.ts +2 -0
  34. package/dist/bin/c4s/commands/list-tags.js +13 -0
  35. package/dist/bin/c4s/commands/list-tags.js.map +1 -0
  36. package/dist/bin/c4s/commands/resolve.d.ts +2 -0
  37. package/dist/bin/c4s/commands/resolve.js +40 -0
  38. package/dist/bin/c4s/commands/resolve.js.map +1 -0
  39. package/dist/bin/c4s/commands/section-ref.d.ts +2 -0
  40. package/dist/bin/c4s/commands/section-ref.js +25 -0
  41. package/dist/bin/c4s/commands/section-ref.js.map +1 -0
  42. package/dist/bin/c4s/commands/single-element.d.ts +2 -0
  43. package/dist/bin/c4s/commands/single-element.js +22 -0
  44. package/dist/bin/c4s/commands/single-element.js.map +1 -0
  45. package/dist/bin/c4s/commands/tagged-list-mixed.d.ts +2 -0
  46. package/dist/bin/c4s/commands/tagged-list-mixed.js +39 -0
  47. package/dist/bin/c4s/commands/tagged-list-mixed.js.map +1 -0
  48. package/dist/bin/c4s/commands/tagged-list.d.ts +2 -0
  49. package/dist/bin/c4s/commands/tagged-list.js +24 -0
  50. package/dist/bin/c4s/commands/tagged-list.js.map +1 -0
  51. package/dist/bin/c4s/context.d.ts +12 -0
  52. package/dist/bin/c4s/context.js +27 -0
  53. package/dist/bin/c4s/context.js.map +1 -0
  54. package/dist/bin/c4s/errors.d.ts +6 -0
  55. package/dist/bin/c4s/errors.js +11 -0
  56. package/dist/bin/c4s/errors.js.map +1 -0
  57. package/dist/bin/c4s/output.d.ts +4 -0
  58. package/dist/bin/c4s/output.js +57 -0
  59. package/dist/bin/c4s/output.js.map +1 -0
  60. package/dist/bin/c4s/project.d.ts +1 -0
  61. package/dist/bin/c4s/project.js +23 -0
  62. package/dist/bin/c4s/project.js.map +1 -0
  63. package/dist/bin/c4s/type-validation.d.ts +3 -0
  64. package/dist/bin/c4s/type-validation.js +11 -0
  65. package/dist/bin/c4s/type-validation.js.map +1 -0
  66. package/dist/bin/c4s-mcp.d.ts +2 -0
  67. package/dist/bin/c4s-mcp.js +118 -0
  68. package/dist/bin/c4s-mcp.js.map +1 -0
  69. package/dist/bin/c4s.d.ts +2 -0
  70. package/dist/bin/c4s.js +134 -0
  71. package/dist/bin/c4s.js.map +1 -0
  72. package/dist/bin/claude4spec.d.ts +2 -0
  73. package/dist/bin/claude4spec.js +132 -0
  74. package/dist/bin/claude4spec.js.map +1 -0
  75. package/dist/bin/gitignore.d.ts +1 -0
  76. package/dist/bin/gitignore.js +44 -0
  77. package/dist/bin/gitignore.js.map +1 -0
  78. package/dist/client/assets/arc-D8brDDag.js +1 -0
  79. package/dist/client/assets/architectureDiagram-3BPJPVTR-Bmh1uTQZ.js +36 -0
  80. package/dist/client/assets/blockDiagram-GPEHLZMM-55jaVWwd.js +132 -0
  81. package/dist/client/assets/c4Diagram-AAUBKEIU-Dxm0tLsZ.js +10 -0
  82. package/dist/client/assets/channel-ArVcv4Yl.js +1 -0
  83. package/dist/client/assets/chunk-2J33WTMH-vDJ1slcJ.js +1 -0
  84. package/dist/client/assets/chunk-4BX2VUAB-DP6CC-Qn.js +1 -0
  85. package/dist/client/assets/chunk-55IACEB6-SgOSJYkL.js +1 -0
  86. package/dist/client/assets/chunk-727SXJPM-BtRfbjBO.js +206 -0
  87. package/dist/client/assets/chunk-AQP2D5EJ-yIRaTgFg.js +231 -0
  88. package/dist/client/assets/chunk-FMBD7UC4-B_VD4t8N.js +15 -0
  89. package/dist/client/assets/chunk-ND2GUHAM-BvJdtX82.js +1 -0
  90. package/dist/client/assets/chunk-QZHKN3VN-BLNWKymD.js +1 -0
  91. package/dist/client/assets/classDiagram-4FO5ZUOK-B3nmPR7w.js +1 -0
  92. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B3nmPR7w.js +1 -0
  93. package/dist/client/assets/cose-bilkent-S5V4N54A-BQyA-r-y.js +1 -0
  94. package/dist/client/assets/cytoscape.esm-D_LviqZs.js +331 -0
  95. package/dist/client/assets/dagre-BM42HDAG-CAh0mTzA.js +4 -0
  96. package/dist/client/assets/defaultLocale-DX6XiGOO.js +1 -0
  97. package/dist/client/assets/diagram-2AECGRRQ-C83TGK4o.js +43 -0
  98. package/dist/client/assets/diagram-5GNKFQAL-2L6uowvf.js +10 -0
  99. package/dist/client/assets/diagram-KO2AKTUF-Cj5n4jdq.js +3 -0
  100. package/dist/client/assets/diagram-LMA3HP47-Bp5SDMjg.js +24 -0
  101. package/dist/client/assets/diagram-OG6HWLK6-cFsDQ8Qk.js +24 -0
  102. package/dist/client/assets/erDiagram-TEJ5UH35-D8G5xpg3.js +85 -0
  103. package/dist/client/assets/flowDiagram-I6XJVG4X-CuNudlCD.js +162 -0
  104. package/dist/client/assets/ganttDiagram-6RSMTGT7-CtFlsB15.js +292 -0
  105. package/dist/client/assets/gitGraphDiagram-PVQCEYII-h66Tso4O.js +106 -0
  106. package/dist/client/assets/graph-CAnANduQ.js +1 -0
  107. package/dist/client/assets/index-CZOpb3O7.css +1 -0
  108. package/dist/client/assets/index-D5ljIkCJ.js +727 -0
  109. package/dist/client/assets/index-aJE-l7h7.js +11 -0
  110. package/dist/client/assets/index-aPVup1Re.js +51 -0
  111. package/dist/client/assets/infoDiagram-5YYISTIA-CO_BLfuW.js +2 -0
  112. package/dist/client/assets/init-Gi6I4Gst.js +1 -0
  113. package/dist/client/assets/ishikawaDiagram-YF4QCWOH-D4rSRnQA.js +70 -0
  114. package/dist/client/assets/journeyDiagram-JHISSGLW-GyHI6dB8.js +139 -0
  115. package/dist/client/assets/kanban-definition-UN3LZRKU-CrH33WLe.js +89 -0
  116. package/dist/client/assets/katex-CQk2-UhE.js +257 -0
  117. package/dist/client/assets/layout-DGIYPm2g.js +1 -0
  118. package/dist/client/assets/linear-Dh1OyvSm.js +1 -0
  119. package/dist/client/assets/mermaid.core-C45sMDhS.js +309 -0
  120. package/dist/client/assets/mindmap-definition-RKZ34NQL-Bgwb0vwA.js +96 -0
  121. package/dist/client/assets/ordinal-Cboi1Yqb.js +1 -0
  122. package/dist/client/assets/pieDiagram-4H26LBE5-l9cCpVfG.js +30 -0
  123. package/dist/client/assets/quadrantDiagram-W4KKPZXB-BCPSUbC3.js +7 -0
  124. package/dist/client/assets/requirementDiagram-4Y6WPE33-TEGOe-vV.js +84 -0
  125. package/dist/client/assets/sankeyDiagram-5OEKKPKP-C69pv_7D.js +40 -0
  126. package/dist/client/assets/sequenceDiagram-3UESZ5HK-arinzeCk.js +162 -0
  127. package/dist/client/assets/stateDiagram-AJRCARHV-C2YENpmw.js +1 -0
  128. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CS6ocDH6.js +1 -0
  129. package/dist/client/assets/timeline-definition-PNZ67QCA-h5qtI99f.js +120 -0
  130. package/dist/client/assets/vennDiagram-CIIHVFJN-CnuK75Ut.js +34 -0
  131. package/dist/client/assets/wardley-L42UT6IY-B4bQ0Xyy.js +173 -0
  132. package/dist/client/assets/wardleyDiagram-YWT4CUSO-apV8olQc.js +78 -0
  133. package/dist/client/assets/xychartDiagram-2RQKCTM6-OTP6zeEy.js +7 -0
  134. package/dist/client/index.html +19 -0
  135. package/dist/server/config.d.ts +59 -0
  136. package/dist/server/config.js +211 -0
  137. package/dist/server/config.js.map +1 -0
  138. package/dist/server/core/plugin-host/cross-cutting.d.ts +8 -0
  139. package/dist/server/core/plugin-host/cross-cutting.js +14 -0
  140. package/dist/server/core/plugin-host/cross-cutting.js.map +1 -0
  141. package/dist/server/core/plugin-host/entities-router.d.ts +11 -0
  142. package/dist/server/core/plugin-host/entities-router.js +77 -0
  143. package/dist/server/core/plugin-host/entities-router.js.map +1 -0
  144. package/dist/server/core/plugin-host/host.d.ts +11 -0
  145. package/dist/server/core/plugin-host/host.js +128 -0
  146. package/dist/server/core/plugin-host/host.js.map +1 -0
  147. package/dist/server/core/plugin-host/legacy-adapter.d.ts +31 -0
  148. package/dist/server/core/plugin-host/legacy-adapter.js +88 -0
  149. package/dist/server/core/plugin-host/legacy-adapter.js.map +1 -0
  150. package/dist/server/core/plugin-host/serialization-engine.d.ts +35 -0
  151. package/dist/server/core/plugin-host/serialization-engine.js +132 -0
  152. package/dist/server/core/plugin-host/serialization-engine.js.map +1 -0
  153. package/dist/server/core/plugin-host/types.d.ts +143 -0
  154. package/dist/server/core/plugin-host/types.js +10 -0
  155. package/dist/server/core/plugin-host/types.js.map +1 -0
  156. package/dist/server/db/fixups/backfill-plan-titles.d.ts +2 -0
  157. package/dist/server/db/fixups/backfill-plan-titles.js +22 -0
  158. package/dist/server/db/fixups/backfill-plan-titles.js.map +1 -0
  159. package/dist/server/db/index.d.ts +6 -0
  160. package/dist/server/db/index.js +26 -0
  161. package/dist/server/db/index.js.map +1 -0
  162. package/dist/server/db/migrate.d.ts +2 -0
  163. package/dist/server/db/migrate.js +33 -0
  164. package/dist/server/db/migrate.js.map +1 -0
  165. package/dist/server/db/migrations/000_init.sql +7 -0
  166. package/dist/server/db/migrations/001_endpoint.sql +51 -0
  167. package/dist/server/db/migrations/002_dto.sql +23 -0
  168. package/dist/server/db/migrations/003_drop_endpoint_body.sql +5 -0
  169. package/dist/server/db/migrations/004_drop_module_and_status.sql +31 -0
  170. package/dist/server/db/migrations/005_chat.sql +23 -0
  171. package/dist/server/db/migrations/006_database_table.sql +10 -0
  172. package/dist/server/db/migrations/007_sections.sql +30 -0
  173. package/dist/server/db/migrations/008_subagent_task.sql +20 -0
  174. package/dist/server/db/migrations/009_chat_todo_snapshot.sql +4 -0
  175. package/dist/server/db/migrations/010_chat_plan_mode.sql +5 -0
  176. package/dist/server/db/migrations/011_chat_initial_system_prompt.sql +4 -0
  177. package/dist/server/db/migrations/012_chat_message_status.sql +5 -0
  178. package/dist/server/db/migrations/013_chat_usage_snapshot.sql +7 -0
  179. package/dist/server/db/migrations/014_plans.sql +33 -0
  180. package/dist/server/db/migrations/015_dto_examples.sql +4 -0
  181. package/dist/server/db/migrations/016_ui_view.sql +10 -0
  182. package/dist/server/db/migrations/017_entity_version_m17.sql +23 -0
  183. package/dist/server/db/migrations/018_page_version.sql +20 -0
  184. package/dist/server/db/migrations/019_spec_release.sql +13 -0
  185. package/dist/server/db/migrations/020_drop_plan_status.sql +10 -0
  186. package/dist/server/db/migrations/021_plans_n1.sql +36 -0
  187. package/dist/server/db/migrations/022_brief_chat_columns.sql +23 -0
  188. package/dist/server/db/migrations/023_page_version_kind.sql +26 -0
  189. package/dist/server/db/migrations/024_chat_context_size.sql +10 -0
  190. package/dist/server/db/migrations/025_ac.sql +19 -0
  191. package/dist/server/db/migrations/026_ac_seed.sql +75 -0
  192. package/dist/server/db/migrations/027_page_version_change_summary.sql +10 -0
  193. package/dist/server/db/readonly.d.ts +12 -0
  194. package/dist/server/db/readonly.js +32 -0
  195. package/dist/server/db/readonly.js.map +1 -0
  196. package/dist/server/domain/raw-entity-reader.d.ts +76 -0
  197. package/dist/server/domain/raw-entity-reader.js +240 -0
  198. package/dist/server/domain/raw-entity-reader.js.map +1 -0
  199. package/dist/server/entities/ac/mcp-server.d.ts +10 -0
  200. package/dist/server/entities/ac/mcp-server.js +154 -0
  201. package/dist/server/entities/ac/mcp-server.js.map +1 -0
  202. package/dist/server/entities/ac/plugin.d.ts +2 -0
  203. package/dist/server/entities/ac/plugin.js +33 -0
  204. package/dist/server/entities/ac/plugin.js.map +1 -0
  205. package/dist/server/entities/ac/routes.d.ts +4 -0
  206. package/dist/server/entities/ac/routes.js +92 -0
  207. package/dist/server/entities/ac/routes.js.map +1 -0
  208. package/dist/server/entities/ac/serializer.d.ts +13 -0
  209. package/dist/server/entities/ac/serializer.js +124 -0
  210. package/dist/server/entities/ac/serializer.js.map +1 -0
  211. package/dist/server/entities/ac/services.d.ts +35 -0
  212. package/dist/server/entities/ac/services.js +261 -0
  213. package/dist/server/entities/ac/services.js.map +1 -0
  214. package/dist/server/entities/ac/system-prompt.d.ts +2 -0
  215. package/dist/server/entities/ac/system-prompt.js +18 -0
  216. package/dist/server/entities/ac/system-prompt.js.map +1 -0
  217. package/dist/server/entities/database-table/mcp-server.d.ts +10 -0
  218. package/dist/server/entities/database-table/mcp-server.js +184 -0
  219. package/dist/server/entities/database-table/mcp-server.js.map +1 -0
  220. package/dist/server/entities/database-table/plugin.d.ts +2 -0
  221. package/dist/server/entities/database-table/plugin.js +33 -0
  222. package/dist/server/entities/database-table/plugin.js.map +1 -0
  223. package/dist/server/entities/database-table/routes.d.ts +5 -0
  224. package/dist/server/entities/database-table/routes.js +86 -0
  225. package/dist/server/entities/database-table/routes.js.map +1 -0
  226. package/dist/server/entities/database-table/serializer.d.ts +12 -0
  227. package/dist/server/entities/database-table/serializer.js +192 -0
  228. package/dist/server/entities/database-table/serializer.js.map +1 -0
  229. package/dist/server/entities/database-table/services.d.ts +45 -0
  230. package/dist/server/entities/database-table/services.js +323 -0
  231. package/dist/server/entities/database-table/services.js.map +1 -0
  232. package/dist/server/entities/database-table/system-prompt.d.ts +2 -0
  233. package/dist/server/entities/database-table/system-prompt.js +11 -0
  234. package/dist/server/entities/database-table/system-prompt.js.map +1 -0
  235. package/dist/server/entities/dto/mcp-server.d.ts +10 -0
  236. package/dist/server/entities/dto/mcp-server.js +141 -0
  237. package/dist/server/entities/dto/mcp-server.js.map +1 -0
  238. package/dist/server/entities/dto/plugin.d.ts +2 -0
  239. package/dist/server/entities/dto/plugin.js +33 -0
  240. package/dist/server/entities/dto/plugin.js.map +1 -0
  241. package/dist/server/entities/dto/routes.d.ts +4 -0
  242. package/dist/server/entities/dto/routes.js +74 -0
  243. package/dist/server/entities/dto/routes.js.map +1 -0
  244. package/dist/server/entities/dto/serializer.d.ts +12 -0
  245. package/dist/server/entities/dto/serializer.js +184 -0
  246. package/dist/server/entities/dto/serializer.js.map +1 -0
  247. package/dist/server/entities/dto/services.d.ts +30 -0
  248. package/dist/server/entities/dto/services.js +242 -0
  249. package/dist/server/entities/dto/services.js.map +1 -0
  250. package/dist/server/entities/dto/system-prompt.d.ts +2 -0
  251. package/dist/server/entities/dto/system-prompt.js +11 -0
  252. package/dist/server/entities/dto/system-prompt.js.map +1 -0
  253. package/dist/server/entities/endpoint/mcp-server.d.ts +10 -0
  254. package/dist/server/entities/endpoint/mcp-server.js +156 -0
  255. package/dist/server/entities/endpoint/mcp-server.js.map +1 -0
  256. package/dist/server/entities/endpoint/plugin.d.ts +2 -0
  257. package/dist/server/entities/endpoint/plugin.js +36 -0
  258. package/dist/server/entities/endpoint/plugin.js.map +1 -0
  259. package/dist/server/entities/endpoint/routes.d.ts +4 -0
  260. package/dist/server/entities/endpoint/routes.js +107 -0
  261. package/dist/server/entities/endpoint/routes.js.map +1 -0
  262. package/dist/server/entities/endpoint/serializer.d.ts +17 -0
  263. package/dist/server/entities/endpoint/serializer.js +217 -0
  264. package/dist/server/entities/endpoint/serializer.js.map +1 -0
  265. package/dist/server/entities/endpoint/services.d.ts +30 -0
  266. package/dist/server/entities/endpoint/services.js +260 -0
  267. package/dist/server/entities/endpoint/services.js.map +1 -0
  268. package/dist/server/entities/endpoint/system-prompt.d.ts +2 -0
  269. package/dist/server/entities/endpoint/system-prompt.js +11 -0
  270. package/dist/server/entities/endpoint/system-prompt.js.map +1 -0
  271. package/dist/server/entities/ui-view/mcp-server.d.ts +10 -0
  272. package/dist/server/entities/ui-view/mcp-server.js +161 -0
  273. package/dist/server/entities/ui-view/mcp-server.js.map +1 -0
  274. package/dist/server/entities/ui-view/plugin.d.ts +2 -0
  275. package/dist/server/entities/ui-view/plugin.js +33 -0
  276. package/dist/server/entities/ui-view/plugin.js.map +1 -0
  277. package/dist/server/entities/ui-view/routes.d.ts +5 -0
  278. package/dist/server/entities/ui-view/routes.js +82 -0
  279. package/dist/server/entities/ui-view/routes.js.map +1 -0
  280. package/dist/server/entities/ui-view/serializer.d.ts +12 -0
  281. package/dist/server/entities/ui-view/serializer.js +262 -0
  282. package/dist/server/entities/ui-view/serializer.js.map +1 -0
  283. package/dist/server/entities/ui-view/services.d.ts +35 -0
  284. package/dist/server/entities/ui-view/services.js +255 -0
  285. package/dist/server/entities/ui-view/services.js.map +1 -0
  286. package/dist/server/entities/ui-view/system-prompt.d.ts +7 -0
  287. package/dist/server/entities/ui-view/system-prompt.js +15 -0
  288. package/dist/server/entities/ui-view/system-prompt.js.map +1 -0
  289. package/dist/server/external-skills/brief-implementer-template.d.ts +2 -0
  290. package/dist/server/external-skills/brief-implementer-template.js +123 -0
  291. package/dist/server/external-skills/brief-implementer-template.js.map +1 -0
  292. package/dist/server/external-skills/external-skills-service.d.ts +3 -0
  293. package/dist/server/external-skills/external-skills-service.js +47 -0
  294. package/dist/server/external-skills/external-skills-service.js.map +1 -0
  295. package/dist/server/external-skills/spec-reader-template.d.ts +2 -0
  296. package/dist/server/external-skills/spec-reader-template.js +47 -0
  297. package/dist/server/external-skills/spec-reader-template.js.map +1 -0
  298. package/dist/server/fs/watcher.d.ts +26 -0
  299. package/dist/server/fs/watcher.js +64 -0
  300. package/dist/server/fs/watcher.js.map +1 -0
  301. package/dist/server/index.d.ts +18 -0
  302. package/dist/server/index.js +474 -0
  303. package/dist/server/index.js.map +1 -0
  304. package/dist/server/mcp/brief-tools.d.ts +19 -0
  305. package/dist/server/mcp/brief-tools.js +189 -0
  306. package/dist/server/mcp/brief-tools.js.map +1 -0
  307. package/dist/server/mcp/c4s-reader.d.ts +12 -0
  308. package/dist/server/mcp/c4s-reader.js +263 -0
  309. package/dist/server/mcp/c4s-reader.js.map +1 -0
  310. package/dist/server/mcp/database-tools.d.ts +10 -0
  311. package/dist/server/mcp/database-tools.js +184 -0
  312. package/dist/server/mcp/database-tools.js.map +1 -0
  313. package/dist/server/mcp/dependency-tools.d.ts +12 -0
  314. package/dist/server/mcp/dependency-tools.js +205 -0
  315. package/dist/server/mcp/dependency-tools.js.map +1 -0
  316. package/dist/server/mcp/dto-tools.d.ts +10 -0
  317. package/dist/server/mcp/dto-tools.js +141 -0
  318. package/dist/server/mcp/dto-tools.js.map +1 -0
  319. package/dist/server/mcp/endpoint-tools.d.ts +10 -0
  320. package/dist/server/mcp/endpoint-tools.js +156 -0
  321. package/dist/server/mcp/endpoint-tools.js.map +1 -0
  322. package/dist/server/mcp/ensure-mcp-json.d.ts +6 -0
  323. package/dist/server/mcp/ensure-mcp-json.js +30 -0
  324. package/dist/server/mcp/ensure-mcp-json.js.map +1 -0
  325. package/dist/server/mcp/index.d.ts +29 -0
  326. package/dist/server/mcp/index.js +40 -0
  327. package/dist/server/mcp/index.js.map +1 -0
  328. package/dist/server/mcp/plan-tools.d.ts +7 -0
  329. package/dist/server/mcp/plan-tools.js +105 -0
  330. package/dist/server/mcp/plan-tools.js.map +1 -0
  331. package/dist/server/mcp/reference-tools.d.ts +17 -0
  332. package/dist/server/mcp/reference-tools.js +630 -0
  333. package/dist/server/mcp/reference-tools.js.map +1 -0
  334. package/dist/server/mcp/release-tools/index.d.ts +21 -0
  335. package/dist/server/mcp/release-tools/index.js +140 -0
  336. package/dist/server/mcp/release-tools/index.js.map +1 -0
  337. package/dist/server/mcp/release-tools/projection.d.ts +32 -0
  338. package/dist/server/mcp/release-tools/projection.js +278 -0
  339. package/dist/server/mcp/release-tools/projection.js.map +1 -0
  340. package/dist/server/mcp/release-tools/types.d.ts +91 -0
  341. package/dist/server/mcp/release-tools/types.js +11 -0
  342. package/dist/server/mcp/release-tools/types.js.map +1 -0
  343. package/dist/server/mcp/release-tools.d.ts +14 -0
  344. package/dist/server/mcp/release-tools.js +83 -0
  345. package/dist/server/mcp/release-tools.js.map +1 -0
  346. package/dist/server/mcp/ui-view-tools.d.ts +10 -0
  347. package/dist/server/mcp/ui-view-tools.js +161 -0
  348. package/dist/server/mcp/ui-view-tools.js.map +1 -0
  349. package/dist/server/routes/briefs.d.ts +8 -0
  350. package/dist/server/routes/briefs.js +178 -0
  351. package/dist/server/routes/briefs.js.map +1 -0
  352. package/dist/server/routes/chat.d.ts +29 -0
  353. package/dist/server/routes/chat.js +604 -0
  354. package/dist/server/routes/chat.js.map +1 -0
  355. package/dist/server/routes/database-tables.d.ts +5 -0
  356. package/dist/server/routes/database-tables.js +86 -0
  357. package/dist/server/routes/database-tables.js.map +1 -0
  358. package/dist/server/routes/dependencies.d.ts +6 -0
  359. package/dist/server/routes/dependencies.js +164 -0
  360. package/dist/server/routes/dependencies.js.map +1 -0
  361. package/dist/server/routes/dtos.d.ts +4 -0
  362. package/dist/server/routes/dtos.js +74 -0
  363. package/dist/server/routes/dtos.js.map +1 -0
  364. package/dist/server/routes/endpoints.d.ts +4 -0
  365. package/dist/server/routes/endpoints.js +107 -0
  366. package/dist/server/routes/endpoints.js.map +1 -0
  367. package/dist/server/routes/entities.d.ts +8 -0
  368. package/dist/server/routes/entities.js +84 -0
  369. package/dist/server/routes/entities.js.map +1 -0
  370. package/dist/server/routes/errors.d.ts +2 -0
  371. package/dist/server/routes/errors.js +37 -0
  372. package/dist/server/routes/errors.js.map +1 -0
  373. package/dist/server/routes/page-links.d.ts +3 -0
  374. package/dist/server/routes/page-links.js +40 -0
  375. package/dist/server/routes/page-links.js.map +1 -0
  376. package/dist/server/routes/pages.d.ts +5 -0
  377. package/dist/server/routes/pages.js +142 -0
  378. package/dist/server/routes/pages.js.map +1 -0
  379. package/dist/server/routes/plans.d.ts +3 -0
  380. package/dist/server/routes/plans.js +192 -0
  381. package/dist/server/routes/plans.js.map +1 -0
  382. package/dist/server/routes/references.d.ts +3 -0
  383. package/dist/server/routes/references.js +34 -0
  384. package/dist/server/routes/references.js.map +1 -0
  385. package/dist/server/routes/releases.d.ts +4 -0
  386. package/dist/server/routes/releases.js +122 -0
  387. package/dist/server/routes/releases.js.map +1 -0
  388. package/dist/server/routes/sections.d.ts +3 -0
  389. package/dist/server/routes/sections.js +32 -0
  390. package/dist/server/routes/sections.js.map +1 -0
  391. package/dist/server/routes/tags.d.ts +4 -0
  392. package/dist/server/routes/tags.js +56 -0
  393. package/dist/server/routes/tags.js.map +1 -0
  394. package/dist/server/routes/threads.d.ts +3 -0
  395. package/dist/server/routes/threads.js +78 -0
  396. package/dist/server/routes/threads.js.map +1 -0
  397. package/dist/server/routes/todos.d.ts +3 -0
  398. package/dist/server/routes/todos.js +28 -0
  399. package/dist/server/routes/todos.js.map +1 -0
  400. package/dist/server/routes/ui-views.d.ts +5 -0
  401. package/dist/server/routes/ui-views.js +82 -0
  402. package/dist/server/routes/ui-views.js.map +1 -0
  403. package/dist/server/serialization/auto-schema.d.ts +3 -0
  404. package/dist/server/serialization/auto-schema.js +55 -0
  405. package/dist/server/serialization/auto-schema.js.map +1 -0
  406. package/dist/server/serialization/fallback.d.ts +4 -0
  407. package/dist/server/serialization/fallback.js +27 -0
  408. package/dist/server/serialization/fallback.js.map +1 -0
  409. package/dist/server/serialization/inline-renderer.d.ts +4 -0
  410. package/dist/server/serialization/inline-renderer.js +151 -0
  411. package/dist/server/serialization/inline-renderer.js.map +1 -0
  412. package/dist/server/serialization/registerAll.d.ts +6 -0
  413. package/dist/server/serialization/registerAll.js +7 -0
  414. package/dist/server/serialization/registerAll.js.map +1 -0
  415. package/dist/server/serialization/registry.d.ts +26 -0
  416. package/dist/server/serialization/registry.js +121 -0
  417. package/dist/server/serialization/registry.js.map +1 -0
  418. package/dist/server/serialization/resolve-page.d.ts +24 -0
  419. package/dist/server/serialization/resolve-page.js +192 -0
  420. package/dist/server/serialization/resolve-page.js.map +1 -0
  421. package/dist/server/serialization/serializers/database-table.d.ts +1 -0
  422. package/dist/server/serialization/serializers/database-table.js +46 -0
  423. package/dist/server/serialization/serializers/database-table.js.map +1 -0
  424. package/dist/server/serialization/serializers/dto.d.ts +1 -0
  425. package/dist/server/serialization/serializers/dto.js +48 -0
  426. package/dist/server/serialization/serializers/dto.js.map +1 -0
  427. package/dist/server/serialization/serializers/endpoint.d.ts +1 -0
  428. package/dist/server/serialization/serializers/endpoint.js +93 -0
  429. package/dist/server/serialization/serializers/endpoint.js.map +1 -0
  430. package/dist/server/serialization/serializers/section.d.ts +1 -0
  431. package/dist/server/serialization/serializers/section.js +24 -0
  432. package/dist/server/serialization/serializers/section.js.map +1 -0
  433. package/dist/server/serialization/serializers/ui-view.d.ts +1 -0
  434. package/dist/server/serialization/serializers/ui-view.js +124 -0
  435. package/dist/server/serialization/serializers/ui-view.js.map +1 -0
  436. package/dist/server/serialization/snapshot.d.ts +22 -0
  437. package/dist/server/serialization/snapshot.js +102 -0
  438. package/dist/server/serialization/snapshot.js.map +1 -0
  439. package/dist/server/serialization/types.d.ts +70 -0
  440. package/dist/server/serialization/types.js +7 -0
  441. package/dist/server/serialization/types.js.map +1 -0
  442. package/dist/server/serialization/writer.d.ts +41 -0
  443. package/dist/server/serialization/writer.js +13 -0
  444. package/dist/server/serialization/writer.js.map +1 -0
  445. package/dist/server/services/brief.d.ts +86 -0
  446. package/dist/server/services/brief.js +218 -0
  447. package/dist/server/services/brief.js.map +1 -0
  448. package/dist/server/services/chat-context.d.ts +26 -0
  449. package/dist/server/services/chat-context.js +434 -0
  450. package/dist/server/services/chat-context.js.map +1 -0
  451. package/dist/server/services/chat.d.ts +50 -0
  452. package/dist/server/services/chat.js +309 -0
  453. package/dist/server/services/chat.js.map +1 -0
  454. package/dist/server/services/database-table.d.ts +36 -0
  455. package/dist/server/services/database-table.js +303 -0
  456. package/dist/server/services/database-table.js.map +1 -0
  457. package/dist/server/services/dependencies.d.ts +45 -0
  458. package/dist/server/services/dependencies.js +302 -0
  459. package/dist/server/services/dependencies.js.map +1 -0
  460. package/dist/server/services/dto.d.ts +22 -0
  461. package/dist/server/services/dto.js +222 -0
  462. package/dist/server/services/dto.js.map +1 -0
  463. package/dist/server/services/endpoint.d.ts +22 -0
  464. package/dist/server/services/endpoint.js +239 -0
  465. package/dist/server/services/endpoint.js.map +1 -0
  466. package/dist/server/services/entity-writer.d.ts +46 -0
  467. package/dist/server/services/entity-writer.js +137 -0
  468. package/dist/server/services/entity-writer.js.map +1 -0
  469. package/dist/server/services/page-serializer.d.ts +109 -0
  470. package/dist/server/services/page-serializer.js +359 -0
  471. package/dist/server/services/page-serializer.js.map +1 -0
  472. package/dist/server/services/page-version.d.ts +75 -0
  473. package/dist/server/services/page-version.js +159 -0
  474. package/dist/server/services/page-version.js.map +1 -0
  475. package/dist/server/services/pages-frontmatter-indexer.d.ts +51 -0
  476. package/dist/server/services/pages-frontmatter-indexer.js +138 -0
  477. package/dist/server/services/pages-frontmatter-indexer.js.map +1 -0
  478. package/dist/server/services/pages-link-indexer.d.ts +36 -0
  479. package/dist/server/services/pages-link-indexer.js +474 -0
  480. package/dist/server/services/pages-link-indexer.js.map +1 -0
  481. package/dist/server/services/pages.d.ts +16 -0
  482. package/dist/server/services/pages.js +149 -0
  483. package/dist/server/services/pages.js.map +1 -0
  484. package/dist/server/services/plan.d.ts +59 -0
  485. package/dist/server/services/plan.js +459 -0
  486. package/dist/server/services/plan.js.map +1 -0
  487. package/dist/server/services/references.d.ts +17 -0
  488. package/dist/server/services/references.js +175 -0
  489. package/dist/server/services/references.js.map +1 -0
  490. package/dist/server/services/release.d.ts +146 -0
  491. package/dist/server/services/release.js +602 -0
  492. package/dist/server/services/release.js.map +1 -0
  493. package/dist/server/services/section-indexer.d.ts +20 -0
  494. package/dist/server/services/section-indexer.js +276 -0
  495. package/dist/server/services/section-indexer.js.map +1 -0
  496. package/dist/server/services/sections.d.ts +34 -0
  497. package/dist/server/services/sections.js +136 -0
  498. package/dist/server/services/sections.js.map +1 -0
  499. package/dist/server/services/skill-registry.d.ts +38 -0
  500. package/dist/server/services/skill-registry.js +171 -0
  501. package/dist/server/services/skill-registry.js.map +1 -0
  502. package/dist/server/services/slug.d.ts +7 -0
  503. package/dist/server/services/slug.js +41 -0
  504. package/dist/server/services/slug.js.map +1 -0
  505. package/dist/server/services/tags.d.ts +27 -0
  506. package/dist/server/services/tags.js +153 -0
  507. package/dist/server/services/tags.js.map +1 -0
  508. package/dist/server/services/todos-indexer.d.ts +21 -0
  509. package/dist/server/services/todos-indexer.js +123 -0
  510. package/dist/server/services/todos-indexer.js.map +1 -0
  511. package/dist/server/services/ui-view.d.ts +26 -0
  512. package/dist/server/services/ui-view.js +235 -0
  513. package/dist/server/services/ui-view.js.map +1 -0
  514. package/dist/server/services/versions.d.ts +59 -0
  515. package/dist/server/services/versions.js +181 -0
  516. package/dist/server/services/versions.js.map +1 -0
  517. package/dist/server/skills/brief-author/SKILL.md +117 -0
  518. package/dist/server/skills/layered-vertical-slices/SKILL.md +135 -0
  519. package/dist/server/skills/layered-vertical-slices/templates/index.md +97 -0
  520. package/dist/server/skills/layered-vertical-slices/templates/layer.md +42 -0
  521. package/dist/server/skills/layered-vertical-slices/templates/module.md +52 -0
  522. package/dist/server/skills/layered-vertical-slices/workflows/bootstrap.md +116 -0
  523. package/dist/server/skills/layered-vertical-slices/workflows/brief.md +154 -0
  524. package/dist/server/skills/layered-vertical-slices/workflows/daily.md +77 -0
  525. package/dist/server/ws/gateway.d.ts +10 -0
  526. package/dist/server/ws/gateway.js +35 -0
  527. package/dist/server/ws/gateway.js.map +1 -0
  528. package/dist/shared/anchor-pattern.d.ts +15 -0
  529. package/dist/shared/anchor-pattern.js +16 -0
  530. package/dist/shared/anchor-pattern.js.map +1 -0
  531. package/dist/shared/diagram-source-escape.d.ts +2 -0
  532. package/dist/shared/diagram-source-escape.js +19 -0
  533. package/dist/shared/diagram-source-escape.js.map +1 -0
  534. package/dist/shared/entities.d.ts +622 -0
  535. package/dist/shared/entities.js +9 -0
  536. package/dist/shared/entities.js.map +1 -0
  537. package/dist/shared/page-links.d.ts +40 -0
  538. package/dist/shared/page-links.js +2 -0
  539. package/dist/shared/page-links.js.map +1 -0
  540. package/dist/shared/plugin-host/types.d.ts +66 -0
  541. package/dist/shared/plugin-host/types.js +11 -0
  542. package/dist/shared/plugin-host/types.js.map +1 -0
  543. package/dist/shared/reference-extensions.d.ts +13 -0
  544. package/dist/shared/reference-extensions.js +17 -0
  545. package/dist/shared/reference-extensions.js.map +1 -0
  546. package/dist/shared/types.d.ts +86 -0
  547. package/dist/shared/types.js +2 -0
  548. package/dist/shared/types.js.map +1 -0
  549. package/dist/shared/xml-tags.d.ts +16 -0
  550. package/dist/shared/xml-tags.js +101 -0
  551. package/dist/shared/xml-tags.js.map +1 -0
  552. package/package.json +110 -0
@@ -0,0 +1,359 @@
1
+ /**
2
+ * PageSerializer — M02 stays out of L9 plugin host (M17 decyzja 1).
3
+ * Lives outside `EntitySerializer` registry; provides parallel
4
+ * snapshot/restore/diff for markdown pages.
5
+ *
6
+ * Snapshot shape — `PageSnapshotData` per `db-m17-snapshots.md` (`dbm17shp01`).
7
+ * Diff variant C (M17 decyzja 10): section-level operations + mandatory
8
+ * `line_diff` inside each `section_modified` + `frontmatter_diff` /
9
+ * `xml_refs_diff` side-channels.
10
+ */
11
+ import fs from 'node:fs/promises';
12
+ import path from 'node:path';
13
+ import matter from 'gray-matter';
14
+ import { diffLines } from 'diff';
15
+ import { ANCHOR_PATTERN_SOURCE } from '../../shared/anchor-pattern.js';
16
+ import { parseXmlTags } from '../../shared/xml-tags.js';
17
+ export const PAGE_SERIALIZER_VERSION = '1.1.0';
18
+ const ANCHOR_RE = new RegExp(ANCHOR_PATTERN_SOURCE, 'g');
19
+ const ANCHOR_LINE_RE = new RegExp(`^\\s*${ANCHOR_PATTERN_SOURCE}\\s*$`);
20
+ const ANCHOR_INLINE_RE = new RegExp(ANCHOR_PATTERN_SOURCE);
21
+ const CODE_FENCE_RE = /^\s*```/m;
22
+ const HEADING_RE = /^(#{1,6})\s+(.+?)\s*$/;
23
+ /**
24
+ * Compute line-level diff between two strings using Myers algorithm
25
+ * (via `diff` npm). Returns a flat list of keep/added/removed lines
26
+ * preserving order. Trailing newlines are normalized so identical
27
+ * content with/without final \n compares equal.
28
+ */
29
+ export function computeLineDiff(a, b) {
30
+ const lines = [];
31
+ const parts = diffLines(a, b);
32
+ for (const part of parts) {
33
+ const op = part.added ? 'added' : part.removed ? 'removed' : 'keep';
34
+ const partLines = part.value.split('\n');
35
+ // diffLines emits trailing empty string for blocks that end in \n; drop it.
36
+ if (partLines.length > 0 && partLines[partLines.length - 1] === '')
37
+ partLines.pop();
38
+ for (const content of partLines) {
39
+ lines.push({ op, content });
40
+ }
41
+ }
42
+ // Inside fenced code blocks (```), whitespace and HTML comments can be
43
+ // semantically meaningful (YAML, Python, indent-DSL, markdown-in-markdown).
44
+ // Skip noise filtering entirely when either side contains a code fence.
45
+ if (CODE_FENCE_RE.test(a) || CODE_FENCE_RE.test(b)) {
46
+ return { lines };
47
+ }
48
+ const filtered = lines.filter((l) => {
49
+ if (l.op === 'keep')
50
+ return true;
51
+ if (l.content.trim() === '')
52
+ return false;
53
+ if (ANCHOR_LINE_RE.test(l.content))
54
+ return false;
55
+ return true;
56
+ });
57
+ return { lines: filtered };
58
+ }
59
+ /** Extract anchors in document order. */
60
+ export function extractAnchorsInOrder(content) {
61
+ const out = [];
62
+ ANCHOR_RE.lastIndex = 0;
63
+ let m;
64
+ while ((m = ANCHOR_RE.exec(content)) !== null) {
65
+ if (m[1])
66
+ out.push(m[1]);
67
+ }
68
+ return out;
69
+ }
70
+ export class PageSerializer {
71
+ pages;
72
+ version = PAGE_SERIALIZER_VERSION;
73
+ constructor(pages) {
74
+ this.pages = pages;
75
+ }
76
+ /**
77
+ * Read the file from disk and produce a deterministic, byte-faithful
78
+ * snapshot. Reads `content` byte-for-byte (preserves BOM, line endings).
79
+ */
80
+ async snapshot(relPath) {
81
+ const abs = path.join(this.pages.root, relPath);
82
+ const raw = await fs.readFile(abs, 'utf-8');
83
+ return this.snapshotFromContent(relPath, raw);
84
+ }
85
+ /** Build snapshot from already-read content (used for delete tombstones). */
86
+ snapshotFromContent(relPath, content) {
87
+ const parsed = matter(content);
88
+ const anchors = extractAnchorsInOrder(content);
89
+ const xml_refs = parseXmlTags(content).map((t) => ({
90
+ tagType: t.kind,
91
+ attributes: t.attrs,
92
+ position: t.start,
93
+ }));
94
+ return {
95
+ path: relPath,
96
+ content,
97
+ frontmatter: (parsed.data ?? {}),
98
+ anchors,
99
+ xml_refs,
100
+ };
101
+ }
102
+ /**
103
+ * Section-level diff (variant C in M17 decyzja 10). Sections keyed by
104
+ * 8-char anchor (`<!-- anchor: ... -->`). Reorder without content change
105
+ * → moved_section. Heading edited → counted as modified (heading is part
106
+ * of section content in our parser). Each `modified` section carries a
107
+ * mandatory `line_diff` computed via Myers diff over section bodies.
108
+ */
109
+ diff(a, b, relPath) {
110
+ const empty = {
111
+ added_sections: [],
112
+ removed_sections: [],
113
+ modified_sections: [],
114
+ moved_sections: [],
115
+ };
116
+ if (a == null && b == null) {
117
+ return { path: relPath, op: 'noop', ...empty, frontmatter_diff: null, xml_refs_diff: null };
118
+ }
119
+ if (a == null) {
120
+ const sections = parseSections(b.content);
121
+ return {
122
+ path: relPath,
123
+ op: 'created',
124
+ added_sections: sections,
125
+ removed_sections: [],
126
+ modified_sections: [],
127
+ moved_sections: [],
128
+ frontmatter_diff: frontmatterDiff({}, b.frontmatter),
129
+ xml_refs_diff: { added: b.xml_refs, removed: [] },
130
+ };
131
+ }
132
+ if (b == null) {
133
+ const sections = parseSections(a.content);
134
+ return {
135
+ path: relPath,
136
+ op: 'deleted',
137
+ added_sections: [],
138
+ removed_sections: sections,
139
+ modified_sections: [],
140
+ moved_sections: [],
141
+ frontmatter_diff: frontmatterDiff(a.frontmatter, {}),
142
+ xml_refs_diff: { added: [], removed: a.xml_refs },
143
+ };
144
+ }
145
+ const aSec = parseSections(a.content);
146
+ const bSec = parseSections(b.content);
147
+ const aMap = new Map(aSec.map((s) => [s.anchor, s]));
148
+ const bMap = new Map(bSec.map((s) => [s.anchor, s]));
149
+ const added = [];
150
+ const removed = [];
151
+ const modified = [];
152
+ const moved = [];
153
+ for (const [anchor, sec] of bMap) {
154
+ if (!aMap.has(anchor))
155
+ added.push(sec);
156
+ }
157
+ for (const [anchor, sec] of aMap) {
158
+ const other = bMap.get(anchor);
159
+ if (!other) {
160
+ removed.push(sec);
161
+ continue;
162
+ }
163
+ if (sec.content === other.content && sec.heading === other.heading) {
164
+ if (sec.position !== other.position) {
165
+ moved.push({ anchor, from_position: sec.position, to_position: other.position });
166
+ }
167
+ continue;
168
+ }
169
+ const lineDiff = computeLineDiff(sec.content, other.content);
170
+ const hasContentChange = lineDiff.lines.some((l) => l.op !== 'keep');
171
+ const headingChanged = sec.heading !== other.heading;
172
+ if (hasContentChange || headingChanged) {
173
+ modified.push({
174
+ anchor,
175
+ heading: other.heading,
176
+ level: other.level,
177
+ line_diff: lineDiff,
178
+ });
179
+ }
180
+ else if (sec.position !== other.position) {
181
+ moved.push({ anchor, from_position: sec.position, to_position: other.position });
182
+ }
183
+ }
184
+ const fmDiff = frontmatterDiff(a.frontmatter, b.frontmatter);
185
+ const xmlDiff = xmlRefsDiff(a.xml_refs, b.xml_refs);
186
+ const anyChange = added.length || removed.length || modified.length || moved.length || fmDiff || xmlDiff;
187
+ return {
188
+ path: relPath,
189
+ op: anyChange ? 'modified' : 'noop',
190
+ added_sections: added,
191
+ removed_sections: removed,
192
+ modified_sections: modified,
193
+ moved_sections: moved,
194
+ frontmatter_diff: fmDiff,
195
+ xml_refs_diff: xmlDiff,
196
+ };
197
+ }
198
+ }
199
+ /**
200
+ * Split markdown content into sections keyed by 8-char anchor. A section spans
201
+ * from a heading (with anchor comment) to the next heading of equal or higher
202
+ * level. Content without an anchor is grouped under an implicit root section
203
+ * keyed by `__root__`.
204
+ */
205
+ export function parseSections(content) {
206
+ const lines = content.split('\n');
207
+ const sections = [];
208
+ let position = 0;
209
+ let currentAnchor = null;
210
+ let currentHeading = '';
211
+ let currentLevel = 0;
212
+ let currentLines = [];
213
+ const flush = () => {
214
+ if (currentAnchor) {
215
+ sections.push({
216
+ anchor: currentAnchor,
217
+ heading: currentHeading,
218
+ level: currentLevel,
219
+ content: currentLines.join('\n'),
220
+ position: position++,
221
+ });
222
+ }
223
+ else if (currentLines.length > 0 && currentLines.some((l) => l.trim().length > 0)) {
224
+ sections.push({
225
+ anchor: '__root__',
226
+ heading: '',
227
+ level: 0,
228
+ content: currentLines.join('\n'),
229
+ position: position++,
230
+ });
231
+ }
232
+ currentAnchor = null;
233
+ currentHeading = '';
234
+ currentLevel = 0;
235
+ currentLines = [];
236
+ };
237
+ let pendingAnchor = null;
238
+ let pendingBlanks = [];
239
+ // Orphan a pending anchor + its buffered blank lines into the current section
240
+ // (i.e. anchor never met a heading — fall back to treating it as inline content).
241
+ const orphanPending = () => {
242
+ if (pendingAnchor !== null) {
243
+ currentLines.push(`<!-- anchor: ${pendingAnchor} -->`);
244
+ pendingAnchor = null;
245
+ }
246
+ if (pendingBlanks.length > 0) {
247
+ currentLines.push(...pendingBlanks);
248
+ pendingBlanks = [];
249
+ }
250
+ };
251
+ for (const line of lines) {
252
+ const anchorMatch = line.match(ANCHOR_INLINE_RE);
253
+ if (anchorMatch && anchorMatch[1]) {
254
+ // A second anchor before any heading appeared — orphan the previous one
255
+ // (matches historical behavior for the rare `anchor\nanchor\nheading` case)
256
+ // before adopting the new pending anchor.
257
+ orphanPending();
258
+ pendingAnchor = anchorMatch[1];
259
+ continue;
260
+ }
261
+ // Blank line between anchor and heading: buffer it, keep the anchor pending.
262
+ // Canonical indexer layout is `anchor\n\nheading`, so this is the common case.
263
+ if (pendingAnchor !== null && line.trim() === '') {
264
+ pendingBlanks.push(line);
265
+ continue;
266
+ }
267
+ const headingMatch = line.match(HEADING_RE);
268
+ if (headingMatch && pendingAnchor !== null) {
269
+ flush();
270
+ currentAnchor = pendingAnchor;
271
+ currentLevel = headingMatch[1].length;
272
+ currentHeading = headingMatch[2].trim();
273
+ // Buffered blanks (if any) become leading whitespace of the new section,
274
+ // so concatenating section contents reconstructs the on-disk body modulo
275
+ // the consumed anchor line itself.
276
+ currentLines = pendingBlanks.length > 0 ? [...pendingBlanks, line] : [line];
277
+ pendingAnchor = null;
278
+ pendingBlanks = [];
279
+ continue;
280
+ }
281
+ // Non-blank, non-heading, non-anchor line: anchor (if any) never found its
282
+ // heading — orphan it together with any buffered blanks, then push current line.
283
+ orphanPending();
284
+ currentLines.push(line);
285
+ }
286
+ // File ended with a dangling anchor (and maybe blanks) — orphan into trailing content.
287
+ orphanPending();
288
+ flush();
289
+ return sections;
290
+ }
291
+ function frontmatterDiff(a, b) {
292
+ const added = {};
293
+ const removed = {};
294
+ const changed = [];
295
+ const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
296
+ for (const key of keys) {
297
+ const inA = key in a;
298
+ const inB = key in b;
299
+ if (!inA && inB)
300
+ added[key] = b[key];
301
+ else if (inA && !inB)
302
+ removed[key] = a[key];
303
+ else if (JSON.stringify(a[key]) !== JSON.stringify(b[key])) {
304
+ changed.push({ key, from: a[key], to: b[key] });
305
+ }
306
+ }
307
+ if (Object.keys(added).length === 0 && Object.keys(removed).length === 0 && changed.length === 0) {
308
+ return null;
309
+ }
310
+ return { added, removed, changed };
311
+ }
312
+ function xmlRefsDiff(a, b) {
313
+ // Identity = (tagType, canonical attrs). Position is EXCLUDED on purpose:
314
+ // inserting text above a tag shifts its byte offset, which would otherwise
315
+ // surface as a fake `removed @ oldPos + added @ newPos` pair for a tag that
316
+ // didn't actually change. Identical-attribute occurrences are deduped by
317
+ // multiset count (not by Set membership), so duplicates are tracked correctly:
318
+ // 2 occurrences before, 1 after → exactly 1 reported as removed.
319
+ const keyOf = (r) => `${r.tagType}|${JSON.stringify(canonicalAttrs(r.attributes))}`;
320
+ const groupBy = (refs) => {
321
+ const m = new Map();
322
+ for (const r of refs) {
323
+ const k = keyOf(r);
324
+ const bucket = m.get(k);
325
+ if (bucket)
326
+ bucket.push(r);
327
+ else
328
+ m.set(k, [r]);
329
+ }
330
+ return m;
331
+ };
332
+ const aByKey = groupBy(a);
333
+ const bByKey = groupBy(b);
334
+ const added = [];
335
+ const removed = [];
336
+ const allKeys = new Set([...aByKey.keys(), ...bByKey.keys()]);
337
+ for (const k of allKeys) {
338
+ const aArr = aByKey.get(k) ?? [];
339
+ const bArr = bByKey.get(k) ?? [];
340
+ if (bArr.length > aArr.length) {
341
+ added.push(...bArr.slice(aArr.length));
342
+ }
343
+ else if (aArr.length > bArr.length) {
344
+ removed.push(...aArr.slice(bArr.length));
345
+ }
346
+ // Equal counts: same identity present in both → no event emitted, regardless
347
+ // of position changes. Pure positional shifts are not changes.
348
+ }
349
+ if (added.length === 0 && removed.length === 0)
350
+ return null;
351
+ return { added, removed };
352
+ }
353
+ function canonicalAttrs(attrs) {
354
+ const out = {};
355
+ for (const key of Object.keys(attrs).sort())
356
+ out[key] = attrs[key];
357
+ return out;
358
+ }
359
+ //# sourceMappingURL=page-serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-serializer.js","sourceRoot":"","sources":["../../../src/server/services/page-serializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * PageVersionService — append-only versioning of markdown pages (M17 Phase 4).
3
+ * Parallel to VersionService but for filesystem pages. Each capture produces
4
+ * one row in `page_version` with `release_id = NULL` (assigned by
5
+ * `releaseService.createRelease`).
6
+ */
7
+ import type Database from 'better-sqlite3';
8
+ import { PageSerializer, type PageSnapshotData } from './page-serializer.js';
9
+ export type PageChangedBy = 'user' | 'agent' | 'filesystem';
10
+ export type PageOp = 'create' | 'update' | 'delete';
11
+ /**
12
+ * Dyskryminator źródła w `page_version`. `'page'` = pagesDir (M02), `'brief'` =
13
+ * briefsDir (M21). Filtruje briefy z release snapshot/diff/restore — brief jest
14
+ * artefaktem POST-release, nie częścią release'u (M17 spec, sekcja m17top001).
15
+ */
16
+ export type PageKind = 'page' | 'brief';
17
+ export interface PageVersionListItem {
18
+ id: number;
19
+ path: string;
20
+ version: number;
21
+ op: PageOp;
22
+ changedBy: PageChangedBy;
23
+ releaseId: number | null;
24
+ serializerVersion: string;
25
+ createdAt: string;
26
+ /** Human-readable opis zmiany. Null = brak (filesystem watcher, legacy). */
27
+ changeSummary: string | null;
28
+ }
29
+ export interface PageVersionDetail extends PageVersionListItem {
30
+ data: PageSnapshotData;
31
+ }
32
+ export declare class PageVersionService {
33
+ private db;
34
+ private serializer;
35
+ constructor(db: Database.Database, serializer: PageSerializer);
36
+ /**
37
+ * Capture a new version of a page. For `op = 'delete'`, the caller must
38
+ * provide the last-known content (since the file is gone) — used to build
39
+ * a tombstone snapshot.
40
+ *
41
+ * M21 (m02multidir): caller can pass an alternative `serializer` so this
42
+ * single shared `PageVersionService` can capture both `pagesDir` and
43
+ * `briefsDir` files. Each `PageSerializer` is bound to a specific
44
+ * `PagesService` (= rootDir) at construction time; the path-keyed
45
+ * `page_version` table itself is rootDir-agnostic.
46
+ */
47
+ recordVersion(relPath: string, op: PageOp, changedBy: PageChangedBy, fallbackContent?: string, serializer?: PageSerializer, kind?: PageKind, changeSummary?: string | null): Promise<PageVersionListItem>;
48
+ listVersions(relPath: string): PageVersionListItem[];
49
+ getVersion(relPath: string, version: number): PageVersionDetail | null;
50
+ /**
51
+ * M17: latest captured version of a page at-or-before a given release.
52
+ * Mirrors VersionService.getLatestVersionForEntity.
53
+ */
54
+ getLatestForPath(relPath: string, releaseId?: number | null): PageVersionDetail | null;
55
+ /** True when this path has any captured version. Used by initial-sync hook. */
56
+ hasAny(relPath: string): boolean;
57
+ /** Distinct paths captured at-or-before a given release (or all if undefined). */
58
+ listPathsForRelease(releaseId: number): string[];
59
+ /**
60
+ * Count page captures with `release_id IS NULL` (waiting to be picked up by
61
+ * next release). Excludes briefs — briefs nigdy nie wpadają do release'u
62
+ * (M21 spec, sekcja m21db0001).
63
+ */
64
+ countUnreleased(): number;
65
+ /**
66
+ * Atomic: assign all unreleased page_version rows (kind='page') to a release.
67
+ * Returns the count of rows updated. Briefy (kind='brief') NIGDY nie wpadają
68
+ * do release'u — mają własną oś czasu, niezależną od release timeline.
69
+ */
70
+ assignToRelease(releaseId: number): number;
71
+ private nextVersionNumber;
72
+ private synthesizeDeleteFromLastVersion;
73
+ private toListItem;
74
+ private toDetail;
75
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * PageVersionService — append-only versioning of markdown pages (M17 Phase 4).
3
+ * Parallel to VersionService but for filesystem pages. Each capture produces
4
+ * one row in `page_version` with `release_id = NULL` (assigned by
5
+ * `releaseService.createRelease`).
6
+ */
7
+ export class PageVersionService {
8
+ db;
9
+ serializer;
10
+ constructor(db, serializer) {
11
+ this.db = db;
12
+ this.serializer = serializer;
13
+ }
14
+ /**
15
+ * Capture a new version of a page. For `op = 'delete'`, the caller must
16
+ * provide the last-known content (since the file is gone) — used to build
17
+ * a tombstone snapshot.
18
+ *
19
+ * M21 (m02multidir): caller can pass an alternative `serializer` so this
20
+ * single shared `PageVersionService` can capture both `pagesDir` and
21
+ * `briefsDir` files. Each `PageSerializer` is bound to a specific
22
+ * `PagesService` (= rootDir) at construction time; the path-keyed
23
+ * `page_version` table itself is rootDir-agnostic.
24
+ */
25
+ async recordVersion(relPath, op, changedBy, fallbackContent, serializer, kind = 'page', changeSummary) {
26
+ const ser = serializer ?? this.serializer;
27
+ const data = op === 'delete' && fallbackContent !== undefined
28
+ ? ser.snapshotFromContent(relPath, fallbackContent)
29
+ : op === 'delete'
30
+ ? this.synthesizeDeleteFromLastVersion(relPath)
31
+ : await ser.snapshot(relPath);
32
+ const next = this.nextVersionNumber(relPath);
33
+ const summary = typeof changeSummary === 'string' && changeSummary.length > 0
34
+ ? changeSummary
35
+ : null;
36
+ const info = this.db
37
+ .prepare(`INSERT INTO page_version (path, version, data, serializer_version, op, changed_by, kind, change_summary)
38
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
39
+ .run(relPath, next, JSON.stringify(data), ser.version, op, changedBy, kind, summary);
40
+ const row = this.db
41
+ .prepare(`SELECT * FROM page_version WHERE id = ?`)
42
+ .get(info.lastInsertRowid);
43
+ return this.toListItem(row);
44
+ }
45
+ listVersions(relPath) {
46
+ const rows = this.db
47
+ .prepare(`SELECT * FROM page_version WHERE path = ? ORDER BY version DESC`)
48
+ .all(relPath);
49
+ return rows.map((r) => this.toListItem(r));
50
+ }
51
+ getVersion(relPath, version) {
52
+ const row = this.db
53
+ .prepare(`SELECT * FROM page_version WHERE path = ? AND version = ?`)
54
+ .get(relPath, version);
55
+ return row ? this.toDetail(row) : null;
56
+ }
57
+ /**
58
+ * M17: latest captured version of a page at-or-before a given release.
59
+ * Mirrors VersionService.getLatestVersionForEntity.
60
+ */
61
+ getLatestForPath(relPath, releaseId) {
62
+ let row;
63
+ if (releaseId === undefined) {
64
+ row = this.db
65
+ .prepare(`SELECT * FROM page_version WHERE path = ?
66
+ ORDER BY version DESC LIMIT 1`)
67
+ .get(relPath);
68
+ }
69
+ else if (releaseId === null) {
70
+ row = this.db
71
+ .prepare(`SELECT * FROM page_version WHERE path = ? AND release_id IS NULL
72
+ ORDER BY version DESC LIMIT 1`)
73
+ .get(relPath);
74
+ }
75
+ else {
76
+ row = this.db
77
+ .prepare(`SELECT * FROM page_version
78
+ WHERE path = ? AND release_id IS NOT NULL AND release_id <= ?
79
+ ORDER BY version DESC LIMIT 1`)
80
+ .get(relPath, releaseId);
81
+ }
82
+ return row ? this.toDetail(row) : null;
83
+ }
84
+ /** True when this path has any captured version. Used by initial-sync hook. */
85
+ hasAny(relPath) {
86
+ const row = this.db
87
+ .prepare(`SELECT 1 FROM page_version WHERE path = ? LIMIT 1`)
88
+ .get(relPath);
89
+ return !!row;
90
+ }
91
+ /** Distinct paths captured at-or-before a given release (or all if undefined). */
92
+ listPathsForRelease(releaseId) {
93
+ const rows = this.db
94
+ .prepare(`SELECT DISTINCT path FROM page_version WHERE release_id = ? ORDER BY path`)
95
+ .all(releaseId);
96
+ return rows.map((r) => r.path);
97
+ }
98
+ /**
99
+ * Count page captures with `release_id IS NULL` (waiting to be picked up by
100
+ * next release). Excludes briefs — briefs nigdy nie wpadają do release'u
101
+ * (M21 spec, sekcja m21db0001).
102
+ */
103
+ countUnreleased() {
104
+ const row = this.db
105
+ .prepare(`SELECT COUNT(*) AS n FROM page_version WHERE release_id IS NULL AND kind = 'page'`)
106
+ .get();
107
+ return row.n;
108
+ }
109
+ /**
110
+ * Atomic: assign all unreleased page_version rows (kind='page') to a release.
111
+ * Returns the count of rows updated. Briefy (kind='brief') NIGDY nie wpadają
112
+ * do release'u — mają własną oś czasu, niezależną od release timeline.
113
+ */
114
+ assignToRelease(releaseId) {
115
+ const info = this.db
116
+ .prepare(`UPDATE page_version SET release_id = ? WHERE release_id IS NULL AND kind = 'page'`)
117
+ .run(releaseId);
118
+ return Number(info.changes);
119
+ }
120
+ nextVersionNumber(relPath) {
121
+ const row = this.db
122
+ .prepare(`SELECT MAX(version) AS v FROM page_version WHERE path = ?`)
123
+ .get(relPath);
124
+ return (row.v ?? 0) + 1;
125
+ }
126
+ synthesizeDeleteFromLastVersion(relPath) {
127
+ const last = this.getLatestForPath(relPath);
128
+ if (last)
129
+ return last.data;
130
+ // No prior version — we don't have content. Tombstone with empty content.
131
+ return {
132
+ path: relPath,
133
+ content: '',
134
+ frontmatter: {},
135
+ anchors: [],
136
+ xml_refs: [],
137
+ };
138
+ }
139
+ toListItem(row) {
140
+ return {
141
+ id: row.id,
142
+ path: row.path,
143
+ version: row.version,
144
+ op: row.op,
145
+ changedBy: row.changed_by,
146
+ releaseId: row.release_id,
147
+ serializerVersion: row.serializer_version,
148
+ createdAt: row.created_at,
149
+ changeSummary: row.change_summary,
150
+ };
151
+ }
152
+ toDetail(row) {
153
+ return {
154
+ ...this.toListItem(row),
155
+ data: JSON.parse(row.data),
156
+ };
157
+ }
158
+ }
159
+ //# sourceMappingURL=page-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-version.js","sourceRoot":"","sources":["../../../src/server/services/page-version.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * M21 / M02 (m02fmidx): in-memory index of YAML frontmatter for every markdown
3
+ * file under both `pagesDir` and `briefsDir`. Fed by both `PagesWatcher`
4
+ * instances. Provides synchronous lookups for:
5
+ * - hidden-tree filter (`pagesRouter` excludes pages with `frontmatter.type === 'brief'`)
6
+ * - `briefService.listBriefs()` (find by `frontmatter.type === 'brief'`)
7
+ * - any future module that wants to discover pages by frontmatter type
8
+ *
9
+ * Pattern derived from `TodosIndexerService` / `PagesLinkIndexerService`:
10
+ * debounced reindex per file, in-memory `Map<path, Record>`, WS broadcast.
11
+ */
12
+ import type { PagesService } from './pages.js';
13
+ import type { WsGateway } from '../ws/gateway.js';
14
+ import type { PagesRootDir } from '../../shared/types.js';
15
+ export interface FrontmatterRecord {
16
+ rootDir: PagesRootDir;
17
+ frontmatter: Record<string, unknown>;
18
+ }
19
+ export interface FrontmatterFindOptions {
20
+ rootDir?: PagesRootDir;
21
+ }
22
+ export declare class PagesFrontmatterIndexer {
23
+ private pages;
24
+ private briefs;
25
+ private ws;
26
+ private debounceMs;
27
+ private pending;
28
+ /** Composite key `${rootDir}:${path}` so the same path could theoretically
29
+ * exist in both roots without collision (defensive — collision would be a
30
+ * config-misconfiguration, but indexer must remain correct). */
31
+ private byKey;
32
+ constructor(pages: PagesService, briefs: PagesService, ws: WsGateway);
33
+ private rootFor;
34
+ private key;
35
+ schedulePage(rootDir: PagesRootDir, relPath: string): void;
36
+ handleUnlink(rootDir: PagesRootDir, relPath: string): void;
37
+ indexAll(): Promise<void>;
38
+ indexPage(rootDir: PagesRootDir, relPath: string, opts?: {
39
+ silent?: boolean;
40
+ }): Promise<void>;
41
+ getFrontmatter(rootDir: PagesRootDir, relPath: string): Record<string, unknown> | null;
42
+ /**
43
+ * Find paths whose frontmatter has `type === <type>`. Optionally restrict
44
+ * to a single rootDir (defaults to all). Returns sorted by path.
45
+ */
46
+ findByFrontmatterType(type: string, opts?: FrontmatterFindOptions): Array<{
47
+ rootDir: PagesRootDir;
48
+ path: string;
49
+ frontmatter: Record<string, unknown>;
50
+ }>;
51
+ }