spexcode 0.6.2 → 0.6.6
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.
- package/README.md +3 -1
- package/bin/spex.mjs +4 -0
- package/node_modules/@spexcode/session-core/dist/delivery-queue.d.ts +23 -0
- package/node_modules/@spexcode/session-core/dist/delivery-queue.js +195 -0
- package/node_modules/@spexcode/session-core/dist/index.d.ts +5 -0
- package/node_modules/@spexcode/session-core/dist/index.js +5 -0
- package/node_modules/@spexcode/session-core/dist/internal.d.ts +3 -0
- package/node_modules/@spexcode/session-core/dist/internal.js +3 -0
- package/node_modules/@spexcode/session-core/dist/message.d.ts +22 -0
- package/node_modules/@spexcode/session-core/dist/message.js +52 -0
- package/node_modules/@spexcode/session-core/dist/record-lock.d.ts +7 -0
- package/node_modules/@spexcode/session-core/dist/record-lock.js +152 -0
- package/node_modules/@spexcode/session-core/dist/runtime-session.d.ts +50 -0
- package/node_modules/@spexcode/session-core/dist/runtime-session.js +286 -0
- package/node_modules/@spexcode/session-core/dist/session-cursors.d.ts +14 -0
- package/node_modules/@spexcode/session-core/dist/session-cursors.js +82 -0
- package/node_modules/@spexcode/session-core/dist/session-timeline.d.ts +46 -0
- package/node_modules/@spexcode/session-core/dist/session-timeline.js +216 -0
- package/node_modules/@spexcode/session-core/package.json +33 -0
- package/node_modules/@spexcode/spec-cli/bin/spex.mjs +77 -0
- package/node_modules/@spexcode/spec-cli/dist/attach.d.ts +2 -0
- package/node_modules/@spexcode/spec-cli/dist/attach.js +48 -0
- package/node_modules/@spexcode/spec-cli/dist/claude-headless.d.ts +36 -0
- package/node_modules/@spexcode/spec-cli/dist/claude-headless.js +316 -0
- package/node_modules/@spexcode/spec-cli/dist/cli.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/cli.js +1908 -0
- package/node_modules/@spexcode/spec-cli/dist/client.d.ts +112 -0
- package/node_modules/@spexcode/spec-cli/dist/client.js +481 -0
- package/node_modules/@spexcode/spec-cli/dist/cockpit.d.ts +7 -0
- package/node_modules/@spexcode/spec-cli/dist/cockpit.js +26 -0
- package/node_modules/@spexcode/spec-cli/dist/codex-headless.d.ts +1 -0
- package/{spec-cli/src/codex-headless.ts → node_modules/@spexcode/spec-cli/dist/codex-headless.js} +3 -9
- package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.d.ts +58 -0
- package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.js +798 -0
- package/node_modules/@spexcode/spec-cli/dist/commit-surgery.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/commit-surgery.js +90 -0
- package/node_modules/@spexcode/spec-cli/dist/contract-filter.d.ts +14 -0
- package/node_modules/@spexcode/spec-cli/dist/contract-filter.js +219 -0
- package/node_modules/@spexcode/spec-cli/dist/dashboard-assets.d.ts +6 -0
- package/node_modules/@spexcode/spec-cli/dist/dashboard-assets.js +50 -0
- package/node_modules/@spexcode/spec-cli/dist/doctor.d.ts +9 -0
- package/node_modules/@spexcode/spec-cli/dist/doctor.js +553 -0
- package/node_modules/@spexcode/spec-cli/dist/eval-host.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/eval-host.js +19 -0
- package/node_modules/@spexcode/spec-cli/dist/execution-trace.d.ts +26 -0
- package/node_modules/@spexcode/spec-cli/dist/execution-trace.js +475 -0
- package/node_modules/@spexcode/spec-cli/dist/file-write.d.ts +2 -0
- package/node_modules/@spexcode/spec-cli/dist/file-write.js +26 -0
- package/node_modules/@spexcode/spec-cli/dist/flat.d.ts +89 -0
- package/node_modules/@spexcode/spec-cli/dist/flat.js +1076 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway-auth.d.ts +56 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway-auth.js +168 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway-hub.d.ts +28 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway-hub.js +363 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway.d.ts +38 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway.js +527 -0
- package/node_modules/@spexcode/spec-cli/dist/graphCache.d.ts +27 -0
- package/node_modules/@spexcode/spec-cli/dist/graphCache.js +717 -0
- package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.d.ts +14 -0
- package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.js +36 -0
- package/node_modules/@spexcode/spec-cli/dist/graphStream.d.ts +85 -0
- package/node_modules/@spexcode/spec-cli/dist/graphStream.js +1195 -0
- package/node_modules/@spexcode/spec-cli/dist/guidance-catalog.d.ts +64 -0
- package/node_modules/@spexcode/spec-cli/dist/guidance-catalog.js +166 -0
- package/node_modules/@spexcode/spec-cli/dist/guide.d.ts +8 -0
- package/{spec-cli/src/guide.ts → node_modules/@spexcode/spec-cli/dist/guide.js} +36 -32
- package/node_modules/@spexcode/spec-cli/dist/harness-select.d.ts +18 -0
- package/node_modules/@spexcode/spec-cli/dist/harness-select.js +62 -0
- package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +338 -0
- package/node_modules/@spexcode/spec-cli/dist/harness.js +3146 -0
- package/node_modules/@spexcode/spec-cli/dist/headless-controller.d.ts +9 -0
- package/node_modules/@spexcode/spec-cli/dist/headless-controller.js +47 -0
- package/node_modules/@spexcode/spec-cli/dist/help.d.ts +15 -0
- package/node_modules/@spexcode/spec-cli/dist/help.js +594 -0
- package/node_modules/@spexcode/spec-cli/dist/hook-prompts.d.ts +18 -0
- package/node_modules/@spexcode/spec-cli/dist/hook-prompts.js +122 -0
- package/node_modules/@spexcode/spec-cli/dist/hooks.d.ts +1 -0
- package/{spec-cli/src/hooks.ts → node_modules/@spexcode/spec-cli/dist/hooks.js} +15 -15
- package/node_modules/@spexcode/spec-cli/dist/host-resources.d.ts +97 -0
- package/node_modules/@spexcode/spec-cli/dist/host-resources.js +795 -0
- package/node_modules/@spexcode/spec-cli/dist/host.d.ts +88 -0
- package/node_modules/@spexcode/spec-cli/dist/host.js +663 -0
- package/node_modules/@spexcode/spec-cli/dist/index.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/index.js +899 -0
- package/node_modules/@spexcode/spec-cli/dist/init.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/init.js +284 -0
- package/node_modules/@spexcode/spec-cli/dist/issues-cli.d.ts +6 -0
- package/node_modules/@spexcode/spec-cli/dist/issues-cli.js +334 -0
- package/node_modules/@spexcode/spec-cli/dist/issues.d.ts +69 -0
- package/node_modules/@spexcode/spec-cli/dist/issues.js +189 -0
- package/node_modules/@spexcode/spec-cli/dist/lint.d.ts +34 -0
- package/node_modules/@spexcode/spec-cli/dist/lint.js +476 -0
- package/node_modules/@spexcode/spec-cli/dist/listen.d.ts +8 -0
- package/node_modules/@spexcode/spec-cli/dist/listen.js +24 -0
- package/node_modules/@spexcode/spec-cli/dist/localIssues.d.ts +65 -0
- package/node_modules/@spexcode/spec-cli/dist/localIssues.js +582 -0
- package/node_modules/@spexcode/spec-cli/dist/login-page.d.ts +5 -0
- package/{spec-cli/src/login-page.ts → node_modules/@spexcode/spec-cli/dist/login-page.js} +7 -7
- package/node_modules/@spexcode/spec-cli/dist/loop-in.d.ts +23 -0
- package/{spec-cli/src/loop-in.ts → node_modules/@spexcode/spec-cli/dist/loop-in.js} +35 -45
- package/node_modules/@spexcode/spec-cli/dist/machine-peer.d.ts +69 -0
- package/node_modules/@spexcode/spec-cli/dist/machine-peer.js +603 -0
- package/node_modules/@spexcode/spec-cli/dist/materialize.d.ts +18 -0
- package/node_modules/@spexcode/spec-cli/dist/materialize.js +468 -0
- package/node_modules/@spexcode/spec-cli/dist/mentions.d.ts +50 -0
- package/node_modules/@spexcode/spec-cli/dist/mentions.js +117 -0
- package/node_modules/@spexcode/spec-cli/dist/opencode-headless.d.ts +5 -0
- package/node_modules/@spexcode/spec-cli/dist/opencode-headless.js +215 -0
- package/node_modules/@spexcode/spec-cli/dist/opencode.d.ts +3 -0
- package/{spec-cli/src/opencode.ts → node_modules/@spexcode/spec-cli/dist/opencode.js} +9 -13
- package/node_modules/@spexcode/spec-cli/dist/pi-harness.d.ts +3 -0
- package/{spec-cli/src/pi-harness.ts → node_modules/@spexcode/spec-cli/dist/pi-harness.js} +45 -40
- package/node_modules/@spexcode/spec-cli/dist/pi-headless.d.ts +25 -0
- package/node_modules/@spexcode/spec-cli/dist/pi-headless.js +196 -0
- package/node_modules/@spexcode/spec-cli/dist/plugin-harness.d.ts +21 -0
- package/node_modules/@spexcode/spec-cli/dist/plugin-harness.js +146 -0
- package/node_modules/@spexcode/spec-cli/dist/pty-bridge.d.ts +10 -0
- package/node_modules/@spexcode/spec-cli/dist/pty-bridge.js +404 -0
- package/node_modules/@spexcode/spec-cli/dist/pty-helper.d.mts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/pty-helper.mjs +101 -0
- package/node_modules/@spexcode/spec-cli/dist/pty-native-helper.d.mts +2 -0
- package/node_modules/@spexcode/spec-cli/dist/pty-native-helper.mjs +23 -0
- package/node_modules/@spexcode/spec-cli/dist/public-graph.d.ts +46 -0
- package/node_modules/@spexcode/spec-cli/dist/public-graph.js +56 -0
- package/node_modules/@spexcode/spec-cli/dist/ranker.d.ts +15 -0
- package/node_modules/@spexcode/spec-cli/dist/ranker.js +188 -0
- package/node_modules/@spexcode/spec-cli/dist/reaper.d.ts +6 -0
- package/node_modules/@spexcode/spec-cli/dist/reaper.js +81 -0
- package/node_modules/@spexcode/spec-cli/dist/reviews.d.ts +189 -0
- package/node_modules/@spexcode/spec-cli/dist/reviews.js +350 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-guard.d.ts +6 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-guard.js +37 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.d.ts +21 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.js +84 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-rotate.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-rotate.js +58 -0
- package/node_modules/@spexcode/spec-cli/dist/search.bench.d.mts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/search.bench.mjs +75 -0
- package/node_modules/@spexcode/spec-cli/dist/search.d.ts +20 -0
- package/node_modules/@spexcode/spec-cli/dist/search.js +61 -0
- package/node_modules/@spexcode/spec-cli/dist/session-declarations.d.ts +13 -0
- package/node_modules/@spexcode/spec-cli/dist/session-declarations.js +126 -0
- package/node_modules/@spexcode/spec-cli/dist/session-execution.d.ts +10 -0
- package/node_modules/@spexcode/spec-cli/dist/session-execution.js +70 -0
- package/node_modules/@spexcode/spec-cli/dist/session-files.d.ts +28 -0
- package/node_modules/@spexcode/spec-cli/dist/session-files.js +130 -0
- package/node_modules/@spexcode/spec-cli/dist/session-follow.d.ts +31 -0
- package/node_modules/@spexcode/spec-cli/dist/session-follow.js +179 -0
- package/node_modules/@spexcode/spec-cli/dist/session-reparent.d.ts +10 -0
- package/node_modules/@spexcode/spec-cli/dist/session-reparent.js +33 -0
- package/node_modules/@spexcode/spec-cli/dist/session-timeline.d.ts +11 -0
- package/node_modules/@spexcode/spec-cli/dist/session-timeline.js +20 -0
- package/node_modules/@spexcode/spec-cli/dist/session-web.d.ts +24 -0
- package/node_modules/@spexcode/spec-cli/dist/session-web.js +141 -0
- package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +433 -0
- package/node_modules/@spexcode/spec-cli/dist/sessions.js +4667 -0
- package/node_modules/@spexcode/spec-cli/dist/sh.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/sh.js +3 -0
- package/node_modules/@spexcode/spec-cli/dist/shim-runtime.d.ts +1 -0
- package/{spec-cli/src/shim-runtime.ts → node_modules/@spexcode/spec-cli/dist/shim-runtime.js} +3 -4
- package/node_modules/@spexcode/spec-cli/dist/slash-commands.d.ts +9 -0
- package/node_modules/@spexcode/spec-cli/dist/slash-commands.js +307 -0
- package/node_modules/@spexcode/spec-cli/dist/source-files.d.ts +9 -0
- package/node_modules/@spexcode/spec-cli/dist/source-files.js +113 -0
- package/node_modules/@spexcode/spec-cli/dist/supervise.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/supervise.js +308 -0
- package/node_modules/@spexcode/spec-cli/dist/tree.d.ts +25 -0
- package/node_modules/@spexcode/spec-cli/dist/tree.js +98 -0
- package/node_modules/@spexcode/spec-cli/dist/tsx-bin.d.ts +3 -0
- package/node_modules/@spexcode/spec-cli/dist/tsx-bin.js +41 -0
- package/node_modules/@spexcode/spec-cli/dist/uninstall.d.ts +3 -0
- package/node_modules/@spexcode/spec-cli/dist/uninstall.js +177 -0
- package/node_modules/@spexcode/spec-cli/dist/uploads.d.ts +36 -0
- package/node_modules/@spexcode/spec-cli/dist/uploads.js +243 -0
- package/node_modules/@spexcode/spec-cli/dist/worktree-sources.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/worktree-sources.js +47 -0
- package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/dispatch.sh +5 -5
- package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/harness.sh +1 -1
- package/node_modules/@spexcode/spec-cli/package.json +49 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +8 -0
- package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-first/spec-first.sh +1 -1
- package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-of-file/spec-of-file.sh +1 -0
- package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/stop-gate/spec.md +2 -2
- package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/stop-gate/stop-gate.sh +31 -29
- package/node_modules/@spexcode/spec-core/dist/anchors.d.ts +94 -0
- package/node_modules/@spexcode/spec-core/dist/anchors.js +730 -0
- package/node_modules/@spexcode/spec-core/dist/git.d.ts +170 -0
- package/node_modules/@spexcode/spec-core/dist/git.js +2768 -0
- package/node_modules/@spexcode/spec-core/dist/graph-delta.d.ts +44 -0
- package/node_modules/@spexcode/spec-core/dist/graph-delta.js +72 -0
- package/node_modules/@spexcode/spec-core/dist/graph.d.ts +34 -0
- package/node_modules/@spexcode/spec-core/dist/graph.js +237 -0
- package/node_modules/@spexcode/spec-core/dist/graphDelta.d.ts +3 -0
- package/node_modules/@spexcode/spec-core/dist/graphDelta.js +13 -0
- package/node_modules/@spexcode/spec-core/dist/harness-identity.d.ts +31 -0
- package/node_modules/@spexcode/spec-core/dist/harness-identity.js +20 -0
- package/node_modules/@spexcode/spec-core/dist/identity-presets.d.ts +152 -0
- package/node_modules/@spexcode/spec-core/dist/identity-presets.js +132 -0
- package/node_modules/@spexcode/spec-core/dist/index.d.ts +45 -0
- package/node_modules/@spexcode/spec-core/dist/index.js +19 -0
- package/node_modules/@spexcode/spec-core/dist/layout.d.ts +187 -0
- package/node_modules/@spexcode/spec-core/dist/layout.js +548 -0
- package/node_modules/@spexcode/spec-core/dist/process-identity.d.ts +37 -0
- package/node_modules/@spexcode/spec-core/dist/process-identity.js +214 -0
- package/node_modules/@spexcode/spec-core/dist/project-identity.d.ts +12 -0
- package/node_modules/@spexcode/spec-core/dist/project-identity.js +71 -0
- package/node_modules/@spexcode/spec-core/dist/project-store.d.ts +3 -0
- package/node_modules/@spexcode/spec-core/dist/project-store.js +14 -0
- package/node_modules/@spexcode/spec-core/dist/resilience.d.ts +2 -0
- package/node_modules/@spexcode/spec-core/dist/resilience.js +40 -0
- package/node_modules/@spexcode/spec-core/dist/review/index.d.ts +3 -0
- package/node_modules/@spexcode/spec-core/dist/review/index.js +5 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.d.ts +77 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.js +308 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.d.ts +66 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.js +180 -0
- package/node_modules/@spexcode/spec-core/dist/review/session.d.ts +4 -0
- package/node_modules/@spexcode/spec-core/dist/review/session.js +8 -0
- package/node_modules/@spexcode/spec-core/dist/reviewSnapshot.d.ts +15 -0
- package/node_modules/@spexcode/spec-core/dist/reviewSnapshot.js +12 -0
- package/node_modules/@spexcode/spec-core/dist/root-lru.d.ts +4 -0
- package/{spec-cli/src/root-lru.ts → node_modules/@spexcode/spec-core/dist/root-lru.js} +26 -30
- package/node_modules/@spexcode/spec-core/dist/specs.d.ts +117 -0
- package/node_modules/@spexcode/spec-core/dist/specs.js +489 -0
- package/node_modules/@spexcode/spec-core/package.json +28 -0
- package/node_modules/@spexcode/spec-eval/dist/cache.d.ts +10 -0
- package/node_modules/@spexcode/spec-eval/dist/cache.js +50 -0
- package/node_modules/@spexcode/spec-eval/dist/cli.d.ts +22 -0
- package/node_modules/@spexcode/spec-eval/dist/cli.js +981 -0
- package/node_modules/@spexcode/spec-eval/dist/evaltab.d.ts +98 -0
- package/node_modules/@spexcode/spec-eval/dist/evaltab.js +176 -0
- package/node_modules/@spexcode/spec-eval/dist/filing.d.ts +16 -0
- package/node_modules/@spexcode/spec-eval/dist/filing.js +36 -0
- package/node_modules/@spexcode/spec-eval/dist/freshness.d.ts +48 -0
- package/node_modules/@spexcode/spec-eval/dist/freshness.js +799 -0
- package/node_modules/@spexcode/spec-eval/dist/host.d.ts +46 -0
- package/node_modules/@spexcode/spec-eval/dist/host.js +53 -0
- package/node_modules/@spexcode/spec-eval/dist/humanok.d.ts +11 -0
- package/node_modules/@spexcode/spec-eval/dist/humanok.js +27 -0
- package/node_modules/@spexcode/spec-eval/dist/index.d.ts +4 -0
- package/node_modules/@spexcode/spec-eval/dist/index.js +4 -0
- package/node_modules/@spexcode/spec-eval/dist/remarks.d.ts +31 -0
- package/node_modules/@spexcode/spec-eval/dist/remarks.js +1 -0
- package/node_modules/@spexcode/spec-eval/dist/scenariofresh.d.ts +13 -0
- package/node_modules/@spexcode/spec-eval/dist/scenariofresh.js +303 -0
- package/node_modules/@spexcode/spec-eval/dist/scenarios.d.ts +99 -0
- package/node_modules/@spexcode/spec-eval/dist/scenarios.js +650 -0
- package/node_modules/@spexcode/spec-eval/dist/sessioneval.d.ts +307 -0
- package/node_modules/@spexcode/spec-eval/dist/sessioneval.js +1883 -0
- package/node_modules/@spexcode/spec-eval/dist/sidecar.d.ts +55 -0
- package/node_modules/@spexcode/spec-eval/dist/sidecar.js +82 -0
- package/node_modules/@spexcode/spec-eval/dist/timeline.d.ts +25 -0
- package/node_modules/@spexcode/spec-eval/dist/timeline.js +65 -0
- package/node_modules/@spexcode/spec-eval/dist/ui-path.d.ts +1 -0
- package/node_modules/@spexcode/spec-eval/dist/ui-path.js +2 -0
- package/node_modules/@spexcode/spec-eval/package.json +36 -0
- package/node_modules/@spexcode/spec-forge/dist/cache.d.ts +29 -0
- package/node_modules/@spexcode/spec-forge/dist/cache.js +59 -0
- package/node_modules/@spexcode/spec-forge/dist/cli.d.ts +1 -0
- package/node_modules/@spexcode/spec-forge/dist/cli.js +100 -0
- package/node_modules/@spexcode/spec-forge/dist/drivers/github.d.ts +2 -0
- package/node_modules/@spexcode/spec-forge/dist/drivers/github.js +116 -0
- package/node_modules/@spexcode/spec-forge/dist/drivers/gitlab.d.ts +7 -0
- package/node_modules/@spexcode/spec-forge/dist/drivers/gitlab.js +144 -0
- package/node_modules/@spexcode/spec-forge/dist/drivers.d.ts +10 -0
- package/node_modules/@spexcode/spec-forge/dist/drivers.js +83 -0
- package/node_modules/@spexcode/spec-forge/dist/index.d.ts +4 -0
- package/node_modules/@spexcode/spec-forge/dist/index.js +4 -0
- package/node_modules/@spexcode/spec-forge/dist/links.d.ts +15 -0
- package/node_modules/@spexcode/spec-forge/dist/links.js +65 -0
- package/node_modules/@spexcode/spec-forge/dist/needs-eval.d.ts +10 -0
- package/node_modules/@spexcode/spec-forge/dist/needs-eval.js +20 -0
- package/node_modules/@spexcode/spec-forge/dist/port.d.ts +53 -0
- package/node_modules/@spexcode/spec-forge/dist/port.js +1 -0
- package/node_modules/@spexcode/spec-forge/dist/resident.d.ts +7 -0
- package/node_modules/@spexcode/spec-forge/dist/resident.js +43 -0
- package/node_modules/@spexcode/spec-forge/package.json +32 -0
- package/package.json +33 -19
- package/spec-cli/bin/spex.mjs +0 -69
- package/spec-cli/src/anchors.ts +0 -728
- package/spec-cli/src/attach.ts +0 -43
- package/spec-cli/src/claude-headless.ts +0 -321
- package/spec-cli/src/cli.ts +0 -1258
- package/spec-cli/src/client.ts +0 -414
- package/spec-cli/src/cockpit.ts +0 -43
- package/spec-cli/src/codex-runtime-generations.ts +0 -646
- package/spec-cli/src/commit-surgery.ts +0 -68
- package/spec-cli/src/contract-filter.ts +0 -202
- package/spec-cli/src/delivery-queue.ts +0 -165
- package/spec-cli/src/doctor.ts +0 -516
- package/spec-cli/src/execution-trace.ts +0 -444
- package/spec-cli/src/file-write.ts +0 -22
- package/spec-cli/src/gateway-auth.ts +0 -181
- package/spec-cli/src/gateway-hub.ts +0 -358
- package/spec-cli/src/gateway.ts +0 -461
- package/spec-cli/src/git.ts +0 -2556
- package/spec-cli/src/graph.ts +0 -271
- package/spec-cli/src/graphCache.ts +0 -710
- package/spec-cli/src/graphDelta.ts +0 -77
- package/spec-cli/src/graphStream.ts +0 -1019
- package/spec-cli/src/harness-select.ts +0 -77
- package/spec-cli/src/harness.ts +0 -3025
- package/spec-cli/src/headless-controller.ts +0 -63
- package/spec-cli/src/help.ts +0 -492
- package/spec-cli/src/host-resources.ts +0 -762
- package/spec-cli/src/host.ts +0 -611
- package/spec-cli/src/identity-presets.d.ts +0 -13
- package/spec-cli/src/identity-presets.js +0 -138
- package/spec-cli/src/index.ts +0 -818
- package/spec-cli/src/init.ts +0 -258
- package/spec-cli/src/issues-cli.ts +0 -276
- package/spec-cli/src/issues.ts +0 -237
- package/spec-cli/src/layout.ts +0 -640
- package/spec-cli/src/lint.ts +0 -488
- package/spec-cli/src/listen.ts +0 -28
- package/spec-cli/src/localIssues.ts +0 -538
- package/spec-cli/src/materialize.ts +0 -417
- package/spec-cli/src/mentions.ts +0 -81
- package/spec-cli/src/opencode-headless.ts +0 -205
- package/spec-cli/src/pi-headless.ts +0 -153
- package/spec-cli/src/plugin-harness.ts +0 -157
- package/spec-cli/src/process-identity.ts +0 -207
- package/spec-cli/src/project-identity.ts +0 -73
- package/spec-cli/src/project-store.ts +0 -17
- package/spec-cli/src/pty-bridge.ts +0 -396
- package/spec-cli/src/pty-helper.mjs +0 -96
- package/spec-cli/src/pty-native-helper.mjs +0 -22
- package/spec-cli/src/ranker.ts +0 -191
- package/spec-cli/src/reaper.ts +0 -125
- package/spec-cli/src/resilience.ts +0 -41
- package/spec-cli/src/reviewSnapshot.ts +0 -28
- package/spec-cli/src/reviews.ts +0 -434
- package/spec-cli/src/runtime-guard.ts +0 -35
- package/spec-cli/src/runtime-ownership.ts +0 -88
- package/spec-cli/src/search.bench.mjs +0 -80
- package/spec-cli/src/search.ts +0 -63
- package/spec-cli/src/session-cursors.ts +0 -91
- package/spec-cli/src/session-execution.ts +0 -68
- package/spec-cli/src/session-files.ts +0 -121
- package/spec-cli/src/session-follow.ts +0 -182
- package/spec-cli/src/session-reparent.ts +0 -33
- package/spec-cli/src/session-timeline.ts +0 -247
- package/spec-cli/src/session-web.ts +0 -135
- package/spec-cli/src/sessions.ts +0 -3883
- package/spec-cli/src/sh.ts +0 -3
- package/spec-cli/src/slash-commands.ts +0 -318
- package/spec-cli/src/source-files.ts +0 -104
- package/spec-cli/src/specs.ts +0 -498
- package/spec-cli/src/supervise.ts +0 -245
- package/spec-cli/src/tree.ts +0 -118
- package/spec-cli/src/tsx-bin.ts +0 -18
- package/spec-cli/src/uninstall.ts +0 -171
- package/spec-cli/src/uploads.ts +0 -253
- package/spec-cli/src/worktree-sources.ts +0 -42
- package/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +0 -8
- package/spec-dashboard/dist/assets/App-B6IbFbGu.js +0 -2
- package/spec-dashboard/dist/assets/Dashboard-C5ap-Sga.css +0 -1
- package/spec-dashboard/dist/assets/Dashboard-_sDk7Rcg.js +0 -27
- package/spec-dashboard/dist/assets/EvalsPage-BT357Lyt.js +0 -2
- package/spec-dashboard/dist/assets/IssuesPage-BG9rNOgV.js +0 -1
- package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/spec-dashboard/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/spec-dashboard/dist/assets/MobileApp-D9yPMR3A.js +0 -2
- package/spec-dashboard/dist/assets/Modal-B3EcgeA3.js +0 -1
- package/spec-dashboard/dist/assets/PageScroll-CNZOugWV.js +0 -1
- package/spec-dashboard/dist/assets/ProjectsPage-C2CRHmvs.js +0 -1
- package/spec-dashboard/dist/assets/SessionInterface-6GBZ9nXN.css +0 -32
- package/spec-dashboard/dist/assets/SessionInterface-DOEjuT3l.js +0 -40
- package/spec-dashboard/dist/assets/SessionWindow-1nYgZ4CL.js +0 -1
- package/spec-dashboard/dist/assets/Settings-7WeTJn0V.js +0 -1
- package/spec-dashboard/dist/assets/Thread-CEbzAFQn.js +0 -13
- package/spec-dashboard/dist/assets/bindings-BC9vqpYU.js +0 -1
- package/spec-dashboard/dist/assets/data-SlvxNA2r.js +0 -1
- package/spec-dashboard/dist/assets/index-DLVeOHL-.js +0 -41
- package/spec-dashboard/dist/assets/index-DYLGfPjx.css +0 -1
- package/spec-dashboard/dist/assets/launch-Cp579UoJ.css +0 -1
- package/spec-dashboard/dist/assets/launch-yxCYr64x.js +0 -276
- package/spec-dashboard/dist/assets/sessionSurface--7l69h4F.js +0 -1
- package/spec-dashboard/dist/index.html +0 -29
- package/spec-dashboard/src/reviewFilters.js +0 -322
- package/spec-dashboard/src/reviewQuery.js +0 -174
- package/spec-dashboard/src/session.js +0 -199
- package/spec-eval/src/cache.ts +0 -57
- package/spec-eval/src/cli.ts +0 -894
- package/spec-eval/src/evaltab.ts +0 -264
- package/spec-eval/src/filing.ts +0 -39
- package/spec-eval/src/freshness.ts +0 -836
- package/spec-eval/src/humanok.ts +0 -28
- package/spec-eval/src/scenariofresh.ts +0 -244
- package/spec-eval/src/scenarios.ts +0 -672
- package/spec-eval/src/sessioneval.ts +0 -2220
- package/spec-eval/src/sidecar.ts +0 -93
- package/spec-eval/src/timeline.ts +0 -54
- package/spec-forge/src/__fixtures__/github-forge.json +0 -63
- package/spec-forge/src/cache.ts +0 -66
- package/spec-forge/src/cli.ts +0 -99
- package/spec-forge/src/drivers/github.ts +0 -132
- package/spec-forge/src/drivers/gitlab.ts +0 -153
- package/spec-forge/src/drivers.ts +0 -73
- package/spec-forge/src/links.ts +0 -72
- package/spec-forge/src/needs-eval.ts +0 -29
- package/spec-forge/src/port.ts +0 -36
- package/spec-forge/src/resident.ts +0 -46
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/README.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/compat/mark-active-0.5.2-eef1.fixture +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/hooks/compat/mark-active-sed-v0.fixture +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/commit-msg +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/post-checkout +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/post-merge +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/pre-commit +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/prepare-commit-msg +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/hooks/reference-transaction +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/extract/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/regroup/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/rename/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/commands/tidy/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/comment-altitude/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/idle/idle.sh +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/idle/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/mark-active/mark-active.sh +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/mark-active/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/session-fail/fail.sh +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/session-fail/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-first/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec-of-file/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/core/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/atomic-landing/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/forge-link/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/memory-hygiene/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/prompts/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/distill/digest.mjs +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/distill/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/skills/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/.plugins/spec.md +0 -0
- /package/{spec-cli → node_modules/@spexcode/spec-cli}/templates/spec/project/spec.md +0 -0
- /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,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
|
+
}
|