spexcode 0.6.2 → 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 (479) hide show
  1. package/README.md +3 -1
  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} +36 -32
  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 +1 -1
  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/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-first/spec-first.sh +1 -1
  167. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-of-file/spec-of-file.sh +1 -0
  168. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/stop-gate/spec.md +2 -2
  169. package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/stop-gate/stop-gate.sh +31 -29
  170. package/node_modules/@spexcode/spec-core/dist/anchors.d.ts +94 -0
  171. package/node_modules/@spexcode/spec-core/dist/anchors.js +730 -0
  172. package/node_modules/@spexcode/spec-core/dist/git.d.ts +166 -0
  173. package/node_modules/@spexcode/spec-core/dist/git.js +2736 -0
  174. package/node_modules/@spexcode/spec-core/dist/graph-delta.d.ts +44 -0
  175. package/node_modules/@spexcode/spec-core/dist/graph-delta.js +72 -0
  176. package/node_modules/@spexcode/spec-core/dist/graph.d.ts +34 -0
  177. package/node_modules/@spexcode/spec-core/dist/graph.js +237 -0
  178. package/node_modules/@spexcode/spec-core/dist/graphDelta.d.ts +3 -0
  179. package/node_modules/@spexcode/spec-core/dist/graphDelta.js +13 -0
  180. package/node_modules/@spexcode/spec-core/dist/harness-identity.d.ts +31 -0
  181. package/node_modules/@spexcode/spec-core/dist/harness-identity.js +20 -0
  182. package/node_modules/@spexcode/spec-core/dist/identity-presets.d.ts +152 -0
  183. package/node_modules/@spexcode/spec-core/dist/identity-presets.js +132 -0
  184. package/node_modules/@spexcode/spec-core/dist/index.d.ts +45 -0
  185. package/node_modules/@spexcode/spec-core/dist/index.js +19 -0
  186. package/node_modules/@spexcode/spec-core/dist/layout.d.ts +183 -0
  187. package/node_modules/@spexcode/spec-core/dist/layout.js +548 -0
  188. package/node_modules/@spexcode/spec-core/dist/process-identity.d.ts +37 -0
  189. package/node_modules/@spexcode/spec-core/dist/process-identity.js +214 -0
  190. package/node_modules/@spexcode/spec-core/dist/project-identity.d.ts +12 -0
  191. package/node_modules/@spexcode/spec-core/dist/project-identity.js +71 -0
  192. package/node_modules/@spexcode/spec-core/dist/project-store.d.ts +3 -0
  193. package/node_modules/@spexcode/spec-core/dist/project-store.js +14 -0
  194. package/node_modules/@spexcode/spec-core/dist/resilience.d.ts +2 -0
  195. package/node_modules/@spexcode/spec-core/dist/resilience.js +40 -0
  196. package/node_modules/@spexcode/spec-core/dist/review/index.d.ts +3 -0
  197. package/node_modules/@spexcode/spec-core/dist/review/index.js +5 -0
  198. package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.d.ts +77 -0
  199. package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.js +308 -0
  200. package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.d.ts +66 -0
  201. package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.js +180 -0
  202. package/node_modules/@spexcode/spec-core/dist/review/session.d.ts +4 -0
  203. package/node_modules/@spexcode/spec-core/dist/review/session.js +8 -0
  204. package/node_modules/@spexcode/spec-core/dist/reviewSnapshot.d.ts +15 -0
  205. package/node_modules/@spexcode/spec-core/dist/reviewSnapshot.js +12 -0
  206. package/node_modules/@spexcode/spec-core/dist/root-lru.d.ts +4 -0
  207. package/{spec-cli/src/root-lru.ts → node_modules/@spexcode/spec-core/dist/root-lru.js} +26 -30
  208. package/node_modules/@spexcode/spec-core/dist/specs.d.ts +117 -0
  209. package/node_modules/@spexcode/spec-core/dist/specs.js +489 -0
  210. package/node_modules/@spexcode/spec-core/package.json +28 -0
  211. package/node_modules/@spexcode/spec-eval/dist/cache.d.ts +10 -0
  212. package/node_modules/@spexcode/spec-eval/dist/cache.js +50 -0
  213. package/node_modules/@spexcode/spec-eval/dist/cli.d.ts +22 -0
  214. package/node_modules/@spexcode/spec-eval/dist/cli.js +981 -0
  215. package/node_modules/@spexcode/spec-eval/dist/evaltab.d.ts +98 -0
  216. package/node_modules/@spexcode/spec-eval/dist/evaltab.js +176 -0
  217. package/node_modules/@spexcode/spec-eval/dist/filing.d.ts +16 -0
  218. package/node_modules/@spexcode/spec-eval/dist/filing.js +36 -0
  219. package/node_modules/@spexcode/spec-eval/dist/freshness.d.ts +48 -0
  220. package/node_modules/@spexcode/spec-eval/dist/freshness.js +799 -0
  221. package/node_modules/@spexcode/spec-eval/dist/host.d.ts +46 -0
  222. package/node_modules/@spexcode/spec-eval/dist/host.js +53 -0
  223. package/node_modules/@spexcode/spec-eval/dist/humanok.d.ts +11 -0
  224. package/node_modules/@spexcode/spec-eval/dist/humanok.js +27 -0
  225. package/node_modules/@spexcode/spec-eval/dist/index.d.ts +4 -0
  226. package/node_modules/@spexcode/spec-eval/dist/index.js +4 -0
  227. package/node_modules/@spexcode/spec-eval/dist/remarks.d.ts +31 -0
  228. package/node_modules/@spexcode/spec-eval/dist/remarks.js +1 -0
  229. package/node_modules/@spexcode/spec-eval/dist/scenariofresh.d.ts +13 -0
  230. package/node_modules/@spexcode/spec-eval/dist/scenariofresh.js +303 -0
  231. package/node_modules/@spexcode/spec-eval/dist/scenarios.d.ts +99 -0
  232. package/node_modules/@spexcode/spec-eval/dist/scenarios.js +650 -0
  233. package/node_modules/@spexcode/spec-eval/dist/sessioneval.d.ts +307 -0
  234. package/node_modules/@spexcode/spec-eval/dist/sessioneval.js +1883 -0
  235. package/node_modules/@spexcode/spec-eval/dist/sidecar.d.ts +55 -0
  236. package/node_modules/@spexcode/spec-eval/dist/sidecar.js +82 -0
  237. package/node_modules/@spexcode/spec-eval/dist/timeline.d.ts +25 -0
  238. package/node_modules/@spexcode/spec-eval/dist/timeline.js +65 -0
  239. package/node_modules/@spexcode/spec-eval/dist/ui-path.d.ts +1 -0
  240. package/node_modules/@spexcode/spec-eval/dist/ui-path.js +2 -0
  241. package/node_modules/@spexcode/spec-eval/package.json +36 -0
  242. package/node_modules/@spexcode/spec-forge/dist/cache.d.ts +29 -0
  243. package/node_modules/@spexcode/spec-forge/dist/cache.js +59 -0
  244. package/node_modules/@spexcode/spec-forge/dist/cli.d.ts +1 -0
  245. package/node_modules/@spexcode/spec-forge/dist/cli.js +100 -0
  246. package/node_modules/@spexcode/spec-forge/dist/drivers/github.d.ts +2 -0
  247. package/node_modules/@spexcode/spec-forge/dist/drivers/github.js +116 -0
  248. package/node_modules/@spexcode/spec-forge/dist/drivers/gitlab.d.ts +7 -0
  249. package/node_modules/@spexcode/spec-forge/dist/drivers/gitlab.js +144 -0
  250. package/node_modules/@spexcode/spec-forge/dist/drivers.d.ts +10 -0
  251. package/node_modules/@spexcode/spec-forge/dist/drivers.js +83 -0
  252. package/node_modules/@spexcode/spec-forge/dist/index.d.ts +4 -0
  253. package/node_modules/@spexcode/spec-forge/dist/index.js +4 -0
  254. package/node_modules/@spexcode/spec-forge/dist/links.d.ts +15 -0
  255. package/node_modules/@spexcode/spec-forge/dist/links.js +65 -0
  256. package/node_modules/@spexcode/spec-forge/dist/needs-eval.d.ts +10 -0
  257. package/node_modules/@spexcode/spec-forge/dist/needs-eval.js +20 -0
  258. package/node_modules/@spexcode/spec-forge/dist/port.d.ts +53 -0
  259. package/node_modules/@spexcode/spec-forge/dist/port.js +1 -0
  260. package/node_modules/@spexcode/spec-forge/dist/resident.d.ts +7 -0
  261. package/node_modules/@spexcode/spec-forge/dist/resident.js +43 -0
  262. package/node_modules/@spexcode/spec-forge/package.json +32 -0
  263. package/package.json +33 -19
  264. package/spec-cli/bin/spex.mjs +0 -69
  265. package/spec-cli/src/anchors.ts +0 -728
  266. package/spec-cli/src/attach.ts +0 -43
  267. package/spec-cli/src/claude-headless.ts +0 -321
  268. package/spec-cli/src/cli.ts +0 -1258
  269. package/spec-cli/src/client.ts +0 -414
  270. package/spec-cli/src/cockpit.ts +0 -43
  271. package/spec-cli/src/codex-runtime-generations.ts +0 -646
  272. package/spec-cli/src/commit-surgery.ts +0 -68
  273. package/spec-cli/src/contract-filter.ts +0 -202
  274. package/spec-cli/src/delivery-queue.ts +0 -165
  275. package/spec-cli/src/doctor.ts +0 -516
  276. package/spec-cli/src/execution-trace.ts +0 -444
  277. package/spec-cli/src/file-write.ts +0 -22
  278. package/spec-cli/src/gateway-auth.ts +0 -181
  279. package/spec-cli/src/gateway-hub.ts +0 -358
  280. package/spec-cli/src/gateway.ts +0 -461
  281. package/spec-cli/src/git.ts +0 -2556
  282. package/spec-cli/src/graph.ts +0 -271
  283. package/spec-cli/src/graphCache.ts +0 -710
  284. package/spec-cli/src/graphDelta.ts +0 -77
  285. package/spec-cli/src/graphStream.ts +0 -1019
  286. package/spec-cli/src/harness-select.ts +0 -77
  287. package/spec-cli/src/harness.ts +0 -3025
  288. package/spec-cli/src/headless-controller.ts +0 -63
  289. package/spec-cli/src/help.ts +0 -492
  290. package/spec-cli/src/host-resources.ts +0 -762
  291. package/spec-cli/src/host.ts +0 -611
  292. package/spec-cli/src/identity-presets.d.ts +0 -13
  293. package/spec-cli/src/identity-presets.js +0 -138
  294. package/spec-cli/src/index.ts +0 -818
  295. package/spec-cli/src/init.ts +0 -258
  296. package/spec-cli/src/issues-cli.ts +0 -276
  297. package/spec-cli/src/issues.ts +0 -237
  298. package/spec-cli/src/layout.ts +0 -640
  299. package/spec-cli/src/lint.ts +0 -488
  300. package/spec-cli/src/localIssues.ts +0 -538
  301. package/spec-cli/src/materialize.ts +0 -417
  302. package/spec-cli/src/mentions.ts +0 -81
  303. package/spec-cli/src/opencode-headless.ts +0 -205
  304. package/spec-cli/src/pi-headless.ts +0 -153
  305. package/spec-cli/src/plugin-harness.ts +0 -157
  306. package/spec-cli/src/process-identity.ts +0 -207
  307. package/spec-cli/src/project-identity.ts +0 -73
  308. package/spec-cli/src/project-store.ts +0 -17
  309. package/spec-cli/src/pty-bridge.ts +0 -396
  310. package/spec-cli/src/pty-helper.mjs +0 -96
  311. package/spec-cli/src/pty-native-helper.mjs +0 -22
  312. package/spec-cli/src/ranker.ts +0 -191
  313. package/spec-cli/src/reaper.ts +0 -125
  314. package/spec-cli/src/resilience.ts +0 -41
  315. package/spec-cli/src/reviewSnapshot.ts +0 -28
  316. package/spec-cli/src/reviews.ts +0 -434
  317. package/spec-cli/src/runtime-guard.ts +0 -35
  318. package/spec-cli/src/runtime-ownership.ts +0 -88
  319. package/spec-cli/src/search.bench.mjs +0 -80
  320. package/spec-cli/src/search.ts +0 -63
  321. package/spec-cli/src/session-cursors.ts +0 -91
  322. package/spec-cli/src/session-execution.ts +0 -68
  323. package/spec-cli/src/session-files.ts +0 -121
  324. package/spec-cli/src/session-follow.ts +0 -182
  325. package/spec-cli/src/session-reparent.ts +0 -33
  326. package/spec-cli/src/session-timeline.ts +0 -247
  327. package/spec-cli/src/session-web.ts +0 -135
  328. package/spec-cli/src/sessions.ts +0 -3883
  329. package/spec-cli/src/sh.ts +0 -3
  330. package/spec-cli/src/slash-commands.ts +0 -318
  331. package/spec-cli/src/source-files.ts +0 -104
  332. package/spec-cli/src/specs.ts +0 -498
  333. package/spec-cli/src/supervise.ts +0 -245
  334. package/spec-cli/src/tree.ts +0 -118
  335. package/spec-cli/src/tsx-bin.ts +0 -18
  336. package/spec-cli/src/uninstall.ts +0 -171
  337. package/spec-cli/src/uploads.ts +0 -253
  338. package/spec-cli/src/worktree-sources.ts +0 -42
  339. package/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +0 -8
  340. package/spec-dashboard/dist/assets/App-B6IbFbGu.js +0 -2
  341. package/spec-dashboard/dist/assets/Dashboard-C5ap-Sga.css +0 -1
  342. package/spec-dashboard/dist/assets/Dashboard-_sDk7Rcg.js +0 -27
  343. package/spec-dashboard/dist/assets/EvalsPage-BT357Lyt.js +0 -2
  344. package/spec-dashboard/dist/assets/IssuesPage-BG9rNOgV.js +0 -1
  345. package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  346. package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  347. package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  348. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  349. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  350. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  351. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  352. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  353. package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  354. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  355. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  356. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  357. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  358. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  359. package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  360. package/spec-dashboard/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  361. package/spec-dashboard/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  362. package/spec-dashboard/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  363. package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  364. package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  365. package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  366. package/spec-dashboard/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  367. package/spec-dashboard/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  368. package/spec-dashboard/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  369. package/spec-dashboard/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  370. package/spec-dashboard/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  371. package/spec-dashboard/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  372. package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  373. package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  374. package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  375. package/spec-dashboard/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  376. package/spec-dashboard/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  377. package/spec-dashboard/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  378. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  379. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  380. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  381. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  382. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  383. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  384. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  385. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  386. package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  387. package/spec-dashboard/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  388. package/spec-dashboard/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  389. package/spec-dashboard/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  390. package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  391. package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  392. package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  393. package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  394. package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  395. package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  396. package/spec-dashboard/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  397. package/spec-dashboard/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  398. package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  399. package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  400. package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  401. package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  402. package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  403. package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  404. package/spec-dashboard/dist/assets/MobileApp-D9yPMR3A.js +0 -2
  405. package/spec-dashboard/dist/assets/Modal-B3EcgeA3.js +0 -1
  406. package/spec-dashboard/dist/assets/PageScroll-CNZOugWV.js +0 -1
  407. package/spec-dashboard/dist/assets/ProjectsPage-C2CRHmvs.js +0 -1
  408. package/spec-dashboard/dist/assets/SessionInterface-6GBZ9nXN.css +0 -32
  409. package/spec-dashboard/dist/assets/SessionInterface-DOEjuT3l.js +0 -40
  410. package/spec-dashboard/dist/assets/SessionWindow-1nYgZ4CL.js +0 -1
  411. package/spec-dashboard/dist/assets/Settings-7WeTJn0V.js +0 -1
  412. package/spec-dashboard/dist/assets/Thread-CEbzAFQn.js +0 -13
  413. package/spec-dashboard/dist/assets/bindings-BC9vqpYU.js +0 -1
  414. package/spec-dashboard/dist/assets/data-SlvxNA2r.js +0 -1
  415. package/spec-dashboard/dist/assets/index-DLVeOHL-.js +0 -41
  416. package/spec-dashboard/dist/assets/index-DYLGfPjx.css +0 -1
  417. package/spec-dashboard/dist/assets/launch-Cp579UoJ.css +0 -1
  418. package/spec-dashboard/dist/assets/launch-yxCYr64x.js +0 -276
  419. package/spec-dashboard/dist/assets/sessionSurface--7l69h4F.js +0 -1
  420. package/spec-dashboard/dist/index.html +0 -29
  421. package/spec-dashboard/src/reviewFilters.js +0 -322
  422. package/spec-dashboard/src/reviewQuery.js +0 -174
  423. package/spec-dashboard/src/session.js +0 -199
  424. package/spec-eval/src/cache.ts +0 -57
  425. package/spec-eval/src/cli.ts +0 -894
  426. package/spec-eval/src/evaltab.ts +0 -264
  427. package/spec-eval/src/filing.ts +0 -39
  428. package/spec-eval/src/freshness.ts +0 -836
  429. package/spec-eval/src/humanok.ts +0 -28
  430. package/spec-eval/src/scenariofresh.ts +0 -244
  431. package/spec-eval/src/scenarios.ts +0 -672
  432. package/spec-eval/src/sessioneval.ts +0 -2220
  433. package/spec-eval/src/sidecar.ts +0 -93
  434. package/spec-eval/src/timeline.ts +0 -54
  435. package/spec-forge/src/__fixtures__/github-forge.json +0 -63
  436. package/spec-forge/src/cache.ts +0 -66
  437. package/spec-forge/src/cli.ts +0 -99
  438. package/spec-forge/src/drivers/github.ts +0 -132
  439. package/spec-forge/src/drivers/gitlab.ts +0 -153
  440. package/spec-forge/src/drivers.ts +0 -73
  441. package/spec-forge/src/links.ts +0 -72
  442. package/spec-forge/src/needs-eval.ts +0 -29
  443. package/spec-forge/src/port.ts +0 -36
  444. package/spec-forge/src/resident.ts +0 -46
  445. /package/{spec-cli → node_modules/@spexcode/spec-cli}/README.md +0 -0
  446. /package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/compat/mark-active-0.5.2-eef1.fixture +0 -0
  447. /package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/compat/mark-active-sed-v0.fixture +0 -0
  448. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/commit-msg +0 -0
  449. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/post-checkout +0 -0
  450. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/post-merge +0 -0
  451. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/pre-commit +0 -0
  452. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/prepare-commit-msg +0 -0
  453. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/reference-transaction +0 -0
  454. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/extract/spec.md +0 -0
  455. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/regroup/spec.md +0 -0
  456. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/rename/spec.md +0 -0
  457. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/spec.md +0 -0
  458. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/tidy/spec.md +0 -0
  459. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/comment-altitude/spec.md +0 -0
  460. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/idle/idle.sh +0 -0
  461. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/idle/spec.md +0 -0
  462. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/mark-active/mark-active.sh +0 -0
  463. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/mark-active/spec.md +0 -0
  464. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/session-fail/fail.sh +0 -0
  465. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/session-fail/spec.md +0 -0
  466. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-first/spec.md +0 -0
  467. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-of-file/spec.md +0 -0
  468. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec.md +0 -0
  469. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/atomic-landing/spec.md +0 -0
  470. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/forge-link/spec.md +0 -0
  471. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/memory-hygiene/spec.md +0 -0
  472. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +0 -0
  473. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/spec.md +0 -0
  474. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/distill/digest.mjs +0 -0
  475. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/distill/spec.md +0 -0
  476. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/spec.md +0 -0
  477. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/spec.md +0 -0
  478. /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/spec.md +0 -0
  479. /package/{spec-cli → node_modules/@spexcode/spec-core}/templates/spexcode.json +0 -0
