spexcode 0.6.1 → 0.6.5

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 (480) hide show
  1. package/README.md +99 -149
  2. package/bin/spex.mjs +4 -0
  3. package/node_modules/@spexcode/spec-cli/bin/spex.mjs +76 -0
  4. package/node_modules/@spexcode/spec-cli/dist/attach.d.ts +2 -0
  5. package/node_modules/@spexcode/spec-cli/dist/attach.js +48 -0
  6. package/node_modules/@spexcode/spec-cli/dist/claude-headless.d.ts +33 -0
  7. package/node_modules/@spexcode/spec-cli/dist/claude-headless.js +307 -0
  8. package/node_modules/@spexcode/spec-cli/dist/cli.d.ts +1 -0
  9. package/node_modules/@spexcode/spec-cli/dist/cli.js +1859 -0
  10. package/node_modules/@spexcode/spec-cli/dist/client.d.ts +111 -0
  11. package/node_modules/@spexcode/spec-cli/dist/client.js +476 -0
  12. package/node_modules/@spexcode/spec-cli/dist/cockpit.d.ts +7 -0
  13. package/node_modules/@spexcode/spec-cli/dist/cockpit.js +26 -0
  14. package/node_modules/@spexcode/spec-cli/dist/codex-headless.d.ts +1 -0
  15. package/{spec-cli/src/codex-headless.ts → node_modules/@spexcode/spec-cli/dist/codex-headless.js} +3 -9
  16. package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.d.ts +53 -0
  17. package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.js +686 -0
  18. package/node_modules/@spexcode/spec-cli/dist/commit-surgery.d.ts +1 -0
  19. package/node_modules/@spexcode/spec-cli/dist/commit-surgery.js +90 -0
  20. package/node_modules/@spexcode/spec-cli/dist/contract-filter.d.ts +14 -0
  21. package/node_modules/@spexcode/spec-cli/dist/contract-filter.js +219 -0
  22. package/node_modules/@spexcode/spec-cli/dist/dashboard-assets.d.ts +6 -0
  23. package/node_modules/@spexcode/spec-cli/dist/dashboard-assets.js +50 -0
  24. package/node_modules/@spexcode/spec-cli/dist/delivery-queue.d.ts +23 -0
  25. package/node_modules/@spexcode/spec-cli/dist/delivery-queue.js +179 -0
  26. package/node_modules/@spexcode/spec-cli/dist/doctor.d.ts +9 -0
  27. package/node_modules/@spexcode/spec-cli/dist/doctor.js +547 -0
  28. package/node_modules/@spexcode/spec-cli/dist/eval-host.d.ts +1 -0
  29. package/node_modules/@spexcode/spec-cli/dist/eval-host.js +19 -0
  30. package/node_modules/@spexcode/spec-cli/dist/execution-trace.d.ts +26 -0
  31. package/node_modules/@spexcode/spec-cli/dist/execution-trace.js +475 -0
  32. package/node_modules/@spexcode/spec-cli/dist/file-write.d.ts +2 -0
  33. package/node_modules/@spexcode/spec-cli/dist/file-write.js +26 -0
  34. package/node_modules/@spexcode/spec-cli/dist/flat.d.ts +89 -0
  35. package/node_modules/@spexcode/spec-cli/dist/flat.js +1076 -0
  36. package/node_modules/@spexcode/spec-cli/dist/gateway-auth.d.ts +56 -0
  37. package/node_modules/@spexcode/spec-cli/dist/gateway-auth.js +168 -0
  38. package/node_modules/@spexcode/spec-cli/dist/gateway-hub.d.ts +28 -0
  39. package/node_modules/@spexcode/spec-cli/dist/gateway-hub.js +361 -0
  40. package/node_modules/@spexcode/spec-cli/dist/gateway.d.ts +37 -0
  41. package/node_modules/@spexcode/spec-cli/dist/gateway.js +503 -0
  42. package/node_modules/@spexcode/spec-cli/dist/graphCache.d.ts +27 -0
  43. package/node_modules/@spexcode/spec-cli/dist/graphCache.js +716 -0
  44. package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.d.ts +14 -0
  45. package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.js +35 -0
  46. package/node_modules/@spexcode/spec-cli/dist/graphStream.d.ts +85 -0
  47. package/node_modules/@spexcode/spec-cli/dist/graphStream.js +1195 -0
  48. package/node_modules/@spexcode/spec-cli/dist/guidance-catalog.d.ts +64 -0
  49. package/node_modules/@spexcode/spec-cli/dist/guidance-catalog.js +166 -0
  50. package/node_modules/@spexcode/spec-cli/dist/guide.d.ts +8 -0
  51. package/{spec-cli/src/guide.ts → node_modules/@spexcode/spec-cli/dist/guide.js} +115 -22
  52. package/node_modules/@spexcode/spec-cli/dist/harness-select.d.ts +18 -0
  53. package/node_modules/@spexcode/spec-cli/dist/harness-select.js +62 -0
  54. package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +325 -0
  55. package/node_modules/@spexcode/spec-cli/dist/harness.js +3026 -0
  56. package/node_modules/@spexcode/spec-cli/dist/headless-controller.d.ts +9 -0
  57. package/node_modules/@spexcode/spec-cli/dist/headless-controller.js +47 -0
  58. package/node_modules/@spexcode/spec-cli/dist/help.d.ts +10 -0
  59. package/node_modules/@spexcode/spec-cli/dist/help.js +574 -0
  60. package/node_modules/@spexcode/spec-cli/dist/hook-prompts.d.ts +18 -0
  61. package/node_modules/@spexcode/spec-cli/dist/hook-prompts.js +122 -0
  62. package/node_modules/@spexcode/spec-cli/dist/hooks.d.ts +1 -0
  63. package/{spec-cli/src/hooks.ts → node_modules/@spexcode/spec-cli/dist/hooks.js} +15 -15
  64. package/node_modules/@spexcode/spec-cli/dist/host-resources.d.ts +97 -0
  65. package/node_modules/@spexcode/spec-cli/dist/host-resources.js +795 -0
  66. package/node_modules/@spexcode/spec-cli/dist/host.d.ts +88 -0
  67. package/node_modules/@spexcode/spec-cli/dist/host.js +663 -0
  68. package/node_modules/@spexcode/spec-cli/dist/index.d.ts +1 -0
  69. package/node_modules/@spexcode/spec-cli/dist/index.js +899 -0
  70. package/node_modules/@spexcode/spec-cli/dist/init.d.ts +1 -0
  71. package/node_modules/@spexcode/spec-cli/dist/init.js +284 -0
  72. package/node_modules/@spexcode/spec-cli/dist/issues-cli.d.ts +6 -0
  73. package/node_modules/@spexcode/spec-cli/dist/issues-cli.js +334 -0
  74. package/node_modules/@spexcode/spec-cli/dist/issues.d.ts +69 -0
  75. package/node_modules/@spexcode/spec-cli/dist/issues.js +189 -0
  76. package/node_modules/@spexcode/spec-cli/dist/lint.d.ts +34 -0
  77. package/node_modules/@spexcode/spec-cli/dist/lint.js +476 -0
  78. package/node_modules/@spexcode/spec-cli/dist/listen.d.ts +7 -0
  79. package/{spec-cli/src/listen.ts → node_modules/@spexcode/spec-cli/dist/listen.js} +13 -17
  80. package/node_modules/@spexcode/spec-cli/dist/localIssues.d.ts +65 -0
  81. package/node_modules/@spexcode/spec-cli/dist/localIssues.js +582 -0
  82. package/node_modules/@spexcode/spec-cli/dist/login-page.d.ts +5 -0
  83. package/{spec-cli/src/login-page.ts → node_modules/@spexcode/spec-cli/dist/login-page.js} +7 -7
  84. package/node_modules/@spexcode/spec-cli/dist/loop-in.d.ts +23 -0
  85. package/{spec-cli/src/loop-in.ts → node_modules/@spexcode/spec-cli/dist/loop-in.js} +35 -45
  86. package/node_modules/@spexcode/spec-cli/dist/machine-peer.d.ts +69 -0
  87. package/node_modules/@spexcode/spec-cli/dist/machine-peer.js +603 -0
  88. package/node_modules/@spexcode/spec-cli/dist/materialize.d.ts +18 -0
  89. package/node_modules/@spexcode/spec-cli/dist/materialize.js +468 -0
  90. package/node_modules/@spexcode/spec-cli/dist/mentions.d.ts +50 -0
  91. package/node_modules/@spexcode/spec-cli/dist/mentions.js +117 -0
  92. package/node_modules/@spexcode/spec-cli/dist/opencode-headless.d.ts +4 -0
  93. package/node_modules/@spexcode/spec-cli/dist/opencode-headless.js +208 -0
  94. package/node_modules/@spexcode/spec-cli/dist/opencode.d.ts +3 -0
  95. package/{spec-cli/src/opencode.ts → node_modules/@spexcode/spec-cli/dist/opencode.js} +9 -13
  96. package/node_modules/@spexcode/spec-cli/dist/pi-harness.d.ts +3 -0
  97. package/{spec-cli/src/pi-harness.ts → node_modules/@spexcode/spec-cli/dist/pi-harness.js} +45 -40
  98. package/node_modules/@spexcode/spec-cli/dist/pi-headless.d.ts +25 -0
  99. package/node_modules/@spexcode/spec-cli/dist/pi-headless.js +196 -0
  100. package/node_modules/@spexcode/spec-cli/dist/plugin-harness.d.ts +21 -0
  101. package/node_modules/@spexcode/spec-cli/dist/plugin-harness.js +146 -0
  102. package/node_modules/@spexcode/spec-cli/dist/pty-bridge.d.ts +10 -0
  103. package/node_modules/@spexcode/spec-cli/dist/pty-bridge.js +404 -0
  104. package/node_modules/@spexcode/spec-cli/dist/pty-helper.d.mts +1 -0
  105. package/node_modules/@spexcode/spec-cli/dist/pty-helper.mjs +101 -0
  106. package/node_modules/@spexcode/spec-cli/dist/pty-native-helper.d.mts +2 -0
  107. package/node_modules/@spexcode/spec-cli/dist/pty-native-helper.mjs +23 -0
  108. package/node_modules/@spexcode/spec-cli/dist/public-graph.d.ts +46 -0
  109. package/node_modules/@spexcode/spec-cli/dist/public-graph.js +56 -0
  110. package/node_modules/@spexcode/spec-cli/dist/ranker.d.ts +15 -0
  111. package/node_modules/@spexcode/spec-cli/dist/ranker.js +188 -0
  112. package/node_modules/@spexcode/spec-cli/dist/reaper.d.ts +6 -0
  113. package/node_modules/@spexcode/spec-cli/dist/reaper.js +81 -0
  114. package/node_modules/@spexcode/spec-cli/dist/reviews.d.ts +189 -0
  115. package/node_modules/@spexcode/spec-cli/dist/reviews.js +350 -0
  116. package/node_modules/@spexcode/spec-cli/dist/runtime-guard.d.ts +6 -0
  117. package/node_modules/@spexcode/spec-cli/dist/runtime-guard.js +37 -0
  118. package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.d.ts +21 -0
  119. package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.js +84 -0
  120. package/node_modules/@spexcode/spec-cli/dist/search.bench.d.mts +1 -0
  121. package/node_modules/@spexcode/spec-cli/dist/search.bench.mjs +75 -0
  122. package/node_modules/@spexcode/spec-cli/dist/search.d.ts +20 -0
  123. package/node_modules/@spexcode/spec-cli/dist/search.js +61 -0
  124. package/node_modules/@spexcode/spec-cli/dist/session-cursors.d.ts +14 -0
  125. package/node_modules/@spexcode/spec-cli/dist/session-cursors.js +82 -0
  126. package/node_modules/@spexcode/spec-cli/dist/session-declarations.d.ts +13 -0
  127. package/node_modules/@spexcode/spec-cli/dist/session-declarations.js +126 -0
  128. package/node_modules/@spexcode/spec-cli/dist/session-execution.d.ts +10 -0
  129. package/node_modules/@spexcode/spec-cli/dist/session-execution.js +70 -0
  130. package/node_modules/@spexcode/spec-cli/dist/session-files.d.ts +28 -0
  131. package/node_modules/@spexcode/spec-cli/dist/session-files.js +130 -0
  132. package/node_modules/@spexcode/spec-cli/dist/session-follow.d.ts +31 -0
  133. package/node_modules/@spexcode/spec-cli/dist/session-follow.js +179 -0
  134. package/node_modules/@spexcode/spec-cli/dist/session-reparent.d.ts +10 -0
  135. package/node_modules/@spexcode/spec-cli/dist/session-reparent.js +33 -0
  136. package/node_modules/@spexcode/spec-cli/dist/session-timeline.d.ts +51 -0
  137. package/node_modules/@spexcode/spec-cli/dist/session-timeline.js +233 -0
  138. package/node_modules/@spexcode/spec-cli/dist/session-web.d.ts +24 -0
  139. package/node_modules/@spexcode/spec-cli/dist/session-web.js +141 -0
  140. package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +412 -0
  141. package/node_modules/@spexcode/spec-cli/dist/sessions.js +4239 -0
  142. package/node_modules/@spexcode/spec-cli/dist/sh.d.ts +1 -0
  143. package/node_modules/@spexcode/spec-cli/dist/sh.js +3 -0
  144. package/node_modules/@spexcode/spec-cli/dist/shim-runtime.d.ts +1 -0
  145. package/{spec-cli/src/shim-runtime.ts → node_modules/@spexcode/spec-cli/dist/shim-runtime.js} +3 -4
  146. package/node_modules/@spexcode/spec-cli/dist/slash-commands.d.ts +9 -0
  147. package/node_modules/@spexcode/spec-cli/dist/slash-commands.js +307 -0
  148. package/node_modules/@spexcode/spec-cli/dist/source-files.d.ts +9 -0
  149. package/node_modules/@spexcode/spec-cli/dist/source-files.js +113 -0
  150. package/node_modules/@spexcode/spec-cli/dist/supervise.d.ts +1 -0
  151. package/node_modules/@spexcode/spec-cli/dist/supervise.js +308 -0
  152. package/node_modules/@spexcode/spec-cli/dist/tree.d.ts +25 -0
  153. package/node_modules/@spexcode/spec-cli/dist/tree.js +98 -0
  154. package/node_modules/@spexcode/spec-cli/dist/tsx-bin.d.ts +3 -0
  155. package/node_modules/@spexcode/spec-cli/dist/tsx-bin.js +41 -0
  156. package/node_modules/@spexcode/spec-cli/dist/uninstall.d.ts +3 -0
  157. package/node_modules/@spexcode/spec-cli/dist/uninstall.js +177 -0
  158. package/node_modules/@spexcode/spec-cli/dist/uploads.d.ts +36 -0
  159. package/node_modules/@spexcode/spec-cli/dist/uploads.js +243 -0
  160. package/node_modules/@spexcode/spec-cli/dist/worktree-sources.d.ts +1 -0
  161. package/node_modules/@spexcode/spec-cli/dist/worktree-sources.js +47 -0
  162. package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/dispatch.sh +5 -5
  163. package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/harness.sh +27 -7
  164. package/node_modules/@spexcode/spec-cli/package.json +47 -0
  165. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +8 -0
  166. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/comment-altitude/spec.md +9 -0
  167. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-first/spec-first.sh +1 -1
  168. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-of-file/spec-of-file.sh +1 -0
  169. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/spec.md +22 -0
  170. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/stop-gate/spec.md +2 -2
  171. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/stop-gate/stop-gate.sh +31 -29
  172. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/atomic-landing/spec.md +15 -0
  173. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/forge-link/spec.md +10 -0
  174. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/memory-hygiene/spec.md +13 -0
  175. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +12 -0
  176. package/node_modules/@spexcode/spec-core/dist/anchors.d.ts +94 -0
  177. package/node_modules/@spexcode/spec-core/dist/anchors.js +730 -0
  178. package/node_modules/@spexcode/spec-core/dist/git.d.ts +166 -0
  179. package/node_modules/@spexcode/spec-core/dist/git.js +2736 -0
  180. package/node_modules/@spexcode/spec-core/dist/graph-delta.d.ts +44 -0
  181. package/node_modules/@spexcode/spec-core/dist/graph-delta.js +72 -0
  182. package/node_modules/@spexcode/spec-core/dist/graph.d.ts +34 -0
  183. package/node_modules/@spexcode/spec-core/dist/graph.js +237 -0
  184. package/node_modules/@spexcode/spec-core/dist/graphDelta.d.ts +3 -0
  185. package/node_modules/@spexcode/spec-core/dist/graphDelta.js +13 -0
  186. package/node_modules/@spexcode/spec-core/dist/harness-identity.d.ts +31 -0
  187. package/node_modules/@spexcode/spec-core/dist/harness-identity.js +20 -0
  188. package/node_modules/@spexcode/spec-core/dist/identity-presets.d.ts +152 -0
  189. package/node_modules/@spexcode/spec-core/dist/identity-presets.js +132 -0
  190. package/node_modules/@spexcode/spec-core/dist/index.d.ts +45 -0
  191. package/node_modules/@spexcode/spec-core/dist/index.js +19 -0
  192. package/node_modules/@spexcode/spec-core/dist/layout.d.ts +183 -0
  193. package/node_modules/@spexcode/spec-core/dist/layout.js +548 -0
  194. package/node_modules/@spexcode/spec-core/dist/process-identity.d.ts +37 -0
  195. package/node_modules/@spexcode/spec-core/dist/process-identity.js +214 -0
  196. package/node_modules/@spexcode/spec-core/dist/project-identity.d.ts +12 -0
  197. package/node_modules/@spexcode/spec-core/dist/project-identity.js +71 -0
  198. package/node_modules/@spexcode/spec-core/dist/project-store.d.ts +3 -0
  199. package/node_modules/@spexcode/spec-core/dist/project-store.js +14 -0
  200. package/node_modules/@spexcode/spec-core/dist/resilience.d.ts +2 -0
  201. package/node_modules/@spexcode/spec-core/dist/resilience.js +40 -0
  202. package/node_modules/@spexcode/spec-core/dist/review/index.d.ts +3 -0
  203. package/node_modules/@spexcode/spec-core/dist/review/index.js +5 -0
  204. package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.d.ts +77 -0
  205. package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.js +308 -0
  206. package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.d.ts +66 -0
  207. package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.js +180 -0
  208. package/node_modules/@spexcode/spec-core/dist/review/session.d.ts +4 -0
  209. package/node_modules/@spexcode/spec-core/dist/review/session.js +8 -0
  210. package/node_modules/@spexcode/spec-core/dist/reviewSnapshot.d.ts +15 -0
  211. package/node_modules/@spexcode/spec-core/dist/reviewSnapshot.js +12 -0
  212. package/node_modules/@spexcode/spec-core/dist/root-lru.d.ts +4 -0
  213. package/{spec-cli/src/root-lru.ts → node_modules/@spexcode/spec-core/dist/root-lru.js} +26 -30
  214. package/node_modules/@spexcode/spec-core/dist/specs.d.ts +117 -0
  215. package/node_modules/@spexcode/spec-core/dist/specs.js +489 -0
  216. package/node_modules/@spexcode/spec-core/package.json +28 -0
  217. package/node_modules/@spexcode/spec-eval/dist/cache.d.ts +10 -0
  218. package/node_modules/@spexcode/spec-eval/dist/cache.js +50 -0
  219. package/node_modules/@spexcode/spec-eval/dist/cli.d.ts +22 -0
  220. package/node_modules/@spexcode/spec-eval/dist/cli.js +981 -0
  221. package/node_modules/@spexcode/spec-eval/dist/evaltab.d.ts +98 -0
  222. package/node_modules/@spexcode/spec-eval/dist/evaltab.js +176 -0
  223. package/node_modules/@spexcode/spec-eval/dist/filing.d.ts +16 -0
  224. package/node_modules/@spexcode/spec-eval/dist/filing.js +36 -0
  225. package/node_modules/@spexcode/spec-eval/dist/freshness.d.ts +48 -0
  226. package/node_modules/@spexcode/spec-eval/dist/freshness.js +799 -0
  227. package/node_modules/@spexcode/spec-eval/dist/host.d.ts +46 -0
  228. package/node_modules/@spexcode/spec-eval/dist/host.js +53 -0
  229. package/node_modules/@spexcode/spec-eval/dist/humanok.d.ts +11 -0
  230. package/node_modules/@spexcode/spec-eval/dist/humanok.js +27 -0
  231. package/node_modules/@spexcode/spec-eval/dist/index.d.ts +4 -0
  232. package/node_modules/@spexcode/spec-eval/dist/index.js +4 -0
  233. package/node_modules/@spexcode/spec-eval/dist/remarks.d.ts +31 -0
  234. package/node_modules/@spexcode/spec-eval/dist/remarks.js +1 -0
  235. package/node_modules/@spexcode/spec-eval/dist/scenariofresh.d.ts +13 -0
  236. package/node_modules/@spexcode/spec-eval/dist/scenariofresh.js +303 -0
  237. package/node_modules/@spexcode/spec-eval/dist/scenarios.d.ts +99 -0
  238. package/node_modules/@spexcode/spec-eval/dist/scenarios.js +650 -0
  239. package/node_modules/@spexcode/spec-eval/dist/sessioneval.d.ts +307 -0
  240. package/node_modules/@spexcode/spec-eval/dist/sessioneval.js +1883 -0
  241. package/node_modules/@spexcode/spec-eval/dist/sidecar.d.ts +55 -0
  242. package/node_modules/@spexcode/spec-eval/dist/sidecar.js +82 -0
  243. package/node_modules/@spexcode/spec-eval/dist/timeline.d.ts +25 -0
  244. package/node_modules/@spexcode/spec-eval/dist/timeline.js +65 -0
  245. package/node_modules/@spexcode/spec-eval/dist/ui-path.d.ts +1 -0
  246. package/node_modules/@spexcode/spec-eval/dist/ui-path.js +2 -0
  247. package/node_modules/@spexcode/spec-eval/package.json +36 -0
  248. package/node_modules/@spexcode/spec-forge/dist/cache.d.ts +29 -0
  249. package/node_modules/@spexcode/spec-forge/dist/cache.js +59 -0
  250. package/node_modules/@spexcode/spec-forge/dist/cli.d.ts +1 -0
  251. package/node_modules/@spexcode/spec-forge/dist/cli.js +100 -0
  252. package/node_modules/@spexcode/spec-forge/dist/drivers/github.d.ts +2 -0
  253. package/node_modules/@spexcode/spec-forge/dist/drivers/github.js +116 -0
  254. package/node_modules/@spexcode/spec-forge/dist/drivers/gitlab.d.ts +7 -0
  255. package/node_modules/@spexcode/spec-forge/dist/drivers/gitlab.js +144 -0
  256. package/node_modules/@spexcode/spec-forge/dist/drivers.d.ts +10 -0
  257. package/node_modules/@spexcode/spec-forge/dist/drivers.js +83 -0
  258. package/node_modules/@spexcode/spec-forge/dist/index.d.ts +4 -0
  259. package/node_modules/@spexcode/spec-forge/dist/index.js +4 -0
  260. package/node_modules/@spexcode/spec-forge/dist/links.d.ts +15 -0
  261. package/node_modules/@spexcode/spec-forge/dist/links.js +65 -0
  262. package/node_modules/@spexcode/spec-forge/dist/needs-eval.d.ts +10 -0
  263. package/node_modules/@spexcode/spec-forge/dist/needs-eval.js +20 -0
  264. package/node_modules/@spexcode/spec-forge/dist/port.d.ts +53 -0
  265. package/node_modules/@spexcode/spec-forge/dist/port.js +1 -0
  266. package/node_modules/@spexcode/spec-forge/dist/resident.d.ts +7 -0
  267. package/node_modules/@spexcode/spec-forge/dist/resident.js +43 -0
  268. package/node_modules/@spexcode/spec-forge/package.json +32 -0
  269. package/package.json +33 -19
  270. package/spec-cli/bin/spex.mjs +0 -69
  271. package/spec-cli/src/anchors.ts +0 -706
  272. package/spec-cli/src/attach.ts +0 -43
  273. package/spec-cli/src/claude-headless.ts +0 -321
  274. package/spec-cli/src/cli.ts +0 -1115
  275. package/spec-cli/src/client.ts +0 -315
  276. package/spec-cli/src/cockpit.ts +0 -43
  277. package/spec-cli/src/codex-runtime-generations.ts +0 -646
  278. package/spec-cli/src/commit-surgery.ts +0 -68
  279. package/spec-cli/src/contract-filter.ts +0 -202
  280. package/spec-cli/src/delivery-queue.ts +0 -107
  281. package/spec-cli/src/doctor.ts +0 -516
  282. package/spec-cli/src/file-write.ts +0 -22
  283. package/spec-cli/src/gateway-auth.ts +0 -181
  284. package/spec-cli/src/gateway-hub.ts +0 -356
  285. package/spec-cli/src/gateway.ts +0 -368
  286. package/spec-cli/src/git.ts +0 -2180
  287. package/spec-cli/src/graph.ts +0 -221
  288. package/spec-cli/src/graphCache.ts +0 -641
  289. package/spec-cli/src/graphDelta.ts +0 -77
  290. package/spec-cli/src/graphStream.ts +0 -1019
  291. package/spec-cli/src/harness-select.ts +0 -77
  292. package/spec-cli/src/harness.ts +0 -2747
  293. package/spec-cli/src/headless-controller.ts +0 -63
  294. package/spec-cli/src/help.ts +0 -480
  295. package/spec-cli/src/host-resources.ts +0 -707
  296. package/spec-cli/src/host.ts +0 -611
  297. package/spec-cli/src/identity-presets.d.ts +0 -13
  298. package/spec-cli/src/identity-presets.js +0 -128
  299. package/spec-cli/src/index.ts +0 -730
  300. package/spec-cli/src/init.ts +0 -258
  301. package/spec-cli/src/issues-cli.ts +0 -276
  302. package/spec-cli/src/issues.ts +0 -237
  303. package/spec-cli/src/layout.ts +0 -557
  304. package/spec-cli/src/lint.ts +0 -458
  305. package/spec-cli/src/localIssues.ts +0 -538
  306. package/spec-cli/src/materialize.ts +0 -412
  307. package/spec-cli/src/mentions.ts +0 -81
  308. package/spec-cli/src/opencode-headless.ts +0 -205
  309. package/spec-cli/src/pi-headless.ts +0 -153
  310. package/spec-cli/src/plugin-harness.ts +0 -157
  311. package/spec-cli/src/process-identity.ts +0 -207
  312. package/spec-cli/src/project-identity.ts +0 -73
  313. package/spec-cli/src/project-store.ts +0 -17
  314. package/spec-cli/src/pty-bridge.ts +0 -396
  315. package/spec-cli/src/pty-helper.mjs +0 -96
  316. package/spec-cli/src/pty-native-helper.mjs +0 -22
  317. package/spec-cli/src/ranker.ts +0 -191
  318. package/spec-cli/src/reaper.ts +0 -125
  319. package/spec-cli/src/resilience.ts +0 -41
  320. package/spec-cli/src/reviewSnapshot.ts +0 -28
  321. package/spec-cli/src/reviews.ts +0 -405
  322. package/spec-cli/src/runtime-guard.ts +0 -35
  323. package/spec-cli/src/runtime-ownership.ts +0 -88
  324. package/spec-cli/src/search.bench.mjs +0 -80
  325. package/spec-cli/src/search.ts +0 -63
  326. package/spec-cli/src/session-cursors.ts +0 -91
  327. package/spec-cli/src/session-follow.ts +0 -182
  328. package/spec-cli/src/session-timeline.ts +0 -98
  329. package/spec-cli/src/sessions.ts +0 -3403
  330. package/spec-cli/src/sh.ts +0 -3
  331. package/spec-cli/src/slash-commands.ts +0 -318
  332. package/spec-cli/src/source-files.ts +0 -104
  333. package/spec-cli/src/specs.ts +0 -498
  334. package/spec-cli/src/supervise.ts +0 -245
  335. package/spec-cli/src/tree.ts +0 -118
  336. package/spec-cli/src/tsx-bin.ts +0 -18
  337. package/spec-cli/src/uninstall.ts +0 -171
  338. package/spec-cli/src/uploads.ts +0 -253
  339. package/spec-cli/src/worktree-sources.ts +0 -42
  340. package/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +0 -8
  341. package/spec-cli/templates/spec/project/.plugins/core/comment-altitude/spec.md +0 -28
  342. package/spec-cli/templates/spec/project/.plugins/core/spec.md +0 -23
  343. package/spec-cli/templates/spec/project/.plugins/prompts/atomic-landing/spec.md +0 -32
  344. package/spec-cli/templates/spec/project/.plugins/prompts/forge-link/spec.md +0 -9
  345. package/spec-cli/templates/spec/project/.plugins/prompts/memory-hygiene/spec.md +0 -15
  346. package/spec-cli/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +0 -18
  347. package/spec-dashboard/dist/assets/App-F9uaAVcH.js +0 -2
  348. package/spec-dashboard/dist/assets/Dashboard-Ba_jhxp1.js +0 -27
  349. package/spec-dashboard/dist/assets/Dashboard-C5ap-Sga.css +0 -1
  350. package/spec-dashboard/dist/assets/EvalsPage-FixoOg_n.js +0 -2
  351. package/spec-dashboard/dist/assets/IssuesPage-CuKLFhH3.js +0 -1
  352. package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  353. package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  354. package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  355. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  356. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  357. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  358. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  359. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  360. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  361. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  362. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  363. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  364. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  365. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  366. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  367. package/spec-dashboard/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  368. package/spec-dashboard/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  369. package/spec-dashboard/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  370. package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  371. package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  372. package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  373. package/spec-dashboard/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  374. package/spec-dashboard/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  375. package/spec-dashboard/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  376. package/spec-dashboard/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  377. package/spec-dashboard/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  378. package/spec-dashboard/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  379. package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  380. package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  381. package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  382. package/spec-dashboard/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  383. package/spec-dashboard/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  384. package/spec-dashboard/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  385. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  386. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  387. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  388. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  389. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  390. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  391. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  392. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  393. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  394. package/spec-dashboard/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  395. package/spec-dashboard/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  396. package/spec-dashboard/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  397. package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  398. package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  399. package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  400. package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  401. package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  402. package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  403. package/spec-dashboard/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  404. package/spec-dashboard/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  405. package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  406. package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  407. package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  408. package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  409. package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  410. package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  411. package/spec-dashboard/dist/assets/MobileApp-CHgEHORJ.js +0 -2
  412. package/spec-dashboard/dist/assets/Modal-CQgYymmr.js +0 -1
  413. package/spec-dashboard/dist/assets/PageScroll-hT7UTLvD.js +0 -1
  414. package/spec-dashboard/dist/assets/ProjectsPage-CtXxakF9.js +0 -1
  415. package/spec-dashboard/dist/assets/SessionInterface-6GBZ9nXN.css +0 -32
  416. package/spec-dashboard/dist/assets/SessionInterface-Bpie-9fs.js +0 -39
  417. package/spec-dashboard/dist/assets/SessionWindow-CixDi4PI.js +0 -1
  418. package/spec-dashboard/dist/assets/Settings-C2MsucfE.js +0 -1
  419. package/spec-dashboard/dist/assets/Thread-C6Go8HRh.js +0 -13
  420. package/spec-dashboard/dist/assets/bindings-BC9vqpYU.js +0 -1
  421. package/spec-dashboard/dist/assets/data-B-RQmit6.js +0 -1
  422. package/spec-dashboard/dist/assets/index-CsI8DElI.css +0 -1
  423. package/spec-dashboard/dist/assets/index-DrVao0Ep.js +0 -41
  424. package/spec-dashboard/dist/assets/launch-BBH02b1v.js +0 -276
  425. package/spec-dashboard/dist/assets/launch-Cp579UoJ.css +0 -1
  426. package/spec-dashboard/dist/assets/terminalFont-C6oGNKrf.js +0 -1
  427. package/spec-dashboard/dist/index.html +0 -29
  428. package/spec-dashboard/src/reviewFilters.js +0 -322
  429. package/spec-dashboard/src/reviewQuery.js +0 -174
  430. package/spec-dashboard/src/session.js +0 -199
  431. package/spec-eval/src/cache.ts +0 -57
  432. package/spec-eval/src/cli.ts +0 -889
  433. package/spec-eval/src/evaltab.ts +0 -262
  434. package/spec-eval/src/filing.ts +0 -39
  435. package/spec-eval/src/freshness.ts +0 -557
  436. package/spec-eval/src/humanok.ts +0 -28
  437. package/spec-eval/src/scenariofresh.ts +0 -244
  438. package/spec-eval/src/scenarios.ts +0 -672
  439. package/spec-eval/src/sessioneval.ts +0 -2226
  440. package/spec-eval/src/sidecar.ts +0 -93
  441. package/spec-eval/src/timeline.ts +0 -54
  442. package/spec-forge/src/__fixtures__/github-forge.json +0 -63
  443. package/spec-forge/src/cache.ts +0 -66
  444. package/spec-forge/src/cli.ts +0 -99
  445. package/spec-forge/src/drivers/github.ts +0 -132
  446. package/spec-forge/src/drivers/gitlab.ts +0 -153
  447. package/spec-forge/src/drivers.ts +0 -73
  448. package/spec-forge/src/links.ts +0 -72
  449. package/spec-forge/src/needs-eval.ts +0 -29
  450. package/spec-forge/src/port.ts +0 -36
  451. package/spec-forge/src/resident.ts +0 -46
  452. /package/{spec-cli → node_modules/@spexcode/spec-cli}/README.md +0 -0
  453. /package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/compat/mark-active-0.5.2-eef1.fixture +0 -0
  454. /package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/compat/mark-active-sed-v0.fixture +0 -0
  455. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/commit-msg +0 -0
  456. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/post-checkout +0 -0
  457. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/post-merge +0 -0
  458. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/pre-commit +0 -0
  459. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/prepare-commit-msg +0 -0
  460. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/reference-transaction +0 -0
  461. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/extract/spec.md +0 -0
  462. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/regroup/spec.md +0 -0
  463. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/rename/spec.md +0 -0
  464. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/spec.md +0 -0
  465. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/tidy/spec.md +0 -0
  466. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/idle/idle.sh +0 -0
  467. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/idle/spec.md +0 -0
  468. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/mark-active/mark-active.sh +0 -0
  469. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/mark-active/spec.md +0 -0
  470. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/session-fail/fail.sh +0 -0
  471. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/session-fail/spec.md +0 -0
  472. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-first/spec.md +0 -0
  473. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-of-file/spec.md +0 -0
  474. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/spec.md +0 -0
  475. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/distill/digest.mjs +0 -0
  476. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/distill/spec.md +0 -0
  477. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/spec.md +0 -0
  478. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/spec.md +0 -0
  479. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/spec.md +0 -0
  480. /package/{spec-cli → node_modules/@spexcode/spec-core}/templates/spexcode.json +0 -0
