@svenroth-ai/shipwright 0.25.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 (134) hide show
  1. package/client/dist/assets/{EmbeddedTerminal-5QvKe3_a.js → EmbeddedTerminal-D3wpPNZP.js} +1 -1
  2. package/client/dist/assets/{abnfDiagram-VRR7QNED-CXi9HegQ.js → abnfDiagram-VRR7QNED-BkLIltB3.js} +1 -1
  3. package/client/dist/assets/{arc-DLh4GiqR.js → arc-Sw-Gh0nI.js} +1 -1
  4. package/client/dist/assets/{architectureDiagram-ZJ3FMSHR-DUypQ8dQ.js → architectureDiagram-ZJ3FMSHR-rdxUi9Ks.js} +1 -1
  5. package/client/dist/assets/{blockDiagram-677ZJIJ3-D2cVMKJG.js → blockDiagram-677ZJIJ3-Ch_9dj8a.js} +1 -1
  6. package/client/dist/assets/{c4Diagram-LMCZKHZV-DtruBGJw.js → c4Diagram-LMCZKHZV-CkFlO65x.js} +1 -1
  7. package/client/dist/assets/channel-BYPbLjRl.js +1 -0
  8. package/client/dist/assets/{chunk-2Q5K7J3B-CAfQkFw2.js → chunk-2Q5K7J3B-CypX83xu.js} +1 -1
  9. package/client/dist/assets/{chunk-32BRIVSS-CPWXoLnQ.js → chunk-32BRIVSS-DxVLYGdl.js} +1 -1
  10. package/client/dist/assets/{chunk-5VM5RSS4-xVc3oppQ.js → chunk-5VM5RSS4-Cxk1evhx.js} +1 -1
  11. package/client/dist/assets/{chunk-EX3LRPZG-CUpl6fRR.js → chunk-EX3LRPZG-n9q5S4yJ.js} +1 -1
  12. package/client/dist/assets/{chunk-JWPE2WC7-NejUp56x.js → chunk-JWPE2WC7-jeL4xvir.js} +1 -1
  13. package/client/dist/assets/{chunk-MOJQB5TN-C9-2lLg0.js → chunk-MOJQB5TN-DDSHN0cj.js} +1 -1
  14. package/client/dist/assets/{chunk-RYQCIY6F-BAPtwABy.js → chunk-RYQCIY6F-C0bo383g.js} +1 -1
  15. package/client/dist/assets/{chunk-V7JOEXUC-Dwzihw26.js → chunk-V7JOEXUC-C0jDXXAU.js} +1 -1
  16. package/client/dist/assets/{chunk-VR4S4FIN-9-iArFJM.js → chunk-VR4S4FIN-h-Rr4Pn2.js} +1 -1
  17. package/client/dist/assets/{chunk-XXDRQBXY-DiWHOrqe.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-Cp04EOcH.js → cose-bilkent-JH36ORCC-BQXzaioj.js} +1 -1
  21. package/client/dist/assets/{cynefin-VYW2F7L2-D--GN1v8.js → cynefin-VYW2F7L2-BJIofhfe.js} +1 -1
  22. package/client/dist/assets/{cynefinDiagram-TSTJHNR4-BGH0o_qp.js → cynefinDiagram-TSTJHNR4-DmPqTM1T.js} +1 -1
  23. package/client/dist/assets/{dagre-VKFMJZFB-DSKkIKlj.js → dagre-VKFMJZFB-1xljvw6X.js} +1 -1
  24. package/client/dist/assets/{diagram-FQU43EPY-Cs_C4lb-.js → diagram-FQU43EPY-iyL9muCG.js} +1 -1
  25. package/client/dist/assets/{diagram-G47NLZAW-oDtAA8O_.js → diagram-G47NLZAW-DREp2Th6.js} +1 -1
  26. package/client/dist/assets/{diagram-NH7WQ7WH-BiFMjqSH.js → diagram-NH7WQ7WH-h0X3Is2S.js} +1 -1
  27. package/client/dist/assets/{diagram-OA4YK3LP-Ccs3thCj.js → diagram-OA4YK3LP-Bj8YZRFJ.js} +1 -1
  28. package/client/dist/assets/{diagram-WEI45ONY-CdZNqgO3.js → diagram-WEI45ONY-BZOf805d.js} +1 -1
  29. package/client/dist/assets/{ebnfDiagram-CCIWWBDH-CapTA0VL.js → ebnfDiagram-CCIWWBDH-DO5JnXda.js} +1 -1
  30. package/client/dist/assets/{erDiagram-Q63AITRT-BcRNEP8s.js → erDiagram-Q63AITRT-DRgcqg1T.js} +1 -1
  31. package/client/dist/assets/{flowDiagram-23GEKE2U-CJ_zF7e_.js → flowDiagram-23GEKE2U-C3J9QmrW.js} +1 -1
  32. package/client/dist/assets/{ganttDiagram-NO4QXBWP-CnJdcg9A.js → ganttDiagram-NO4QXBWP-BIEl3Tkm.js} +1 -1
  33. package/client/dist/assets/{gitGraphDiagram-IHSO6WYX-YTUQ_ELk.js → gitGraphDiagram-IHSO6WYX-BNF0tFWC.js} +1 -1
  34. package/client/dist/assets/{index-irQhGNpn.js → index-BnTOrFHb.js} +203 -202
  35. package/client/dist/assets/index-CYPc6qxw.css +1 -0
  36. package/client/dist/assets/{infoDiagram-FWYZ7A6U-CLOP_ZWD.js → infoDiagram-FWYZ7A6U-DEyFxiyY.js} +1 -1
  37. package/client/dist/assets/{ishikawaDiagram-FXEZZL3T-aFTIzr7o.js → ishikawaDiagram-FXEZZL3T-B_ehlg3I.js} +1 -1
  38. package/client/dist/assets/{journeyDiagram-5HDEW3XC-CbPJB4xd.js → journeyDiagram-5HDEW3XC-Dp00FyJS.js} +1 -1
  39. package/client/dist/assets/{kanban-definition-HUTT4EX6-BoyhytIS.js → kanban-definition-HUTT4EX6-CTAf16q8.js} +1 -1
  40. package/client/dist/assets/{linear-1VXA-uBg.js → linear-9vNUgmYd.js} +1 -1
  41. package/client/dist/assets/{mermaid.core-D_lO2yK9.js → mermaid.core-A6tjaEVD.js} +4 -4
  42. package/client/dist/assets/{mindmap-definition-LN4V7U3C-iFK7LXMx.js → mindmap-definition-LN4V7U3C-DRW3bmCY.js} +1 -1
  43. package/client/dist/assets/{pegDiagram-2B236MQR-DNmcmfA-.js → pegDiagram-2B236MQR-DJFCjHp2.js} +1 -1
  44. package/client/dist/assets/{pieDiagram-ENE6RG2P-ekx83O5b.js → pieDiagram-ENE6RG2P-KRd-sGvC.js} +1 -1
  45. package/client/dist/assets/{quadrantDiagram-ABIIQ3AL-DayyD1l8.js → quadrantDiagram-ABIIQ3AL-9TLZE3Hu.js} +1 -1
  46. package/client/dist/assets/{railroadDiagram-RFXS5EU6-Bdgz7S6G.js → railroadDiagram-RFXS5EU6-y4tLtjXg.js} +1 -1
  47. package/client/dist/assets/{requirementDiagram-TGXJPOKE-szP3Muld.js → requirementDiagram-TGXJPOKE-B9EOQDQM.js} +1 -1
  48. package/client/dist/assets/{sankeyDiagram-HTMAVEWB-Ct3rzgUj.js → sankeyDiagram-HTMAVEWB-zfwiDzkT.js} +1 -1
  49. package/client/dist/assets/{sequenceDiagram-DBY2YBRQ-_69EfmOU.js → sequenceDiagram-DBY2YBRQ-DW1LWepL.js} +1 -1
  50. package/client/dist/assets/{sizeCapture-X5ZJPWSS-BSOU06J2.js → sizeCapture-X5ZJPWSS-BM81Mik0.js} +1 -1
  51. package/client/dist/assets/{stateDiagram-2N3HPSRC-HmOmFwQm.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-CVg_4oT7.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-CBBaDKXm.js → timeline-definition-FHXFAJF6-ByzIfvL5.js} +1 -1
  56. package/client/dist/assets/{vennDiagram-L72KCM5P-CBXiWPMc.js → vennDiagram-L72KCM5P-Xep38xBH.js} +1 -1
  57. package/client/dist/assets/{wardleyDiagram-EHGQE667-uhBCZoW0.js → wardleyDiagram-EHGQE667-DKWDpx6g.js} +1 -1
  58. package/client/dist/assets/{xychartDiagram-FW5EYKEG-xxE_wY5O.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 +68 -68
  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/mission-context/association.d.ts +46 -0
  73. package/server/dist/core/mission-context/association.d.ts.map +1 -1
  74. package/server/dist/core/mission-context/association.js +69 -0
  75. package/server/dist/core/mission-context/association.js.map +1 -1
  76. package/server/dist/core/mission-context/resolver-iterate.d.ts +6 -0
  77. package/server/dist/core/mission-context/resolver-iterate.d.ts.map +1 -0
  78. package/server/dist/core/mission-context/resolver-iterate.js +202 -0
  79. package/server/dist/core/mission-context/resolver-iterate.js.map +1 -0
  80. package/server/dist/core/mission-context/resolver-parts.d.ts +20 -0
  81. package/server/dist/core/mission-context/resolver-parts.d.ts.map +1 -1
  82. package/server/dist/core/mission-context/resolver-parts.js +92 -0
  83. package/server/dist/core/mission-context/resolver-parts.js.map +1 -1
  84. package/server/dist/core/mission-context/resolver.d.ts +1 -1
  85. package/server/dist/core/mission-context/resolver.d.ts.map +1 -1
  86. package/server/dist/core/mission-context/resolver.js +17 -199
  87. package/server/dist/core/mission-context/resolver.js.map +1 -1
  88. package/server/dist/core/mission-context/run-id-recovery.d.ts +21 -5
  89. package/server/dist/core/mission-context/run-id-recovery.d.ts.map +1 -1
  90. package/server/dist/core/mission-context/run-id-recovery.js +32 -5
  91. package/server/dist/core/mission-context/run-id-recovery.js.map +1 -1
  92. package/server/dist/core/mission-context/scenario.d.ts +18 -11
  93. package/server/dist/core/mission-context/scenario.d.ts.map +1 -1
  94. package/server/dist/core/mission-context/scenario.js +40 -3
  95. package/server/dist/core/mission-context/scenario.js.map +1 -1
  96. package/server/dist/core/path-guard.d.ts +1 -1
  97. package/server/dist/core/path-guard.d.ts.map +1 -1
  98. package/server/dist/core/path-guard.js +9 -2
  99. package/server/dist/core/path-guard.js.map +1 -1
  100. package/server/dist/core/shipslog-docs-reader.d.ts +4 -0
  101. package/server/dist/core/shipslog-docs-reader.d.ts.map +1 -0
  102. package/server/dist/core/shipslog-docs-reader.js +181 -0
  103. package/server/dist/core/shipslog-docs-reader.js.map +1 -0
  104. package/server/dist/core/shipslog-docs-types.d.ts +15 -0
  105. package/server/dist/core/shipslog-docs-types.d.ts.map +1 -0
  106. package/server/dist/core/shipslog-docs-types.js +14 -0
  107. package/server/dist/core/shipslog-docs-types.js.map +1 -0
  108. package/server/dist/external/design-review/serve.js +27 -27
  109. package/server/dist/external/mission-context/association-write.d.ts +22 -0
  110. package/server/dist/external/mission-context/association-write.d.ts.map +1 -0
  111. package/server/dist/external/mission-context/association-write.js +90 -0
  112. package/server/dist/external/mission-context/association-write.js.map +1 -0
  113. package/server/dist/external/mission-context/routes.d.ts.map +1 -1
  114. package/server/dist/external/mission-context/routes.js +18 -31
  115. package/server/dist/external/mission-context/routes.js.map +1 -1
  116. package/server/dist/external/routes.d.ts.map +1 -1
  117. package/server/dist/external/routes.js +9 -6
  118. package/server/dist/external/routes.js.map +1 -1
  119. package/server/dist/external/shipslog-docs/routes.d.ts +10 -0
  120. package/server/dist/external/shipslog-docs/routes.d.ts.map +1 -0
  121. package/server/dist/external/shipslog-docs/routes.js +41 -0
  122. package/server/dist/external/shipslog-docs/routes.js.map +1 -0
  123. package/server/package.json +1 -1
  124. package/server/profiles/PROFILE_SCHEMA_VERSION +1 -1
  125. package/server/profiles/README.md +27 -27
  126. package/server/profiles/python-plugin-monorepo.json +35 -35
  127. package/server/profiles/supabase-nextjs.json +253 -253
  128. package/server/profiles/vite-hono.json +92 -92
  129. package/client/dist/assets/channel-C_k-9jsa.js +0 -1
  130. package/client/dist/assets/classDiagram-OUVF2IWQ-CsEPq9Ac.js +0 -1
  131. package/client/dist/assets/classDiagram-v2-EOCWNBFH-CsEPq9Ac.js +0 -1
  132. package/client/dist/assets/index-6nZ1bt0a.css +0 -1
  133. package/client/dist/assets/stateDiagram-v2-6OUMAXLB-BW8H33dv.js +0 -1
  134. package/client/dist/assets/swimlanesDiagram-G3AALYLV-BaRlxcPD.js +0 -8
@@ -8,12 +8,15 @@
8
8
  * 1. custom_actions — a VALIDATED custom-actions project → HIDE the Mission
9
9
  * tab entirely (only Files & Terminal).
10
10
  * 2. iterate — a VALIDATED `iterate_active` pointer, or the persisted
11
- * association once that pointer has been pruned.
11
+ * association once that pointer has been pruned — UNLESS a corroborated
12
+ * transcript footer (below) names a different, newer run, which
13
+ * supersedes a stale association (iterate-2026-08-31-mission-feed-gaps).
12
14
  * 3. pipeline — phaseTaskId + runId (run-config v2 phase_tasks).
13
15
  * 4. campaign — a `campaign:<slug>` title AND a real campaign record.
14
16
  * 5. iterate — a CORROBORATED `Run-ID` footer in this session's own
15
- * transcript (run-id-recovery.ts). Last resort, and deliberately ranked
16
- * below pipeline/campaign — see `recoverTranscriptRunId`.
17
+ * transcript (run-id-recovery.ts). Last resort when NO association
18
+ * exists, and deliberately ranked below pipeline/campaign — see
19
+ * `recoverTranscriptRunId`.
17
20
  * 6. plain — everything else (scenarios 1/4): narration, no rail.
18
21
  *
19
22
  * Two DECIDED asymmetries, both "fail toward showing the tab":
@@ -24,6 +27,7 @@
24
27
  * - A `campaign:` TITLE without a matching record is NOT a campaign. Titles
25
28
  * are user-editable; a record is evidence.
26
29
  */
30
+ import { isProvablyNewerRunId } from "./run-id-recovery.js";
27
31
  /** The four builtin action ids. Anything else is a user-defined custom action. */
28
32
  export const BUILTIN_ACTION_IDS = new Set([
29
33
  "new-task",
@@ -111,6 +115,39 @@ export function detectScenario(inputs) {
111
115
  // validation is a signal something is wrong, and quietly resolving via a
112
116
  // stored id would mask it.
113
117
  if (inputs.pointer.status === "absent" && inputs.association?.runId) {
118
+ // Before trusting the stored value, give the transcript one chance to
119
+ // SUPERSEDE it (iterate-2026-08-31-mission-feed-gaps). The association is
120
+ // only ever refreshed by catching a LIVE pointer (rule 2) — a narrow
121
+ // window that only opens while a worktree exists, between setup and
122
+ // Finalize. A task whose Mission tab is not open during that window keeps
123
+ // whatever association it last caught, forever, even after several more
124
+ // iterates finish: production evidence (a `new-plain` task with 9+
125
+ // completed PRs after its one caught association) showed a stale
126
+ // association can outlive the run it names by weeks.
127
+ //
128
+ // `recoverTranscriptRunId` finds the LAST `Run-ID:` footer in the
129
+ // transcript, corroborated against this project's OWN completed-run
130
+ // records (run-id-recovery.ts) — the same evidence rule 5 below trusts
131
+ // enough to identify a run with NO association at all. It is therefore
132
+ // not "quoted text" here either: when it names a DIFFERENT, corroborated,
133
+ // and PROVABLY NEWER run than the one on file (`isProvablyNewerRunId` —
134
+ // same-day or unparseable is not proof, external code review, openai
135
+ // MEDIUM), that is proof a newer run finished. The resolver rate-limits
136
+ // the actual scan per (session, association, transcript-content) so this
137
+ // does not reintroduce the "every poll forever" cost PR #309 removed (see
138
+ // resolver.ts), and the route persists the correction (association.ts
139
+ // `supersedeMissionContext`) so it survives instead of re-proving itself
140
+ // every poll.
141
+ const recovered = inputs.recoverTranscriptRunId?.() ?? null;
142
+ if (recovered && recovered !== inputs.association.runId && isProvablyNewerRunId(recovered, inputs.association.runId)) {
143
+ return {
144
+ scenario: "iterate",
145
+ missionTabVisible: true,
146
+ runId: recovered,
147
+ runIdSource: "transcript",
148
+ pointerInvalidReason: null,
149
+ };
150
+ }
114
151
  return {
115
152
  scenario: "iterate",
116
153
  missionTabVisible: true,
@@ -1 +1 @@
1
- {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../../src/core/mission-context/scenario.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../../src/core/mission-context/scenario.ts"],"names":[],"mappings":"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"}
@@ -36,5 +36,5 @@ export declare function pathGuard(projectRoot: string, relpath: string): PathGua
36
36
  * guard.absolute, though in practice fs reads against either produce the
37
37
  * same bytes as long as both land under the root).
38
38
  */
39
- export declare function realPathGuard(projectRoot: string, absoluteInsideRoot: string): PathGuardResult;
39
+ export declare function realPathGuard(projectRoot: string, absoluteInsideRoot: string, precomputedRealRoot?: string): PathGuardResult;
40
40
  //# sourceMappingURL=path-guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-guard.d.ts","sourceRoot":"","sources":["../../src/core/path-guard.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CA0E/E;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,GACzB,eAAe,CAqCjB"}
1
+ {"version":3,"file":"path-guard.d.ts","sourceRoot":"","sources":["../../src/core/path-guard.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CA0E/E;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,EAC1B,mBAAmB,CAAC,EAAE,MAAM,GAC3B,eAAe,CA4CjB"}
@@ -112,12 +112,19 @@ export function pathGuard(projectRoot, relpath) {
112
112
  * guard.absolute, though in practice fs reads against either produce the
113
113
  * same bytes as long as both land under the root).
114
114
  */
115
- export function realPathGuard(projectRoot, absoluteInsideRoot) {
115
+ export function realPathGuard(projectRoot, absoluteInsideRoot, precomputedRealRoot) {
116
116
  const resolvedRoot = path.resolve(projectRoot);
117
117
  let realRoot;
118
118
  let realTarget;
119
119
  try {
120
- realRoot = realpathSync(resolvedRoot);
120
+ // A batch caller resolving many targets against the same project root
121
+ // (e.g. exists-routes.ts) can pass its own once-per-request realpath of
122
+ // that root here, instead of paying a redundant realpathSync(root) on
123
+ // every one of up to N iterations (doubt-review finding,
124
+ // iterate-2026-08-30-triage-file-viewer-followups). Single-path callers
125
+ // are unaffected — the parameter is optional and falls back to the
126
+ // original per-call resolution.
127
+ realRoot = precomputedRealRoot ?? realpathSync(resolvedRoot);
121
128
  realTarget = realpathSync(absoluteInsideRoot);
122
129
  }
123
130
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"path-guard.js","sourceRoot":"","sources":["../../src/core/path-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAYvC;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,OAAe;IAC5D,wEAAwE;IACxE,MAAM,KAAK,GAAG,OAAO,IAAI,EAAE,CAAC;IAE5B,sEAAsE;IACtE,yEAAyE;IACzE,0DAA0D;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC5C,CAAC;IAED,oEAAoE;IACpE,yEAAyE;IACzE,sDAAsD;IACtD,EAAE;IACF,0EAA0E;IAC1E,sEAAsE;IACtE,wEAAwE;IACxE,sCAAsC;IACtC,IACE,KAAK,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAC/B,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAEnD,qEAAqE;IACrE,wEAAwE;IACxE,sEAAsE;IACtE,qDAAqD;IACrD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,IACE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvB,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC3B,SAAS,KAAK,aAAa,EAC3B,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,2DAA2D;IAC3D,mEAAmE;IACnE,mEAAmE;IACnE,2EAA2E;IAC3E,qEAAqE;IACrE,2BAA2B;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAElD,IACE,GAAG,KAAK,IAAI;QACZ,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EACrB,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC5C,CAAC;IAED,uEAAuE;IACvE,iEAAiE;IACjE,gBAAgB;IAChB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAC3B,WAAmB,EACnB,kBAA0B;IAE1B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,QAAgB,CAAC;IACrB,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QACtC,UAAU,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,gDAAgD;QAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,6DAA6D;IAC7D,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACrD,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,IACE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvB,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC;YACzB,SAAS,KAAK,WAAW,EACzB,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAChD,IACE,GAAG,KAAK,IAAI;QACZ,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;QACrB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EACpB,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"path-guard.js","sourceRoot":"","sources":["../../src/core/path-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAYvC;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,OAAe;IAC5D,wEAAwE;IACxE,MAAM,KAAK,GAAG,OAAO,IAAI,EAAE,CAAC;IAE5B,sEAAsE;IACtE,yEAAyE;IACzE,0DAA0D;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC5C,CAAC;IAED,oEAAoE;IACpE,yEAAyE;IACzE,sDAAsD;IACtD,EAAE;IACF,0EAA0E;IAC1E,sEAAsE;IACtE,wEAAwE;IACxE,sCAAsC;IACtC,IACE,KAAK,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAC/B,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAEnD,qEAAqE;IACrE,wEAAwE;IACxE,sEAAsE;IACtE,qDAAqD;IACrD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,IACE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvB,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC3B,SAAS,KAAK,aAAa,EAC3B,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,2DAA2D;IAC3D,mEAAmE;IACnE,mEAAmE;IACnE,2EAA2E;IAC3E,qEAAqE;IACrE,2BAA2B;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAElD,IACE,GAAG,KAAK,IAAI;QACZ,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EACrB,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC5C,CAAC;IAED,uEAAuE;IACvE,iEAAiE;IACjE,gBAAgB;IAChB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAC3B,WAAmB,EACnB,kBAA0B,EAC1B,mBAA4B;IAE5B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,QAAgB,CAAC;IACrB,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,sEAAsE;QACtE,wEAAwE;QACxE,sEAAsE;QACtE,yDAAyD;QACzD,wEAAwE;QACxE,mEAAmE;QACnE,gCAAgC;QAChC,QAAQ,GAAG,mBAAmB,IAAI,YAAY,CAAC,YAAY,CAAC,CAAC;QAC7D,UAAU,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,gDAAgD;QAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,6DAA6D;IAC7D,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACrD,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,IACE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;YACvB,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC;YACzB,SAAS,KAAK,WAAW,EACzB,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAChD,IACE,GAAG,KAAK,IAAI;QACZ,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;QACrB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EACpB,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ShipsLogDocsBundle } from "./shipslog-docs-types.js";
2
+ export type { ShipsLogDocRow, ShipsLogDocsBundle } from "./shipslog-docs-types.js";
3
+ export declare function readShipsLogDocs(projectRoot: string): Promise<ShipsLogDocsBundle>;
4
+ //# sourceMappingURL=shipslog-docs-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipslog-docs-reader.d.ts","sourceRoot":"","sources":["../../src/core/shipslog-docs-reader.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAkB,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnF,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAyInF,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiBvF"}
@@ -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"}
@@ -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,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"}
@@ -0,0 +1,90 @@
1
+ /*
2
+ * external/mission-context/association-write.ts — the ONE guarded
3
+ * association write (CONTRACT §5), split out of routes.ts (2026-08-31,
4
+ * iterate-2026-08-31-mission-feed-gaps) to stay under the 300-line file-size
5
+ * limit. Pure continuation of the GET handler's persistence step: routes.ts
6
+ * resolves the context and hands the decision here.
7
+ *
8
+ * Idempotent for a first association: the store no-ops when one already
9
+ * exists, so repeated polls perform exactly zero writes after the first.
10
+ * Never a per-GET side-effect.
11
+ */
12
+ import { revertMissionContext, revertSupersession, setMissionContextOnce, supersedeMissionContext, } from "../../core/mission-context/association.js";
13
+ /**
14
+ * Persist a resolved association — either the FIRST one for a task, or a
15
+ * confirmed supersession of a stale one. Caller must have already checked
16
+ * `associateRunId` is non-null.
17
+ *
18
+ * `associationAtResolve` is the snapshot `resolveMissionContext` actually
19
+ * decided against (captured by the caller BEFORE its slow async work, e.g.
20
+ * `routes.ts`) — not re-read here. Both write paths compare against it, not
21
+ * a fresh `task.missionContext`: by the time this async function runs, a
22
+ * concurrent poll may already have written a NEWER association, and a fresh
23
+ * read here would silently adopt that as the "expected" value, letting THIS
24
+ * poll's now-stale decision overwrite it with no failure involved (a plain
25
+ * lost-update race, doubt-reviewer HIGH, iterate-2026-08-31-mission-feed-gaps
26
+ * — ELOCKED rollback cannot catch it because nothing fails).
27
+ */
28
+ export async function persistMissionAssociation(store, task, associationAtResolve, associateRunId, associateSource, now, wideWindows) {
29
+ if (!associationAtResolve) {
30
+ const association = {
31
+ kind: "iterate",
32
+ runId: associateRunId,
33
+ observedAt: now().toISOString(),
34
+ source: associateSource,
35
+ };
36
+ if (setMissionContextOnce(store, task.taskId, association)) {
37
+ try {
38
+ await store.persist();
39
+ }
40
+ catch {
41
+ // A lock contention (ELOCKED) or I/O fault must not fail the READ —
42
+ // but the in-memory field MUST be rolled back, or every later poll
43
+ // would see it set, skip the write, and the association would never
44
+ // reach disk (external code review, openai HIGH).
45
+ revertMissionContext(store, task.taskId, association);
46
+ // …and the reach-back must be rolled back WITH it. The marker was
47
+ // recorded before the resolve; leaving it would make every later poll
48
+ // read only the ordinary tail while the task is unidentified again —
49
+ // permanently unreachable for a footer beyond it, which is the very
50
+ // data loss the rollback above exists to prevent, re-entered through
51
+ // the read side (internal code review, MEDIUM).
52
+ wideWindows.delete(task.taskId);
53
+ }
54
+ }
55
+ return;
56
+ }
57
+ if (associateSource === "transcript_run_id" && associateRunId !== associationAtResolve.runId) {
58
+ // THE evidence-gated supersession write (association.ts,
59
+ // iterate-2026-08-31-mission-feed-gaps, external code review, openai
60
+ // HIGH). scenario.ts rule 2b has already required a corroborated
61
+ // footer naming a PROVABLY newer run before offering `associateRunId`
62
+ // here — this is the write that makes that correction durable instead
63
+ // of re-proving itself from the transcript on every poll forever.
64
+ const previous = associationAtResolve;
65
+ const association = {
66
+ kind: "iterate",
67
+ runId: associateRunId,
68
+ observedAt: now().toISOString(),
69
+ source: associateSource,
70
+ };
71
+ // Compare-and-set against `previous` (association.ts, external code
72
+ // review openai MEDIUM + doubt-reviewer HIGH): the store's CURRENT value
73
+ // must still equal what this decision was based on, or the write is
74
+ // skipped and the next poll resolves fresh against whatever is now
75
+ // current — never a blind overwrite of a value a faster concurrent poll
76
+ // already corrected further.
77
+ if (supersedeMissionContext(store, task.taskId, association, previous)) {
78
+ try {
79
+ await store.persist();
80
+ }
81
+ catch {
82
+ // Same ELOCKED/I-O-fault posture as the first-association rollback
83
+ // above — but there is a PREVIOUS association to restore here, not
84
+ // an empty field to revert to.
85
+ revertSupersession(store, task.taskId, association, previous);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ //# sourceMappingURL=association-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"association-write.js","sourceRoot":"","sources":["../../../src/external/mission-context/association-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,2CAA2C,CAAC;AAInD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAuB,EACvB,IAAkB,EAClB,oBAAsD,EACtD,cAAsB,EACtB,eAAoD,EACpD,GAAe,EACf,WAA2D;IAE3D,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,MAAM,WAAW,GAA8B;YAC7C,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,cAAc;YACrB,UAAU,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;YAC/B,MAAM,EAAE,eAAe;SACxB,CAAC;QACF,IAAI,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC;YAC3D,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;gBACpE,mEAAmE;gBACnE,oEAAoE;gBACpE,kDAAkD;gBAClD,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;gBACtD,kEAAkE;gBAClE,sEAAsE;gBACtE,qEAAqE;gBACrE,oEAAoE;gBACpE,qEAAqE;gBACrE,gDAAgD;gBAChD,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,eAAe,KAAK,mBAAmB,IAAI,cAAc,KAAK,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAC7F,yDAAyD;QACzD,qEAAqE;QACrE,iEAAiE;QACjE,sEAAsE;QACtE,sEAAsE;QACtE,kEAAkE;QAClE,MAAM,QAAQ,GAAG,oBAAoB,CAAC;QACtC,MAAM,WAAW,GAA8B;YAC7C,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,cAAc;YACrB,UAAU,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE;YAC/B,MAAM,EAAE,eAAe;SACxB,CAAC;QACF,oEAAoE;QACpE,yEAAyE;QACzE,oEAAoE;QACpE,mEAAmE;QACnE,wEAAwE;QACxE,6BAA6B;QAC7B,IAAI,uBAAuB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,mEAAmE;gBACnE,mEAAmE;gBACnE,+BAA+B;gBAC/B,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/external/mission-context/routes.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,wCAAwC,CAAC;AAIhD,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,mBAAmB,QAAc,CAAC;AAS/C,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,gBAAgB,CAAC;IACxB,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,wBAAwB,GAAG,SAAS,CAAC;IACrE;;;;;;;;;;;;OAYG;IACH,kBAAkB,EAAE,CAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,yDAAyD;IACzD,gBAAgB,EAAE,CAChB,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,YAAY,KACf,OAAO,CAAC;QACX,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;QACnC,eAAe,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;QACnD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,0EAA0E;QAC1E,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;QACtC,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;KACvC,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI,CA0K/E"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/external/mission-context/routes.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,wCAAwC,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAGtE,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,mBAAmB,QAAc,CAAC;AAS/C,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,gBAAgB,CAAC;IACxB,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,wBAAwB,GAAG,SAAS,CAAC;IACrE;;;;;;;;;;;;OAYG;IACH,kBAAkB,EAAE,CAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,yDAAyD;IACzD,gBAAgB,EAAE,CAChB,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,YAAY,KACf,OAAO,CAAC;QACX,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;QACnC,eAAe,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;QACnD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,0EAA0E;QAC1E,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;QACtC,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;KACvC,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI,CAuK/E"}