spexcode 0.6.1 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -149
- package/bin/spex.mjs +4 -0
- package/node_modules/@spexcode/spec-cli/bin/spex.mjs +76 -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 +33 -0
- package/node_modules/@spexcode/spec-cli/dist/claude-headless.js +307 -0
- package/node_modules/@spexcode/spec-cli/dist/cli.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/cli.js +1859 -0
- package/node_modules/@spexcode/spec-cli/dist/client.d.ts +111 -0
- package/node_modules/@spexcode/spec-cli/dist/client.js +476 -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 +53 -0
- package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.js +686 -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/delivery-queue.d.ts +23 -0
- package/node_modules/@spexcode/spec-cli/dist/delivery-queue.js +179 -0
- package/node_modules/@spexcode/spec-cli/dist/doctor.d.ts +9 -0
- package/node_modules/@spexcode/spec-cli/dist/doctor.js +547 -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 +361 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway.d.ts +37 -0
- package/node_modules/@spexcode/spec-cli/dist/gateway.js +503 -0
- package/node_modules/@spexcode/spec-cli/dist/graphCache.d.ts +27 -0
- package/node_modules/@spexcode/spec-cli/dist/graphCache.js +716 -0
- package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.d.ts +14 -0
- package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.js +35 -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} +115 -22
- 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 +325 -0
- package/node_modules/@spexcode/spec-cli/dist/harness.js +3026 -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 +10 -0
- package/node_modules/@spexcode/spec-cli/dist/help.js +574 -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 +7 -0
- package/{spec-cli/src/listen.ts → node_modules/@spexcode/spec-cli/dist/listen.js} +13 -17
- 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 +4 -0
- package/node_modules/@spexcode/spec-cli/dist/opencode-headless.js +208 -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/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-cursors.d.ts +14 -0
- package/node_modules/@spexcode/spec-cli/dist/session-cursors.js +82 -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 +51 -0
- package/node_modules/@spexcode/spec-cli/dist/session-timeline.js +233 -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 +412 -0
- package/node_modules/@spexcode/spec-cli/dist/sessions.js +4239 -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 +27 -7
- package/node_modules/@spexcode/spec-cli/package.json +47 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/commands/supervisor/spec.md +8 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/comment-altitude/spec.md +9 -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/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/spec.md +22 -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-cli/templates/spec/project/.plugins/prompts/atomic-landing/spec.md +15 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/forge-link/spec.md +10 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/memory-hygiene/spec.md +13 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +12 -0
- 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 +166 -0
- package/node_modules/@spexcode/spec-core/dist/git.js +2736 -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 +183 -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 -706
- package/spec-cli/src/attach.ts +0 -43
- package/spec-cli/src/claude-headless.ts +0 -321
- package/spec-cli/src/cli.ts +0 -1115
- package/spec-cli/src/client.ts +0 -315
- 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 -107
- package/spec-cli/src/doctor.ts +0 -516
- 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 -356
- package/spec-cli/src/gateway.ts +0 -368
- package/spec-cli/src/git.ts +0 -2180
- package/spec-cli/src/graph.ts +0 -221
- package/spec-cli/src/graphCache.ts +0 -641
- 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 -2747
- package/spec-cli/src/headless-controller.ts +0 -63
- package/spec-cli/src/help.ts +0 -480
- package/spec-cli/src/host-resources.ts +0 -707
- 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 -128
- package/spec-cli/src/index.ts +0 -730
- 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 -557
- package/spec-cli/src/lint.ts +0 -458
- package/spec-cli/src/localIssues.ts +0 -538
- package/spec-cli/src/materialize.ts +0 -412
- 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 -405
- 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-follow.ts +0 -182
- package/spec-cli/src/session-timeline.ts +0 -98
- package/spec-cli/src/sessions.ts +0 -3403
- 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-cli/templates/spec/project/.plugins/core/comment-altitude/spec.md +0 -28
- package/spec-cli/templates/spec/project/.plugins/core/spec.md +0 -23
- package/spec-cli/templates/spec/project/.plugins/prompts/atomic-landing/spec.md +0 -32
- package/spec-cli/templates/spec/project/.plugins/prompts/forge-link/spec.md +0 -9
- package/spec-cli/templates/spec/project/.plugins/prompts/memory-hygiene/spec.md +0 -15
- package/spec-cli/templates/spec/project/.plugins/prompts/reproduce-before-fix/spec.md +0 -18
- package/spec-dashboard/dist/assets/App-F9uaAVcH.js +0 -2
- package/spec-dashboard/dist/assets/Dashboard-Ba_jhxp1.js +0 -27
- package/spec-dashboard/dist/assets/Dashboard-C5ap-Sga.css +0 -1
- package/spec-dashboard/dist/assets/EvalsPage-FixoOg_n.js +0 -2
- package/spec-dashboard/dist/assets/IssuesPage-CuKLFhH3.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-CHgEHORJ.js +0 -2
- package/spec-dashboard/dist/assets/Modal-CQgYymmr.js +0 -1
- package/spec-dashboard/dist/assets/PageScroll-hT7UTLvD.js +0 -1
- package/spec-dashboard/dist/assets/ProjectsPage-CtXxakF9.js +0 -1
- package/spec-dashboard/dist/assets/SessionInterface-6GBZ9nXN.css +0 -32
- package/spec-dashboard/dist/assets/SessionInterface-Bpie-9fs.js +0 -39
- package/spec-dashboard/dist/assets/SessionWindow-CixDi4PI.js +0 -1
- package/spec-dashboard/dist/assets/Settings-C2MsucfE.js +0 -1
- package/spec-dashboard/dist/assets/Thread-C6Go8HRh.js +0 -13
- package/spec-dashboard/dist/assets/bindings-BC9vqpYU.js +0 -1
- package/spec-dashboard/dist/assets/data-B-RQmit6.js +0 -1
- package/spec-dashboard/dist/assets/index-CsI8DElI.css +0 -1
- package/spec-dashboard/dist/assets/index-DrVao0Ep.js +0 -41
- package/spec-dashboard/dist/assets/launch-BBH02b1v.js +0 -276
- package/spec-dashboard/dist/assets/launch-Cp579UoJ.css +0 -1
- package/spec-dashboard/dist/assets/terminalFont-C6oGNKrf.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 -889
- package/spec-eval/src/evaltab.ts +0 -262
- package/spec-eval/src/filing.ts +0 -39
- package/spec-eval/src/freshness.ts +0 -557
- 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 -2226
- 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/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/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,144 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
let ctx = null;
|
|
3
|
+
function gitlabCtx() {
|
|
4
|
+
if (ctx)
|
|
5
|
+
return ctx;
|
|
6
|
+
const remote = execFileSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf8' }).trim();
|
|
7
|
+
const parsed = parseRemote(remote);
|
|
8
|
+
if (!parsed)
|
|
9
|
+
throw new Error(`gitlab: cannot parse origin remote '${remote}' as a GitLab URL`);
|
|
10
|
+
const token = process.env.GITLAB_TOKEN || credentialToken(parsed.host);
|
|
11
|
+
if (!token) {
|
|
12
|
+
throw new Error(`gitlab: no token for ${parsed.host} — set GITLAB_TOKEN, or store a PAT in git's credential store:\n` +
|
|
13
|
+
` printf "protocol=https\\nhost=${parsed.host}\\nusername=<user>\\npassword=<token>\\n\\n" | git credential approve`);
|
|
14
|
+
}
|
|
15
|
+
ctx = { ...parsed, token };
|
|
16
|
+
return ctx;
|
|
17
|
+
}
|
|
18
|
+
export function parseRemote(remote) {
|
|
19
|
+
let m = remote.match(/^(https?:\/\/[^/]+)\/(.+?)(?:\.git)?\/?$/);
|
|
20
|
+
if (m)
|
|
21
|
+
return { base: m[1], host: m[1].replace(/^https?:\/\//, ''), project: m[2] };
|
|
22
|
+
m = remote.match(/^(?:ssh:\/\/)?[\w.-]+@([\w.-]+)(?::\d+)?[:/](.+?)(?:\.git)?\/?$/);
|
|
23
|
+
if (m)
|
|
24
|
+
return { base: `https://${m[1]}`, host: m[1], project: m[2] };
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function credentialToken(host) {
|
|
28
|
+
try {
|
|
29
|
+
const out = execFileSync('git', ['credential', 'fill'], {
|
|
30
|
+
input: `protocol=https\nhost=${host}\n\n`,
|
|
31
|
+
encoding: 'utf8',
|
|
32
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0', GIT_ASKPASS: 'true' },
|
|
33
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
34
|
+
});
|
|
35
|
+
return out.match(/^password=(.+)$/m)?.[1] ?? '';
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function api(path, init) {
|
|
42
|
+
const { base, project, token } = gitlabCtx();
|
|
43
|
+
const sep = path.includes('?') ? '&' : '?';
|
|
44
|
+
const url = `${base}/api/v4/projects/${encodeURIComponent(project)}/${path}${init?.method ? '' : `${sep}per_page=100`}`;
|
|
45
|
+
const res = await fetch(url, {
|
|
46
|
+
...init,
|
|
47
|
+
headers: { 'PRIVATE-TOKEN': token, 'content-type': 'application/json', ...init?.headers },
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
throw new Error(`gitlab: ${init?.method ?? 'GET'} ${path} → ${res.status} ${(await res.text()).slice(0, 300)}`);
|
|
51
|
+
return (await res.json());
|
|
52
|
+
}
|
|
53
|
+
// GitLab's API has no bounded list query; stop at a short page and cap the walk.
|
|
54
|
+
async function paged(path) {
|
|
55
|
+
const sep = path.includes('?') ? '&' : '?';
|
|
56
|
+
const out = [];
|
|
57
|
+
for (let page = 1; page <= 20; page++) {
|
|
58
|
+
const rows = await api(`${path}${sep}page=${page}`);
|
|
59
|
+
out.push(...rows);
|
|
60
|
+
if (rows.length < 100)
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
async function toIssue(r) {
|
|
66
|
+
return {
|
|
67
|
+
number: r.iid,
|
|
68
|
+
title: r.title,
|
|
69
|
+
body: r.description ?? '',
|
|
70
|
+
url: r.web_url,
|
|
71
|
+
state: normalizeState(r.state),
|
|
72
|
+
labels: forgeLabels(r.labels),
|
|
73
|
+
author: r.author?.username ?? '',
|
|
74
|
+
createdAt: r.created_at ?? '',
|
|
75
|
+
comments: r.user_notes_count > 0 ? await listNotes(r.iid) : [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function forgeLabels(labels) {
|
|
79
|
+
return (labels ?? []).flatMap((label) => {
|
|
80
|
+
const name = typeof label === 'string' ? label : label.name ?? '';
|
|
81
|
+
if (!name)
|
|
82
|
+
return [];
|
|
83
|
+
if (typeof label === 'string')
|
|
84
|
+
return [{ name }];
|
|
85
|
+
return [{ name, ...(label.color ? { color: label.color } : {}), ...(label.text_color ? { textColor: label.text_color } : {}) }];
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function normalizeState(state) {
|
|
89
|
+
const s = (state || '').toLowerCase();
|
|
90
|
+
return s === 'opened' ? 'open' : s;
|
|
91
|
+
}
|
|
92
|
+
async function listNotes(iid) {
|
|
93
|
+
const rows = await paged(`issues/${iid}/notes`);
|
|
94
|
+
return rows
|
|
95
|
+
.filter((n) => !n.system)
|
|
96
|
+
.map((n) => ({ author: n.author?.username ?? '', createdAt: n.created_at ?? '', body: n.body ?? '' }));
|
|
97
|
+
}
|
|
98
|
+
export const gitlabDriver = {
|
|
99
|
+
host: 'gitlab',
|
|
100
|
+
async listIssues() {
|
|
101
|
+
const rows = await paged('issues?state=all&with_labels_details=true');
|
|
102
|
+
return Promise.all(rows.map(toIssue));
|
|
103
|
+
},
|
|
104
|
+
async listIssuesSince(sinceISO) {
|
|
105
|
+
const rows = await paged(`issues?state=all&with_labels_details=true&updated_after=${encodeURIComponent(sinceISO)}`);
|
|
106
|
+
return Promise.all(rows.map(toIssue));
|
|
107
|
+
},
|
|
108
|
+
async listPRs() {
|
|
109
|
+
const rows = await paged('merge_requests?state=opened');
|
|
110
|
+
return Promise.all(rows.map(async (r) => ({
|
|
111
|
+
number: r.iid,
|
|
112
|
+
title: r.title,
|
|
113
|
+
url: r.web_url,
|
|
114
|
+
state: normalizeState(r.state),
|
|
115
|
+
headRefName: r.source_branch,
|
|
116
|
+
closesIssues: (await paged(`merge_requests/${r.iid}/closes_issues`)).map((i) => i.iid),
|
|
117
|
+
})));
|
|
118
|
+
},
|
|
119
|
+
async createIssue({ title, body }) {
|
|
120
|
+
const r = await api('issues', {
|
|
121
|
+
method: 'POST',
|
|
122
|
+
body: JSON.stringify({ title, description: body }),
|
|
123
|
+
});
|
|
124
|
+
if (!r.web_url?.startsWith('http') || !Number.isFinite(r.iid))
|
|
125
|
+
throw new Error(`gitlab: issue create returned an unexpected result: ${JSON.stringify(r)}`);
|
|
126
|
+
return { number: r.iid, url: r.web_url };
|
|
127
|
+
},
|
|
128
|
+
async createComment({ number, body }) {
|
|
129
|
+
const { base, project } = gitlabCtx();
|
|
130
|
+
const r = await api(`issues/${number}/notes`, { method: 'POST', body: JSON.stringify({ body }) });
|
|
131
|
+
if (!Number.isFinite(r.id))
|
|
132
|
+
throw new Error(`gitlab: note create returned an unexpected result: ${JSON.stringify(r)}`);
|
|
133
|
+
return { url: `${base}/${project}/-/issues/${number}#note_${r.id}` };
|
|
134
|
+
},
|
|
135
|
+
async closeIssue({ number }) {
|
|
136
|
+
const r = await api(`issues/${number}`, {
|
|
137
|
+
method: 'PUT',
|
|
138
|
+
body: JSON.stringify({ state_event: 'close' }),
|
|
139
|
+
});
|
|
140
|
+
if (!r.web_url?.startsWith('http'))
|
|
141
|
+
throw new Error(`gitlab: issue close returned an unexpected result: ${JSON.stringify(r)}`);
|
|
142
|
+
return { url: r.web_url };
|
|
143
|
+
},
|
|
144
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ForgeDriver } from './port.js';
|
|
2
|
+
export declare const FORGE_DRIVERS: ForgeDriver[];
|
|
3
|
+
export declare const DEFAULT_FORGE_HOST = "github";
|
|
4
|
+
export declare function forgeDriverFor(host: string): ForgeDriver | undefined;
|
|
5
|
+
export declare function forgeIssueStores(): {
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
kind: 'forge';
|
|
9
|
+
}[];
|
|
10
|
+
export declare function resolveForgeHost(): string;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { githubDriver } from './drivers/github.js';
|
|
5
|
+
import { gitlabDriver } from './drivers/gitlab.js';
|
|
6
|
+
export const FORGE_DRIVERS = [githubDriver, gitlabDriver];
|
|
7
|
+
export const DEFAULT_FORGE_HOST = 'github';
|
|
8
|
+
export function forgeDriverFor(host) {
|
|
9
|
+
return FORGE_DRIVERS.find((d) => d.host === host);
|
|
10
|
+
}
|
|
11
|
+
export function forgeIssueStores() {
|
|
12
|
+
const driver = forgeDriverFor(resolveForgeHost());
|
|
13
|
+
return driver ? [{ id: driver.host, label: driver.host, kind: 'forge' }] : [];
|
|
14
|
+
}
|
|
15
|
+
function gitEnv() {
|
|
16
|
+
const env = { ...process.env };
|
|
17
|
+
delete env.GIT_DIR;
|
|
18
|
+
delete env.GIT_WORK_TREE;
|
|
19
|
+
delete env.GIT_INDEX_FILE;
|
|
20
|
+
delete env.GIT_OBJECT_DIRECTORY;
|
|
21
|
+
return env;
|
|
22
|
+
}
|
|
23
|
+
function gitOut(args) {
|
|
24
|
+
try {
|
|
25
|
+
return execFileSync('git', args, { env: gitEnv(), encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() || null;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function configuredHost() {
|
|
32
|
+
const root = gitOut(['rev-parse', '--show-toplevel']);
|
|
33
|
+
if (!root)
|
|
34
|
+
return null;
|
|
35
|
+
for (const name of ['spexcode.local.json', 'spexcode.json']) {
|
|
36
|
+
const p = join(root, name);
|
|
37
|
+
if (!existsSync(p))
|
|
38
|
+
continue;
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(readFileSync(p, 'utf8'));
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
throw new Error(`${p} is not valid JSON: ${e.message}`);
|
|
45
|
+
}
|
|
46
|
+
const host = parsed?.forge?.host;
|
|
47
|
+
if (typeof host === 'string' && host.trim())
|
|
48
|
+
return host.trim();
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function remoteHostname(url) {
|
|
53
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(url)) {
|
|
54
|
+
try {
|
|
55
|
+
return new URL(url).hostname || null;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const scp = /^(?:[^@\s/]+@)?([^:/\s]+):./.exec(url);
|
|
62
|
+
return scp ? scp[1] : null;
|
|
63
|
+
}
|
|
64
|
+
function hostFor(hostname) {
|
|
65
|
+
const h = hostname.toLowerCase();
|
|
66
|
+
if (h.includes('github'))
|
|
67
|
+
return 'github';
|
|
68
|
+
if (h.includes('bitbucket'))
|
|
69
|
+
return 'bitbucket';
|
|
70
|
+
return 'gitlab';
|
|
71
|
+
}
|
|
72
|
+
let cached = null;
|
|
73
|
+
const RESOLVE_TTL_MS = 30_000;
|
|
74
|
+
export function resolveForgeHost() {
|
|
75
|
+
const now = Date.now();
|
|
76
|
+
if (cached && now - cached.at < RESOLVE_TTL_MS)
|
|
77
|
+
return cached.host;
|
|
78
|
+
const url = gitOut(['remote', 'get-url', 'origin']);
|
|
79
|
+
const hostname = url ? remoteHostname(url) : null;
|
|
80
|
+
const host = configuredHost() ?? (hostname ? hostFor(hostname) : DEFAULT_FORGE_HOST);
|
|
81
|
+
cached = { host, at: now };
|
|
82
|
+
return host;
|
|
83
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ForgeIssue, ForgePR } from './port.js';
|
|
2
|
+
export type LinkedIssue = ForgeIssue & {
|
|
3
|
+
via: 'marker' | 'pr';
|
|
4
|
+
};
|
|
5
|
+
export type LinkedPR = ForgePR & {
|
|
6
|
+
via: 'branch';
|
|
7
|
+
};
|
|
8
|
+
export type NodeLinks = {
|
|
9
|
+
node: string;
|
|
10
|
+
issues: LinkedIssue[];
|
|
11
|
+
prs: LinkedPR[];
|
|
12
|
+
};
|
|
13
|
+
export declare function parseSpecMarkers(body: string): string[];
|
|
14
|
+
export declare function branchToNode(branch: string, nodeIds: string[]): string | null;
|
|
15
|
+
export declare function resolveLinks(issues: ForgeIssue[], prs: ForgePR[], nodeIds: string[]): NodeLinks[];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export function parseSpecMarkers(body) {
|
|
2
|
+
const ids = [];
|
|
3
|
+
for (const m of (body || '').matchAll(/^\s*spec:\s*(.+)$/gim)) {
|
|
4
|
+
for (const part of m[1].split(',')) {
|
|
5
|
+
const id = part.trim();
|
|
6
|
+
if (id)
|
|
7
|
+
ids.push(id);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return ids;
|
|
11
|
+
}
|
|
12
|
+
export function branchToNode(branch, nodeIds) {
|
|
13
|
+
if (!branch?.startsWith('node/'))
|
|
14
|
+
return null;
|
|
15
|
+
const rest = branch.slice('node/'.length);
|
|
16
|
+
let best = null;
|
|
17
|
+
for (const id of nodeIds) {
|
|
18
|
+
if (rest === id || rest.startsWith(id + '-')) {
|
|
19
|
+
if (!best || id.length > best.length)
|
|
20
|
+
best = id;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return best;
|
|
24
|
+
}
|
|
25
|
+
export function resolveLinks(issues, prs, nodeIds) {
|
|
26
|
+
const known = new Set(nodeIds);
|
|
27
|
+
const byNode = new Map();
|
|
28
|
+
const slot = (node) => {
|
|
29
|
+
let s = byNode.get(node);
|
|
30
|
+
if (!s) {
|
|
31
|
+
s = { issues: new Map(), prs: new Map() };
|
|
32
|
+
byNode.set(node, s);
|
|
33
|
+
}
|
|
34
|
+
return s;
|
|
35
|
+
};
|
|
36
|
+
const prNode = new Map();
|
|
37
|
+
for (const pr of prs) {
|
|
38
|
+
const node = branchToNode(pr.headRefName, nodeIds);
|
|
39
|
+
if (!node)
|
|
40
|
+
continue;
|
|
41
|
+
prNode.set(pr.number, node);
|
|
42
|
+
slot(node).prs.set(pr.number, { ...pr, via: 'branch' });
|
|
43
|
+
}
|
|
44
|
+
const issueByNumber = new Map(issues.map((i) => [i.number, i]));
|
|
45
|
+
for (const issue of issues) {
|
|
46
|
+
for (const id of parseSpecMarkers(issue.body)) {
|
|
47
|
+
if (known.has(id))
|
|
48
|
+
slot(id).issues.set(issue.number, { ...issue, via: 'marker' });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const pr of prs) {
|
|
52
|
+
const node = prNode.get(pr.number);
|
|
53
|
+
if (!node)
|
|
54
|
+
continue;
|
|
55
|
+
for (const num of pr.closesIssues) {
|
|
56
|
+
const issue = issueByNumber.get(num);
|
|
57
|
+
if (issue && !slot(node).issues.has(num)) {
|
|
58
|
+
slot(node).issues.set(num, { ...issue, via: 'pr' });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return [...byNode.entries()]
|
|
63
|
+
.map(([node, s]) => ({ node, issues: [...s.issues.values()], prs: [...s.prs.values()] }))
|
|
64
|
+
.sort((a, b) => a.node.localeCompare(b.node));
|
|
65
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ForgeIssue, ForgePR } from './port.js';
|
|
2
|
+
import { type LinkedIssue } from './links.js';
|
|
3
|
+
export declare const NEEDS_EVAL = "needs-eval";
|
|
4
|
+
export declare function isNeedsEval(issue: ForgeIssue): boolean;
|
|
5
|
+
export type EvalPending = LinkedIssue;
|
|
6
|
+
export type NodeEvalPending = {
|
|
7
|
+
node: string;
|
|
8
|
+
pending: EvalPending[];
|
|
9
|
+
};
|
|
10
|
+
export declare function resolveEvalPending(issues: ForgeIssue[], prs: ForgePR[], nodeIds: string[]): NodeEvalPending[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { resolveLinks } from './links.js';
|
|
2
|
+
export const NEEDS_EVAL = 'needs-eval';
|
|
3
|
+
const BODY_MARKER = new RegExp(`^\\s*${NEEDS_EVAL}\\s*:?\\s*$`, 'im');
|
|
4
|
+
export function isNeedsEval(issue) {
|
|
5
|
+
if (issue.labels.some((l) => l.name.trim().toLowerCase() === NEEDS_EVAL))
|
|
6
|
+
return true;
|
|
7
|
+
return BODY_MARKER.test(issue.body || '');
|
|
8
|
+
}
|
|
9
|
+
export function resolveEvalPending(issues, prs, nodeIds) {
|
|
10
|
+
const flagged = new Set(issues.filter(isNeedsEval).map((i) => i.number));
|
|
11
|
+
if (!flagged.size)
|
|
12
|
+
return [];
|
|
13
|
+
const out = [];
|
|
14
|
+
for (const { node, issues: linked } of resolveLinks(issues, prs, nodeIds)) {
|
|
15
|
+
const pending = linked.filter((i) => i.state === 'open' && flagged.has(i.number));
|
|
16
|
+
if (pending.length)
|
|
17
|
+
out.push({ node, pending });
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type ForgeComment = {
|
|
2
|
+
author: string;
|
|
3
|
+
createdAt: string;
|
|
4
|
+
body: string;
|
|
5
|
+
};
|
|
6
|
+
export type ForgeLabel = {
|
|
7
|
+
name: string;
|
|
8
|
+
color?: string;
|
|
9
|
+
textColor?: string;
|
|
10
|
+
};
|
|
11
|
+
export type ForgeIssue = {
|
|
12
|
+
number: number;
|
|
13
|
+
title: string;
|
|
14
|
+
body: string;
|
|
15
|
+
url: string;
|
|
16
|
+
state: string;
|
|
17
|
+
labels: ForgeLabel[];
|
|
18
|
+
author: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
comments: ForgeComment[];
|
|
21
|
+
};
|
|
22
|
+
export type ForgePR = {
|
|
23
|
+
number: number;
|
|
24
|
+
title: string;
|
|
25
|
+
url: string;
|
|
26
|
+
state: string;
|
|
27
|
+
headRefName: string;
|
|
28
|
+
closesIssues: number[];
|
|
29
|
+
};
|
|
30
|
+
export interface ForgeDriver {
|
|
31
|
+
readonly host: string;
|
|
32
|
+
listIssues(): Promise<ForgeIssue[]>;
|
|
33
|
+
listPRs(): Promise<ForgePR[]>;
|
|
34
|
+
createIssue(input: {
|
|
35
|
+
title: string;
|
|
36
|
+
body: string;
|
|
37
|
+
}): Promise<{
|
|
38
|
+
number: number;
|
|
39
|
+
url: string;
|
|
40
|
+
}>;
|
|
41
|
+
createComment(input: {
|
|
42
|
+
number: number;
|
|
43
|
+
body: string;
|
|
44
|
+
}): Promise<{
|
|
45
|
+
url: string;
|
|
46
|
+
}>;
|
|
47
|
+
closeIssue(input: {
|
|
48
|
+
number: number;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
url: string;
|
|
51
|
+
}>;
|
|
52
|
+
listIssuesSince?(sinceISO: string): Promise<ForgeIssue[]>;
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ForgeIssue, ForgePR } from './port.js';
|
|
2
|
+
export declare function residentForgeState(): {
|
|
3
|
+
issues: ForgeIssue[];
|
|
4
|
+
prs: ForgePR[];
|
|
5
|
+
};
|
|
6
|
+
export declare function residentForgeRevision(): number;
|
|
7
|
+
export declare function refreshForgeNow(): Promise<void>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ForgeCache } from './cache.js';
|
|
2
|
+
import { forgeDriverFor, resolveForgeHost } from './drivers.js';
|
|
3
|
+
const cache = new ForgeCache();
|
|
4
|
+
let inFlight = null;
|
|
5
|
+
let lastAttempt = 0;
|
|
6
|
+
const TTL_MS = 20_000;
|
|
7
|
+
let lastIssueSync = null;
|
|
8
|
+
let lastFull = 0;
|
|
9
|
+
const FULL_MS = 30 * 60_000;
|
|
10
|
+
function refreshIfStale(now) {
|
|
11
|
+
if (inFlight || (lastAttempt && now - lastAttempt < TTL_MS))
|
|
12
|
+
return;
|
|
13
|
+
const driver = forgeDriverFor(resolveForgeHost());
|
|
14
|
+
if (!driver)
|
|
15
|
+
return;
|
|
16
|
+
lastAttempt = now;
|
|
17
|
+
const startISO = new Date(now).toISOString(); // stamped at fetch START so an update during the fetch lands in the next window
|
|
18
|
+
const incremental = lastIssueSync && driver.listIssuesSince && now - lastFull < FULL_MS;
|
|
19
|
+
inFlight = (incremental
|
|
20
|
+
? Promise.all([
|
|
21
|
+
driver.listIssuesSince(lastIssueSync).then((delta) => cache.applyIssues(delta)),
|
|
22
|
+
driver.listPRs().then((prs) => cache.setPRs(prs)),
|
|
23
|
+
]).then(() => { lastIssueSync = startISO; })
|
|
24
|
+
: cache.reconcile(driver).then(() => { lastFull = now; lastIssueSync = startISO; }))
|
|
25
|
+
.catch(() => { })
|
|
26
|
+
.finally(() => { inFlight = null; });
|
|
27
|
+
}
|
|
28
|
+
export function residentForgeState() {
|
|
29
|
+
refreshIfStale(Date.now());
|
|
30
|
+
return cache.state();
|
|
31
|
+
}
|
|
32
|
+
export function residentForgeRevision() {
|
|
33
|
+
return cache.stateRevision();
|
|
34
|
+
}
|
|
35
|
+
export async function refreshForgeNow() {
|
|
36
|
+
if (inFlight)
|
|
37
|
+
await inFlight;
|
|
38
|
+
lastAttempt = 0;
|
|
39
|
+
lastFull = 0;
|
|
40
|
+
refreshIfStale(Date.now());
|
|
41
|
+
if (inFlight)
|
|
42
|
+
await inFlight;
|
|
43
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spexcode/spec-forge",
|
|
3
|
+
"version": "0.6.5",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./dist/index.js",
|
|
7
|
+
"./port": "./dist/port.js",
|
|
8
|
+
"./links": "./dist/links.js",
|
|
9
|
+
"./drivers": "./dist/drivers.js",
|
|
10
|
+
"./resident": "./dist/resident.js",
|
|
11
|
+
"./cli": "./dist/cli.js",
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"description": "Host-agnostic forge link tracer — reads a forge's open issues/PRs and resolves each to the spec node it serves (issue-body `Spec: <id>` marker + `node/<id>` PR branch). Read-only; a node's status stays git-derived.",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "node ../scripts/build-dist.mjs",
|
|
21
|
+
"prepublishOnly": "node ../scripts/release-publish.mjs --from-package-publish",
|
|
22
|
+
"test": "tsx --test src/*.test.ts"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@spexcode/spec-core": "0.6.5"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.16.0",
|
|
29
|
+
"tsx": "^4.19.2",
|
|
30
|
+
"typescript": "^5.6.3"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,42 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spexcode",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SpexCode — a spec-driven, self-developing dev tool. The `spex` CLI + spec server reads the .spec tree and its git history, and serves the dashboard.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
8
|
-
"spex": "
|
|
8
|
+
"spex": "bin/spex.mjs"
|
|
9
9
|
},
|
|
10
|
+
"workspaces": [
|
|
11
|
+
"packages/*",
|
|
12
|
+
"spec-cli",
|
|
13
|
+
"spec-eval",
|
|
14
|
+
"spec-forge",
|
|
15
|
+
"spec-dashboard"
|
|
16
|
+
],
|
|
10
17
|
"files": [
|
|
11
|
-
"
|
|
12
|
-
"!spec-cli/src/**/*.test.ts",
|
|
13
|
-
"spec-cli/bin",
|
|
14
|
-
"spec-cli/templates",
|
|
15
|
-
"spec-cli/hooks",
|
|
16
|
-
"spec-eval/src",
|
|
17
|
-
"!spec-eval/src/**/*.test.ts",
|
|
18
|
-
"spec-forge/src",
|
|
19
|
-
"!spec-forge/src/**/*.test.ts",
|
|
20
|
-
"spec-dashboard/dist",
|
|
21
|
-
"spec-dashboard/src/reviewFilters.js",
|
|
22
|
-
"spec-dashboard/src/reviewQuery.js",
|
|
23
|
-
"spec-dashboard/src/session.js",
|
|
24
|
-
"README.md"
|
|
18
|
+
"bin"
|
|
25
19
|
],
|
|
26
20
|
"engines": {
|
|
27
21
|
"node": ">=22"
|
|
28
22
|
},
|
|
29
23
|
"scripts": {
|
|
30
|
-
"
|
|
24
|
+
"build": "npm run build --workspace=@spexcode/spec-core && npm run build --workspace=@spexcode/spec-eval && npm run build --workspace=@spexcode/spec-forge && npm run build --workspace=@spexcode/spec-cli",
|
|
25
|
+
"api": "npm run build && node bin/spex.mjs serve",
|
|
31
26
|
"web": "cd spec-dashboard && npm run dev",
|
|
27
|
+
"build:public": "node scripts/public-graph-build.mjs",
|
|
28
|
+
"test:public-graph": "npm run build:public && node spec-dashboard/test/public-graph-static.e2e.mjs",
|
|
32
29
|
"lint": "node scripts/sync-init-plugins.mjs --check && cd spec-cli && npm run -s lint",
|
|
33
30
|
"sync:init-plugins": "node scripts/sync-init-plugins.mjs --write",
|
|
34
31
|
"test:init-plugins": "node --test scripts/sync-init-plugins.test.mjs",
|
|
32
|
+
"test:release-publish": "node --test scripts/release-publish.test.mjs",
|
|
33
|
+
"release:check": "node scripts/release-publish.mjs",
|
|
34
|
+
"release:publish": "node scripts/release-publish.mjs --publish",
|
|
35
|
+
"prepublishOnly": "node scripts/release-publish.mjs --from-package-publish",
|
|
36
|
+
"test:docs-release": "node --test scripts/docs-release.test.mjs scripts/reference-snapshot.test.mjs",
|
|
35
37
|
"hooks": "bash scripts/install-hooks.sh",
|
|
36
38
|
"prepack": "node scripts/sync-init-plugins.mjs --check && node scripts/prepack.mjs"
|
|
37
39
|
},
|
|
38
40
|
"dependencies": {
|
|
39
|
-
"
|
|
41
|
+
"@spexcode/spec-cli": "0.6.5"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
40
45
|
},
|
|
41
46
|
"optionalDependencies": {
|
|
42
47
|
"@hono/node-server": "^1.13.7",
|
|
@@ -47,5 +52,14 @@
|
|
|
47
52
|
"devDependencies": {
|
|
48
53
|
"@types/node": "^20.16.0",
|
|
49
54
|
"typescript": "^5.6.3"
|
|
50
|
-
}
|
|
55
|
+
},
|
|
56
|
+
"bundleDependencies": [
|
|
57
|
+
"@spexcode/spec-cli"
|
|
58
|
+
],
|
|
59
|
+
"main": "index.js",
|
|
60
|
+
"directories": {
|
|
61
|
+
"doc": "docs"
|
|
62
|
+
},
|
|
63
|
+
"keywords": [],
|
|
64
|
+
"author": ""
|
|
51
65
|
}
|
package/spec-cli/bin/spex.mjs
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// @@@ spex launcher - this repo has no build step, so the installed `spex` bin shells to tsx to
|
|
3
|
-
// run the TypeScript CLI directly. After `npm link` (or a global install) `spex lint` works anywhere.
|
|
4
|
-
import { spawn } from 'node:child_process'
|
|
5
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
6
|
-
import { createRequire } from 'node:module'
|
|
7
|
-
import { fileURLToPath } from 'node:url'
|
|
8
|
-
import { dirname, join } from 'node:path'
|
|
9
|
-
|
|
10
|
-
// @@@ self-contained - resolve tsx + cli from THIS package, not the cwd. A fresh worktree off main has
|
|
11
|
-
// no node_modules, so `npx tsx` there would try to install; using the package's own tsx makes a global
|
|
12
|
-
// `spex` work from any cwd (agents, git hooks) against this package's code, operating on the cwd.
|
|
13
|
-
const pkg = join(dirname(fileURLToPath(import.meta.url)), '..') // spec-cli/
|
|
14
|
-
const cli = join(pkg, 'src', 'cli.ts')
|
|
15
|
-
|
|
16
|
-
// @@@ mid-merge guard - no build step means every spex call parses this package's live TypeScript, so
|
|
17
|
-
// while a merge conflict is being resolved in the checkout that hosts it, the source holds conflict
|
|
18
|
-
// markers and tsx dies with a raw esbuild stacktrace — on EVERY call, including the Stop hook and an
|
|
19
|
-
// agent's `spex session done`. Catch that one transient state up front: scan the source trees the CLI
|
|
20
|
-
// imports (spec-cli ←→ spec-eval ←→ spec-forge), and if any file carries a marker, print one actionable
|
|
21
|
-
// line and exit 75 (EX_TEMPFAIL: transient, retry) instead of spawning tsx into the stacktrace.
|
|
22
|
-
const srcRoots = [join(pkg, 'src'), join(pkg, '..', 'spec-eval', 'src'), join(pkg, '..', 'spec-forge', 'src')]
|
|
23
|
-
const conflicted = srcRoots.flatMap((root) => {
|
|
24
|
-
if (!existsSync(root)) return []
|
|
25
|
-
return readdirSync(root, { recursive: true })
|
|
26
|
-
.filter((f) => /\.(ts|tsx|js|mjs)$/.test(String(f)))
|
|
27
|
-
.map((f) => join(root, String(f)))
|
|
28
|
-
.filter((path) => {
|
|
29
|
-
try { return /^<{7} /m.test(readFileSync(path, 'utf8')) } catch { return false }
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
if (conflicted.length) {
|
|
33
|
-
console.error('spex: paused mid-merge — unresolved conflict markers in the source spex runs:')
|
|
34
|
-
for (const f of conflicted) console.error(` ${f}`)
|
|
35
|
-
console.error('spex executes this TypeScript directly (no build step); resolve the merge, then retry. (exit 75)')
|
|
36
|
-
process.exit(75)
|
|
37
|
-
}
|
|
38
|
-
// @@@ cross-platform tsx resolution ([[platform-support]]) - resolve tsx's JS ENTRY (dist/cli.mjs) with
|
|
39
|
-
// Node's own resolver from spec-cli, then run it through THIS node binary (process.execPath). tsx may live
|
|
40
|
-
// in spec-cli/node_modules (dev) or be hoisted above the installed `spexcode` package (a real consumer
|
|
41
|
-
// project) — one resolver covers both without hardcoded consumer paths. We deliberately never spawn the
|
|
42
|
-
// `.bin/tsx` shim, nor a `.mjs` directly: on Windows the shim is an extensionless sh script and the `.mjs`
|
|
43
|
-
// leans on a shebang, neither of which `child_process.spawn` can execute — that is the #37 crash
|
|
44
|
-
// (`spawn …\node_modules\.bin\tsx ENOENT`) of `spex init`. `node dist/cli.mjs …` is shell-free and identical
|
|
45
|
-
// on every OS.
|
|
46
|
-
function resolveTsxCli() {
|
|
47
|
-
try {
|
|
48
|
-
const req = createRequire(join(pkg, 'package.json'))
|
|
49
|
-
return join(dirname(req.resolve('tsx/package.json')), 'dist', 'cli.mjs')
|
|
50
|
-
} catch {
|
|
51
|
-
console.error('spex: cannot find the `tsx` runtime this package needs — run `npm install` in the SpexCode package, then retry.')
|
|
52
|
-
process.exit(69)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const tsxCli = resolveTsxCli()
|
|
56
|
-
const args = process.argv.slice(2)
|
|
57
|
-
const env = { ...process.env }
|
|
58
|
-
// A backend/dashboard is a project or host control plane, never the managed session that happened to start
|
|
59
|
-
// it. Scrub before tsx starts: doing this inside cli.ts is too late because tsx's resident esbuild helper has
|
|
60
|
-
// already inherited the caller. New session launches provide the adapter-registry-derived key manifest; the
|
|
61
|
-
// fallback covers sessions created before that manifest existed.
|
|
62
|
-
if (args[0] === 'serve' || args[0] === 'dashboard') {
|
|
63
|
-
const identityKeys = (env.SPEXCODE_SESSION_IDENTITY_VARS
|
|
64
|
-
|| 'SPEXCODE_SESSION_ID,CLAUDE_CODE_SESSION_ID,CODEX_THREAD_ID,OPENCODE_SESSION_ID,PI_SESSION_ID')
|
|
65
|
-
.split(',').map((key) => key.trim()).filter(Boolean)
|
|
66
|
-
for (const key of identityKeys) delete env[key]
|
|
67
|
-
}
|
|
68
|
-
spawn(process.execPath, [tsxCli, cli, ...args], { stdio: 'inherit', env })
|
|
69
|
-
.on('exit', (code) => process.exit(code ?? 0))
|