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,14 @@
1
+ import type { TimelineEvent } from './session-timeline.js';
2
+ export type Cursors = {
3
+ version: 1;
4
+ follows: Record<string, number>;
5
+ };
6
+ export declare function readCursors(id: string): Cursors;
7
+ export declare const followCursor: (id: string, target: string) => number | null;
8
+ export declare function advanceFollow(id: string, target: string, to: number): void;
9
+ export declare const followedSessions: (id: string) => string[];
10
+ export declare function unreadSince(events: TimelineEvent[], from: number): {
11
+ events: TimelineEvent[];
12
+ at: number[];
13
+ next: number;
14
+ };
@@ -0,0 +1,82 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { sessionArtifactPath, sessionStoreDir } from '@spexcode/spec-core';
4
+ const cursorsPath = (id) => sessionArtifactPath(id, 'cursors.json');
5
+ const at = (v) => (typeof v === 'number' && Number.isFinite(v) && v > 0 ? Math.floor(v) : 0);
6
+ // Never throws: a missing, empty, or unparseable file reads as "nothing consumed", because re-showing a
7
+ // message is the honest recovery for a lost position and skipping one is not. Followed entries whose target
8
+ // store dir is gone are dropped here — expiry is this read, and the next write persists it.
9
+ export function readCursors(id) {
10
+ let raw = null;
11
+ try {
12
+ raw = JSON.parse(readFileSync(cursorsPath(id), 'utf8'));
13
+ }
14
+ catch { /* no cursors yet */ }
15
+ const follows = {};
16
+ const stored = raw?.follows;
17
+ if (stored && typeof stored === 'object') {
18
+ for (const [target, pos] of Object.entries(stored)) {
19
+ if (!target || !existsSync(sessionStoreDir(target)))
20
+ continue;
21
+ follows[target] = at(pos);
22
+ }
23
+ }
24
+ return { version: 1, follows };
25
+ }
26
+ // Written whole and atomically, one field per line — the same shape as the session record, so a position stays
27
+ // readable by an exact whole-line match where a value regex would not be.
28
+ function writeCursors(id, cursors) {
29
+ const dir = sessionStoreDir(id);
30
+ mkdirSync(dir, { recursive: true });
31
+ const tmp = join(dir, `.cursors.json.${process.pid}.tmp`);
32
+ writeFileSync(tmp, JSON.stringify(cursors, null, 2) + '\n');
33
+ renameSync(tmp, cursorsPath(id));
34
+ }
35
+ export const followCursor = (id, target) => {
36
+ const stored = readCursors(id).follows[target];
37
+ return stored === undefined ? null : stored;
38
+ };
39
+ // Start or advance a follow. Following IS this entry existing, so the first call registers the relationship.
40
+ // Monotonic: a stale read can leave a position too low (an event read twice), never too high (one lost).
41
+ export function advanceFollow(id, target, to) {
42
+ const cursors = readCursors(id);
43
+ const stored = cursors.follows[target];
44
+ if (stored !== undefined && to <= stored)
45
+ return;
46
+ writeCursors(id, { ...cursors, follows: { ...cursors.follows, [target]: Math.max(0, Math.floor(to)) } });
47
+ }
48
+ export const followedSessions = (id) => Object.keys(readCursors(id).follows);
49
+ const sameStatus = (a, b) => a.kind === 'status' && b.kind === 'status' && a.status === b.status
50
+ && (a.proposal ?? null) === (b.proposal ?? null) && (a.note ?? null) === (b.note ?? null);
51
+ // @@@ edges, not lines - what a reader has not yet seen, with repeated status lines dropped. X→X IS NOT A
52
+ // TRANSITION: the log is append-only and already holds runs of identical status lines from before the
53
+ // timeline observer was deleted (every stray `spex serve` process ran an fs.watch over the same store and
54
+ // re-recorded each real move, so ONE transition landed as up to 6 lines within ~200ms). Those bytes are
55
+ // history and stay. Any consumer that decides "did it move?" must therefore compare VALUES, never adjacency,
56
+ // and must compare against the last status the reader ALREADY saw — otherwise a duplicate straddling the
57
+ // cursor boundary reads as a fresh move on the very next tick. `next` is where the cursor goes after consuming
58
+ // the WHOLE slice: the full length, because a dropped duplicate is still consumed. `at[i]` is the absolute
59
+ // index of `events[i]`, which is what lets a reader that STOPS on one event ([[session-follow]]'s take-one
60
+ // wait) advance to exactly `at[i] + 1` and leave the lines behind it unread for the next reader.
61
+ export function unreadSince(events, from) {
62
+ const start = Math.min(Math.max(0, Math.floor(from)), events.length);
63
+ let prev = null;
64
+ for (let i = start - 1; i >= 0; i--)
65
+ if (events[i].kind === 'status') {
66
+ prev = events[i];
67
+ break;
68
+ }
69
+ const out = [];
70
+ const at = [];
71
+ for (let i = start; i < events.length; i++) {
72
+ const e = events[i];
73
+ if (e.kind === 'status') {
74
+ if (prev && sameStatus(prev, e))
75
+ continue;
76
+ prev = e;
77
+ }
78
+ out.push(e);
79
+ at.push(i);
80
+ }
81
+ return { events: out, at, next: events.length };
82
+ }
@@ -0,0 +1,13 @@
1
+ type DeclarationVerb = 'done' | 'park' | 'ask';
2
+ export declare function sessionStateKit(sessionId?: string): Promise<{
3
+ s: typeof import("./sessions.js");
4
+ sess: string | undefined;
5
+ noRecord: () => string;
6
+ mark: (fn: () => boolean) => {
7
+ ok: boolean;
8
+ reason?: string;
9
+ };
10
+ noteEcho: (note?: string) => string;
11
+ }>;
12
+ export declare function runSessionDeclaration(verb: DeclarationVerb, argv?: readonly string[]): Promise<void>;
13
+ export {};
@@ -0,0 +1,126 @@
1
+ // @@@ worker declarations ([[cli-surface]] / [[state]]) - these are the three porcelain writes an
2
+ // agent performs from its own worktree. Keep their session resolution, no-record diagnosis, durable note
3
+ // receipt, and state write together so the CLI hub only selects the verb and never becomes a second owner.
4
+ const DECLARED = ' — recorded; the human sees it in the dashboard. This declaration remains in the session timeline; your next tool call flips only the current graph state back to active (the mark-active hook, by design).';
5
+ // appended ONLY to a propose-close declaration: a worktree about to be discarded may still own ephemeral things the agent started to test this change; nudge (not gate) it to reclaim them before the worktree goes, keyed on whether the thing should outlive the task — never on who started it (a deliberately long-running service / a production build is started-by-you yet must be left alone). Project-agnostic on purpose.
6
+ // @@@ the sweep never includes THIS session - the nudge names sessions as sweepable, and it is read at the one moment a session is thinking about closing. Said loosely it reads as permission to close yourself, which deletes the worktree the reading agent is running in. So the target is scoped to sessions the agent spawned, and the exclusion is stated rather than implied.
7
+ const CLOSE_CLEANUP = '\n\nBefore this worktree closes, check whether you left anything running that you started to test this change — a background process, a dev or preview server, a bound port, a throwaway session you spawned. If nothing depends on it anymore, shut it down, or it keeps running as an orphan. Leave anything meant to keep running: a service you deliberately stood up, a production build, anything other work relies on. What matters is whether it still needs to exist after this task, not whether you started it. If unsure, leave it. This sweep never includes THIS session: you have PROPOSED that the human close it, and closing your own session would delete the worktree you are running in. This is a reminder to check, not a required step.';
8
+ const flag = (argv, name) => {
9
+ const i = argv.indexOf(`--${name}`);
10
+ return i >= 0 ? argv[i + 1] : undefined;
11
+ };
12
+ function nothingProposalTrap() {
13
+ console.error('`spex session done --propose nothing` is an intended trap: no state was recorded.');
14
+ console.error('Choose the true destination:');
15
+ console.error(' `merge` - committed spec and code have not landed in `main`.');
16
+ console.error(' `close` - work is complete: it has landed (or had nothing to land), is verified, and no worktree, human decision/follow-up, or posted artifact needs human inspection.');
17
+ console.error(' `ask` - a human reply, direction, or decision is needed, including a reported finding/recommendation, handoff, or posted artifact inspection.');
18
+ console.error(' `park` - a managed delivery or background job will resume a named next action; watching terminal children is not a wake-up.');
19
+ process.exit(2);
20
+ }
21
+ // Shared with `spex internal session-*`: machine lifecycle producers use the same record-resolution and
22
+ // diagnostic rules, but they do not own any porcelain declaration verb.
23
+ export async function sessionStateKit(sessionId) {
24
+ const s = await import('./sessions.js');
25
+ const l = await import('@spexcode/spec-core');
26
+ const { existsSync, writeFileSync } = await import('node:fs');
27
+ // the agent-authored state writers resolve WHICH session by id: a `--session <id>` flag (the lifecycle
28
+ // hooks pass it, parsed from the payload, since they no longer have a cwd `.session`) wins, else the
29
+ // harness env var (ownSessionId — the agent's own `spex session …` carries the harness session id).
30
+ const sess = sessionId;
31
+ // @@@ no-record diagnosis ([[state]]) - the session store resolves from the CURRENT directory (runtimeRoot
32
+ // ← the cwd's git common dir), so the classic declaration failure is a cd OUTSIDE the session's project —
33
+ // and a bare "no session record" told the author none of that (field-reported). Name the actual cause and
34
+ // route the fix; each branch is a distinct situation, distinguished by probing the same store the writer used.
35
+ const noRecord = () => {
36
+ // cwd probe FIRST: outside a git repo nothing below can resolve — not the store, and not even the env
37
+ // id (ownSessionId's alias walk reads the store too) — so diagnose the cwd before touching either.
38
+ let ids;
39
+ try {
40
+ ids = l.listSessionIds();
41
+ }
42
+ catch {
43
+ ids = null;
44
+ }
45
+ if (ids === null)
46
+ return `no session record — declarations resolve the session store from the CURRENT directory, and ${process.cwd()} is not inside a git repository. cd back into the session's worktree and re-declare.`;
47
+ const wid = sess || s.ownSessionId(); // safe now: the store just resolved, so the alias walk cannot throw
48
+ if (!wid)
49
+ return 'no session record — no session id to write: this shell carries no harness session env (SPEXCODE_SESSION_ID / CLAUDE_CODE_SESSION_ID) and no --session was given. Pass --session <id> (spex session ls lists ids).';
50
+ if (ids.length === 0)
51
+ return `no session record for ${wid.slice(0, 8)} — declarations resolve the session store from the CURRENT directory, and the project at ${process.cwd()} has no sessions at all: you are in a different project's checkout. cd back into the session's worktree and re-declare.`;
52
+ return `no session record for ${wid.slice(0, 8)} — this project's store (resolved from ${process.cwd()}) holds ${ids.length} session(s) but not this one: a wrong --session id, or you are declaring from a different project's checkout. cd back into the session's worktree and re-declare, or pass a valid --session <id> (spex session ls).`;
53
+ };
54
+ // a state writer from a non-repo cwd throws git's not-a-repo before it can return false — map exactly
55
+ // that throw to the no-record path (noRecord re-probes and names the cwd); anything else stays loud.
56
+ // A record that exists but CANNOT carry state (unreadable bytes, or a worktree that is gone) is its own
57
+ // answer: the writer refused on purpose and already knows why, so that reason is what the caller prints —
58
+ // never the no-record diagnosis, which would send the author chasing a wrong cwd ([[sessions-core]]).
59
+ const mark = (fn) => {
60
+ try {
61
+ return { ok: fn() };
62
+ }
63
+ catch (e) {
64
+ if (e instanceof s.SessionRecordUnusable)
65
+ return { ok: false, reason: e.message };
66
+ if (/not a git repository/i.test(String(e?.stderr ?? e)))
67
+ return { ok: false };
68
+ throw e;
69
+ }
70
+ };
71
+ // Taught once per record: the CLI's explicit NOTE column is the only note display that cuts prose.
72
+ const noteEcho = (note) => {
73
+ if (!note)
74
+ return '';
75
+ const tableCut = s.displayWidth(note) > s.NOTE_BOARD_LIMIT;
76
+ if (!tableCut)
77
+ return '';
78
+ const wid = sess || s.ownSessionId();
79
+ const rid = wid ? (l.readAliasedRawRecord(wid)?.session_id ?? wid) : null; // sentinel lives in the RECORD's dir, so an aliased codex id lands on the same file
80
+ if (rid) {
81
+ const sentinel = l.sessionArtifactPath(rid, 'note-echo-taught');
82
+ try {
83
+ if (existsSync(sentinel))
84
+ return '';
85
+ writeFileSync(sentinel, `${new Date().toISOString()}\n`); // only reached on a successful declaration (the echo rides the success branch)
86
+ }
87
+ catch { /* unreadable/unwritable store dir → fall through and teach again; never block the echo */ }
88
+ }
89
+ return `\nyour note is ${note.length} chars — the session table's NOTE column shows only the first ${s.NOTE_BOARD_LIMIT} display columns. the full text IS recorded, and readable via spex session review ${(wid || '<your-session>').slice(0, 8)} / spex session ls --json. (said once — later cut notes won't repeat this.)`;
90
+ };
91
+ return { s, sess, noRecord, mark, noteEcho };
92
+ }
93
+ export async function runSessionDeclaration(verb, argv = process.argv) {
94
+ const sessionId = flag(argv, 'session');
95
+ const note = flag(argv, 'note');
96
+ if (verb === 'done') {
97
+ // `merge`/`close` are awaiting declarations; `nothing` is an intentional no-write correction trap.
98
+ const proposal = flag(argv, 'propose') || 'nothing';
99
+ if (proposal === 'nothing')
100
+ nothingProposalTrap();
101
+ const { s, sess, mark, noRecord, noteEcho } = await sessionStateKit(sessionId);
102
+ let closeNote = proposal === 'close' ? CLOSE_CLEANUP : '';
103
+ if (proposal === 'close') {
104
+ // The closeout nudge is advisory: a declaration must land even if the local issue store fails.
105
+ try {
106
+ closeNote += (await import('./localIssues.js')).closeoutNudge(sess ?? s.ownSessionId());
107
+ }
108
+ catch (e) {
109
+ console.error(`issue closeout check failed (declaration unaffected): ${e instanceof Error ? e.message : e}`);
110
+ }
111
+ }
112
+ const done = mark(() => s.markDone(proposal, sess, note));
113
+ console.log(done.ok ? `done (${proposal})${DECLARED}${noteEcho(note)}${closeNote}` : done.reason ?? noRecord());
114
+ return;
115
+ }
116
+ const { s, sess, mark, noRecord, noteEcho } = await sessionStateKit(sessionId);
117
+ if (verb === 'park') {
118
+ // sugar: the agent is waiting on a background task; it will self-resume (NOT idle/awaiting)
119
+ const parked = mark(() => s.markState('parked', { note, sessionId: sess }));
120
+ console.log(parked.ok ? `parked${DECLARED}${noteEcho(note)}` : parked.reason ?? noRecord());
121
+ return;
122
+ }
123
+ // The agent deliberately pauses for a human response. This is authored state, not an active-only inference.
124
+ const asked = mark(() => s.markState('asking', { note, sessionId: sess }));
125
+ console.log(asked.ok ? `asking${DECLARED}${noteEcho(note)}` : asked.reason ?? noRecord());
126
+ }
@@ -0,0 +1,10 @@
1
+ import type { Context } from 'hono';
2
+ import type { ExecutionStep } from './execution-trace.js';
3
+ export type SessionExecution = Readonly<{
4
+ revision: string;
5
+ turnId: string | null;
6
+ workingNote: string | null;
7
+ steps: readonly ExecutionStep[];
8
+ }>;
9
+ export declare function readSessionExecution(id: string): SessionExecution | null;
10
+ export declare function sessionExecutionStream(c: Context): Promise<Response>;
@@ -0,0 +1,70 @@
1
+ import { streamSSE } from 'hono/streaming';
2
+ import { harnessById } from './harness.js';
3
+ import { readAliasedRawRecord } from '@spexcode/spec-core';
4
+ import { currentHumanTurn } from './session-timeline.js';
5
+ const absentExecution = (turn = null) => ({ revision: `turn:${turn?.token ?? '0'}`, turnId: turn?.token ?? null, workingNote: null, steps: [] });
6
+ // This is deliberately a read projection. Native transcript bytes stay within the adapter, while the API owns
7
+ // only enough information for the frontend's fixed renderer to paint the current execution slice.
8
+ export function readSessionExecution(id) {
9
+ let record;
10
+ try {
11
+ record = readAliasedRawRecord(id);
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ if (!record?.governed)
17
+ return null;
18
+ const turn = currentHumanTurn(id);
19
+ const threadId = typeof record.harness_session_id === 'string' ? record.harness_session_id : '';
20
+ if (!threadId)
21
+ return absentExecution(turn);
22
+ try {
23
+ const trace = harnessById(typeof record.harness === 'string' && record.harness ? record.harness : 'claude')
24
+ .executionTrace(threadId, turn);
25
+ return trace || absentExecution(turn);
26
+ }
27
+ catch {
28
+ // A missing/unreadable native source is an absent transient trace, not a synthetic conversation failure.
29
+ return absentExecution(turn);
30
+ }
31
+ }
32
+ const TRACE_TICK_MS = 500;
33
+ const HEARTBEAT_TICKS = 20;
34
+ export async function sessionExecutionStream(c) {
35
+ const id = c.req.param('id') || '';
36
+ if (!readSessionExecution(id))
37
+ return c.json({ error: 'no such session' }, 404);
38
+ return streamSSE(c, async (stream) => {
39
+ let aborted = false;
40
+ let lastRevision = '';
41
+ let ticks = 0;
42
+ const publish = async () => {
43
+ const execution = readSessionExecution(id);
44
+ if (!execution)
45
+ return false;
46
+ if (execution.revision === lastRevision)
47
+ return true;
48
+ lastRevision = execution.revision;
49
+ await stream.writeSSE({ event: 'execution', data: JSON.stringify(execution) });
50
+ return true;
51
+ };
52
+ stream.onAbort(() => { aborted = true; });
53
+ try {
54
+ if (!await publish())
55
+ return;
56
+ while (!aborted) {
57
+ await stream.sleep(TRACE_TICK_MS);
58
+ if (aborted)
59
+ break;
60
+ if (!await publish())
61
+ break;
62
+ if (++ticks % HEARTBEAT_TICKS === 0)
63
+ await stream.writeSSE({ event: 'ping', data: 'x' });
64
+ }
65
+ }
66
+ catch {
67
+ // EventSource reconnects a dropped stream. A native trace read must never take down the session server.
68
+ }
69
+ });
70
+ }
@@ -0,0 +1,28 @@
1
+ export declare class SessionFileError extends Error {
2
+ readonly status: 400 | 403 | 404 | 500;
3
+ constructor(status: 400 | 403 | 404 | 500, message: string);
4
+ }
5
+ type SessionFileLock = <T>(id: string, body: () => T) => T;
6
+ export declare const SESSION_FILE_PREVIEW_MAX_BYTES: number;
7
+ export type SessionFilePreviewKind = 'text' | 'image' | 'html';
8
+ export declare function listSessionFiles(id: string): string[];
9
+ export declare function readSessionFiles(id: string): string[];
10
+ export declare function addSessionFile(id: string, input: string, lock: SessionFileLock, cwd?: string): {
11
+ path: string;
12
+ added: boolean;
13
+ };
14
+ export declare function retractSessionFile(id: string, input: string, lock: SessionFileLock, cwd?: string): {
15
+ path: string;
16
+ removed: boolean;
17
+ };
18
+ export declare function openSessionFile(id: string, path: string): {
19
+ path: string;
20
+ name: string;
21
+ size: number;
22
+ };
23
+ export declare function sessionFilePreviewKind(path: string): {
24
+ kind: SessionFilePreviewKind;
25
+ contentType: string;
26
+ } | null;
27
+ export declare const sessionFilesPath: (id: string) => string;
28
+ export {};
@@ -0,0 +1,130 @@
1
+ import { accessSync, constants, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { basename, isAbsolute, resolve } from 'node:path';
3
+ import { readRecordEntry, sessionArtifactPath } from '@spexcode/spec-core';
4
+ export class SessionFileError extends Error {
5
+ status;
6
+ constructor(status, message) {
7
+ super(message);
8
+ this.status = status;
9
+ this.name = 'SessionFileError';
10
+ }
11
+ }
12
+ export const SESSION_FILE_PREVIEW_MAX_BYTES = 2 * 1024 * 1024;
13
+ const HTML_EXTENSIONS = new Set(['.html', '.htm']);
14
+ const TEXT_EXTENSIONS = new Set(['.txt', '.md', '.markdown', '.json', '.yaml', '.yml', '.toml', '.ini', '.log', '.csv', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.css', '.xml', '.py', '.go', '.rs', '.java', '.sh', '.sql']);
15
+ const IMAGE_TYPES = {
16
+ '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.webp': 'image/webp',
17
+ };
18
+ const filesPath = (id) => sessionArtifactPath(id, 'files.json');
19
+ function requireSession(id) {
20
+ const record = readRecordEntry(id);
21
+ if (record.kind === 'absent')
22
+ throw new SessionFileError(404, `session ${id} does not exist`);
23
+ if (record.kind === 'corrupt')
24
+ throw new SessionFileError(500, `session ${id} has an unreadable record: ${record.error}`);
25
+ }
26
+ function readFiles(id) {
27
+ const path = filesPath(id);
28
+ let parsed;
29
+ try {
30
+ parsed = JSON.parse(readFileSync(path, 'utf8'));
31
+ }
32
+ catch (error) {
33
+ if (error.code === 'ENOENT')
34
+ return [];
35
+ throw new SessionFileError(500, `session file list is unreadable: ${path} — ${error instanceof Error ? error.message : String(error)}`);
36
+ }
37
+ if (!Array.isArray(parsed) || parsed.some((value) => typeof value !== 'string' || !isAbsolute(value)))
38
+ throw new SessionFileError(500, `session file list is invalid: ${path}`);
39
+ return [...new Set(parsed)];
40
+ }
41
+ function writeFiles(id, files) {
42
+ const path = filesPath(id);
43
+ const tmp = `${path}.${process.pid}.tmp`;
44
+ try {
45
+ writeFileSync(tmp, `${JSON.stringify(files, null, 2)}\n`);
46
+ renameSync(tmp, path);
47
+ }
48
+ finally {
49
+ try {
50
+ unlinkSync(tmp);
51
+ }
52
+ catch { /* rename already consumed the temporary file */ }
53
+ }
54
+ }
55
+ function currentFile(path) {
56
+ try {
57
+ if (!statSync(path).isFile())
58
+ throw new SessionFileError(400, `not a regular file: ${path}`);
59
+ accessSync(path, constants.R_OK);
60
+ }
61
+ catch (error) {
62
+ if (error instanceof SessionFileError)
63
+ throw error;
64
+ const code = error.code;
65
+ if (code === 'ENOENT' || code === 'ENOTDIR')
66
+ throw new SessionFileError(404, `file does not exist: ${path}`);
67
+ throw new SessionFileError(403, `file is not readable: ${path}`);
68
+ }
69
+ }
70
+ export function listSessionFiles(id) {
71
+ requireSession(id);
72
+ return readSessionFiles(id);
73
+ }
74
+ // Session projections already hold a parsed record; re-checking session.json here would make an in-memory
75
+ // projection depend on the public route's existence guard. The route-facing list keeps that guard above.
76
+ export function readSessionFiles(id) {
77
+ return readFiles(id);
78
+ }
79
+ export function addSessionFile(id, input, lock, cwd = process.cwd()) {
80
+ const path = resolve(cwd, input);
81
+ currentFile(path);
82
+ return lock(id, () => {
83
+ requireSession(id);
84
+ const files = readFiles(id);
85
+ if (files.includes(path))
86
+ return { path, added: false };
87
+ writeFiles(id, [...files, path]);
88
+ return { path, added: true };
89
+ });
90
+ }
91
+ export function retractSessionFile(id, input, lock, cwd = process.cwd()) {
92
+ const path = resolve(cwd, input);
93
+ return lock(id, () => {
94
+ requireSession(id);
95
+ const files = readFiles(id);
96
+ if (!files.includes(path))
97
+ return { path, removed: false };
98
+ writeFiles(id, files.filter((file) => file !== path));
99
+ return { path, removed: true };
100
+ });
101
+ }
102
+ export function openSessionFile(id, path) {
103
+ requireSession(id);
104
+ if (!readFiles(id).includes(path))
105
+ throw new SessionFileError(403, 'that path was not posted by this session');
106
+ try {
107
+ const stat = statSync(path);
108
+ if (!stat.isFile())
109
+ throw new SessionFileError(404, `file no longer exists: ${path}`);
110
+ accessSync(path, constants.R_OK);
111
+ return { path, name: basename(path) || 'download', size: stat.size };
112
+ }
113
+ catch (error) {
114
+ if (error instanceof SessionFileError)
115
+ throw error;
116
+ throw new SessionFileError(404, `file no longer exists: ${path}`);
117
+ }
118
+ }
119
+ export function sessionFilePreviewKind(path) {
120
+ const extension = basename(path).toLowerCase().match(/\.[^.]+$/)?.[0];
121
+ if (!extension)
122
+ return null;
123
+ if (HTML_EXTENSIONS.has(extension))
124
+ return { kind: 'html', contentType: 'text/html; charset=utf-8' };
125
+ if (TEXT_EXTENSIONS.has(extension))
126
+ return { kind: 'text', contentType: 'text/plain; charset=utf-8' };
127
+ const contentType = IMAGE_TYPES[extension];
128
+ return contentType ? { kind: 'image', contentType } : null;
129
+ }
130
+ export const sessionFilesPath = (id) => filesPath(id);
@@ -0,0 +1,31 @@
1
+ import { type DisplayStatus, type Session } from './sessions.js';
2
+ export declare function sessionEvent(s: Session): string;
3
+ export declare function launchEvent(s: Session): string;
4
+ export type FollowOpts = {
5
+ targets: () => string[];
6
+ self?: string | null;
7
+ statuses?: string[];
8
+ includeIdle?: boolean;
9
+ intervalMs?: number;
10
+ as?: string;
11
+ take?: boolean;
12
+ timeoutMs?: number;
13
+ onObserved?: (id: string, status: DisplayStatus, previous: DisplayStatus | null) => void;
14
+ row?: (id: string, status: DisplayStatus, note: string | null) => Session | null;
15
+ };
16
+ export type FollowOutcome = {
17
+ reached: DisplayStatus;
18
+ id: string;
19
+ path: DisplayStatus[];
20
+ } | {
21
+ mail: {
22
+ from: string | null;
23
+ text: string;
24
+ };
25
+ } | {
26
+ timedOut: true;
27
+ path: DisplayStatus[];
28
+ } | {
29
+ gone: string;
30
+ };
31
+ export declare function followSessions(emit: (line: string) => void, opts: FollowOpts): Promise<FollowOutcome>;