@svenroth-ai/shipwright 0.24.7-next.0 → 0.26.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 (239) hide show
  1. package/client/dist/assets/{EmbeddedTerminal-D2BLGWdW.js → EmbeddedTerminal-D3wpPNZP.js} +20 -20
  2. package/client/dist/assets/{abnfDiagram-VRR7QNED-C-W_2Jd4.js → abnfDiagram-VRR7QNED-BkLIltB3.js} +1 -1
  3. package/client/dist/assets/{arc-CpqwESP5.js → arc-Sw-Gh0nI.js} +1 -1
  4. package/client/dist/assets/{architectureDiagram-ZJ3FMSHR-DZVZ895V.js → architectureDiagram-ZJ3FMSHR-rdxUi9Ks.js} +1 -1
  5. package/client/dist/assets/{blockDiagram-677ZJIJ3-CCCZiAA7.js → blockDiagram-677ZJIJ3-Ch_9dj8a.js} +1 -1
  6. package/client/dist/assets/{c4Diagram-LMCZKHZV-Bg1beZAE.js → c4Diagram-LMCZKHZV-CkFlO65x.js} +1 -1
  7. package/client/dist/assets/channel-BYPbLjRl.js +1 -0
  8. package/client/dist/assets/{chunk-2Q5K7J3B-CoaXSarh.js → chunk-2Q5K7J3B-CypX83xu.js} +1 -1
  9. package/client/dist/assets/{chunk-32BRIVSS-CeFXS-CM.js → chunk-32BRIVSS-DxVLYGdl.js} +1 -1
  10. package/client/dist/assets/{chunk-5VM5RSS4-QyJMVe0m.js → chunk-5VM5RSS4-Cxk1evhx.js} +1 -1
  11. package/client/dist/assets/{chunk-EX3LRPZG-BIOtWVF8.js → chunk-EX3LRPZG-n9q5S4yJ.js} +1 -1
  12. package/client/dist/assets/{chunk-JWPE2WC7-Dcq-lWyX.js → chunk-JWPE2WC7-jeL4xvir.js} +1 -1
  13. package/client/dist/assets/{chunk-MOJQB5TN-C95323ja.js → chunk-MOJQB5TN-DDSHN0cj.js} +1 -1
  14. package/client/dist/assets/{chunk-RYQCIY6F-C0HPwpWy.js → chunk-RYQCIY6F-C0bo383g.js} +1 -1
  15. package/client/dist/assets/{chunk-V7JOEXUC-BPrTbZqA.js → chunk-V7JOEXUC-C0jDXXAU.js} +1 -1
  16. package/client/dist/assets/{chunk-VR4S4FIN--BCnNoqt.js → chunk-VR4S4FIN-h-Rr4Pn2.js} +1 -1
  17. package/client/dist/assets/{chunk-XXDRQBXY-Dj8vtcXf.js → chunk-XXDRQBXY-BexSo0-s.js} +1 -1
  18. package/client/dist/assets/classDiagram-OUVF2IWQ-CsFIeTju.js +1 -0
  19. package/client/dist/assets/classDiagram-v2-EOCWNBFH-CsFIeTju.js +1 -0
  20. package/client/dist/assets/{cose-bilkent-JH36ORCC-y51otZKz.js → cose-bilkent-JH36ORCC-BQXzaioj.js} +1 -1
  21. package/client/dist/assets/{cynefin-VYW2F7L2-BRfS3cHo.js → cynefin-VYW2F7L2-BJIofhfe.js} +1 -1
  22. package/client/dist/assets/{cynefinDiagram-TSTJHNR4-Dpg2RtfL.js → cynefinDiagram-TSTJHNR4-DmPqTM1T.js} +1 -1
  23. package/client/dist/assets/{dagre-VKFMJZFB-BdZtXgKZ.js → dagre-VKFMJZFB-1xljvw6X.js} +1 -1
  24. package/client/dist/assets/{diagram-FQU43EPY-K-RCwWxW.js → diagram-FQU43EPY-iyL9muCG.js} +1 -1
  25. package/client/dist/assets/{diagram-G47NLZAW-CHNn7F2-.js → diagram-G47NLZAW-DREp2Th6.js} +1 -1
  26. package/client/dist/assets/{diagram-NH7WQ7WH-B3zu6xib.js → diagram-NH7WQ7WH-h0X3Is2S.js} +1 -1
  27. package/client/dist/assets/{diagram-OA4YK3LP-Wp5ju7L7.js → diagram-OA4YK3LP-Bj8YZRFJ.js} +1 -1
  28. package/client/dist/assets/{diagram-WEI45ONY-C94GpsRk.js → diagram-WEI45ONY-BZOf805d.js} +1 -1
  29. package/client/dist/assets/{ebnfDiagram-CCIWWBDH-DXrTPOrP.js → ebnfDiagram-CCIWWBDH-DO5JnXda.js} +1 -1
  30. package/client/dist/assets/{erDiagram-Q63AITRT-CGejnW0f.js → erDiagram-Q63AITRT-DRgcqg1T.js} +1 -1
  31. package/client/dist/assets/{flowDiagram-23GEKE2U-CFJMM637.js → flowDiagram-23GEKE2U-C3J9QmrW.js} +1 -1
  32. package/client/dist/assets/{ganttDiagram-NO4QXBWP-DnaH94Su.js → ganttDiagram-NO4QXBWP-BIEl3Tkm.js} +1 -1
  33. package/client/dist/assets/{gitGraphDiagram-IHSO6WYX-DT-D0gbn.js → gitGraphDiagram-IHSO6WYX-BNF0tFWC.js} +1 -1
  34. package/client/dist/assets/index-BnTOrFHb.js +829 -0
  35. package/client/dist/assets/index-CYPc6qxw.css +1 -0
  36. package/client/dist/assets/{infoDiagram-FWYZ7A6U-DW3Ps00w.js → infoDiagram-FWYZ7A6U-DEyFxiyY.js} +1 -1
  37. package/client/dist/assets/{ishikawaDiagram-FXEZZL3T-DjxjIT3n.js → ishikawaDiagram-FXEZZL3T-B_ehlg3I.js} +1 -1
  38. package/client/dist/assets/{journeyDiagram-5HDEW3XC-DTQRI93Y.js → journeyDiagram-5HDEW3XC-Dp00FyJS.js} +1 -1
  39. package/client/dist/assets/{kanban-definition-HUTT4EX6-BeDvbiEs.js → kanban-definition-HUTT4EX6-CTAf16q8.js} +1 -1
  40. package/client/dist/assets/{linear-B4foxDlh.js → linear-9vNUgmYd.js} +1 -1
  41. package/client/dist/assets/{mermaid.core-c-L4qgSB.js → mermaid.core-A6tjaEVD.js} +4 -4
  42. package/client/dist/assets/{mindmap-definition-LN4V7U3C-dh8v0J8T.js → mindmap-definition-LN4V7U3C-DRW3bmCY.js} +1 -1
  43. package/client/dist/assets/{pegDiagram-2B236MQR-D5vNrtFh.js → pegDiagram-2B236MQR-DJFCjHp2.js} +1 -1
  44. package/client/dist/assets/{pieDiagram-ENE6RG2P-CIjg_6lR.js → pieDiagram-ENE6RG2P-KRd-sGvC.js} +1 -1
  45. package/client/dist/assets/{quadrantDiagram-ABIIQ3AL-CF37qWQD.js → quadrantDiagram-ABIIQ3AL-9TLZE3Hu.js} +1 -1
  46. package/client/dist/assets/{railroadDiagram-RFXS5EU6-x0Hn30Kj.js → railroadDiagram-RFXS5EU6-y4tLtjXg.js} +1 -1
  47. package/client/dist/assets/{requirementDiagram-TGXJPOKE-BE2QnVbN.js → requirementDiagram-TGXJPOKE-B9EOQDQM.js} +1 -1
  48. package/client/dist/assets/{sankeyDiagram-HTMAVEWB-CUv6cIlV.js → sankeyDiagram-HTMAVEWB-zfwiDzkT.js} +1 -1
  49. package/client/dist/assets/{sequenceDiagram-DBY2YBRQ-C3ACj5LS.js → sequenceDiagram-DBY2YBRQ-DW1LWepL.js} +1 -1
  50. package/client/dist/assets/{sizeCapture-X5ZJPWSS-DTMIb5gX.js → sizeCapture-X5ZJPWSS-BM81Mik0.js} +1 -1
  51. package/client/dist/assets/{stateDiagram-2N3HPSRC-DI1Z8P74.js → stateDiagram-2N3HPSRC-D0EMIw1w.js} +1 -1
  52. package/client/dist/assets/stateDiagram-v2-6OUMAXLB-B3E4_xxT.js +1 -0
  53. package/client/dist/assets/{swimlanes-5IMT3BWC-CLSr9w29.js → swimlanes-5IMT3BWC-CKXNCX6M.js} +2 -2
  54. package/client/dist/assets/swimlanesDiagram-G3AALYLV-BegQBqnC.js +8 -0
  55. package/client/dist/assets/{timeline-definition-FHXFAJF6-BTWmUhDh.js → timeline-definition-FHXFAJF6-ByzIfvL5.js} +1 -1
  56. package/client/dist/assets/{vennDiagram-L72KCM5P-Ce1dlLCM.js → vennDiagram-L72KCM5P-Xep38xBH.js} +1 -1
  57. package/client/dist/assets/{wardleyDiagram-EHGQE667-ClOE-aae.js → wardleyDiagram-EHGQE667-DKWDpx6g.js} +1 -1
  58. package/client/dist/assets/{xychartDiagram-FW5EYKEG-Fa2pqWKw.js → xychartDiagram-FW5EYKEG-BGcwZTnu.js} +1 -1
  59. package/client/dist/index.html +27 -27
  60. package/lib/claude-cli.mjs +173 -173
  61. package/lib/preflight.mjs +252 -252
  62. package/lib/probe-path.mjs +84 -84
  63. package/lib/server.mjs +369 -369
  64. package/lib/util.mjs +157 -157
  65. package/lib/win32-spawn.mjs +253 -253
  66. package/package.json +1 -1
  67. package/scripts/deploy-procs.mjs +208 -208
  68. package/scripts/deploy-swap.mjs +276 -276
  69. package/scripts/kill-targets.js +140 -140
  70. package/scripts/repair-claude-json.mjs +295 -295
  71. package/server/dist/config/default-actions.json +90 -90
  72. package/server/dist/core/grade-runner.d.ts +4 -4
  73. package/server/dist/core/grade-runner.d.ts.map +1 -1
  74. package/server/dist/core/grade-runner.js +51 -26
  75. package/server/dist/core/grade-runner.js.map +1 -1
  76. package/server/dist/core/grade-target.d.ts +8 -0
  77. package/server/dist/core/grade-target.d.ts.map +1 -1
  78. package/server/dist/core/grade-target.js +10 -0
  79. package/server/dist/core/grade-target.js.map +1 -1
  80. package/server/dist/core/mission-context/association.d.ts +46 -0
  81. package/server/dist/core/mission-context/association.d.ts.map +1 -1
  82. package/server/dist/core/mission-context/association.js +69 -0
  83. package/server/dist/core/mission-context/association.js.map +1 -1
  84. package/server/dist/core/mission-context/resolver-iterate.d.ts +6 -0
  85. package/server/dist/core/mission-context/resolver-iterate.d.ts.map +1 -0
  86. package/server/dist/core/mission-context/resolver-iterate.js +202 -0
  87. package/server/dist/core/mission-context/resolver-iterate.js.map +1 -0
  88. package/server/dist/core/mission-context/resolver-parts.d.ts +20 -0
  89. package/server/dist/core/mission-context/resolver-parts.d.ts.map +1 -1
  90. package/server/dist/core/mission-context/resolver-parts.js +92 -0
  91. package/server/dist/core/mission-context/resolver-parts.js.map +1 -1
  92. package/server/dist/core/mission-context/resolver.d.ts +1 -1
  93. package/server/dist/core/mission-context/resolver.d.ts.map +1 -1
  94. package/server/dist/core/mission-context/resolver.js +17 -199
  95. package/server/dist/core/mission-context/resolver.js.map +1 -1
  96. package/server/dist/core/mission-context/run-id-recovery.d.ts +21 -5
  97. package/server/dist/core/mission-context/run-id-recovery.d.ts.map +1 -1
  98. package/server/dist/core/mission-context/run-id-recovery.js +32 -5
  99. package/server/dist/core/mission-context/run-id-recovery.js.map +1 -1
  100. package/server/dist/core/mission-context/scenario.d.ts +18 -11
  101. package/server/dist/core/mission-context/scenario.d.ts.map +1 -1
  102. package/server/dist/core/mission-context/scenario.js +40 -3
  103. package/server/dist/core/mission-context/scenario.js.map +1 -1
  104. package/server/dist/core/path-guard.d.ts +1 -1
  105. package/server/dist/core/path-guard.d.ts.map +1 -1
  106. package/server/dist/core/path-guard.js +9 -2
  107. package/server/dist/core/path-guard.js.map +1 -1
  108. package/server/dist/core/shipslog-docs-reader.d.ts +4 -0
  109. package/server/dist/core/shipslog-docs-reader.d.ts.map +1 -0
  110. package/server/dist/core/shipslog-docs-reader.js +181 -0
  111. package/server/dist/core/shipslog-docs-reader.js.map +1 -0
  112. package/server/dist/core/shipslog-docs-types.d.ts +15 -0
  113. package/server/dist/core/shipslog-docs-types.d.ts.map +1 -0
  114. package/server/dist/core/shipslog-docs-types.js +14 -0
  115. package/server/dist/core/shipslog-docs-types.js.map +1 -0
  116. package/server/dist/core/triage-cli-runner.d.ts.map +1 -1
  117. package/server/dist/core/triage-cli-runner.js +29 -10
  118. package/server/dist/core/triage-cli-runner.js.map +1 -1
  119. package/server/dist/core/uv-runner.d.ts +23 -0
  120. package/server/dist/core/uv-runner.d.ts.map +1 -0
  121. package/server/dist/core/uv-runner.js +39 -0
  122. package/server/dist/core/uv-runner.js.map +1 -0
  123. package/server/dist/external/design-review/serve.js +27 -27
  124. package/server/dist/external/file/exists-routes.d.ts +7 -0
  125. package/server/dist/external/file/exists-routes.d.ts.map +1 -0
  126. package/server/dist/external/file/exists-routes.js +91 -0
  127. package/server/dist/external/file/exists-routes.js.map +1 -0
  128. package/server/dist/external/mission-context/association-write.d.ts +22 -0
  129. package/server/dist/external/mission-context/association-write.d.ts.map +1 -0
  130. package/server/dist/external/mission-context/association-write.js +90 -0
  131. package/server/dist/external/mission-context/association-write.js.map +1 -0
  132. package/server/dist/external/mission-context/routes.d.ts.map +1 -1
  133. package/server/dist/external/mission-context/routes.js +18 -31
  134. package/server/dist/external/mission-context/routes.js.map +1 -1
  135. package/server/dist/external/org/audit-log.d.ts +27 -0
  136. package/server/dist/external/org/audit-log.d.ts.map +1 -0
  137. package/server/dist/external/org/audit-log.js +92 -0
  138. package/server/dist/external/org/audit-log.js.map +1 -0
  139. package/server/dist/external/org/beat-register.d.ts +15 -22
  140. package/server/dist/external/org/beat-register.d.ts.map +1 -1
  141. package/server/dist/external/org/beat-register.js +37 -32
  142. package/server/dist/external/org/beat-register.js.map +1 -1
  143. package/server/dist/external/org/file-read.d.ts +16 -0
  144. package/server/dist/external/org/file-read.d.ts.map +1 -1
  145. package/server/dist/external/org/file-read.js +86 -46
  146. package/server/dist/external/org/file-read.js.map +1 -1
  147. package/server/dist/external/org/file-write-core.d.ts +18 -0
  148. package/server/dist/external/org/file-write-core.d.ts.map +1 -0
  149. package/server/dist/external/org/file-write-core.js +97 -0
  150. package/server/dist/external/org/file-write-core.js.map +1 -0
  151. package/server/dist/external/org/file-write.d.ts +25 -0
  152. package/server/dist/external/org/file-write.d.ts.map +1 -1
  153. package/server/dist/external/org/file-write.js +82 -132
  154. package/server/dist/external/org/file-write.js.map +1 -1
  155. package/server/dist/external/org/last-run.d.ts +25 -16
  156. package/server/dist/external/org/last-run.d.ts.map +1 -1
  157. package/server/dist/external/org/last-run.js +78 -64
  158. package/server/dist/external/org/last-run.js.map +1 -1
  159. package/server/dist/external/org/lead-doc-read.d.ts +21 -0
  160. package/server/dist/external/org/lead-doc-read.d.ts.map +1 -0
  161. package/server/dist/external/org/lead-doc-read.js +84 -0
  162. package/server/dist/external/org/lead-doc-read.js.map +1 -0
  163. package/server/dist/external/org/mount.d.ts +12 -0
  164. package/server/dist/external/org/mount.d.ts.map +1 -0
  165. package/server/dist/external/org/mount.js +34 -0
  166. package/server/dist/external/org/mount.js.map +1 -0
  167. package/server/dist/external/org/org-chart-lookup.d.ts +13 -0
  168. package/server/dist/external/org/org-chart-lookup.d.ts.map +1 -1
  169. package/server/dist/external/org/org-chart-lookup.js +40 -5
  170. package/server/dist/external/org/org-chart-lookup.js.map +1 -1
  171. package/server/dist/external/org/org-chart.d.ts +21 -12
  172. package/server/dist/external/org/org-chart.d.ts.map +1 -1
  173. package/server/dist/external/org/org-chart.js +50 -32
  174. package/server/dist/external/org/org-chart.js.map +1 -1
  175. package/server/dist/external/org/role-extract.d.ts +8 -0
  176. package/server/dist/external/org/role-extract.d.ts.map +1 -0
  177. package/server/dist/external/org/role-extract.js +72 -0
  178. package/server/dist/external/org/role-extract.js.map +1 -0
  179. package/server/dist/external/org/usage.d.ts +15 -11
  180. package/server/dist/external/org/usage.d.ts.map +1 -1
  181. package/server/dist/external/org/usage.js +64 -54
  182. package/server/dist/external/org/usage.js.map +1 -1
  183. package/server/dist/external/routes.d.ts +1 -1
  184. package/server/dist/external/routes.d.ts.map +1 -1
  185. package/server/dist/external/routes.js +19 -17
  186. package/server/dist/external/routes.js.map +1 -1
  187. package/server/dist/external/shipslog-docs/routes.d.ts +10 -0
  188. package/server/dist/external/shipslog-docs/routes.d.ts.map +1 -0
  189. package/server/dist/external/shipslog-docs/routes.js +41 -0
  190. package/server/dist/external/shipslog-docs/routes.js.map +1 -0
  191. package/server/dist/routes/grade.d.ts.map +1 -1
  192. package/server/dist/routes/grade.js +3 -2
  193. package/server/dist/routes/grade.js.map +1 -1
  194. package/server/dist/routes/org-leads-composite.d.ts +21 -0
  195. package/server/dist/routes/org-leads-composite.d.ts.map +1 -0
  196. package/server/dist/routes/org-leads-composite.js +95 -0
  197. package/server/dist/routes/org-leads-composite.js.map +1 -0
  198. package/server/dist/routes/org.d.ts +15 -0
  199. package/server/dist/routes/org.d.ts.map +1 -0
  200. package/server/dist/routes/org.js +198 -0
  201. package/server/dist/routes/org.js.map +1 -0
  202. package/server/dist/terminal/pty-manager.d.ts +9 -0
  203. package/server/dist/terminal/pty-manager.d.ts.map +1 -1
  204. package/server/dist/terminal/pty-manager.js +15 -0
  205. package/server/dist/terminal/pty-manager.js.map +1 -1
  206. package/server/dist/terminal/replay-snapshot.d.ts +10 -1
  207. package/server/dist/terminal/replay-snapshot.d.ts.map +1 -1
  208. package/server/dist/terminal/replay-snapshot.js +36 -1
  209. package/server/dist/terminal/replay-snapshot.js.map +1 -1
  210. package/server/dist/terminal/ws-upgrade-handler.d.ts +17 -1
  211. package/server/dist/terminal/ws-upgrade-handler.d.ts.map +1 -1
  212. package/server/dist/terminal/ws-upgrade-handler.fixtures.d.ts +1 -0
  213. package/server/dist/terminal/ws-upgrade-handler.fixtures.d.ts.map +1 -1
  214. package/server/dist/terminal/ws-upgrade-handler.fixtures.js +3 -2
  215. package/server/dist/terminal/ws-upgrade-handler.fixtures.js.map +1 -1
  216. package/server/dist/terminal/ws-upgrade-handler.js +45 -4
  217. package/server/dist/terminal/ws-upgrade-handler.js.map +1 -1
  218. package/server/dist/test/python-spawn-guard-util.d.ts +14 -0
  219. package/server/dist/test/python-spawn-guard-util.d.ts.map +1 -0
  220. package/server/dist/test/python-spawn-guard-util.js +124 -0
  221. package/server/dist/test/python-spawn-guard-util.js.map +1 -0
  222. package/server/dist/types/org.d.ts +115 -0
  223. package/server/dist/types/org.d.ts.map +1 -0
  224. package/server/dist/types/org.js +16 -0
  225. package/server/dist/types/org.js.map +1 -0
  226. package/server/package.json +1 -1
  227. package/server/profiles/PROFILE_SCHEMA_VERSION +1 -1
  228. package/server/profiles/README.md +27 -27
  229. package/server/profiles/python-plugin-monorepo.json +35 -35
  230. package/server/profiles/supabase-nextjs.json +253 -253
  231. package/server/profiles/vite-hono.json +92 -92
  232. package/client/dist/assets/MarkdownEditorModal-CP5yG9OU.js +0 -212
  233. package/client/dist/assets/channel-BNXbCvDS.js +0 -1
  234. package/client/dist/assets/classDiagram-OUVF2IWQ-w-wCtLx3.js +0 -1
  235. package/client/dist/assets/classDiagram-v2-EOCWNBFH-w-wCtLx3.js +0 -1
  236. package/client/dist/assets/index-CU2QJgvx.js +0 -609
  237. package/client/dist/assets/index-ftvVcUT8.css +0 -1
  238. package/client/dist/assets/stateDiagram-v2-6OUMAXLB-DvwiHlJv.js +0 -1
  239. package/client/dist/assets/swimlanesDiagram-G3AALYLV-JTQZTlZ3.js +0 -8