@@ -0,0 +1,111 @@
1
+ import { type CockpitReview } from './cockpit.js';
2
+ import { type Session, type SessionClosure, type Resolved, type DispatchResult } from './sessions.js';
3
+ export declare class BackendError extends Error {
4
+ readonly status?: number | undefined;
5
+ readonly transport?: unknown | undefined;
6
+ constructor(message: string, status?: number | undefined, transport?: unknown | undefined);
7
+ }
8
+ export declare function backendConnectionRefused(error: unknown): boolean;
9
+ export declare function localCachedSessions(includeArchived?: boolean): Session[];
10
+ export declare function clientListSessions(includeArchived?: boolean): Promise<Session[]>;
11
+ export declare function clientSessionClosure(selector: string): Promise<SessionClosure | null>;
12
+ export declare function clientResources(): Promise<import('./host-resources.js').ResourceReport>;
13
+ export declare function resolveClientSession(selector: string, includeArchived?: boolean): Promise<Resolved>;
14
+ export type CaptureResult = {
15
+ ok: true;
16
+ pane: string;
17
+ } | {
18
+ ok: false;
19
+ status: number;
20
+ reason: string;
21
+ };
22
+ export declare function clientCapture(id: string): Promise<CaptureResult>;
23
+ export declare function clientSend(id: string, text: string, from?: string): Promise<DispatchResult>;
24
+ export declare function clientSendThroughPeer(sshAddress: string, id: string, text: string, from?: string): Promise<DispatchResult>;
25
+ export declare function clientListSessionsThroughPeer(sshAddress: string, projectAnchor: string): Promise<Session[]>;
26
+ export type PeerSessionCreateInput = {
27
+ prompt: string;
28
+ launcher?: string;
29
+ name?: string;
30
+ base?: string;
31
+ };
32
+ export declare function clientCreateThroughPeer(sshAddress: string, projectAnchor: string, input: PeerSessionCreateInput): Promise<Session>;
33
+ export declare function clientReview(id: string): Promise<CockpitReview | null>;
34
+ export type ExportResult = {
35
+ ok: true;
36
+ body: string;
37
+ } | {
38
+ ok: false;
39
+ status: number;
40
+ };
41
+ export declare function clientEvalExport(id: string): Promise<ExportResult>;
42
+ type SessionEvalPage = {
43
+ items: any[];
44
+ page: number;
45
+ pageCount: number;
46
+ total: number;
47
+ gates: any[];
48
+ unknown: number;
49
+ revision: string;
50
+ summary?: any;
51
+ evalRevision?: any;
52
+ };
53
+ export type EvalsResult = {
54
+ ok: true;
55
+ model: SessionEvalPage & {
56
+ id: string;
57
+ };
58
+ } | {
59
+ ok: false;
60
+ status: number;
61
+ };
62
+ export declare function clientEvals(id: string): Promise<EvalsResult>;
63
+ export declare function clientMerge(id: string): Promise<{
64
+ dispatched: boolean;
65
+ reason?: string;
66
+ code?: string;
67
+ }>;
68
+ export declare function clientResume(id: string, force?: boolean): Promise<{
69
+ ok: boolean;
70
+ error?: string;
71
+ refused?: boolean;
72
+ info?: string;
73
+ }>;
74
+ export declare function clientStop(id: string): Promise<boolean>;
75
+ export declare function clientInterrupt(id: string): Promise<DispatchResult>;
76
+ export declare function clientClose(id: string): Promise<boolean>;
77
+ export declare function clientCloseThroughPeer(sshAddress: string, id: string): Promise<boolean>;
78
+ export declare function clientQuarantine(id: string, witness: {
79
+ adapter: string;
80
+ thread: string | null;
81
+ tmux: string;
82
+ worktree: string;
83
+ branch: string;
84
+ }): Promise<{
85
+ id: string;
86
+ bundle: string;
87
+ sha256: string;
88
+ observedAt: string;
89
+ }>;
90
+ export declare function clientRestoreQuarantine(id: string): Promise<{
91
+ id: string;
92
+ bundle: string;
93
+ sha256: string;
94
+ observedAt: string;
95
+ }>;
96
+ export declare function clientArchive(id: string, on?: boolean): Promise<boolean>;
97
+ export declare function clientRename(id: string, name: string): Promise<boolean>;
98
+ export declare function clientReparent(children: string[], parent: string | null): Promise<import('./sessions.js').SessionReparentResult>;
99
+ export declare function clientSendRawKeys(id: string, keys: string[]): Promise<boolean>;
100
+ export type ShowResult = {
101
+ ok: true;
102
+ session: Session & {
103
+ prompt: string | null;
104
+ };
105
+ } | {
106
+ ok: false;
107
+ status: number;
108
+ };
109
+ export declare function clientShow(id: string): Promise<ShowResult>;
110
+ export declare function clientShowThroughPeer(sshAddress: string, id: string): Promise<ShowResult>;
111
+ export {};
@@ -0,0 +1,476 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { platform } from 'node:os';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { repoRoot } from '@spexcode/spec-core';
5
+ import { resourceBudgets } from './host-resources.js';
6
+ import { envSessionId, listSessionIds, readPublicRecordEntry } from '@spexcode/spec-core';
7
+ import { cockpitReview } from './cockpit.js';
8
+ import { apiBaseInfo, assertProjectMatch, findSessionClosure, fromRaw, optionArgv, resolveSession, toSession } from './sessions.js';
9
+ import { resolveMachinePeer } from './machine-peer.js';
10
+ export class BackendError extends Error {
11
+ status;
12
+ transport;
13
+ constructor(message, status, transport) {
14
+ super(message);
15
+ this.status = status;
16
+ this.transport = transport;
17
+ this.name = 'BackendError'; // cli.ts's top-level handler matches on the NAME, so it needs no import of this class
18
+ }
19
+ }
20
+ const usageError = (message) => {
21
+ const error = new Error(message);
22
+ error.name = 'UsageError';
23
+ return error;
24
+ };
25
+ const hasFlag = (name) => optionArgv().includes(`--${name}`);
26
+ function flagValue(name) {
27
+ const argv = optionArgv();
28
+ const index = argv.indexOf(`--${name}`);
29
+ if (index < 0)
30
+ return null;
31
+ const value = argv[index + 1];
32
+ if (value === undefined || value.startsWith('--'))
33
+ throw usageError(`--${name} expects a value`);
34
+ return value;
35
+ }
36
+ let gatewayCookie = null;
37
+ function prepareTls(base) {
38
+ if (!hasFlag('insecure'))
39
+ return;
40
+ if (new URL(base).protocol !== 'https:')
41
+ throw usageError('--insecure requires an https --api endpoint');
42
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
43
+ }
44
+ function passwordFor(target) {
45
+ const password = flagValue('password') ?? process.env.SPEXCODE_PASSWORD ?? null;
46
+ if (!password)
47
+ return null;
48
+ if (target.source !== 'flag')
49
+ throw usageError('--password and SPEXCODE_PASSWORD require explicit --api routing');
50
+ return password;
51
+ }
52
+ function withCookie(init, cookie) {
53
+ const headers = new Headers(init?.headers);
54
+ headers.set('cookie', cookie);
55
+ return { ...init, headers };
56
+ }
57
+ async function loginGateway(base, password) {
58
+ let response;
59
+ try {
60
+ response = await fetch(`${base}/login`, {
61
+ method: 'POST',
62
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
63
+ body: new URLSearchParams({ password }).toString(),
64
+ redirect: 'manual',
65
+ });
66
+ }
67
+ catch (error) {
68
+ throw new BackendError(`gateway login could not reach ${base}: ${error.message}`, undefined, error);
69
+ }
70
+ if (response.status < 200 || response.status >= 400)
71
+ throw new BackendError(`gateway login rejected credentials at ${base}`, response.status);
72
+ const headers = response.headers;
73
+ const cookies = headers.getSetCookie?.() ?? [response.headers.get('set-cookie') ?? ''];
74
+ const cookie = cookies.map((value) => value.split(';', 1)[0]).find(Boolean);
75
+ if (!cookie)
76
+ throw new BackendError(`gateway login at ${base} did not return an authorization cookie`, response.status);
77
+ return cookie;
78
+ }
79
+ // the ONE seam where "no backend" becomes loud. A network failure (nothing listening at the resolved base)
80
+ // is the only thing thrown; an HTTP Response of any status is returned for the caller to interpret.
81
+ async function apiFetch(path, init) {
82
+ const target = await apiBaseInfo();
83
+ const base = target.url;
84
+ prepareTls(base);
85
+ const request = async (cookie) => {
86
+ try {
87
+ return await fetch(`${base}${path}`, cookie ? withCookie(init, cookie) : init);
88
+ }
89
+ catch (error) {
90
+ throw new BackendError(`no backend reachable at ${base} — run \`spex serve\` in the project, or name one with --api <url> (${error.message})`, undefined, error);
91
+ }
92
+ };
93
+ const existing = gatewayCookie?.base === base ? gatewayCookie.value : undefined;
94
+ const response = await request(existing);
95
+ if (response.status !== 401)
96
+ return response;
97
+ if (existing)
98
+ throw new BackendError(`gateway rejected the authenticated request at ${base}`, 401);
99
+ const password = passwordFor(target);
100
+ if (!password)
101
+ throw new BackendError(`authentication required at ${base} — pass --password <pw> or set SPEXCODE_PASSWORD`, 401);
102
+ const cookie = await loginGateway(base, password);
103
+ gatewayCookie = { base, value: cookie };
104
+ const retried = await request(cookie);
105
+ if (retried.status === 401)
106
+ throw new BackendError(`gateway rejected the authenticated request at ${base}`, 401);
107
+ return retried;
108
+ }
109
+ export function backendConnectionRefused(error) {
110
+ if (!(error instanceof BackendError))
111
+ return false;
112
+ let current = error.transport;
113
+ let sawRefusal = false;
114
+ const seen = new Set();
115
+ while (current && typeof current === 'object' && !seen.has(current)) {
116
+ seen.add(current);
117
+ const code = current.code;
118
+ if (code && code !== 'ECONNREFUSED')
119
+ return false;
120
+ if (code === 'ECONNREFUSED')
121
+ sawRefusal = true;
122
+ current = current.cause;
123
+ }
124
+ return sawRefusal;
125
+ }
126
+ // every MUTATING verb is project-bound ([[remote-client]]'s write guard): resolve the backend, compare its
127
+ // served root to the cwd project, refuse loudly on a same-host mismatch — an explicit --api/--port skips it.
128
+ // Reads stay unguarded (viewer-points-anywhere). Guarding HERE (not per cli.ts branch) covers every caller.
129
+ const guarded = (verb) => assertProjectMatch(`spex ${verb}`);
130
+ const post = (body) => ({ method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });
131
+ const seg = (id) => encodeURIComponent(id);
132
+ // A rendezvous liveness probe can displace the real delivery client.
133
+ function cachedStatus(rec) {
134
+ if (!rec.worktreePath || !existsSync(rec.worktreePath))
135
+ return 'retired';
136
+ if (rec.archived)
137
+ return 'offline';
138
+ if (rec.status === 'awaiting')
139
+ return rec.proposal === 'merge' ? 'review' : rec.proposal === 'close' ? 'close-pending' : 'done';
140
+ return rec.status === 'active' || rec.status === 'idle' ? 'unknown' : rec.status;
141
+ }
142
+ function corruptCachedSession(id, reason) {
143
+ const label = `${id.slice(0, 8)} (unreadable record)`;
144
+ return {
145
+ id, node: null, branch: null, path: '', label, title: label, raw: { name: null, title: null },
146
+ parent: null, harness: 'unknown', capabilities: { headless: false }, launcher: null,
147
+ lifecycle: 'active', proposal: null, merges: 0, status: 'corrupt', liveness: 'unknown',
148
+ note: `session record is unreadable: ${reason}`, archived: false, archiveHazard: null,
149
+ prompt: null, promptPreview: null, created: 0, activity: null, sortKey: null,
150
+ };
151
+ }
152
+ // Also the board a FOLLOW resolves its selectors against ([[session-follow]]): following must work with no
153
+ // `spex serve` running, and asking a backend for the board would cost exactly the tmux/rendezvous probes the
154
+ // follow exists to eliminate. Every field here comes from the store — nothing is probed.
155
+ export function localCachedSessions(includeArchived = false) {
156
+ const rows = [];
157
+ for (const id of listSessionIds()) {
158
+ const entry = readPublicRecordEntry(id);
159
+ if (entry.kind === 'corrupt') {
160
+ rows.push(corruptCachedSession(id, entry.error));
161
+ continue;
162
+ }
163
+ if (entry.kind !== 'ok')
164
+ continue;
165
+ const rec = fromRaw(entry.raw);
166
+ if (!rec.governed)
167
+ continue;
168
+ rows.push(toSession(rec, cachedStatus(rec), 'unknown'));
169
+ }
170
+ return rows.filter((session) => includeArchived || !session.archived)
171
+ .sort((a, b) => (a.sortKey ?? a.created) - (b.sortKey ?? b.created) || a.id.localeCompare(b.id));
172
+ }
173
+ function localCachedResources() {
174
+ const projectRoot = repoRoot();
175
+ const budgets = resourceBudgets(projectRoot);
176
+ const owners = localCachedSessions(true).map((session) => ({
177
+ kind: 'session',
178
+ id: session.id,
179
+ label: session.label,
180
+ status: session.lifecycle,
181
+ liveness: 'unknown',
182
+ proposal: session.proposal,
183
+ note: session.note,
184
+ worktreePath: session.path,
185
+ branch: session.branch,
186
+ archived: session.archived,
187
+ processes: [],
188
+ rssMiB: 0,
189
+ pssMiB: null,
190
+ cpuPercent: 0,
191
+ budget: { rssMiB: budgets.sessionRssMiB, idleCpuPercent: budgets.idleCpuPercent },
192
+ findings: ['local-store-only: runtime liveness and process measurements are unavailable'],
193
+ reclaim: { eligible: false, reason: 'local store read cannot prove runtime ownership or liveness' },
194
+ }));
195
+ return {
196
+ version: 1,
197
+ measuredAt: new Date().toISOString(),
198
+ projectRoot,
199
+ platform: platform(),
200
+ available: false,
201
+ unavailableReason: 'backend unavailable; local session store has no runtime resource measurements',
202
+ host: { memoryTotalMiB: null, memoryUsedMiB: null, memoryAvailableMiB: null, swapTotalMiB: null, swapUsedMiB: null, cpuPercent: null },
203
+ budgets,
204
+ owners,
205
+ totals: { rssMiB: 0, pssMiB: null, cpuPercent: 0 },
206
+ findings: owners.reduce((total, owner) => total + owner.findings.length, 0),
207
+ };
208
+ }
209
+ async function cachedRead(remote, local) {
210
+ try {
211
+ return await remote();
212
+ }
213
+ catch (error) {
214
+ if (!(error instanceof BackendError) || error.status !== undefined || (await apiBaseInfo()).source === 'flag')
215
+ throw error;
216
+ console.error('spex session: backend unreachable; source: local session store (liveness unknown)');
217
+ return await local();
218
+ }
219
+ }
220
+ // GET /api/sessions — the board, used by `spex session ls`, and by `spex session watch`/`wait` as their poll source.
221
+ export async function clientListSessions(includeArchived = false) {
222
+ return cachedRead(async () => {
223
+ const r = await apiFetch(includeArchived ? '/api/sessions?all=1' : '/api/sessions');
224
+ if (!r.ok)
225
+ throw new BackendError(`backend error ${r.status} listing sessions`, r.status);
226
+ return await r.json();
227
+ }, () => localCachedSessions(includeArchived));
228
+ }
229
+ // A terminal close removes the record from the board. The audit lookup is deliberately id-addressed and is
230
+ // consulted only after an explicit selector missed that board, so ordinary lists stay a current-state read.
231
+ export async function clientSessionClosure(selector) {
232
+ return cachedRead(async () => {
233
+ const r = await apiFetch(`/api/sessions/${seg(selector)}/closure`);
234
+ if (r.headers.get('x-spexcode-close-history') !== 'v1')
235
+ throw new BackendError(`backend does not support terminal close history; refusing to label ${selector} as never existed (update the backend)`, 501);
236
+ if (r.status === 404)
237
+ return null;
238
+ if (!r.ok)
239
+ throw new BackendError(`backend error ${r.status} retrieving close history for ${selector}`, r.status);
240
+ return await r.json();
241
+ }, () => findSessionClosure(selector));
242
+ }
243
+ export async function clientResources() {
244
+ return cachedRead(async () => {
245
+ const r = await apiFetch('/api/resources');
246
+ if (!r.ok)
247
+ throw new BackendError(`backend error ${r.status} loading resources: ${await r.text()}`, r.status);
248
+ return await r.json();
249
+ }, localCachedResources);
250
+ }
251
+ // resolve a selector (full id, id-prefix, node, or branch) against the live board, then call with the full id.
252
+ export async function resolveClientSession(selector, includeArchived = true) {
253
+ return resolveSession(selector, await clientListSessions(includeArchived));
254
+ }
255
+ export async function clientCapture(id) {
256
+ const r = await apiFetch(`/api/sessions/${seg(id)}/capture`);
257
+ if (r.ok)
258
+ return { ok: true, pane: await r.text() };
259
+ return { ok: false, status: r.status, reason: (await r.text().catch(() => '')) || `status ${r.status}` };
260
+ }
261
+ // POST /api/sessions/:id/input {kind:"text"} appends the prompt to the durable timeline, then best-effort
262
+ // pokes the resolved adapter. HTTP failure means the append itself was refused.
263
+ export async function clientSend(id, text, from) {
264
+ await guarded('session send');
265
+ // `from` = the sending agent's own session id; the recipient's log records the sender ([[session-timeline]]) only when
266
+ // it's present (an agent send), so a human-shell send stays unrecorded.
267
+ const r = await apiFetch(`/api/sessions/${seg(id)}/input`, post({ kind: 'text', text, ...(from ? { from } : {}) }));
268
+ return await r.json().catch(() => ({ ok: false, error: `bad backend response (${r.status})` }));
269
+ }
270
+ // A machine peer's outbound loopback port is an SSH forward into the remote gateway's dedicated ingress.
271
+ // It exposes only the small session-id allowlist the gateway can safely route to a derived local project.
272
+ async function peerFetch(sshAddress, path, init) {
273
+ const peer = resolveMachinePeer(sshAddress);
274
+ try {
275
+ return await fetch(`http://127.0.0.1:${peer.outboundPort}${path}`, init);
276
+ }
277
+ catch (error) {
278
+ throw new BackendError(`communication tunnel for SSH address ${JSON.stringify(sshAddress)} is unreachable — run \`spex peer connect ${sshAddress}\` to repair it (${error.message})`, undefined, error);
279
+ }
280
+ }
281
+ export async function clientSendThroughPeer(sshAddress, id, text, from) {
282
+ const response = await peerFetch(sshAddress, `/api/sessions/${seg(id)}/input`, post({ kind: 'text', text, ...(from ? { from } : {}) }));
283
+ const body = await response.json().catch(() => ({ ok: false, error: `bad peer response (${response.status})` }));
284
+ const peerBody = body;
285
+ if (!response.ok && peerBody.ok !== false) {
286
+ return { ok: false, error: typeof peerBody.error === 'string' ? peerBody.error : `peer request failed (${response.status})` };
287
+ }
288
+ return body;
289
+ }
290
+ // The full id is the peer gateway's project anchor. Peer lists deliberately use the default board projection:
291
+ // archives would need a new allowlisted operation, not an unreviewed query-string tunnel.
292
+ export async function clientListSessionsThroughPeer(sshAddress, projectAnchor) {
293
+ const response = await peerFetch(sshAddress, `/api/sessions/${seg(projectAnchor)}/project/sessions`);
294
+ if (!response.ok)
295
+ throw new BackendError(`remote backend refused to list sessions for ${projectAnchor}: ${await response.text()}`, response.status);
296
+ return await response.json();
297
+ }
298
+ // Peer creation is deliberately separate from sessions.ts createSession: that function's proven-local-refusal
299
+ // fallback would launch on THIS machine. The closed body lets the peer gateway recreate the normal backend
300
+ // idempotency header without becoming a general header proxy.
301
+ export async function clientCreateThroughPeer(sshAddress, projectAnchor, input) {
302
+ const response = await peerFetch(sshAddress, `/api/sessions/${seg(projectAnchor)}/project/sessions`, post({
303
+ ...input,
304
+ requestKey: randomUUID(),
305
+ }));
306
+ if (!response.ok) {
307
+ const text = await response.text().catch(() => '');
308
+ let message = text;
309
+ try {
310
+ message = JSON.parse(text).error || text;
311
+ }
312
+ catch { }
313
+ throw new BackendError(`remote backend rejected session (${response.status}): ${message}`, response.status);
314
+ }
315
+ return await response.json();
316
+ }
317
+ // GET /api/sessions/:id/review — the manager cockpit review bundle (null on 404).
318
+ export async function clientReview(id) {
319
+ return cachedRead(async () => {
320
+ const r = await apiFetch(`/api/sessions/${seg(id)}/review`);
321
+ if (r.status === 404)
322
+ return null;
323
+ if (!r.ok)
324
+ throw new BackendError(`backend error ${r.status} reviewing ${id}`, r.status);
325
+ return await r.json();
326
+ }, () => cockpitReview(id));
327
+ }
328
+ export async function clientEvalExport(id) {
329
+ const r = await apiFetch(`/api/sessions/${seg(id)}/evals?format=html`);
330
+ if (r.ok)
331
+ return { ok: true, body: await r.text() };
332
+ return { ok: false, status: r.status };
333
+ }
334
+ export async function clientEvals(id) {
335
+ const q = encodeURIComponent(`is:eval scope:${id}`);
336
+ for (let attempt = 0; attempt < 2; attempt++) {
337
+ const items = [];
338
+ let first = null;
339
+ let changed = false;
340
+ for (let page = 1;; page++) {
341
+ const r = await apiFetch(`/api/evals?q=${q}&page=${page}`);
342
+ if (!r.ok)
343
+ return { ok: false, status: r.status };
344
+ const current = await r.json();
345
+ first ??= current;
346
+ if (current.revision !== first.revision) {
347
+ changed = true;
348
+ break;
349
+ }
350
+ items.push(...current.items);
351
+ if (page >= current.pageCount)
352
+ break;
353
+ }
354
+ if (!changed)
355
+ return { ok: true, model: { ...first, id, items } };
356
+ }
357
+ throw new BackendError(`session eval pages changed while fetching ${id}; retry the command`);
358
+ }
359
+ // POST /api/sessions/:id/merge — a human merge intent dispatched to the session's own agent.
360
+ export async function clientMerge(id) {
361
+ await guarded('merge');
362
+ const r = await apiFetch(`/api/sessions/${seg(id)}/merge`, { method: 'POST' });
363
+ return await r.json().catch(() => ({ dispatched: false, reason: `bad backend response (${r.status})` }));
364
+ }
365
+ // POST /api/sessions/:id/resume — bring the agent back (relaunch ONLY if confirmed offline); demotes
366
+ // working→idle, keeps any declaration. The RESUME GUARD REFUSES (409 {refused:true}) on a live/unproven agent;
367
+ // `force` overrides for a wedged-but-alive process. {ok:false} otherwise = no such session (404). `info`
368
+ // carries a non-error advisory.
369
+ export async function clientResume(id, force = false) {
370
+ await guarded('session resume');
371
+ const r = await apiFetch(`/api/sessions/${seg(id)}/resume`, post({ force }));
372
+ return await r.json().catch(() => ({ ok: false, error: `bad backend response (${r.status})` }));
373
+ }
374
+ // POST /api/sessions/:id/stop — the soft stop: kill tmux + socket, KEEP the worktree (session goes offline,
375
+ // resumable). Distinct from close. {ok:false} = no such session.
376
+ export async function clientStop(id) {
377
+ await guarded('session stop');
378
+ const r = await apiFetch(`/api/sessions/${seg(id)}/stop`, post({}));
379
+ if (!r.ok)
380
+ throw new BackendError(`backend refused to stop ${id}: ${await r.text()}`, r.status);
381
+ return !!(await r.json().catch(() => ({ ok: false })))?.ok;
382
+ }
383
+ // POST /api/sessions/:id/interrupt - native hard interrupt of the current turn. Unsupported harnesses and
384
+ // unreachable control planes return the backend's loud DispatchResult; no signal/raw-key fallback exists.
385
+ export async function clientInterrupt(id) {
386
+ await guarded('session interrupt');
387
+ const r = await apiFetch(`/api/sessions/${seg(id)}/interrupt`, post({}));
388
+ return await r.json().catch(() => ({ ok: false, error: `bad backend response (${r.status})` }));
389
+ }
390
+ // POST /api/sessions/:id/close — terminal worktree removal. A client-side session id is only an unverified claim.
391
+ export async function clientClose(id) {
392
+ await guarded('session close');
393
+ const source = envSessionId();
394
+ const r = await apiFetch(`/api/sessions/${seg(id)}/close`, post({ source: source ? { kind: 'unverified-session-claim', id: source } : { kind: 'user' } }));
395
+ if (!r.ok)
396
+ throw new BackendError(`backend refused to close ${id}: ${await r.text()}`, r.status);
397
+ return !!(await r.json().catch(() => ({ ok: false })))?.ok;
398
+ }
399
+ // POST /api/sessions/:id/close through a known peer. The local project guard is inapplicable: the peer is
400
+ // already the caller's explicit remote transport, and the remote gateway derives the owning project by id.
401
+ export async function clientCloseThroughPeer(sshAddress, id) {
402
+ const r = await peerFetch(sshAddress, `/api/sessions/${seg(id)}/close`, post({ source: { kind: 'user' } }));
403
+ if (!r.ok)
404
+ throw new BackendError(`remote backend refused to close ${id}: ${await r.text()}`, r.status);
405
+ return !!(await r.json().catch(() => ({ ok: false })))?.ok;
406
+ }
407
+ export async function clientQuarantine(id, witness) {
408
+ await guarded('session quarantine');
409
+ const r = await apiFetch(`/api/sessions/${seg(id)}/quarantine`, post(witness));
410
+ if (!r.ok)
411
+ throw new BackendError(`backend refused to quarantine ${id}: ${await r.text()}`, r.status);
412
+ const body = await r.json();
413
+ if (!body.ok || !body.id || !body.bundle || !body.sha256 || !body.observedAt)
414
+ throw new BackendError(`backend returned an invalid quarantine result for ${id}`, r.status);
415
+ return { id: body.id, bundle: body.bundle, sha256: body.sha256, observedAt: body.observedAt };
416
+ }
417
+ export async function clientRestoreQuarantine(id) {
418
+ await guarded('session quarantine');
419
+ const r = await apiFetch(`/api/sessions/${seg(id)}/quarantine/restore`, post({}));
420
+ if (!r.ok)
421
+ throw new BackendError(`backend refused to restore ${id}: ${await r.text()}`, r.status);
422
+ const body = await r.json();
423
+ if (!body.ok || !body.id || !body.bundle || !body.sha256 || !body.observedAt)
424
+ throw new BackendError(`backend returned an invalid quarantine restore for ${id}`, r.status);
425
+ return { id: body.id, bundle: body.bundle, sha256: body.sha256, observedAt: body.observedAt };
426
+ }
427
+ // POST /api/sessions/:id/archive — cold-archive the session ([[archive]]). The legacy on=false spelling is a
428
+ // signpost to the same resume transition; it never performs a record-only unarchive.
429
+ export async function clientArchive(id, on = true) {
430
+ await guarded(on ? 'session archive' : 'session unarchive');
431
+ const r = await apiFetch(`/api/sessions/${seg(id)}/archive`, post({ on }));
432
+ if (!r.ok)
433
+ throw new BackendError(`backend refused to ${on ? 'archive' : 'unarchive'} ${id}: ${await r.text()}`, r.status);
434
+ return !!(await r.json().catch(() => ({ ok: false })))?.ok;
435
+ }
436
+ // POST /api/sessions/:id/rename — set (or clear, with a blank) the session's display-name override
437
+ // ([[session-rename]] as a CLI verb). {ok:false} = no such session (404).
438
+ export async function clientRename(id, name) {
439
+ await guarded('session rename');
440
+ const r = await apiFetch(`/api/sessions/${seg(id)}/rename`, post({ name }));
441
+ return !!(await r.json().catch(() => ({ ok: false })))?.ok;
442
+ }
443
+ export async function clientReparent(children, parent) {
444
+ await guarded('session reparent');
445
+ const r = await apiFetch('/api/sessions/reparent', post({ children, parent }));
446
+ if (!r.ok)
447
+ throw new BackendError(`backend refused to reparent sessions: ${await r.text()}`, r.status);
448
+ return await r.json();
449
+ }
450
+ // POST /api/sessions/:id/input {kind:"keys"} — the LAST-RESORT raw nav-key face of send (tmux send-keys,
451
+ // NEVER the prompt socket): an ordered token batch drives an interactive TUI menu
452
+ // ([[nav-mode-key-ordering]]). {ok:false} = unknown session, no live pane, or no valid token delivered.
453
+ export async function clientSendRawKeys(id, keys) {
454
+ await guarded('session send');
455
+ const r = await apiFetch(`/api/sessions/${seg(id)}/input`, post({ kind: 'keys', keys }));
456
+ return !!(await r.json().catch(() => ({ ok: false })))?.ok;
457
+ }
458
+ export async function clientShow(id) {
459
+ return cachedRead(async () => {
460
+ const r = await apiFetch(`/api/sessions/${seg(id)}`);
461
+ if (r.ok)
462
+ return { ok: true, session: await r.json() };
463
+ return { ok: false, status: r.status };
464
+ }, () => {
465
+ const session = localCachedSessions(true).find((item) => item.id === id);
466
+ return session ? { ok: true, session } : { ok: false, status: 404 };
467
+ });
468
+ }
469
+ export async function clientShowThroughPeer(sshAddress, id) {
470
+ const r = await peerFetch(sshAddress, `/api/sessions/${seg(id)}`);
471
+ if (r.ok)
472
+ return { ok: true, session: await r.json() };
473
+ if (r.status === 404)
474
+ return { ok: false, status: 404 };
475
+ throw new BackendError(`remote backend refused to show ${id}: ${await r.text()}`, r.status);
476
+ }
@@ -0,0 +1,7 @@
1
+ import { type ReviewEvalGate, type ReviewPayload } from './sessions.js';
2
+ export type CockpitReview = Omit<ReviewPayload, 'gates'> & {
3
+ gates: ReviewPayload['gates'] & {
4
+ evals: ReviewEvalGate;
5
+ };
6
+ };
7
+ export declare function cockpitReview(id: string): Promise<CockpitReview | null>;
@@ -0,0 +1,26 @@
1
+ import { reviewPayload } from './sessions.js';
2
+ import { sessionEvalProjection } from '@spexcode/spec-eval/sessioneval';
3
+ // @@@ evalGate - the measured-loss readout, taken from [[session-eval]]'s EXISTING projection. This is a cache
4
+ // READ and must stay one: `buildSessionEvals()` calls `reviewPayload()` itself, so BUILDING the model from here
5
+ // would recurse. That hazard used to be held off by a comment; now it is structural — `reviewPayload` no longer
6
+ // carries this field, so the eval side cannot re-enter through it. (It never read the field anyway: `gateRows`
7
+ // consumes lint/conflict/ahead/dirty only. The payload was carrying a value for a caller that ignored it.)
8
+ async function evalGate(id) {
9
+ const projection = sessionEvalProjection(id);
10
+ if (!projection)
11
+ return { phase: 'unavailable' };
12
+ // only a `ready` projection carries a CURRENT value; last-known is deliberately not reported as current.
13
+ if (projection.phase !== 'ready' || !projection.value) {
14
+ return { phase: projection.phase === 'ready' ? 'unavailable' : projection.phase };
15
+ }
16
+ const summary = projection.value;
17
+ return { phase: 'ready', freshPass: summary.pass, freshFail: summary.fail, needReview: summary.review, blind: summary.blind };
18
+ }
19
+ // the cockpit's whole answer for one session: the session-side review plus the eval readout, composed once.
20
+ // The two run in parallel — the eval half is a projection read, independent of every git read in the payload.
21
+ export async function cockpitReview(id) {
22
+ const [payload, evals] = await Promise.all([reviewPayload(id), evalGate(id)]);
23
+ if (!payload)
24
+ return null;
25
+ return { ...payload, gates: { ...payload.gates, evals } };
26
+ }
@@ -0,0 +1 @@
1
+ export declare function codexHeadlessLaunchCommand(id: string, codexCmd?: string, serverCmd?: string, dir?: string): string;
@@ -1,13 +1,7 @@
1
- import { codexLaunchCommand } from './harness.js'
2
-
1
+ import { codexLaunchCommand } from './harness.js';
3
2
  // Codex headless keeps the existing app-server bootstrap and backend-owned thread/start + first turn, but
4
3
  // deliberately omits the final interactive `--remote … resume` attach. The shared app-server remains the
5
4
  // durable home for the thread; follow-up delivery uses codexHarness' existing JSON-RPC transport.
6
- export function codexHeadlessLaunchCommand(
7
- id: string,
8
- codexCmd = 'codex',
9
- serverCmd?: string,
10
- dir?: string,
11
- ): string {
12
- return codexLaunchCommand(id, codexCmd, serverCmd, dir, false)
5
+ export function codexHeadlessLaunchCommand(id, codexCmd = 'codex', serverCmd, dir) {
6
+ return codexLaunchCommand(id, codexCmd, serverCmd, dir, false);
13
7
  }