@@ -1 +0,0 @@
1
- import{P as N}from"./index-DLVeOHL-.js";const u="spexcode.terminal-font-size",T=9,g=18,c=1,r=new Set;function b(){const e=Number.parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--type-terminal"));if(!Number.isFinite(e))throw new Error("Terminal font-size token is missing or invalid");return e}function f(e){const t=Number(e);return Number.isFinite(t)&&t>=T&&t<=g?Math.round(t/c)*c:null}function _(){let e=null;try{e=f(localStorage.getItem(u))}catch{}return e??b()}function p(e){const t=f(e);if(t===null)throw new Error(`Invalid terminal font size: ${e}`);try{localStorage.setItem(u,String(t))}catch{}for(const s of r)s(t);return t}function w(e){return r.add(e),()=>r.delete(e)}const S="terminal",y="conversation",F="spexcode.session-surface.v1",A=new Set([S,y]),o=new Set;let l=null;const d=(e=N)=>`${F}.${e||"root"}`,i=()=>({defaultSurface:S,sessions:{}}),a=e=>A.has(e);function I(e){const t=i();return!e||typeof e!="object"||(a(e.defaultSurface)&&(t.defaultSurface=e.defaultSurface),e.sessions&&typeof e.sessions=="object"&&!Array.isArray(e.sessions)&&(t.sessions=Object.fromEntries(Object.entries(e.sessions).filter(([,s])=>a(s))))),t}function n(){try{const e=localStorage.getItem(d());return e?I(JSON.parse(e)):i()}catch{return l||i()}}function m(e){l=e;try{localStorage.setItem(d(),JSON.stringify(e))}catch{}for(const t of o)t(e);return e}function E(e){if(!a(e))throw new Error(`Invalid session surface: ${e}`);return e}function R(){return n().defaultSurface}function h(e){const t=n();return t.sessions[e]||t.defaultSurface}function z(e){const t=n();return m({...t,defaultSurface:E(e)}).defaultSurface}function M(e,t){if(!e)throw new Error("A session id is required to set its base surface");const s=n();return m({...s,sessions:{...s.sessions,[e]:E(t)}}).sessions[e]}function C(e){return o.add(e),()=>o.delete(e)}export{S,c as T,R as a,y as b,g as c,T as d,z as e,w as f,_ as g,C as h,h as i,M as j,p as s};
@@ -1,29 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>SpexCode</title>
7
- <!-- The runtime writes the route-selected shared identity preset here; data:, is a neutral mount that
8
- keeps the unresolved document from falling back to a route-relative /favicon.ico request. -->
9
- <link rel="icon" href="data:," />
10
- <!-- theme: apply the saved theme choice to <html data-theme> BEFORE first paint, so there's no
11
- wrong-palette flash before the module boots. Anything unsaved, invalid, or legacy (the retired
12
- light/dark codes) resolves to the Minimal default. Mirrors theme.js's getTheme() — keep this
13
- code list in sync with THEMES there. -->
14
- <script>
15
- (function () {
16
- try {
17
- var t = localStorage.getItem('spexcode.theme')
18
- if (['minimal', 'things', 'tokyonight', 'catppuccin', 'everforest', 'gruvbox', 'rosepine', 'dracula'].indexOf(t) < 0) t = 'minimal'
19
- document.documentElement.setAttribute('data-theme', t)
20
- } catch (e) { /* localStorage unavailable — the bare :root default (Minimal) stands */ }
21
- })()
22
- </script>
23
- <script type="module" crossorigin src="/assets/index-DLVeOHL-.js"></script>
24
- <link rel="stylesheet" crossorigin href="/assets/index-DYLGfPjx.css">
25
- </head>
26
- <body>
27
- <div id="root"></div>
28
- </body>
29
- </html>
@@ -1,322 +0,0 @@
1
- import { sessionHeadline, sessionPresent } from './session.js'
2
- import { effectiveTokens, tokenize } from './reviewQuery.js'
3
-
4
- // [[review-filters]]: one pure filter engine — the single home of Issues/Evals FIELD SEMANTICS. Domain
5
- // adapters below provide field values; surfaces provide only the state home and presentation: the
6
- // canonical pages parse their ONE visible token text ([[review-query]]) and bridge it here, the Spec
7
- // Information panes keep plain local state. Neither duplicates matching.
8
-
9
- const text = (value) => String(value ?? '').trim().toLocaleLowerCase()
10
- const values = (value) => (Array.isArray(value) ? value : value == null || value === '' ? [] : [value])
11
- const unique = (items) => [...new Set(items.flatMap(values).filter((value) => value != null && value !== '').map(String))]
12
-
13
- export const EVAL_FILTER_KIND = Object.freeze({
14
- RESULT: 'result',
15
- BLIND: 'blind',
16
- UNMEASURED: 'unmeasured',
17
- DANGLING: 'dangling',
18
- })
19
-
20
- export const evidenceList = (reading) =>
21
- reading?.evidence?.length ? reading.evidence
22
- : reading?.blob != null ? [{ hash: reading.blob, kind: reading.blobKind || 'image', state: reading.blobState || 'present' }]
23
- : []
24
-
25
- export const kindsOf = (reading) => {
26
- const evidence = evidenceList(reading)
27
- if (!evidence.length) return ['note']
28
- return ['video', 'image', 'transcript', 'data'].filter((kind) => evidence.some((item) => item.kind === kind))
29
- }
30
-
31
- const optionLabel = (t, key, fallback) => t ? t(key) : fallback
32
- const allOption = (t) => ({ value: '', label: optionLabel(t, 'reviewList.all', 'All') })
33
- const optionsFor = (items, facet, state, context, t) => {
34
- const active = state[facet.key] != null && String(state[facet.key]) !== ''
35
- // a fixed-value ENUM facet keeps its ACTIVE value as a real (checked) row even when no data carries
36
- // it — an active facet must never hide its own off-switch; data-valued facets stay data-derived.
37
- const found = facet.fixedValues
38
- ? facet.fixedValues.filter((value) => facet.enumerateFixed
39
- || (active && String(state[facet.key]) === String(value))
40
- || items.some((item) => values(facet.values(item, context)).map(String).includes(String(value))))
41
- : unique(items.map((item) => facet.values(item, context)))
42
- const available = facet.available
43
- ? facet.available(found, items, state, context)
44
- : found.length >= (facet.minValues ?? 2)
45
- if (!available && !active) return []
46
- return [allOption(t), ...found.map((value) => ({
47
- value,
48
- label: facet.labelValue ? facet.labelValue(value, context) : value,
49
- }))]
50
- }
51
-
52
- // A SPLIT section reports its count as two named buckets instead of one number. The predicate is BINARY
53
- // and applied to the section's own matched rows, so the buckets always re-add to that section's whole
54
- // population — a surface can lead with one half without the count quietly shrinking. The adapter alone
55
- // decides which sections split and on what axis; the engine invents no bucket.
56
- const splitCount = (matched, split, context) => {
57
- const first = matched.filter((item) => split.is(item, context)).length
58
- return { [split.keys[0]]: first, [split.keys[1]]: matched.length - first }
59
- }
60
-
61
- // the one reading rule for a section count, whichever shape the adapter declared.
62
- export const sectionTotal = (count) => (typeof count === 'number'
63
- ? count
64
- : Object.values(count ?? {}).reduce((sum, value) => sum + value, 0))
65
-
66
- export function filterReviewItems(items, state, config, context = {}) {
67
- // `q` is one substring or an ARRAY of substrings (the token text's bare words/phrases), conjunctive;
68
- // an `impossible` state (an unknown qualifier in the canonical text) honestly matches NOTHING.
69
- const qs = values(state.q).map(text).filter(Boolean)
70
- const faceted = state.impossible ? [] : items.filter((item) => (
71
- qs.every((q) => config.search(item, context).some((value) => text(value).includes(q)))
72
- && config.facets.every((facet) => {
73
- const selected = state[facet.key]
74
- return selected == null || selected === ''
75
- || (facet.matches
76
- ? facet.matches(item, selected, context)
77
- : values(facet.values(item, context)).map(String).includes(String(selected)))
78
- })
79
- ))
80
- const sectionValue = config.section && state[config.section.key]
81
- const sectionMatch = (item, selected) => (config.section.matches
82
- ? config.section.matches(item, selected, context)
83
- : String(config.section.value(item, context)) === String(selected))
84
- const shown = sectionValue == null || sectionValue === ''
85
- ? faceted
86
- : faceted.filter((item) => sectionMatch(item, sectionValue))
87
- const sections = config.section
88
- ? Object.fromEntries(config.section.options.map((option) => {
89
- const matched = faceted.filter((item) => sectionMatch(item, option.value))
90
- return [option.value, option.split && config.section.split
91
- ? splitCount(matched, config.section.split, context)
92
- : matched.length]
93
- }))
94
- : {}
95
- const facets = Object.fromEntries(config.facets.map((facet) => [facet.key, {
96
- key: facet.key,
97
- label: optionLabel(context.t, facet.label, facet.key),
98
- value: state[facet.key] || '',
99
- options: optionsFor(items, facet, state, context, context.t),
100
- }]))
101
- return { state, faceted, shown, sections, facets }
102
- }
103
-
104
- export const reviewActorName = (actor) => String(actor || '').length > 22 ? `${String(actor).slice(0, 8)}…` : actor
105
- // the source-session PRESENCE join ([[live-session-filter]]): originator or any reply author still
106
- // resolves on the board — membership, never liveness.
107
- const issuePresent = (issue, sessions) => !!sessionPresent(sessions, issue.by)
108
- || (Array.isArray(issue.replies) && issue.replies.some((reply) => sessionPresent(sessions, reply.by)))
109
- const presenceFacet = (valuesOf) => ({
110
- key: 'session', label: 'reviewList.facetSession', fixedValues: ['present', 'missing'],
111
- values: valuesOf,
112
- labelValue: (value, { t }) => optionLabel(t, value === 'present' ? 'reviewList.sessionPresent' : 'reviewList.sessionMissing', value),
113
- })
114
-
115
- export function issueFilterState(raw = {}, { defaultSection = '' } = {}) {
116
- const state = raw.state === 'closed' || raw.concluded === '1'
117
- ? 'closed'
118
- : raw.state || defaultSection
119
- return {
120
- q: raw.q || '', state, impossible: raw.impossible === true,
121
- author: raw.author || '', store: raw.store || '', node: raw.node || '',
122
- session: raw.session || '',
123
- }
124
- }
125
-
126
- const ISSUE_CONFIG = {
127
- search: (issue) => [issue.id, issue.concern, issue.by, ...(issue.nodes || [])],
128
- section: {
129
- key: 'state',
130
- value: (issue) => issue.status === 'open' ? 'open' : 'closed',
131
- // open|closed are the lifecycle halves; a concrete concluded spelling (landed) matches that status
132
- // honestly instead of pretending the enum is binary.
133
- matches: (issue, selected) => (selected === 'open' ? issue.status === 'open'
134
- : selected === 'closed' ? issue.status !== 'open' : issue.status === selected),
135
- options: [{ value: 'open', label: 'reviewList.open' }, { value: 'closed', label: 'reviewList.closed' }],
136
- },
137
- facets: [
138
- { key: 'author', label: 'reviewList.facetAuthor', values: (issue) => issue.by, labelValue: reviewActorName },
139
- { key: 'store', label: 'reviewList.facetStore', values: (issue) => issue.store },
140
- { key: 'node', label: 'reviewList.facetNode', values: (issue) => issue.nodes || [] },
141
- presenceFacet((issue, { sessions }) => issuePresent(issue, sessions) ? 'present' : 'missing'),
142
- ],
143
- }
144
-
145
- export function issueFilterModel(items, raw = {}, context = {}) {
146
- const state = issueFilterState(raw, { defaultSection: context.defaultSection ?? '' })
147
- const model = filterReviewItems(items, state, ISSUE_CONFIG, context)
148
- model.section = {
149
- key: 'state', label: optionLabel(context.t, 'reviewList.facetState', 'State'), value: state.state,
150
- meaningful: Object.values(model.sections).filter((count) => sectionTotal(count) > 0).length > 1 || !!state.state,
151
- options: [allOption(context.t), ...ISSUE_CONFIG.section.options.map((option) => ({
152
- value: option.value,
153
- label: optionLabel(context.t, option.label, option.value),
154
- count: sectionTotal(model.sections[option.value]),
155
- }))].filter((option, index, all) => index === 0 || option.count > 0 || option.value === state.state),
156
- }
157
- return model
158
- }
159
-
160
- const evalIsResult = (entry) => entry.filterKind === EVAL_FILTER_KIND.RESULT
161
- const verdictOf = (entry) => evalIsResult(entry)
162
- ? (entry.verdict?.status || 'unscored')
163
- : entry.filterKind === EVAL_FILTER_KIND.BLIND || entry.filterKind === EVAL_FILTER_KIND.UNMEASURED
164
- ? 'unmeasured'
165
- : 'unscored'
166
- const reviewStateOf = (entry) => (evalIsResult(entry) && entry.fresh && entry.humanOk ? 'reviewed' : 'current')
167
- // the ONE freshness axis of the Eval adapter — the facet's option values and the verdict sections' split
168
- // read it, so a chip and its Freshness menu can never disagree about what "stale" counts.
169
- const evalFresh = (entry) => entry.fresh === true
170
- const freshnessOf = (entry) => (evalIsResult(entry) ? (evalFresh(entry) ? 'fresh' : 'stale') : null)
171
- export const evalReviewState = (reading) => {
172
- // an order-only row never had its freshness computed, so it has no verdict to report. Refuse it here
173
- // rather than let its conservative placeholder be published as a measured `stalePass`/`staleFail`: the
174
- // whole point of the deferred pass is that these rows exist only to establish sequence.
175
- if (reading?.freshnessDeferred)
176
- throw new Error(`eval row ${reading.scenario ?? '?'} has deferred freshness — it can order a list, never state a verdict`)
177
- const status = reading?.verdict?.status
178
- if (status !== 'pass' && status !== 'fail') return 'empty'
179
- if (reading.fresh) return status
180
- return status === 'pass' ? 'stalePass' : 'staleFail'
181
- }
182
- const shortSession = (value, sessions) => {
183
- const session = sessions.find((item) => item.id === value)
184
- if (session) return sessionHeadline(session)
185
- return String(value || '').length > 22 ? `${String(value).slice(0, 8)}…` : value
186
- }
187
-
188
- export function evalFilterState(raw = {}, { defaultKind = 'all', defaultSection = '' } = {}) {
189
- const legacyReview = raw.ok === '1' ? 'reviewed' : raw.ok
190
- return {
191
- q: raw.q || '', kind: raw.kind || defaultKind, impossible: raw.impossible === true,
192
- verdict: raw.verdict || '', freshness: raw.freshness || '', node: raw.node || '', filer: raw.filer || '',
193
- session: raw.session || '', review: raw.review || legacyReview || defaultSection,
194
- }
195
- }
196
-
197
- const EVAL_CONFIG = {
198
- search: (entry) => [entry.scenario, entry.node, entry.by, entry.evaluator],
199
- section: {
200
- key: 'verdict', value: verdictOf,
201
- // A MEASURED verdict carries a reading, so it also carries freshness: its count splits into the fresh
202
- // half and the stale half that still owes a re-measurement. The two halves re-add to the verdict's
203
- // whole population — splitting reports the remeasurement debt, it never hides a row. `unmeasured` owns
204
- // no reading and therefore no freshness axis, so it stays one honest number.
205
- split: { keys: ['fresh', 'stale'], is: evalFresh },
206
- options: [
207
- { value: 'fail', label: 'reviewList.verdict.fail', split: true },
208
- { value: 'pass', label: 'reviewList.verdict.pass', split: true },
209
- { value: 'unmeasured', label: 'reviewList.verdict.unmeasured' },
210
- ],
211
- },
212
- facets: [
213
- {
214
- key: 'review', label: 'reviewList.facetReview', fixedValues: ['current', 'reviewed'], enumerateFixed: true,
215
- values: reviewStateOf,
216
- labelValue: (value, { t }) => optionLabel(t, value === 'reviewed' ? 'reviewList.reviewed' : 'reviewList.needsReview', value),
217
- },
218
- {
219
- key: 'freshness', label: 'reviewList.facetFreshness', minValues: 2,
220
- values: (entry) => freshnessOf(entry) ?? [],
221
- labelValue: (value, { t }) => optionLabel(t, `reviewList.freshness.${value}`, value),
222
- },
223
- {
224
- key: 'kind', label: 'reviewList.facetKind', fixedValues: ['video', 'image'], minValues: 1,
225
- values: (entry) => evalIsResult(entry) ? kindsOf(entry).filter((kind) => kind === 'video' || kind === 'image') : [],
226
- matches: (entry, selected) => selected === 'all' || (evalIsResult(entry) && kindsOf(entry).includes(selected)),
227
- labelValue: (value, { t }) => optionLabel(t, `evalsFeed.kind.${value}`, value),
228
- available: (found, _items, state) => found.length > 0 || state.kind !== 'all',
229
- },
230
- { key: 'node', label: 'reviewList.facetNode', values: (entry) => entry.node },
231
- {
232
- key: 'filer', label: 'reviewList.facetFiler', values: (entry) => evalIsResult(entry) ? entry.by : [],
233
- labelValue: (value, { sessions = [] }) => shortSession(value, sessions),
234
- },
235
- presenceFacet((entry, { sessions }) => (evalIsResult(entry)
236
- ? (sessionPresent(sessions, entry.by) ? 'present' : 'missing')
237
- : [])),
238
- ],
239
- }
240
-
241
- export function evalFilterModel(items, raw = {}, context = {}) {
242
- const state = evalFilterState(raw, {
243
- defaultKind: context.defaultKind ?? 'all',
244
- defaultSection: context.defaultSection ?? '',
245
- })
246
- const model = filterReviewItems(items, state, EVAL_CONFIG, context)
247
- model.section = {
248
- key: 'verdict', label: optionLabel(context.t, 'reviewList.facetVerdict', 'Verdict'), value: state.verdict,
249
- meaningful: Object.values(model.sections).some((count) => sectionTotal(count) > 0) || !!state.verdict,
250
- // the menu/popup face of the same sections keeps the verdict's WHOLE count: a compact radio row has no
251
- // room for the split, and it must still agree with the list it filters.
252
- options: [allOption(context.t), ...EVAL_CONFIG.section.options.map((option) => ({
253
- value: option.value,
254
- label: optionLabel(context.t, option.label, option.value),
255
- count: sectionTotal(model.sections[option.value]),
256
- }))].filter((option, index) => index === 0 || option.count > 0 || option.value === state.verdict),
257
- }
258
- const kindFacet = model.facets.kind
259
- if (kindFacet.options.length) {
260
- kindFacet.options = [
261
- { value: 'all', label: optionLabel(context.t, 'evalsFeed.kind.all', 'All') },
262
- ...kindFacet.options.filter((option) => option.value !== '').map((option) => ({ ...option })),
263
- ]
264
- kindFacet.value = state.kind
265
- }
266
- return model
267
- }
268
-
269
- export function filterMenuGroups(model, onChange, keys) {
270
- return keys.map((key) => key === 'section' ? model.section : model.facets[key]).filter((facet) => (
271
- facet?.meaningful !== false
272
- && (facet?.options?.length > 1 || (facet?.value != null && facet.value !== '' && facet.value !== 'all'))
273
- )).map((facet) => ({
274
- key: facet.key,
275
- label: facet.label,
276
- value: facet.value,
277
- active: facet.value != null && facet.value !== '' && facet.value !== 'all',
278
- options: facet.options,
279
- clearLabel: facet.value === 'all' ? null : undefined,
280
- onChange: (value) => onChange({ [facet.key]: value || null }),
281
- }))
282
- }
283
-
284
- // the CANONICAL pages' bridge ([[review-query]] → this engine): parse the ONE visible token text into
285
- // engine state. Bare words/phrases become conjunctive q substrings; duplicate qualifiers are last-wins;
286
- // a qualifier outside the page's map (or a wrong is: identity) marks the state IMPOSSIBLE — the token
287
- // stays verbatim in the text and the list honestly shows nothing. `scope:` maps to no filter: it picks
288
- // the DATA SOURCE upstream ([[evals-view]]), never a per-row predicate.
289
- const TOKEN_MAPS = {
290
- issue: {
291
- is: (v) => (v === 'issue' ? {} : null),
292
- state: (v) => ({ state: v }),
293
- store: (v) => ({ store: v }),
294
- author: (v) => ({ author: v }),
295
- node: (v) => ({ node: v }),
296
- session: (v) => ({ session: v }),
297
- },
298
- eval: {
299
- is: (v) => (v === 'eval' ? {} : null),
300
- state: (v) => ({ review: v }),
301
- verdict: (v) => ({ verdict: v }),
302
- freshness: (v) => ({ freshness: v }),
303
- evidence: (v) => ({ kind: v }),
304
- node: (v) => ({ node: v }),
305
- filer: (v) => ({ filer: v }),
306
- session: (v) => ({ session: v }),
307
- scope: () => ({}),
308
- },
309
- }
310
-
311
- export function tokenFilterState(text, domain) {
312
- const map = TOKEN_MAPS[domain]
313
- const state = { q: [] }
314
- for (const token of effectiveTokens(tokenize(text))) {
315
- if (token.key == null) { state.q.push(token.value); continue }
316
- const toState = map[token.key]
317
- const mapped = toState ? toState(token.value) : null
318
- if (mapped == null) return { impossible: true, q: [] }
319
- Object.assign(state, mapped)
320
- }
321
- return state
322
- }
@@ -1,174 +0,0 @@
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
-
6
- export const ISSUE_QUERY_DEFAULT = 'is:issue state:open'
7
- export const EVAL_QUERY_DEFAULT = 'is:eval'
8
- // the session doors' scoped-list address: the default view, scoped — the text shows exactly that.
9
- export const scopedEvalQuery = (sessionId) => setToken(EVAL_QUERY_DEFAULT, 'scope', sessionId)
10
- // the aggregate score/count doors' address ([[eval-score-badge]]): the default view, node-filtered.
11
- export const nodeEvalQuery = (nodeId) => setToken(EVAL_QUERY_DEFAULT, 'node', nodeId)
12
-
13
- const KEY_RE = /^([A-Za-z][A-Za-z0-9-]*):(.*)$/s
14
- const unquote = (v) => (v.length >= 2 && v.startsWith('"') && v.endsWith('"') ? v.slice(1, -1) : v)
15
- export const quoteValue = (v) => (/\s/.test(String(v)) ? `"${v}"` : String(v))
16
-
17
- // segment scan preserving EVERY character — whitespace runs and tokens (a `"` swallows spaces until it
18
- // closes), each with [start,end) offsets — so the aria-hidden highlight overlay mirrors the input
19
- // glyph-for-glyph and the autocomplete can find the token under the caret.
20
- export function scanQuery(text) {
21
- const s = String(text ?? '')
22
- const out = []
23
- let i = 0
24
- while (i < s.length) {
25
- let j = i
26
- if (/\s/.test(s[i])) {
27
- while (j < s.length && /\s/.test(s[j])) j++
28
- out.push({ ws: true, raw: s.slice(i, j), start: i, end: j })
29
- } else {
30
- while (j < s.length && !/\s/.test(s[j])) {
31
- if (s[j] === '"') {
32
- j++
33
- while (j < s.length && s[j] !== '"') j++
34
- if (j < s.length) j++
35
- } else j++
36
- }
37
- const raw = s.slice(i, j)
38
- const m = KEY_RE.exec(raw)
39
- out.push(m
40
- ? { ws: false, raw, start: i, end: j, key: m[1].toLowerCase(), value: unquote(m[2]) }
41
- : { ws: false, raw, start: i, end: j, key: null, value: unquote(raw) })
42
- }
43
- i = j
44
- }
45
- return out
46
- }
47
-
48
- export const tokenize = (text) => scanQuery(text).filter((seg) => !seg.ws)
49
- export const serialize = (tokens) => tokens.map((t) => t.raw).join(' ')
50
- export const normalizeQuery = (text) => serialize(tokenize(text))
51
- export const sameQuery = (a, b) => normalizeQuery(a) === normalizeQuery(b)
52
-
53
- // duplicate qualifiers: the LAST occurrence wins; bare words all apply.
54
- export const effectiveTokens = (tokens) => {
55
- const last = new Map()
56
- for (const t of tokens) if (t.key != null) last.set(t.key, t)
57
- return tokens.filter((t) => t.key == null || last.get(t.key) === t)
58
- }
59
-
60
- export const readToken = (text, key) => {
61
- const tokens = tokenize(text)
62
- for (let i = tokens.length - 1; i >= 0; i--) if (tokens[i].key === key) return tokens[i].value
63
- return ''
64
- }
65
-
66
- // token SURGERY: rewrite the key at its first position, drop later duplicates, append when absent,
67
- // remove the key entirely on an empty value. Every other token — known or not — survives verbatim.
68
- export function setToken(text, key, value) {
69
- const next = value == null || String(value) === ''
70
- ? null
71
- : { ws: false, raw: `${key}:${quoteValue(value)}`, key, value: String(value) }
72
- const out = []
73
- let placed = false
74
- for (const t of tokenize(text)) {
75
- if (t.key === key) {
76
- if (next && !placed) { out.push(next); placed = true }
77
- continue
78
- }
79
- out.push(t)
80
- }
81
- if (next && !placed) out.push(next)
82
- return serialize(out)
83
- }
84
-
85
- // MATCHING is deliberately NOT here: this module owns text — scan/serialize/surgery/suggestions and the
86
- // canonical-address discipline — while the conjunctive field matching (including the unknown-qualifier
87
- // IMPOSSIBLE state) lives in the ONE [[review-filters]] engine, reached through its tokenFilterState
88
- // bridge. A second predicate here would be the exact fork the fusion removed.
89
-
90
- // canonical address discipline: the default view is the BARE page address; any other state is exactly
91
- // ?q=<raw text>. An emptied submit falls back to the default (→ bare).
92
- export const queryParam = (text, defaultText) => {
93
- const trimmed = String(text ?? '').trim()
94
- if (!trimmed || sameQuery(trimmed, defaultText)) return null
95
- return { q: trimmed }
96
- }
97
-
98
- // A query/filter action resets by omitting page; a PAGINATION action passes a page (including 1) and
99
- // therefore records GitHub's explicit page=1 history form. The distinction is the action, not equivalence.
100
- export const reviewRouteQuery = (text, defaultText, page = null) => {
101
- const query = queryParam(text, defaultText) || {}
102
- if (page != null) query.page = String(page)
103
- return Object.keys(query).length ? query : null
104
- }
105
-
106
- // LEGACY structured params → token pairs. `kind=all` maps to nothing: the evidence default IS all.
107
- const LEGACY_PARAMS = {
108
- state: (v) => ['state', v],
109
- concluded: (v) => (v === '1' ? ['state', 'closed'] : null),
110
- ok: (v) => (v === '1' ? ['state', 'reviewed'] : null),
111
- verdict: (v) => ['verdict', v],
112
- freshness: (v) => ['freshness', v],
113
- kind: (v) => (v === 'all' ? null : ['evidence', v]),
114
- store: (v) => ['store', v],
115
- author: (v) => ['author', v],
116
- node: (v) => ['node', v],
117
- filer: (v) => ['filer', v],
118
- live: (v) => (v === '1' ? ['session', 'present'] : null),
119
- session: (v) => ['scope', v],
120
- }
121
-
122
- export const hasLegacyParams = (query) =>
123
- Object.keys(LEGACY_PARAMS).some((k) => query?.[k] != null && query[k] !== '')
124
-
125
- // the legacy free q was ONE substring search — it must replay as ONE text token. Quote it whenever the
126
- // tokenizer would read it as anything else: spaces (several words), a colon (q=drift:check would become
127
- // an unknown qualifier and match zero), or a stray quote (which would swallow neighbours).
128
- const freeTextToken = (v) => (/[\s:"]/.test(v) ? `"${v.replace(/"/g, '')}"` : v)
129
-
130
- // a legacy LIST address replays as the FULL visible state: the page's default tokens with each legacy
131
- // param surgically applied (live=1→session:present, session=<id>→scope:<id>, ok=1→state:reviewed,
132
- // kind→evidence:), the free-text q appended as ONE bare/phrase token preserving the old
133
- // single-substring search. Returns null when nothing legacy is present.
134
- export function legacyQueryText(defaultText, query) {
135
- if (!hasLegacyParams(query)) return null
136
- let text = defaultText
137
- for (const [param, toPair] of Object.entries(LEGACY_PARAMS)) {
138
- const v = query[param]
139
- if (v == null || v === '') continue
140
- const pair = toPair(String(v))
141
- if (pair) text = setToken(text, pair[0], pair[1])
142
- }
143
- const free = String(query.q ?? '').trim()
144
- if (free) text = `${text} ${freeTextToken(free)}`.trim()
145
- return text
146
- }
147
-
148
- // inline autocomplete at the caret — client-side and BOUNDED. A bare prefix completes qualifier KEYS
149
- // (insert `key:`, keep typing); a `key:prefix` completes VALUES from the page-supplied candidate list
150
- // only (data-derived; scope = sessions on the current board), capped at 8. Everything else stays
151
- // hand-typable and submits verbatim.
152
- export function suggestAt(text, caret, keys = [], values = {}) {
153
- const s = String(text ?? '')
154
- const at = Math.max(0, Math.min(caret ?? s.length, s.length))
155
- const seg = scanQuery(s).find((g) => !g.ws && g.start < at && at <= g.end)
156
- if (!seg) return { start: at, end: at, items: [] }
157
- const typed = s.slice(seg.start, at)
158
- const m = KEY_RE.exec(typed)
159
- if (!m) {
160
- const w = typed.toLowerCase()
161
- if (!w || w.includes('"')) return { start: seg.start, end: seg.end, items: [] }
162
- const items = keys.filter((k) => k.startsWith(w)).slice(0, 8)
163
- .map((k) => ({ type: 'key', key: k, insert: `${k}:` }))
164
- return { start: seg.start, end: seg.end, items }
165
- }
166
- const key = m[1].toLowerCase()
167
- const prefix = m[2].replace(/^"/, '').replace(/"$/, '').toLowerCase()
168
- const pool = values[key] || []
169
- const items = pool
170
- .filter((c) => String(c.value).toLowerCase().startsWith(prefix) && String(c.value).toLowerCase() !== prefix)
171
- .slice(0, 8)
172
- .map((c) => ({ type: 'value', key, value: String(c.value), label: c.label || null, insert: `${key}:${quoteValue(c.value)} ` }))
173
- return { start: seg.start, end: seg.end, items }
174
- }