@@ -0,0 +1,181 @@
1
+ /*
2
+ * shipslog-docs-reader.ts — pure, fs-backed reader for the Ship's-Log
3
+ * Documents panel (iterate-2026-08-31-shipslog-documents-panel). Curates
4
+ * four groups from a project's own tree — no client input beyond
5
+ * `projectRoot` (already resolved server-side from a trusted project
6
+ * record), so every path here is either a fixed constant or discovered by
7
+ * readdir-ing a fixed directory, never client-supplied.
8
+ *
9
+ * "Requirements" = the ur-spec per PLANNING SECTION (a direct subdirectory
10
+ * of .shipwright/planning/ that is not iterate/adr/campaigns and carries
11
+ * its own spec.md) — distinct from "Iterate" (the flat *.md mini-specs
12
+ * under .shipwright/planning/iterate/), which is a SEPARATE tab in the UI
13
+ * (see ShipsLogSpecsTabs.tsx) precisely because they answer different
14
+ * questions ("what did we commit to" vs. "what changed, run by run").
15
+ *
16
+ * Agent Docs / Compliance are a fixed, curated 5-row list each — a file
17
+ * that doesn't exist on disk is skipped silently (no "unavailable" row);
18
+ * these docs are not guaranteed to exist in every clone/fork.
19
+ *
20
+ * Dates are filesystem mtime, not `git log` — cheap even at 200+ iterate
21
+ * specs, and it's already what mtime reflects for these files.
22
+ *
23
+ * CLAUDE.md rule 10 / ADR-044: every path (even a dynamically-readdir'd
24
+ * one) is re-verified with pathGuard + realPathGuard before it is stat'd
25
+ * or returned — the same discipline external/tree/routes.ts applies to a
26
+ * client-supplied path, as defense in depth even though nothing here is
27
+ * client-controlled. `realpathSync(projectRoot)` is hoisted ONCE per read
28
+ * (path-guard.ts's own documented optimization for a batch caller) rather
29
+ * than re-paid on every one of the ~230 iterate-spec entries.
30
+ */
31
+ import { readdir, stat } from "node:fs/promises";
32
+ import { realpathSync } from "node:fs";
33
+ import path from "node:path";
34
+ import { pathGuard, realPathGuard } from "./path-guard.js";
35
+ const AGENT_DOCS = [
36
+ { file: "build_dashboard.md", label: "Dashboard" },
37
+ { file: "architecture.md", label: "Architecture" },
38
+ { file: "decision_log.md", label: "Decision Log" },
39
+ { file: "conventions.md", label: "Conventions" },
40
+ { file: "design_tokens.md", label: "Design Tokens" },
41
+ ];
42
+ const COMPLIANCE_DOCS = [
43
+ { file: "dashboard.md", label: "Dashboard" },
44
+ { file: "traceability-matrix.md", label: "Traceability Matrix" },
45
+ { file: "test-evidence.md", label: "Test Evidence" },
46
+ { file: "change-history.md", label: "Change History" },
47
+ { file: "sbom.md", label: "SBOM" },
48
+ ];
49
+ const PLANNING_SECTION_EXCLUDES = new Set(["iterate", "adr", "campaigns"]);
50
+ /** "01-adopted" → "01 — Adopted"; no dash → the raw name unchanged. */
51
+ function sectionLabel(dirName) {
52
+ const dash = dirName.indexOf("-");
53
+ if (dash === -1)
54
+ return dirName;
55
+ const num = dirName.slice(0, dash);
56
+ const rest = dirName
57
+ .slice(dash + 1)
58
+ .split("-")
59
+ .filter(Boolean)
60
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
61
+ .join(" ");
62
+ return rest ? `${num} — ${rest}` : dirName;
63
+ }
64
+ /** Guard + realpath-verify `relPath`; null if it fails the guard, doesn't
65
+ * exist, or escapes the project root via a symlink (skip-silently caller
66
+ * contract — see module doc). */
67
+ function verifiedAbsolute(projectRoot, realRoot, relPath) {
68
+ const guard = pathGuard(projectRoot, relPath);
69
+ if (!guard.ok)
70
+ return null;
71
+ const real = realPathGuard(projectRoot, guard.absolute, realRoot);
72
+ return real.ok ? real.absolute : null;
73
+ }
74
+ async function mtimeIso(absPath) {
75
+ try {
76
+ const s = await stat(absPath);
77
+ return s.mtime.toISOString();
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ }
83
+ async function curatedRows(projectRoot, realRoot, relDir, files) {
84
+ const rows = [];
85
+ for (const { file, label } of files) {
86
+ const relPath = `${relDir}/${file}`;
87
+ const abs = verifiedAbsolute(projectRoot, realRoot, relPath);
88
+ if (!abs)
89
+ continue; // missing on disk — skip silently, no error row
90
+ const when = await mtimeIso(abs);
91
+ if (when === null)
92
+ continue; // vanished between realpath and stat — skip
93
+ rows.push({ path: relPath, label, when });
94
+ }
95
+ return rows;
96
+ }
97
+ async function readRequirements(projectRoot, realRoot) {
98
+ const planningRel = ".shipwright/planning";
99
+ const guard = pathGuard(projectRoot, planningRel);
100
+ if (!guard.ok)
101
+ return [];
102
+ let entries;
103
+ try {
104
+ entries = await readdir(guard.absolute, { withFileTypes: true });
105
+ }
106
+ catch {
107
+ return [];
108
+ }
109
+ const rows = [];
110
+ for (const d of entries) {
111
+ if (!d.isDirectory() || PLANNING_SECTION_EXCLUDES.has(d.name))
112
+ continue;
113
+ const relPath = `${planningRel}/${d.name}/spec.md`;
114
+ const abs = verifiedAbsolute(projectRoot, realRoot, relPath);
115
+ if (!abs)
116
+ continue; // section without its own spec.md — skip
117
+ const when = await mtimeIso(abs);
118
+ if (when === null)
119
+ continue;
120
+ rows.push({ path: relPath, label: sectionLabel(d.name), when });
121
+ }
122
+ rows.sort((a, b) => a.label.localeCompare(b.label));
123
+ return rows;
124
+ }
125
+ async function readIterateSpecs(projectRoot, realRoot) {
126
+ const relDir = ".shipwright/planning/iterate";
127
+ const guard = pathGuard(projectRoot, relDir);
128
+ if (!guard.ok)
129
+ return [];
130
+ let entries;
131
+ try {
132
+ entries = await readdir(guard.absolute, { withFileTypes: true });
133
+ }
134
+ catch {
135
+ return [];
136
+ }
137
+ const rows = [];
138
+ for (const d of entries) {
139
+ // Flat files only (per the panel's Iterate tab spec) — a subdirectory
140
+ // like campaigns/ or a per-run folder is out of scope here.
141
+ if (!d.isFile() || !d.name.endsWith(".md"))
142
+ continue;
143
+ const relPath = `${relDir}/${d.name}`;
144
+ const abs = verifiedAbsolute(projectRoot, realRoot, relPath);
145
+ if (!abs)
146
+ continue;
147
+ const when = await mtimeIso(abs);
148
+ rows.push({ path: relPath, label: d.name, when });
149
+ }
150
+ // Newest first; a row with no readable mtime sorts last rather than
151
+ // fabricating a position it didn't earn.
152
+ rows.sort((a, b) => {
153
+ if (a.when === b.when)
154
+ return a.label.localeCompare(b.label);
155
+ if (a.when === null)
156
+ return 1;
157
+ if (b.when === null)
158
+ return -1;
159
+ return a.when < b.when ? 1 : -1;
160
+ });
161
+ return rows;
162
+ }
163
+ export async function readShipsLogDocs(projectRoot) {
164
+ let realRoot;
165
+ try {
166
+ realRoot = realpathSync(path.resolve(projectRoot));
167
+ }
168
+ catch {
169
+ // Project root itself unreadable — every group degrades to empty
170
+ // rather than throwing (this is a read-only observer, spec AC-honesty).
171
+ return { requirements: [], iterateSpecs: [], agentDocs: [], compliance: [] };
172
+ }
173
+ const [requirements, iterateSpecs, agentDocs, compliance] = await Promise.all([
174
+ readRequirements(projectRoot, realRoot),
175
+ readIterateSpecs(projectRoot, realRoot),
176
+ curatedRows(projectRoot, realRoot, ".shipwright/agent_docs", AGENT_DOCS),
177
+ curatedRows(projectRoot, realRoot, ".shipwright/compliance", COMPLIANCE_DOCS),
178
+ ]);
179
+ return { requirements, iterateSpecs, agentDocs, compliance };
180
+ }
181
+ //# sourceMappingURL=shipslog-docs-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipslog-docs-reader.js","sourceRoot":"","sources":["../../src/core/shipslog-docs-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface ShipsLogDocRow {
2
+ /** Project-root-relative POSIX path, passed straight to SmartViewerModal. */
3
+ path: string;
4
+ label: string;
5
+ /** ISO mtime, or null when the stat failed after the existence check
6
+ * (a TOCTOU race — treated as "date unknown", never fabricated). */
7
+ when: string | null;
8
+ }
9
+ export interface ShipsLogDocsBundle {
10
+ requirements: ShipsLogDocRow[];
11
+ iterateSpecs: ShipsLogDocRow[];
12
+ agentDocs: ShipsLogDocRow[];
13
+ compliance: ShipsLogDocRow[];
14
+ }
15
+ //# sourceMappingURL=shipslog-docs-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipslog-docs-types.d.ts","sourceRoot":"","sources":["../../src/core/shipslog-docs-types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd;yEACqE;IACrE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B"}
@@ -0,0 +1,14 @@
1
+ /*
2
+ * shipslog-docs-types.ts — shape contract for the Ship's-Log Documents
3
+ * panel read surface (iterate-2026-08-31-shipslog-documents-panel):
4
+ * curated links to a project's Requirements spec(s) (per planning-section
5
+ * ur-spec, .shipwright/planning/<section>/spec.md), Iterate mini-specs
6
+ * (.shipwright/planning/iterate/*.md), Agent Docs and Compliance docs.
7
+ *
8
+ * Split out (not folded into the reader) to match the run-data-types.ts
9
+ * precedent; verbatim-mirrored client-side in
10
+ * client/src/lib/shipsLogDocsApi.ts (ADR-080 — no cross-package import).
11
+ * Drift guard: server/src/test/shipslog-docs-mirror-sync.test.ts.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=shipslog-docs-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipslog-docs-types.js","sourceRoot":"","sources":["../../src/core/shipslog-docs-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -1 +1 @@
1
- {"version":3,"file":"triage-cli-runner.d.ts","sourceRoot":"","sources":["../../src/core/triage-cli-runner.ts"],"names":[],"mappings":"AAeA,OAAO,EAA4E,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE5H,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KACnD,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEnC,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,KAAK,CAAC;IACZ,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAC7B;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAM,GAAG,MAAM,GAAG,IAAI,CAW/H;AAED,eAAO,MAAM,qBAAqB,EAAE,cAsBhC,CAAC;AAML,wBAAsB,uBAAuB,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAIxG;AAMD,0FAA0F;AAC1F,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,eAAe,CAAC,CAgC1B"}
1
+ {"version":3,"file":"triage-cli-runner.d.ts","sourceRoot":"","sources":["../../src/core/triage-cli-runner.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAiD,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAGjG,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KACnD,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEnC,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,KAAK,CAAC;IACZ,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAC7B;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAM,GAAG,MAAM,GAAG,IAAI,CAW/H;AAED,eAAO,MAAM,qBAAqB,EAAE,cAsBhC,CAAC;AAML,wBAAsB,uBAAuB,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAMxG;AAMD,0FAA0F;AAC1F,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,eAAe,CAAC,CAsC1B"}
@@ -3,15 +3,28 @@
3
3
  *
4
4
  * Triage reads remain native TypeScript because they are latency-sensitive and
5
5
  * have no mutual-exclusion requirement. Every transition, however, executes
6
- * the Python CLI so its FileLock owns the compare-and-swap, residence choice,
7
- * schema bootstrap and record-boundary handling. There is deliberately no
6
+ * the Python CLI via `uv run --python ">=3.11"` so its FileLock owns the
7
+ * compare-and-swap, residence choice, schema bootstrap and record-boundary
8
+ * handling — in a Python that actually satisfies triage_cli.py's own floor,
9
+ * not whichever of python3/python/py happened to answer `--version` first
10
+ * (the grade.py sibling of this bug; see `uv-runner.ts`). triage_cli.py has
11
+ * no `pyproject.toml` of its own, so this is `--python`, not `--project`
12
+ * (verified: `uv run --python ">=3.11" triage_cli.py --help` exits 0).
13
+ * `--no-project` is load-bearing, not decorative (Stage-3 doubt review,
14
+ * 2026-08-26): without it, `uv run` walks up from the SPAWNING PROCESS's cwd
15
+ * (never from the script's own path) looking for an ambient `pyproject.toml`
16
+ * to activate — a webui deployment nested inside another Python-tooled
17
+ * checkout would otherwise silently run this script against an unrelated
18
+ * project. `--no-project` makes "no ambient project" structural rather than
19
+ * an accident of this repo currently having none. There is deliberately no
8
20
  * TypeScript append fallback: an unavailable writer disables the UI instead.
9
21
  */
