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,308 @@
1
+ import { sessionHeadline, sessionPresent } from './session.js';
2
+ import { effectiveTokens, tokenize } from './reviewQuery.js';
3
+ // [[review-filters]]: one pure filter engine — the single home of Issues/Evals FIELD SEMANTICS. Domain
4
+ // adapters below provide field values; surfaces provide only the state home and presentation: the
5
+ // canonical pages parse their ONE visible token text ([[review-query]]) and bridge it here, the Spec
6
+ // Information panes keep plain local state. Neither duplicates matching.
7
+ const text = (value) => String(value ?? '').trim().toLocaleLowerCase();
8
+ const values = (value) => (Array.isArray(value) ? value : value == null || value === '' ? [] : [value]);
9
+ const unique = (items) => [...new Set(items.flatMap(values).filter((value) => value != null && value !== '').map(String))];
10
+ export const EVAL_FILTER_KIND = Object.freeze({
11
+ RESULT: 'result',
12
+ BLIND: 'blind',
13
+ UNMEASURED: 'unmeasured',
14
+ DANGLING: 'dangling',
15
+ });
16
+ export const evidenceList = (reading) => reading?.evidence?.length ? reading.evidence
17
+ : reading?.blob != null ? [{ hash: reading.blob, kind: reading.blobKind || 'image', state: reading.blobState || 'present' }]
18
+ : [];
19
+ export const kindsOf = (reading) => {
20
+ const evidence = evidenceList(reading);
21
+ if (!evidence.length)
22
+ return ['note'];
23
+ return ['video', 'image', 'transcript', 'data'].filter((kind) => evidence.some((item) => item.kind === kind));
24
+ };
25
+ const optionLabel = (t, key, fallback) => t ? t(key) : fallback;
26
+ const allOption = (t) => ({ value: '', label: optionLabel(t, 'reviewList.all', 'All') });
27
+ const optionsFor = (items, facet, state, context, t) => {
28
+ const active = state[facet.key] != null && String(state[facet.key]) !== '';
29
+ // a fixed-value ENUM facet keeps its ACTIVE value as a real (checked) row even when no data carries
30
+ // it — an active facet must never hide its own off-switch; data-valued facets stay data-derived.
31
+ const found = facet.fixedValues
32
+ ? facet.fixedValues.filter((value) => facet.enumerateFixed
33
+ || (active && String(state[facet.key]) === String(value))
34
+ || items.some((item) => values(facet.values(item, context)).map(String).includes(String(value))))
35
+ : unique(items.map((item) => facet.values(item, context)));
36
+ const available = facet.available
37
+ ? facet.available(found, items, state, context)
38
+ : found.length >= (facet.minValues ?? 2);
39
+ if (!available && !active)
40
+ return [];
41
+ return [allOption(t), ...found.map((value) => ({
42
+ value,
43
+ label: facet.labelValue ? facet.labelValue(value, context) : value,
44
+ }))];
45
+ };
46
+ // A SPLIT section reports its count as two named buckets instead of one number. The predicate is BINARY
47
+ // and applied to the section's own matched rows, so the buckets always re-add to that section's whole
48
+ // population — a surface can lead with one half without the count quietly shrinking. The adapter alone
49
+ // decides which sections split and on what axis; the engine invents no bucket.
50
+ const splitCount = (matched, split, context) => {
51
+ const first = matched.filter((item) => split.is(item, context)).length;
52
+ return { [split.keys[0]]: first, [split.keys[1]]: matched.length - first };
53
+ };
54
+ // the one reading rule for a section count, whichever shape the adapter declared.
55
+ export const sectionTotal = (count) => (typeof count === 'number'
56
+ ? count
57
+ : Object.values(count ?? {}).reduce((sum, value) => sum + value, 0));
58
+ export function filterReviewItems(items, state, config, context = {}) {
59
+ // `q` is one substring or an ARRAY of substrings (the token text's bare words/phrases), conjunctive;
60
+ // an `impossible` state (an unknown qualifier in the canonical text) honestly matches NOTHING.
61
+ const qs = values(state.q).map(text).filter(Boolean);
62
+ const faceted = state.impossible ? [] : items.filter((item) => (qs.every((q) => config.search(item, context).some((value) => text(value).includes(q)))
63
+ && config.facets.every((facet) => {
64
+ const selected = state[facet.key];
65
+ return selected == null || selected === ''
66
+ || (facet.matches
67
+ ? facet.matches(item, selected, context)
68
+ : values(facet.values(item, context)).map(String).includes(String(selected)));
69
+ })));
70
+ const sectionValue = config.section && state[config.section.key];
71
+ const sectionMatch = (item, selected) => (config.section.matches
72
+ ? config.section.matches(item, selected, context)
73
+ : String(config.section.value(item, context)) === String(selected));
74
+ const shown = sectionValue == null || sectionValue === ''
75
+ ? faceted
76
+ : faceted.filter((item) => sectionMatch(item, sectionValue));
77
+ const sections = config.section
78
+ ? Object.fromEntries(config.section.options.map((option) => {
79
+ const matched = faceted.filter((item) => sectionMatch(item, option.value));
80
+ return [option.value, option.split && config.section.split
81
+ ? splitCount(matched, config.section.split, context)
82
+ : matched.length];
83
+ }))
84
+ : {};
85
+ const facets = Object.fromEntries(config.facets.map((facet) => [facet.key, {
86
+ key: facet.key,
87
+ label: optionLabel(context.t, facet.label, facet.key),
88
+ value: state[facet.key] || '',
89
+ options: optionsFor(items, facet, state, context, context.t),
90
+ }]));
91
+ return { state, faceted, shown, sections, facets };
92
+ }
93
+ export const reviewActorName = (actor) => String(actor || '').length > 22 ? `${String(actor).slice(0, 8)}…` : actor;
94
+ // the source-session PRESENCE join ([[live-session-filter]]): originator or any reply author still
95
+ // resolves on the board — membership, never liveness.
96
+ const issuePresent = (issue, sessions) => !!sessionPresent(sessions, issue.by)
97
+ || (Array.isArray(issue.replies) && issue.replies.some((reply) => sessionPresent(sessions, reply.by)));
98
+ const presenceFacet = (valuesOf) => ({
99
+ key: 'session', label: 'reviewList.facetSession', fixedValues: ['present', 'missing'],
100
+ values: valuesOf,
101
+ labelValue: (value, { t }) => optionLabel(t, value === 'present' ? 'reviewList.sessionPresent' : 'reviewList.sessionMissing', value),
102
+ });
103
+ export function issueFilterState(raw = {}, { defaultSection = '' } = {}) {
104
+ const state = raw.state === 'closed' || raw.concluded === '1'
105
+ ? 'closed'
106
+ : raw.state || defaultSection;
107
+ return {
108
+ q: raw.q || '', state, impossible: raw.impossible === true,
109
+ author: raw.author || '', store: raw.store || '', node: raw.node || '', label: raw.label || '',
110
+ session: raw.session || '',
111
+ };
112
+ }
113
+ const ISSUE_CONFIG = {
114
+ search: (issue) => [issue.id, issue.concern, issue.by, ...(issue.nodes || [])],
115
+ section: {
116
+ key: 'state',
117
+ value: (issue) => issue.status === 'open' ? 'open' : 'closed',
118
+ // open|closed are the lifecycle halves; a concrete concluded spelling (landed) matches that status
119
+ // honestly instead of pretending the enum is binary.
120
+ matches: (issue, selected) => (selected === 'open' ? issue.status === 'open'
121
+ : selected === 'closed' ? issue.status !== 'open' : issue.status === selected),
122
+ options: [{ value: 'open', label: 'reviewList.open' }, { value: 'closed', label: 'reviewList.closed' }],
123
+ },
124
+ facets: [
125
+ { key: 'author', label: 'reviewList.facetAuthor', values: (issue) => issue.by, labelValue: reviewActorName },
126
+ { key: 'store', label: 'reviewList.facetStore', values: (issue) => issue.store },
127
+ { key: 'node', label: 'reviewList.facetNode', values: (issue) => issue.nodes || [] },
128
+ { key: 'label', label: 'reviewList.facetLabel', values: (issue) => (issue.labels || []).map((label) => typeof label === 'string' ? label : label?.name), minValues: 1 },
129
+ presenceFacet((issue, { sessions }) => issuePresent(issue, sessions) ? 'present' : 'missing'),
130
+ ],
131
+ };
132
+ export function issueFilterModel(items, raw = {}, context = {}) {
133
+ const state = issueFilterState(raw, { defaultSection: context.defaultSection ?? '' });
134
+ const model = filterReviewItems(items, state, ISSUE_CONFIG, context);
135
+ model.section = {
136
+ key: 'state', label: optionLabel(context.t, 'reviewList.facetState', 'State'), value: state.state,
137
+ meaningful: Object.values(model.sections).filter((count) => sectionTotal(count) > 0).length > 1 || !!state.state,
138
+ options: [allOption(context.t), ...ISSUE_CONFIG.section.options.map((option) => ({
139
+ value: option.value,
140
+ label: optionLabel(context.t, option.label, option.value),
141
+ count: sectionTotal(model.sections[option.value]),
142
+ }))].filter((option, index, all) => index === 0 || option.count > 0 || option.value === state.state),
143
+ };
144
+ return model;
145
+ }
146
+ const evalIsResult = (entry) => entry.filterKind === EVAL_FILTER_KIND.RESULT;
147
+ const verdictOf = (entry) => evalIsResult(entry)
148
+ ? (entry.verdict?.status || 'unscored')
149
+ : entry.filterKind === EVAL_FILTER_KIND.BLIND || entry.filterKind === EVAL_FILTER_KIND.UNMEASURED
150
+ ? 'unmeasured'
151
+ : 'unscored';
152
+ const reviewStateOf = (entry) => (evalIsResult(entry) && entry.fresh && entry.humanOk ? 'reviewed' : 'current');
153
+ // the ONE freshness axis of the Eval adapter — the facet's option values and the verdict sections' split
154
+ // read it, so a chip and its Freshness menu can never disagree about what "stale" counts.
155
+ const evalFresh = (entry) => entry.fresh === true;
156
+ const freshnessOf = (entry) => (evalIsResult(entry) ? (evalFresh(entry) ? 'fresh' : 'stale') : null);
157
+ export const evalReviewState = (reading) => {
158
+ // an order-only row never had its freshness computed, so it has no verdict to report. Refuse it here
159
+ // rather than let its conservative placeholder be published as a measured `stalePass`/`staleFail`: the
160
+ // whole point of the deferred pass is that these rows exist only to establish sequence.
161
+ if (reading?.freshnessDeferred)
162
+ throw new Error(`eval row ${reading.scenario ?? '?'} has deferred freshness — it can order a list, never state a verdict`);
163
+ const status = reading?.verdict?.status;
164
+ if (status !== 'pass' && status !== 'fail')
165
+ return 'empty';
166
+ if (reading.fresh)
167
+ return status;
168
+ return status === 'pass' ? 'stalePass' : 'staleFail';
169
+ };
170
+ const shortSession = (value, sessions) => {
171
+ const session = sessions.find((item) => item.id === value);
172
+ if (session)
173
+ return sessionHeadline(session);
174
+ return String(value || '').length > 22 ? `${String(value).slice(0, 8)}…` : value;
175
+ };
176
+ export function evalFilterState(raw = {}, { defaultKind = 'all', defaultSection = '' } = {}) {
177
+ const legacyReview = raw.ok === '1' ? 'reviewed' : raw.ok;
178
+ return {
179
+ q: raw.q || '', kind: raw.kind || defaultKind, impossible: raw.impossible === true,
180
+ verdict: raw.verdict || '', freshness: raw.freshness || '', node: raw.node || '', filer: raw.filer || '',
181
+ session: raw.session || '', review: raw.review || legacyReview || defaultSection,
182
+ };
183
+ }
184
+ const EVAL_CONFIG = {
185
+ search: (entry) => [entry.scenario, entry.node, entry.by, entry.evaluator],
186
+ section: {
187
+ key: 'verdict', value: verdictOf,
188
+ // A MEASURED verdict carries a reading, so it also carries freshness: its count splits into the fresh
189
+ // half and the stale half that still owes a re-measurement. The two halves re-add to the verdict's
190
+ // whole population — splitting reports the remeasurement debt, it never hides a row. `unmeasured` owns
191
+ // no reading and therefore no freshness axis, so it stays one honest number.
192
+ split: { keys: ['fresh', 'stale'], is: evalFresh },
193
+ options: [
194
+ { value: 'fail', label: 'reviewList.verdict.fail', split: true },
195
+ { value: 'pass', label: 'reviewList.verdict.pass', split: true },
196
+ { value: 'unmeasured', label: 'reviewList.verdict.unmeasured' },
197
+ ],
198
+ },
199
+ facets: [
200
+ {
201
+ key: 'review', label: 'reviewList.facetReview', fixedValues: ['current', 'reviewed'], enumerateFixed: true,
202
+ values: reviewStateOf,
203
+ labelValue: (value, { t }) => optionLabel(t, value === 'reviewed' ? 'reviewList.reviewed' : 'reviewList.needsReview', value),
204
+ },
205
+ {
206
+ key: 'freshness', label: 'reviewList.facetFreshness', minValues: 2,
207
+ values: (entry) => freshnessOf(entry) ?? [],
208
+ labelValue: (value, { t }) => optionLabel(t, `reviewList.freshness.${value}`, value),
209
+ },
210
+ {
211
+ key: 'kind', label: 'reviewList.facetKind', fixedValues: ['video', 'image'], minValues: 1,
212
+ values: (entry) => evalIsResult(entry) ? kindsOf(entry).filter((kind) => kind === 'video' || kind === 'image') : [],
213
+ matches: (entry, selected) => selected === 'all' || (evalIsResult(entry) && kindsOf(entry).includes(selected)),
214
+ labelValue: (value, { t }) => optionLabel(t, `evalsFeed.kind.${value}`, value),
215
+ available: (found, _items, state) => found.length > 0 || state.kind !== 'all',
216
+ },
217
+ { key: 'node', label: 'reviewList.facetNode', values: (entry) => entry.node },
218
+ {
219
+ key: 'filer', label: 'reviewList.facetFiler', values: (entry) => evalIsResult(entry) ? entry.by : [],
220
+ labelValue: (value, { sessions = [] }) => shortSession(value, sessions),
221
+ },
222
+ presenceFacet((entry, { sessions }) => (evalIsResult(entry)
223
+ ? (sessionPresent(sessions, entry.by) ? 'present' : 'missing')
224
+ : [])),
225
+ ],
226
+ };
227
+ export function evalFilterModel(items, raw = {}, context = {}) {
228
+ const state = evalFilterState(raw, {
229
+ defaultKind: context.defaultKind ?? 'all',
230
+ defaultSection: context.defaultSection ?? '',
231
+ });
232
+ const model = filterReviewItems(items, state, EVAL_CONFIG, context);
233
+ model.section = {
234
+ key: 'verdict', label: optionLabel(context.t, 'reviewList.facetVerdict', 'Verdict'), value: state.verdict,
235
+ meaningful: Object.values(model.sections).some((count) => sectionTotal(count) > 0) || !!state.verdict,
236
+ // the menu/popup face of the same sections keeps the verdict's WHOLE count: a compact radio row has no
237
+ // room for the split, and it must still agree with the list it filters.
238
+ options: [allOption(context.t), ...EVAL_CONFIG.section.options.map((option) => ({
239
+ value: option.value,
240
+ label: optionLabel(context.t, option.label, option.value),
241
+ count: sectionTotal(model.sections[option.value]),
242
+ }))].filter((option, index) => index === 0 || option.count > 0 || option.value === state.verdict),
243
+ };
244
+ const kindFacet = model.facets.kind;
245
+ if (kindFacet.options.length) {
246
+ kindFacet.options = [
247
+ { value: 'all', label: optionLabel(context.t, 'evalsFeed.kind.all', 'All') },
248
+ ...kindFacet.options.filter((option) => option.value !== '').map((option) => ({ ...option })),
249
+ ];
250
+ kindFacet.value = state.kind;
251
+ }
252
+ return model;
253
+ }
254
+ export function filterMenuGroups(model, onChange, keys) {
255
+ return keys.map((key) => key === 'section' ? model.section : model.facets[key]).filter((facet) => (facet?.meaningful !== false
256
+ && (facet?.options?.length > 1 || (facet?.value != null && facet.value !== '' && facet.value !== 'all')))).map((facet) => ({
257
+ key: facet.key,
258
+ label: facet.label,
259
+ value: facet.value,
260
+ active: facet.value != null && facet.value !== '' && facet.value !== 'all',
261
+ options: facet.options,
262
+ clearLabel: facet.value === 'all' ? null : undefined,
263
+ onChange: (value) => onChange({ [facet.key]: value || null }),
264
+ }));
265
+ }
266
+ // the CANONICAL pages' bridge ([[review-query]] → this engine): parse the ONE visible token text into
267
+ // engine state. Bare words/phrases become conjunctive q substrings; duplicate qualifiers are last-wins;
268
+ // a qualifier outside the page's map (or a wrong is: identity) marks the state IMPOSSIBLE — the token
269
+ // stays verbatim in the text and the list honestly shows nothing. `scope:` maps to no filter: it picks
270
+ // the DATA SOURCE upstream ([[evals-view]]), never a per-row predicate.
271
+ const TOKEN_MAPS = {
272
+ issue: {
273
+ is: (v) => (v === 'issue' ? {} : null),
274
+ state: (v) => ({ state: v }),
275
+ store: (v) => ({ store: v }),
276
+ author: (v) => ({ author: v }),
277
+ node: (v) => ({ node: v }),
278
+ label: (v) => ({ label: v }),
279
+ session: (v) => ({ session: v }),
280
+ },
281
+ eval: {
282
+ is: (v) => (v === 'eval' ? {} : null),
283
+ state: (v) => ({ review: v }),
284
+ verdict: (v) => ({ verdict: v }),
285
+ freshness: (v) => ({ freshness: v }),
286
+ evidence: (v) => ({ kind: v }),
287
+ node: (v) => ({ node: v }),
288
+ filer: (v) => ({ filer: v }),
289
+ session: (v) => ({ session: v }),
290
+ scope: () => ({}),
291
+ },
292
+ };
293
+ export function tokenFilterState(text, domain) {
294
+ const map = TOKEN_MAPS[domain];
295
+ const state = { q: [] };
296
+ for (const token of effectiveTokens(tokenize(text))) {
297
+ if (token.key == null) {
298
+ state.q.push(token.value);
299
+ continue;
300
+ }
301
+ const toState = map[token.key];
302
+ const mapped = toState ? toState(token.value) : null;
303
+ if (mapped == null)
304
+ return { impossible: true, q: [] };
305
+ Object.assign(state, mapped);
306
+ }
307
+ return state;
308
+ }
@@ -0,0 +1,66 @@
1
+ export function scanQuery(text: any): ({
2
+ ws: boolean;
3
+ raw: string;
4
+ start: number;
5
+ end: number;
6
+ key?: undefined;
7
+ value?: undefined;
8
+ } | {
9
+ ws: boolean;
10
+ raw: string;
11
+ start: number;
12
+ end: number;
13
+ key: string;
14
+ value: any;
15
+ } | {
16
+ ws: boolean;
17
+ raw: string;
18
+ start: number;
19
+ end: number;
20
+ key: null;
21
+ value: any;
22
+ })[];
23
+ export function setToken(text: any, key: any, value: any): any;
24
+ export function legacyQueryText(defaultText: any, query: any): any;
25
+ export function suggestAt(text: any, caret: any, keys?: any[], values?: {}): {
26
+ start: number;
27
+ end: number;
28
+ items: any;
29
+ };
30
+ export const ISSUE_QUERY_DEFAULT: "is:issue state:open";
31
+ export const EVAL_QUERY_DEFAULT: "is:eval";
32
+ export function scopedEvalQuery(sessionId: any): any;
33
+ export function nodeEvalQuery(nodeId: any): any;
34
+ export function quoteValue(v: any): string;
35
+ export function tokenize(text: any): ({
36
+ ws: boolean;
37
+ raw: string;
38
+ start: number;
39
+ end: number;
40
+ key?: undefined;
41
+ value?: undefined;
42
+ } | {
43
+ ws: boolean;
44
+ raw: string;
45
+ start: number;
46
+ end: number;
47
+ key: string;
48
+ value: any;
49
+ } | {
50
+ ws: boolean;
51
+ raw: string;
52
+ start: number;
53
+ end: number;
54
+ key: null;
55
+ value: any;
56
+ })[];
57
+ export function serialize(tokens: any): any;
58
+ export function normalizeQuery(text: any): any;
59
+ export function sameQuery(a: any, b: any): boolean;
60
+ export function effectiveTokens(tokens: any): any;
61
+ export function readToken(text: any, key: any): any;
62
+ export function queryParam(text: any, defaultText: any): {
63
+ q: string;
64
+ } | null;
65
+ export function reviewRouteQuery(text: any, defaultText: any, page?: null): {} | null;
66
+ export function hasLegacyParams(query: any): boolean;
@@ -0,0 +1,180 @@
1
+ // The ONE token-query engine ([[review-query]]) — pure JS, no React/DOM. Both review ListViews, the
2
+ // route layer's legacy replay, and any consumer minting canonical eval/issue addresses import from HERE:
3
+ // the visible query TEXT is the single source of truth, and every tab/menu/autocomplete is only a
4
+ // BUILDER that rewrites tokens in it (GitHub-measured semantics).
5
+ export const ISSUE_QUERY_DEFAULT = 'is:issue state:open';
6
+ export const EVAL_QUERY_DEFAULT = 'is:eval';
7
+ // the session doors' scoped-list address: the default view, scoped — the text shows exactly that.
8
+ export const scopedEvalQuery = (sessionId) => setToken(EVAL_QUERY_DEFAULT, 'scope', sessionId);
9
+ // the aggregate score/count doors' address ([[eval-score-badge]]): the default view, node-filtered.
10
+ export const nodeEvalQuery = (nodeId) => setToken(EVAL_QUERY_DEFAULT, 'node', nodeId);
11
+ const KEY_RE = /^([A-Za-z][A-Za-z0-9-]*):(.*)$/s;
12
+ const unquote = (v) => (v.length >= 2 && v.startsWith('"') && v.endsWith('"') ? v.slice(1, -1) : v);
13
+ export const quoteValue = (v) => (/\s/.test(String(v)) ? `"${v}"` : String(v));
14
+ // segment scan preserving EVERY character — whitespace runs and tokens (a `"` swallows spaces until it
15
+ // closes), each with [start,end) offsets — so the aria-hidden highlight overlay mirrors the input
16
+ // glyph-for-glyph and the autocomplete can find the token under the caret.
17
+ export function scanQuery(text) {
18
+ const s = String(text ?? '');
19
+ const out = [];
20
+ let i = 0;
21
+ while (i < s.length) {
22
+ let j = i;
23
+ if (/\s/.test(s[i])) {
24
+ while (j < s.length && /\s/.test(s[j]))
25
+ j++;
26
+ out.push({ ws: true, raw: s.slice(i, j), start: i, end: j });
27
+ }
28
+ else {
29
+ while (j < s.length && !/\s/.test(s[j])) {
30
+ if (s[j] === '"') {
31
+ j++;
32
+ while (j < s.length && s[j] !== '"')
33
+ j++;
34
+ if (j < s.length)
35
+ j++;
36
+ }
37
+ else
38
+ j++;
39
+ }
40
+ const raw = s.slice(i, j);
41
+ const m = KEY_RE.exec(raw);
42
+ out.push(m
43
+ ? { ws: false, raw, start: i, end: j, key: m[1].toLowerCase(), value: unquote(m[2]) }
44
+ : { ws: false, raw, start: i, end: j, key: null, value: unquote(raw) });
45
+ }
46
+ i = j;
47
+ }
48
+ return out;
49
+ }
50
+ export const tokenize = (text) => scanQuery(text).filter((seg) => !seg.ws);
51
+ export const serialize = (tokens) => tokens.map((t) => t.raw).join(' ');
52
+ export const normalizeQuery = (text) => serialize(tokenize(text));
53
+ export const sameQuery = (a, b) => normalizeQuery(a) === normalizeQuery(b);
54
+ // duplicate qualifiers: the LAST occurrence wins; bare words all apply.
55
+ export const effectiveTokens = (tokens) => {
56
+ const last = new Map();
57
+ for (const t of tokens)
58
+ if (t.key != null)
59
+ last.set(t.key, t);
60
+ return tokens.filter((t) => t.key == null || last.get(t.key) === t);
61
+ };
62
+ export const readToken = (text, key) => {
63
+ const tokens = tokenize(text);
64
+ for (let i = tokens.length - 1; i >= 0; i--)
65
+ if (tokens[i].key === key)
66
+ return tokens[i].value;
67
+ return '';
68
+ };
69
+ // token SURGERY: rewrite the key at its first position, drop later duplicates, append when absent,
70
+ // remove the key entirely on an empty value. Every other token — known or not — survives verbatim.
71
+ export function setToken(text, key, value) {
72
+ const next = value == null || String(value) === ''
73
+ ? null
74
+ : { ws: false, raw: `${key}:${quoteValue(value)}`, key, value: String(value) };
75
+ const out = [];
76
+ let placed = false;
77
+ for (const t of tokenize(text)) {
78
+ if (t.key === key) {
79
+ if (next && !placed) {
80
+ out.push(next);
81
+ placed = true;
82
+ }
83
+ continue;
84
+ }
85
+ out.push(t);
86
+ }
87
+ if (next && !placed)
88
+ out.push(next);
89
+ return serialize(out);
90
+ }
91
+ // MATCHING is deliberately NOT here: this module owns text — scan/serialize/surgery/suggestions and the
92
+ // canonical-address discipline — while the conjunctive field matching (including the unknown-qualifier
93
+ // IMPOSSIBLE state) lives in the ONE [[review-filters]] engine, reached through its tokenFilterState
94
+ // bridge. A second predicate here would be the exact fork the fusion removed.
95
+ // canonical address discipline: the default view is the BARE page address; any other state is exactly
96
+ // ?q=<raw text>. An emptied submit falls back to the default (→ bare).
97
+ export const queryParam = (text, defaultText) => {
98
+ const trimmed = String(text ?? '').trim();
99
+ if (!trimmed || sameQuery(trimmed, defaultText))
100
+ return null;
101
+ return { q: trimmed };
102
+ };
103
+ // A query/filter action resets by omitting page; a PAGINATION action passes a page (including 1) and
104
+ // therefore records GitHub's explicit page=1 history form. The distinction is the action, not equivalence.
105
+ export const reviewRouteQuery = (text, defaultText, page = null) => {
106
+ const query = queryParam(text, defaultText) || {};
107
+ if (page != null)
108
+ query.page = String(page);
109
+ return Object.keys(query).length ? query : null;
110
+ };
111
+ // LEGACY structured params → token pairs. `kind=all` maps to nothing: the evidence default IS all.
112
+ const LEGACY_PARAMS = {
113
+ state: (v) => ['state', v],
114
+ concluded: (v) => (v === '1' ? ['state', 'closed'] : null),
115
+ ok: (v) => (v === '1' ? ['state', 'reviewed'] : null),
116
+ verdict: (v) => ['verdict', v],
117
+ freshness: (v) => ['freshness', v],
118
+ kind: (v) => (v === 'all' ? null : ['evidence', v]),
119
+ store: (v) => ['store', v],
120
+ author: (v) => ['author', v],
121
+ node: (v) => ['node', v],
122
+ filer: (v) => ['filer', v],
123
+ live: (v) => (v === '1' ? ['session', 'present'] : null),
124
+ session: (v) => ['scope', v],
125
+ };
126
+ export const hasLegacyParams = (query) => Object.keys(LEGACY_PARAMS).some((k) => query?.[k] != null && query[k] !== '');
127
+ // the legacy free q was ONE substring search — it must replay as ONE text token. Quote it whenever the
128
+ // tokenizer would read it as anything else: spaces (several words), a colon (q=drift:check would become
129
+ // an unknown qualifier and match zero), or a stray quote (which would swallow neighbours).
130
+ const freeTextToken = (v) => (/[\s:"]/.test(v) ? `"${v.replace(/"/g, '')}"` : v);
131
+ // a legacy LIST address replays as the FULL visible state: the page's default tokens with each legacy
132
+ // param surgically applied (live=1→session:present, session=<id>→scope:<id>, ok=1→state:reviewed,
133
+ // kind→evidence:), the free-text q appended as ONE bare/phrase token preserving the old
134
+ // single-substring search. Returns null when nothing legacy is present.
135
+ export function legacyQueryText(defaultText, query) {
136
+ if (!hasLegacyParams(query))
137
+ return null;
138
+ let text = defaultText;
139
+ for (const [param, toPair] of Object.entries(LEGACY_PARAMS)) {
140
+ const v = query[param];
141
+ if (v == null || v === '')
142
+ continue;
143
+ const pair = toPair(String(v));
144
+ if (pair)
145
+ text = setToken(text, pair[0], pair[1]);
146
+ }
147
+ const free = String(query.q ?? '').trim();
148
+ if (free)
149
+ text = `${text} ${freeTextToken(free)}`.trim();
150
+ return text;
151
+ }
152
+ // inline autocomplete at the caret — client-side and BOUNDED. A bare prefix completes qualifier KEYS
153
+ // (insert `key:`, keep typing); a `key:prefix` completes VALUES from the page-supplied candidate list
154
+ // only (data-derived; scope = sessions on the current board), capped at 8. Everything else stays
155
+ // hand-typable and submits verbatim.
156
+ export function suggestAt(text, caret, keys = [], values = {}) {
157
+ const s = String(text ?? '');
158
+ const at = Math.max(0, Math.min(caret ?? s.length, s.length));
159
+ const seg = scanQuery(s).find((g) => !g.ws && g.start < at && at <= g.end);
160
+ if (!seg)
161
+ return { start: at, end: at, items: [] };
162
+ const typed = s.slice(seg.start, at);
163
+ const m = KEY_RE.exec(typed);
164
+ if (!m) {
165
+ const w = typed.toLowerCase();
166
+ if (!w || w.includes('"'))
167
+ return { start: seg.start, end: seg.end, items: [] };
168
+ const items = keys.filter((k) => k.startsWith(w)).slice(0, 8)
169
+ .map((k) => ({ type: 'key', key: k, insert: `${k}:` }));
170
+ return { start: seg.start, end: seg.end, items };
171
+ }
172
+ const key = m[1].toLowerCase();
173
+ const prefix = m[2].replace(/^"/, '').replace(/"$/, '').toLowerCase();
174
+ const pool = values[key] || [];
175
+ const items = pool
176
+ .filter((c) => String(c.value).toLowerCase().startsWith(prefix) && String(c.value).toLowerCase() !== prefix)
177
+ .slice(0, 8)
178
+ .map((c) => ({ type: 'value', key, value: String(c.value), label: c.label || null, insert: `${key}:${quoteValue(c.value)} ` }));
179
+ return { start: seg.start, end: seg.end, items };
180
+ }
@@ -0,0 +1,4 @@
1
+ export function sessionPresent(sessions: any, id: any): any;
2
+ export function sessionHeadline(session: any): any;
3
+ export function sessionHandle(session: any): any;
4
+ export function sessionTitle(session: any): any;
@@ -0,0 +1,8 @@
1
+ export const sessionPresent = (sessions, id) => {
2
+ const session = id ? (sessions || []).find((item) => item.id === id) : null;
3
+ return session || null;
4
+ };
5
+ export const sessionHeadline = (session) => session?.title || session?.headline || session?.name || session?.activity || session?.note
6
+ || session?.promptPreview || session?.node || session?.raw?.title || session?.branch || session?.id;
7
+ export const sessionHandle = (session) => session?.label || session?.name || session?.node || session?.title || session?.branch || session?.id;
8
+ export const sessionTitle = sessionHeadline;
@@ -0,0 +1,15 @@
1
+ export type ReviewEvalNode = {
2
+ id: string;
3
+ hue?: number;
4
+ scenarios: any[];
5
+ evals: any[];
6
+ readings: any[];
7
+ };
8
+ export type ReviewSnapshot = {
9
+ issues: any[];
10
+ evalNodes: ReviewEvalNode[];
11
+ forgeRevision: number;
12
+ };
13
+ export declare function publishReviewSnapshot(snapshot: ReviewSnapshot): void;
14
+ export declare function readReviewSnapshot(): ReviewSnapshot;
15
+ export declare function hasReviewSnapshot(): boolean;
@@ -0,0 +1,12 @@
1
+ let current = null;
2
+ export function publishReviewSnapshot(snapshot) {
3
+ current = snapshot;
4
+ }
5
+ export function readReviewSnapshot() {
6
+ if (!current)
7
+ throw new Error('review snapshot is unavailable before the first successful graph build');
8
+ return current;
9
+ }
10
+ export function hasReviewSnapshot() {
11
+ return current !== null;
12
+ }
@@ -0,0 +1,4 @@
1
+ export declare const rootSlots: (env: string | undefined, fallback: number) => number;
2
+ export declare function touchRoot(roots: Map<string, string>, cache: Map<string, unknown> & {
3
+ delete(key: string): boolean;
4
+ }, root: string, key: string, slots: number): void;