10
22
  import { execFile } from "node:child_process";
11
23
  import { existsSync } from "node:fs";
12
24
  import os from "node:os";
13
25
  import path from "node:path";
14
- import { defaultRun, READINESS_REPAIR_COMMAND, resolvePython, shipwrightCacheRoot } from "./readiness-probe.js";
26
+ import { READINESS_REPAIR_COMMAND, shipwrightCacheRoot } from "./readiness-probe.js";
27
+ import { resolveUv } from "./uv-runner.js";
15
28
  export const TRIAGE_CLI_TIMEOUT_MS = 30_000;
16
29
  /** Resolve the single cache-owned CLI shipped with the Shipwright runtime. */
17
30
  export function resolveTriageCliScript(deps = {}) {
@@ -47,8 +60,9 @@ function unavailable(reason) {
47
60
  export async function triageWriteAvailability(deps = {}) {
48
61
  if (!resolveTriageCliScript(deps))
49
62
  return unavailable("The triage write engine isn't installed.");
50
- if (!(await resolvePython(deps.run ?? defaultRun)))
51
- return unavailable("No working Python (3.11+) was found.");
63
+ if (!(await resolveUv({ run: deps.run, homeDir: deps.homeDir, baseEnv: deps.baseEnv }))) {
64
+ return unavailable("uv isn't installed — triage writes need it to run in a managed Python 3.11+.");
65
+ }
52
66
  return { available: true };
53
67
  }
54
68
  function cleanStderr(stderr) {
@@ -59,13 +73,18 @@ export async function runTriageCli(input, deps = {}) {
59
73
  const script = resolveTriageCliScript(deps);
60
74
  if (!script)
61
75
  return { kind: "engine-unavailable", reason: "The triage write engine isn't installed.", repairCommand: READINESS_REPAIR_COMMAND };
62
- const python = await resolvePython(deps.run ?? defaultRun);
63
- if (!python)
64
- return { kind: "engine-unavailable", reason: "No working Python (3.11+) was found.", repairCommand: READINESS_REPAIR_COMMAND };
76
+ const uv = await resolveUv({ run: deps.run, homeDir: deps.homeDir, baseEnv: deps.baseEnv });
77
+ if (!uv) {
78
+ return {
79
+ kind: "engine-unavailable",
80
+ reason: "uv isn't installed — triage writes need it to run in a managed Python 3.11+.",
81
+ repairCommand: READINESS_REPAIR_COMMAND,
82
+ };
83
+ }
65
84
  const spawn = deps.spawn ?? defaultSpawnTriageCli;
66
- const result = await spawn(python.bin, [script, "--project-root", input.projectRoot, input.operation, input.itemId, ...input.args, "--json"], { timeoutMs: deps.timeoutMs ?? TRIAGE_CLI_TIMEOUT_MS, env: deps.baseEnv ?? process.env });
85
+ const result = await spawn(uv.bin, ["run", "--no-project", "--python", ">=3.11", script, "--project-root", input.projectRoot, input.operation, input.itemId, ...input.args, "--json"], { timeoutMs: deps.timeoutMs ?? TRIAGE_CLI_TIMEOUT_MS, env: uv.env });
67
86
  if (result.code === -1) {
68
- return { kind: "engine-unavailable", reason: "Python couldn't start on this machine.", repairCommand: READINESS_REPAIR_COMMAND };
87
+ return { kind: "engine-unavailable", reason: "uv couldn't start on this machine.", repairCommand: READINESS_REPAIR_COMMAND };
69
88
  }
70
89
  if (result.code === 3)
71
90
  return { kind: "precondition" };
@@ -1 +1 @@
1
- {"version":3,"file":"triage-cli-runner.js","sourceRoot":"","sources":["../../src/core/triage-cli-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"triage-cli-runner.js","sourceRoot":"","sources":["../../src/core/triage-cli-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type RunFn } from "./readiness-probe-run.js";
2
+ export interface UvResolution {
3
+ /** Absolute path (POSIX) or the bare "uv" (win32 — libuv reads PATH from
4
+ * the child env block, so a literal name plus the augmented `env` resolves
5
+ * it; mirrors `defaultRun`'s own win32/POSIX split). */
6
+ bin: string;
7
+ /** PATH-augmented env to hand to the actual `uv run` spawn. */
8
+ env: NodeJS.ProcessEnv;
9
+ }
10
+ export interface ResolveUvDeps {
11
+ /** `--version` runner used for the presence probe (test seam). */
12
+ run?: RunFn;
13
+ platform?: NodeJS.Platform;
14
+ homeDir?: string;
15
+ /** Base env the augmented PATH is layered onto (defaults to process.env). */
16
+ baseEnv?: NodeJS.ProcessEnv;
17
+ }
18
+ /**
19
+ * Test-run `uv --version`; on success resolve the bin + env a real `uv run`
20
+ * spawn needs. Null means "uv isn't there" — not "python isn't there".
21
+ */
22
+ export declare function resolveUv(deps?: ResolveUvDeps): Promise<UvResolution | null>;
23
+ //# sourceMappingURL=uv-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uv-runner.d.ts","sourceRoot":"","sources":["../../src/core/uv-runner.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAc,KAAK,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B;;6DAEyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,GAAG,CAAC,EAAE,KAAK,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAUtF"}
@@ -0,0 +1,39 @@
1
+ /*
2
+ * uv-runner — resolves `uv` for call sites that must run a plugin-owned Python
3
+ * script IN THE ENGINE'S OWN ENVIRONMENT (grade.py, triage_cli.py), not the
4
+ * server's ambient interpreter (root cause of the ModuleNotFoundError bug:
5
+ * grade-runner / triage-cli-runner used to spawn `resolvePython()`'s raw
6
+ * python3/python/py — whichever answered `--version` first, unversioned and
7
+ * dependency-free — instead of the `uv run`-managed environment both scripts
8
+ * are built for).
9
+ *
10
+ * `resolveUv` test-runs `uv --version` (never assumed present) via the same
11
+ * PATH-augmented probe `readiness-probe-run.ts` uses (`~/.local/bin` etc. —
12
+ * the uv installer only appends that dir to a shell rc, so a server spawned
13
+ * before a fresh install would otherwise ENOENT a real uv), then resolves the
14
+ * actual bin + env a REAL spawn needs — reusing `probeEnv`/`resolvePosixBin`
15
+ * from `readiness-probe-path.ts` rather than re-deriving PATH logic.
16
+ *
17
+ * Returns null when uv is genuinely absent. Callers MUST surface an honest
18
+ * "engine unavailable" in that case — never fall back to a bare system
19
+ * python, which is the exact silent-fallback this module replaces.
20
+ */
21
+ import os from "node:os";
22
+ import { probeEnv, resolvePosixBin } from "./readiness-probe-path.js";
23
+ import { defaultRun } from "./readiness-probe-run.js";
24
+ /**
25
+ * Test-run `uv --version`; on success resolve the bin + env a real `uv run`
26
+ * spawn needs. Null means "uv isn't there" — not "python isn't there".
27
+ */
28
+ export async function resolveUv(deps = {}) {
29
+ const run = deps.run ?? defaultRun;
30
+ const probe = await run("uv", ["--version"]);
31
+ if (!probe.ok)
32
+ return null;
33
+ const platform = deps.platform ?? process.platform;
34
+ const homeDir = deps.homeDir ?? os.homedir();
35
+ const env = probeEnv(platform, homeDir, deps.baseEnv ?? process.env);
36
+ const bin = platform === "win32" ? "uv" : resolvePosixBin("uv", env);
37
+ return { bin, env };
38
+ }
39
+ //# sourceMappingURL=uv-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uv-runner.js","sourceRoot":"","sources":["../../src/core/uv-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,UAAU,EAAc,MAAM,0BAA0B,CAAC;AAoBlE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAsB,EAAE;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IACrE,MAAM,GAAG,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACtB,CAAC"}
@@ -61,33 +61,33 @@ const SERVE_MIME = Object.freeze({
61
61
  * markdown to the WebUI host. `write()` captures the blob text and posts it;
62
62
  * it must NEVER reject (a throw would drop the viewer into its download
63
63
  * fallback). Posts with `targetOrigin === location.origin` (same-origin host). */
64
- const FEEDBACK_BRIDGE = `<script>
65
- (function () {
66
- var HOST_ORIGIN = window.location.origin;
67
- function post(text) {
68
- try {
69
- window.parent.postMessage(
70
- { type: "shipwright:design-feedback", markdown: String(text) },
71
- HOST_ORIGIN
72
- );
73
- } catch (e) { /* never let a post error trip the viewer's download fallback */ }
74
- }
75
- window.showSaveFilePicker = function () {
76
- return Promise.resolve({
77
- createWritable: function () {
78
- return Promise.resolve({
79
- write: function (blob) {
80
- return Promise.resolve(
81
- blob && typeof blob.text === "function" ? blob.text() : blob
82
- ).then(post, function () { /* swallow */ });
83
- },
84
- close: function () { return Promise.resolve(); },
85
- });
86
- },
87
- });
88
- };
89
- })();
90
- </script>
64
+ const FEEDBACK_BRIDGE = `<script>
65
+ (function () {
66
+ var HOST_ORIGIN = window.location.origin;
67
+ function post(text) {
68
+ try {
69
+ window.parent.postMessage(
70
+ { type: "shipwright:design-feedback", markdown: String(text) },
71
+ HOST_ORIGIN
72
+ );
73
+ } catch (e) { /* never let a post error trip the viewer's download fallback */ }
74
+ }
75
+ window.showSaveFilePicker = function () {
76
+ return Promise.resolve({
77
+ createWritable: function () {
78
+ return Promise.resolve({
79
+ write: function (blob) {
80
+ return Promise.resolve(
81
+ blob && typeof blob.text === "function" ? blob.text() : blob
82
+ ).then(post, function () { /* swallow */ });
83
+ },
84
+ close: function () { return Promise.resolve(); },
85
+ });
86
+ },
87
+ });
88
+ };
89
+ })();
90
+ </script>
91
91
  `;
92
92
  /** Insert the bridge before the first <script> (so the override is defined
93
93
  * before the viewer script runs), else before </body>, else append. */
@@ -0,0 +1,7 @@
1
+ import { Hono } from "hono";
2
+ import type { ExternalRouteProjectView } from "../_shared/helpers.js";
3
+ export interface FileExistsRouterDeps {
4
+ getProjectById?: (id: string) => ExternalRouteProjectView | undefined;
5
+ }
6
+ export declare function createFileExistsRouter(deps: FileExistsRouterDeps): Hono;
7
+ //# sourceMappingURL=exists-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exists-routes.d.ts","sourceRoot":"","sources":["../../../src/external/file/exists-routes.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAKtE,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,wBAAwB,GAAG,SAAS,CAAC;CACvE;AAwBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CA4DvE"}
@@ -0,0 +1,91 @@
1
+ /*
2
+ * external/file/exists-routes.ts — GET
3
+ * /api/external/projects/:projectId/files/exist?paths=a,b,c.
4
+ *
5
+ * Batched, read-only existence check reusing the same `pathGuard` +
6
+ * `realPathGuard` boundary as the file-read route (CLAUDE.md rule 10), but no
7
+ * content is ever read — just `stat`. Feeds the Triage file viewer's
8
+ * link-vs-plain-text decision (iterate-2026-08-30-triage-file-viewer-followups):
9
+ * the caller supplies both the structured `evidencePath` field and
10
+ * regex-extracted free-text mentions, either of which can point at a path
11
+ * that no longer exists or never did — the WHOLE-request 400s stay reserved
12
+ * for a malformed REQUEST (missing project, missing `?paths`, batch cap), but
13
+ * an individual bad path (traversal, absolute, symlink escape, not-a-file,
14
+ * missing) resolves to `false` in the map rather than failing the batch.
15
+ */
16
+ import { Hono } from "hono";
17
+ import { stat, realpath } from "node:fs/promises";
18
+ import { pathGuard, realPathGuard } from "../../core/path-guard.js";
19
+ /** Hard cap on paths per request — this is a UI convenience batch, not a bulk API. */
20
+ const MAX_PATHS_PER_REQUEST = 50;
21
+ async function pathExists(projectPath, relpath, realProjectRoot) {
22
+ const guard = pathGuard(projectPath, relpath);
23
+ if (!guard.ok)
24
+ return false;
25
+ let st;
26
+ try {
27
+ st = await stat(guard.absolute);
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ if (!st.isFile())
33
+ return false;
34
+ // Same symlink-escape defense as the file-read route: a project-local
35
+ // symlink whose target resolves outside the project root must not be
36
+ // reported as an existing, viewable file.
37
+ return realPathGuard(projectPath, guard.absolute, realProjectRoot).ok;
38
+ }
39
+ export function createFileExistsRouter(deps) {
40
+ const app = new Hono();
41
+ const { getProjectById } = deps;
42
+ app.get("/api/external/projects/:projectId/files/exist", async (c) => {
43
+ const projectId = c.req.param("projectId");
44
+ const project = getProjectById?.(projectId);
45
+ if (!project) {
46
+ return c.json({ error: "project_not_found", projectId }, 404);
47
+ }
48
+ if (!project.path) {
49
+ return c.json({ error: "project_path_unavailable", projectId }, 400);
50
+ }
51
+ const raw = c.req.query("paths");
52
+ if (!raw || raw.length === 0) {
53
+ return c.json({ error: "paths_required" }, 400);
54
+ }
55
+ // Each segment is percent-decoded (client encodes with encodeURIComponent)
56
+ // so a literal comma inside a path can't be mistaken for the delimiter —
57
+ // code-review finding, iterate-2026-08-30-triage-file-viewer-followups.
58
+ // A segment that fails to decode (malformed %-escape) is treated as
59
+ // literal text rather than 400ing the whole batch — it will simply not
60
+ // match a real file and resolve to `false` below.
61
+ const paths = raw
62
+ .split(",")
63
+ .filter((p) => p.length > 0)
64
+ .map((p) => {
65
+ try {
66
+ return decodeURIComponent(p);
67
+ }
68
+ catch {
69
+ return p;
70
+ }
71
+ });
72
+ if (paths.length > MAX_PATHS_PER_REQUEST) {
73
+ return c.json({ error: "too_many_paths", max: MAX_PATHS_PER_REQUEST, received: paths.length }, 400);
74
+ }
75
+ // Resolve the project root's realpath ONCE for the whole batch rather
76
+ // than once per path — up to 50 paths would otherwise each pay a
77
+ // redundant realpathSync(root) inside realPathGuard, doubling the
78
+ // blocking-syscall count for no benefit (doubt-review finding,
79
+ // iterate-2026-08-30-triage-file-viewer-followups). `undefined` on
80
+ // failure falls back to realPathGuard's own per-call resolution, which
81
+ // then fails closed exactly as it did before this change.
82
+ const realProjectRoot = await realpath(project.path).catch(() => undefined);
83
+ const results = await Promise.all(paths.map(async (p) => [p, await pathExists(project.path, p, realProjectRoot)]));
84
+ const exists = {};
85
+ for (const [p, ok] of results)
86
+ exists[p] = ok;
87
+ return c.json({ exists });
88
+ });
89
+ return app;
90
+ }
91
+ //# sourceMappingURL=exists-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exists-routes.js","sourceRoot":"","sources":["../../../src/external/file/exists-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { MissionContextAssociation } from "../../core/mission-context/types.js";
2
+ import type { ExternalTask, SdkSessionsStore } from "../../core/sdk-sessions-store.js";
3
+ /**
4
+ * Persist a resolved association — either the FIRST one for a task, or a
5
+ * confirmed supersession of a stale one. Caller must have already checked
6
+ * `associateRunId` is non-null.
7
+ *
8
+ * `associationAtResolve` is the snapshot `resolveMissionContext` actually
9
+ * decided against (captured by the caller BEFORE its slow async work, e.g.
10
+ * `routes.ts`) — not re-read here. Both write paths compare against it, not
11
+ * a fresh `task.missionContext`: by the time this async function runs, a
12
+ * concurrent poll may already have written a NEWER association, and a fresh
13
+ * read here would silently adopt that as the "expected" value, letting THIS
14
+ * poll's now-stale decision overwrite it with no failure involved (a plain
15
+ * lost-update race, doubt-reviewer HIGH, iterate-2026-08-31-mission-feed-gaps
16
+ * — ELOCKED rollback cannot catch it because nothing fails).
17
+ */
18
+ export declare function persistMissionAssociation(store: SdkSessionsStore, task: ExternalTask, associationAtResolve: MissionContextAssociation | null, associateRunId: string, associateSource: MissionContextAssociation["source"], now: () => Date, wideWindows: Map<string, {
19
+ seen: string;
20
+ scanned: string;
21
+ }>): Promise<void>;
22
+ //# sourceMappingURL=association-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"association-write.d.ts","sourceRoot":"","sources":["../../../src/external/mission-context/association-write.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEvF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,YAAY,EAClB,oBAAoB,EAAE,yBAAyB,GAAG,IAAI,EACtD,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EACpD,GAAG,EAAE,MAAM,IAAI,EACf,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1D,OAAO,CAAC,IAAI,CAAC,CA4Df"}