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
package/spec-cli/src/init.ts
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, copyFileSync, readFileSync, readdirSync, renameSync, rmSync, statSync, chmodSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import { join, resolve, relative, dirname } from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
|
-
import { execFileSync } from 'node:child_process'
|
|
5
|
-
import { readConfig, readJsonConfig } from './layout.js'
|
|
6
|
-
import { resolveHarnessTargets, parseHarnessFlag, NATIVE_HARNESS_IDS } from './harness-select.js'
|
|
7
|
-
import { gitBinary } from './git.js'
|
|
8
|
-
|
|
9
|
-
// this file lives at <pkgRoot>/src/init.ts, so `..` is the package root — the same derivation the
|
|
10
|
-
// launch paths use, never a hardcoded repo path (so a relocated/installed package still finds its data).
|
|
11
|
-
const pkgRoot = fileURLToPath(new URL('..', import.meta.url))
|
|
12
|
-
const TEMPLATES = join(pkgRoot, 'templates')
|
|
13
|
-
const MANAGED_HOOK_HEADER = '# spexcode-managed-hook-v1'
|
|
14
|
-
|
|
15
|
-
function isManagedHook(path: string): boolean {
|
|
16
|
-
const source = readFileSync(path, 'utf8')
|
|
17
|
-
return source.split('\n').slice(0, 4).includes(MANAGED_HOOK_HEADER)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function replaceHook(source: string, dest: string): void {
|
|
21
|
-
const temp = `${dest}.spexcode-${process.pid}`
|
|
22
|
-
try {
|
|
23
|
-
copyFileSync(source, temp)
|
|
24
|
-
chmodSync(temp, 0o755)
|
|
25
|
-
renameSync(temp, dest)
|
|
26
|
-
} finally {
|
|
27
|
-
rmSync(temp, { force: true })
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// the cumulative preset chain, lean → cautious (see [[init-preset]]). `default` is the live `.plugins`
|
|
32
|
-
// instance set (planted from templates/spec); a higher tier would be a SEPARATE package under
|
|
33
|
-
// templates/presets/<tier>/ that seeding stacks ON TOP — a superset. No non-default tier ships today
|
|
34
|
-
// (the `careful` package was retired); the chain mechanism stays for when one earns its keep.
|
|
35
|
-
// Selection matters ONLY here at seed time; the running repo just
|
|
36
|
-
// walks whatever `.plugins` ended up planted, so there is no launcher-side preset gate.
|
|
37
|
-
const PRESET_TIERS = ['default'] as const
|
|
38
|
-
const presetRank = (name: string): number => (PRESET_TIERS as readonly string[]).indexOf(name)
|
|
39
|
-
|
|
40
|
-
// recursively copy srcDir -> destDir, NEVER overwriting an existing file. Returns the repo-relative
|
|
41
|
-
// paths of files actually written (so the caller can report exactly what was planted vs already there).
|
|
42
|
-
function copyTreeNoClobber(srcDir: string, destDir: string, base: string): string[] {
|
|
43
|
-
const written: string[] = []
|
|
44
|
-
mkdirSync(destDir, { recursive: true })
|
|
45
|
-
for (const e of readdirSync(srcDir, { withFileTypes: true })) {
|
|
46
|
-
const src = join(srcDir, e.name)
|
|
47
|
-
const dest = join(destDir, e.name)
|
|
48
|
-
if (e.isDirectory()) {
|
|
49
|
-
written.push(...copyTreeNoClobber(src, dest, base))
|
|
50
|
-
} else if (existsSync(dest)) {
|
|
51
|
-
// additive only — a pre-existing file is the user's, leave it untouched.
|
|
52
|
-
continue
|
|
53
|
-
} else {
|
|
54
|
-
copyFileSync(src, dest)
|
|
55
|
-
written.push(relative(base, dest))
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return written
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// resolve the target repo's git hooks dir the same way scripts/install-hooks.sh does — the COMMON dir's
|
|
62
|
-
// hooks/ (shared across all worktrees). Returns null (with a loud reason) when <dir> isn't a git repo.
|
|
63
|
-
function resolveHooksDir(dir: string): string | null {
|
|
64
|
-
try {
|
|
65
|
-
const common = execFileSync(gitBinary(process.env), ['-C', dir, 'rev-parse', '--path-format=absolute', '--git-common-dir'], {
|
|
66
|
-
encoding: 'utf8',
|
|
67
|
-
stdio: ['ignore', 'pipe', 'ignore'], // swallow git's own "fatal: not a git repository" — our warning is the signal
|
|
68
|
-
}).trim()
|
|
69
|
-
return join(common, 'hooks')
|
|
70
|
-
} catch {
|
|
71
|
-
return null
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Detect once, at adoption, while the root checkout still names the branch being adopted. Steady-state
|
|
76
|
-
// layout never re-derives trunk identity from a mutable checkout (an ordinary `git switch node/x` must not
|
|
77
|
-
// turn that feature branch into trunk).
|
|
78
|
-
function adoptionMainBranch(dir: string): string {
|
|
79
|
-
try {
|
|
80
|
-
const common = execFileSync(gitBinary(process.env), ['-C', dir, 'rev-parse', '--path-format=absolute', '--git-common-dir'], { encoding: 'utf8' }).trim()
|
|
81
|
-
const branch = execFileSync(gitBinary(process.env), ['-C', dirname(common), 'symbolic-ref', '--short', 'HEAD'], { encoding: 'utf8' }).trim()
|
|
82
|
-
if (branch) return branch
|
|
83
|
-
} catch { /* render the one product-level repair below */ }
|
|
84
|
-
const error = new Error('cannot determine the source-of-truth branch at adoption — check out the trunk in the root checkout, or set "mainBranch" in spexcode.json before re-running `spex init`')
|
|
85
|
-
error.name = 'ConfigError'
|
|
86
|
-
throw error
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export async function specInit(targetArg: string | undefined, presetArg?: string, harnessArg?: string): Promise<void> {
|
|
90
|
-
const targetDir = resolve(targetArg ?? process.cwd())
|
|
91
|
-
|
|
92
|
-
// the preset the NEW adopter gets — `--preset <name>` wins, else an existing target spexcode.json's
|
|
93
|
-
// `preset` field, else the lean `default`. Validated loudly against the chain (an unknown name would
|
|
94
|
-
// otherwise seed silently). A non-default tier stacks its template package on top of the default set below.
|
|
95
|
-
const selected = (presetArg ?? '').trim() || (readConfig(targetDir).preset ?? '').trim() || 'default'
|
|
96
|
-
if (!(PRESET_TIERS as readonly string[]).includes(selected)) {
|
|
97
|
-
console.error(`spex init: unknown preset '${selected}'. Valid presets (cumulative, lean→cautious): ${PRESET_TIERS.join(', ')}.`)
|
|
98
|
-
process.exit(1)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// SpexCode is git-backed: git IS the version database and the hooks live in `.git`. A non-git target
|
|
102
|
-
// would leave a HALF-STATE — specs on disk but no version history, no hooks, no harness shims, no
|
|
103
|
-
// sessions. So fail LOUD before writing anything, rather than seeding debris and warning past it. We do
|
|
104
|
-
// NOT `git init` for them: creating a repo is a side effect beyond init's remit (a subdir, a dir not
|
|
105
|
-
// meant as a repo root), and `git init` is one deliberate command.
|
|
106
|
-
try {
|
|
107
|
-
execFileSync(gitBinary(process.env), ['-C', targetDir, 'rev-parse', '--is-inside-work-tree'], { stdio: ['ignore', 'ignore', 'ignore'] })
|
|
108
|
-
} catch {
|
|
109
|
-
console.error(`spex init: ${targetDir} is not a git repository. SpexCode is git-backed (git is the version database; the hooks live in .git). Run \`git init\` there first, then \`spex init\`.`)
|
|
110
|
-
process.exit(1)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// the harness DELIVERY TARGET set ([[harness-select]]) is a REQUIRED, explicit choice — `--harness <ids>`
|
|
114
|
-
// stamps it into spexcode.json; absent the flag, a pre-existing explicit `harnesses` field IS the choice.
|
|
115
|
-
// Neither → abort BEFORE writing anything: with many harnesses, a silent "deliver to all" would litter the
|
|
116
|
-
// adopter's tree (and global tool configs) with artifacts for harnesses they never installed. Legality
|
|
117
|
-
// (unknown ids, plugin exclusivity, empty set) fails loud here too, not as a soft materialize warning.
|
|
118
|
-
const flagRaw = (harnessArg ?? '').trim() ? parseHarnessFlag(harnessArg!.trim()) : null
|
|
119
|
-
const chosenHarnesses = flagRaw ?? readConfig(targetDir).harnesses ?? null
|
|
120
|
-
if (chosenHarnesses === null) {
|
|
121
|
-
console.error(`spex init: --harness is required — name the harness(es) this repo delivers into, e.g. \`spex init --harness claude\`. Known native ids: ${NATIVE_HARNESS_IDS.join(', ')} (comma-separate several; a plugin bundle: --harness plugin:<folder>). A pre-existing spexcode.json "harnesses" field also satisfies this.`)
|
|
122
|
-
process.exit(1)
|
|
123
|
-
}
|
|
124
|
-
try {
|
|
125
|
-
resolveHarnessTargets(chosenHarnesses)
|
|
126
|
-
} catch (e) {
|
|
127
|
-
console.error(`spex init: ${(e as Error).message}`)
|
|
128
|
-
process.exit(1)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true })
|
|
132
|
-
console.log(`spex init → ${targetDir}`)
|
|
133
|
-
|
|
134
|
-
// 1. seed the spec tree: templates/spec/* -> <dir>/.spec/* (an existing .spec aborts this phase loudly).
|
|
135
|
-
const specDest = join(targetDir, '.spec')
|
|
136
|
-
if (existsSync(specDest)) {
|
|
137
|
-
console.warn(`• .spec already exists at ${specDest} — skipping spec scaffold (won't overwrite an existing tree).`)
|
|
138
|
-
} else {
|
|
139
|
-
const planted = copyTreeNoClobber(join(TEMPLATES, 'spec'), specDest, targetDir)
|
|
140
|
-
console.log(`✓ seeded ${planted.length} spec file(s) under .spec/ (root 'project' node + default .plugins)`)
|
|
141
|
-
// 1a. stack the selected preset's package(s) ON TOP of the default set — cumulative, so every tier from
|
|
142
|
-
// just above `default` up to the selection is planted. Each lives under templates/presets/<tier>/ mirroring
|
|
143
|
-
// the default layout (its `.plugins/<plugin>` lands in the seeded project node's `.plugins`). See [[init-preset]].
|
|
144
|
-
for (let r = 1; r <= presetRank(selected); r++) {
|
|
145
|
-
const tier = PRESET_TIERS[r]
|
|
146
|
-
const pkg = join(TEMPLATES, 'presets', tier)
|
|
147
|
-
if (!existsSync(pkg)) { console.warn(`• preset '${tier}' has no package at ${pkg} — skipped.`); continue }
|
|
148
|
-
const added = copyTreeNoClobber(pkg, join(specDest, 'project'), targetDir)
|
|
149
|
-
console.log(`✓ seeded preset '${tier}' (${added.length} file(s)) into .plugins`)
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// 1b. plant a starter spexcode.json (the lint/layout knob) carrying the CHOSEN `harnesses` set. The
|
|
154
|
-
// template ships launchers for every native harness; seeding keeps only the SELECTED ones (a launcher for
|
|
155
|
-
// a tool the adopter didn't pick is exactly the litter --harness exists to prevent) — a plugin-only
|
|
156
|
-
// selection keeps them all, since the bundle serves the HOST agent while dispatched sessions still need a
|
|
157
|
-
// launcher. The success message reports values read back from the planted file, never restated literals.
|
|
158
|
-
const cfgDest = join(targetDir, 'spexcode.json')
|
|
159
|
-
const nativeChosen = (chosenHarnesses as unknown[]).filter((m): m is string => typeof m === 'string')
|
|
160
|
-
if (existsSync(cfgDest)) {
|
|
161
|
-
const cfg = (readJsonConfig(cfgDest) ?? {}) as Record<string, unknown>
|
|
162
|
-
const stampedBranch = typeof cfg.mainBranch !== 'string' || !cfg.mainBranch.trim()
|
|
163
|
-
if (stampedBranch) cfg.mainBranch = adoptionMainBranch(targetDir)
|
|
164
|
-
if (flagRaw) cfg.harnesses = flagRaw
|
|
165
|
-
if (flagRaw || stampedBranch) {
|
|
166
|
-
writeFileSync(cfgDest, JSON.stringify(cfg, null, 2) + '\n')
|
|
167
|
-
console.log(`✓ stamped ${[
|
|
168
|
-
flagRaw ? `"harnesses": ${JSON.stringify(flagRaw)}` : '',
|
|
169
|
-
stampedBranch ? `"mainBranch": ${JSON.stringify(cfg.mainBranch)}` : '',
|
|
170
|
-
].filter(Boolean).join(' and ')} into the existing spexcode.json (other fields untouched)`)
|
|
171
|
-
} else {
|
|
172
|
-
console.warn(`• spexcode.json already exists at ${cfgDest} — left untouched (harnesses: ${JSON.stringify(chosenHarnesses)}).`)
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
const cfg = (readJsonConfig(join(TEMPLATES, 'spexcode.json')) ?? {}) as Record<string, any>
|
|
176
|
-
cfg.harnesses = chosenHarnesses
|
|
177
|
-
cfg.mainBranch = adoptionMainBranch(targetDir)
|
|
178
|
-
if (nativeChosen.length && cfg.sessions?.launchers) {
|
|
179
|
-
cfg.sessions.launchers = Object.fromEntries(
|
|
180
|
-
Object.entries(cfg.sessions.launchers as Record<string, { harness?: string }>).filter(([, l]) => nativeChosen.includes(l.harness ?? 'claude')))
|
|
181
|
-
const names = Object.keys(cfg.sessions.launchers)
|
|
182
|
-
if (names.length) cfg.sessions.defaultLauncher = names[0]
|
|
183
|
-
}
|
|
184
|
-
writeFileSync(cfgDest, JSON.stringify(cfg, null, 2) + '\n')
|
|
185
|
-
const roots = JSON.stringify(readJsonConfig(cfgDest)?.lint?.governedRoots ?? null)
|
|
186
|
-
console.log(`✓ planted spexcode.json — mainBranch ${JSON.stringify(cfg.mainBranch)}, harnesses ${JSON.stringify(chosenHarnesses)}, launchers ${JSON.stringify(Object.keys(cfg.sessions?.launchers ?? {}))}; lint.governedRoots starts as ${roots} (the whole git-tracked tree, tests excluded)`)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 2. install the git hooks. Unknown existing hooks are user-owned and stay byte-identical. An exact
|
|
190
|
-
// SpexCode snapshot is refreshed because a multi-hook protocol cannot mix old and new generations.
|
|
191
|
-
const hooksDir = resolveHooksDir(targetDir)
|
|
192
|
-
if (!hooksDir) {
|
|
193
|
-
console.warn(`• ${targetDir} is not a git repository — skipped hook install. Run \`git init\` there, then \`spex init\` again (or \`npm run hooks\`).`)
|
|
194
|
-
} else {
|
|
195
|
-
mkdirSync(hooksDir, { recursive: true })
|
|
196
|
-
const hooksSrc = join(TEMPLATES, 'hooks')
|
|
197
|
-
const installed: string[] = []
|
|
198
|
-
const refreshed: string[] = []
|
|
199
|
-
for (const e of readdirSync(hooksSrc, { withFileTypes: true })) {
|
|
200
|
-
if (!e.isFile()) continue
|
|
201
|
-
const source = join(hooksSrc, e.name)
|
|
202
|
-
const dest = join(hooksDir, e.name)
|
|
203
|
-
if (existsSync(dest)) {
|
|
204
|
-
if (readFileSync(dest).equals(readFileSync(source))) continue
|
|
205
|
-
if (isManagedHook(dest)) {
|
|
206
|
-
replaceHook(source, dest)
|
|
207
|
-
refreshed.push(e.name)
|
|
208
|
-
} else {
|
|
209
|
-
console.warn(`• user hook ${e.name} already exists in ${hooksDir} — left untouched.`)
|
|
210
|
-
}
|
|
211
|
-
continue
|
|
212
|
-
}
|
|
213
|
-
copyFileSync(source, dest)
|
|
214
|
-
chmodSync(dest, 0o755)
|
|
215
|
-
installed.push(e.name)
|
|
216
|
-
}
|
|
217
|
-
if (installed.length) console.log(`✓ installed git hooks (${installed.join(', ')}) → ${hooksDir}`)
|
|
218
|
-
if (refreshed.length) console.log(`✓ refreshed SpexCode hook snapshots (${refreshed.join(', ')}) → ${hooksDir}`)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// 2c. MATERIALIZE the harness-discovered artifacts so a USER-self-launched harness works with zero further
|
|
222
|
-
// steps. Runs with cwd = the target so the loaders read the just-seeded
|
|
223
|
-
// .plugins. Idempotent — the planted git hooks (pre-commit/post-checkout/post-merge) keep it fresh
|
|
224
|
-
// thereafter on the git-native anchors ([[commit-surgery]]); no harness event ever triggers a materialize.
|
|
225
|
-
const prevCwd = process.cwd()
|
|
226
|
-
try {
|
|
227
|
-
process.chdir(targetDir)
|
|
228
|
-
const { materialize } = await import('./materialize.js')
|
|
229
|
-
const result = materialize(targetDir)
|
|
230
|
-
const display = (path: string) => {
|
|
231
|
-
const local = relative(targetDir, path)
|
|
232
|
-
return local && local !== '..' && !local.startsWith('../') && !local.startsWith('..\\') ? local : path
|
|
233
|
-
}
|
|
234
|
-
console.log(`✓ materialized harness artifacts (${result.planted.map((a) => `${a.kind}: ${display(a.path)}`).join(', ')})`)
|
|
235
|
-
} catch (e) {
|
|
236
|
-
console.warn(`• materialize skipped (${(e as Error).message}) — run \`spex materialize\` once the packages are installed.`)
|
|
237
|
-
} finally {
|
|
238
|
-
process.chdir(prevCwd)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// 3. next steps — what the human must do to bring the instance to life. The governedRoots line reads the
|
|
242
|
-
// LIVE value (the planted starter's, or a pre-existing config's) so it can never drift from what's on disk.
|
|
243
|
-
const rootsNow = JSON.stringify(readJsonConfig(cfgDest)?.lint?.governedRoots ?? null)
|
|
244
|
-
console.log(`
|
|
245
|
-
Next steps:
|
|
246
|
-
1. The seeded .spec/ tree and spexcode.json are project source of truth: add and commit them. Generated
|
|
247
|
-
harness artifacts are machine-local and can stay untracked.
|
|
248
|
-
2. Edit .spec/project/spec.md to describe YOUR project, then grow child nodes beneath it.
|
|
249
|
-
3. lint.governedRoots in spexcode.json (currently ${rootsNow}) names what \`spex spec lint\` governs —
|
|
250
|
-
["."] governs the whole git-tracked tree (tests excluded); narrow it to explicit source roots
|
|
251
|
-
when you want a curated graph.
|
|
252
|
-
4. Start the backend and open the dashboard:
|
|
253
|
-
spex serve # http://localhost:8787
|
|
254
|
-
5. \`spex spec lint\` should report 0 errors. Coverage warnings are your adoption TODO (source files no
|
|
255
|
-
spec node claims yet). You're adopting SpexCode — the spec tree is now ground truth.
|
|
256
|
-
(On a fresh CLONE, re-run \`spex init\` — git never clones .git/hooks/, and the harness shims are
|
|
257
|
-
gitignored machine-local files that regenerate per-machine.)`)
|
|
258
|
-
}
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs'
|
|
2
|
-
import { closeIssue, createIssue, findIssue, isRemark, mergedIssues, promote, type ForgeSlice, type Issue } from './issues.js'
|
|
3
|
-
import { FORGE_DRIVERS, forgeDriverFor, resolveForgeHost } from '../../spec-forge/src/drivers.js'
|
|
4
|
-
import { currentSession, issuesEnabled, reply, resolveRemark, retractRemark } from './localIssues.js'
|
|
5
|
-
import { summarizeLoopIn } from './mentions.js'
|
|
6
|
-
import { loadSpecsLite } from './specs.js'
|
|
7
|
-
|
|
8
|
-
// @@@ issues-cli - the `spex issue` / `spex remark` CLI surface: argv parsing, console output, exit codes.
|
|
9
|
-
// It lives ABOVE the eval layer, which is the whole point. These handlers used to sit in `issues.ts` and
|
|
10
|
-
// `localIssues.ts` — modules the eval package imports — and a CLI surface is by definition the topmost layer,
|
|
11
|
-
// so hosting one down there gave those files two altitudes at once. That is what held the spec/eval package
|
|
12
|
-
// cycle: the loop-in's candidate resolution needs eval knowledge, its only callers were these handlers, and
|
|
13
|
-
// they could not reach eval from below it. Nothing here is new logic; it is the same surface at its own height.
|
|
14
|
-
//
|
|
15
|
-
// It is NOT merged into `cli.ts`: that file is the thin dispatch hub ([[cli-surface]]) whose eighty lazy
|
|
16
|
-
// `await import(...)` sites keep one invocation from loading every verb's module. Moving 265 lines of verb
|
|
17
|
-
// implementation there would have traded one two-altitude module for another. The hub gains one lazy line
|
|
18
|
-
// pointing here instead.
|
|
19
|
-
|
|
20
|
-
const fl = (args: string[], name: string): string | undefined => {
|
|
21
|
-
const i = args.indexOf(`--${name}`)
|
|
22
|
-
return i >= 0 ? args[i + 1] : undefined
|
|
23
|
-
}
|
|
24
|
-
const hasFlag = (args: string[], name: string) => args.includes(`--${name}`)
|
|
25
|
-
|
|
26
|
-
// the CLI's live forge pull — `ls` and `show` own their freshness (a live driver read), degrading LOUDLY
|
|
27
|
-
// to local-only (one stderr note) when the forge is unreachable: local reading never hostages on a network.
|
|
28
|
-
async function liveForgeSlice(verb: string): Promise<ForgeSlice | null> {
|
|
29
|
-
try {
|
|
30
|
-
const host = resolveForgeHost()
|
|
31
|
-
const driver = forgeDriverFor(host)
|
|
32
|
-
if (!driver) throw new Error(`no driver for this repo's forge host '${host}' (known: ${FORGE_DRIVERS.map((d) => d.host).join(', ')})`)
|
|
33
|
-
const [issues, prs] = await Promise.all([driver.listIssues(), driver.listPRs()])
|
|
34
|
-
return { host: driver.host, state: { issues, prs } }
|
|
35
|
-
} catch (e) {
|
|
36
|
-
console.error(`spex issue ${verb}: forge unreachable — local only (${e instanceof Error ? e.message.split('\n')[0] : e})`)
|
|
37
|
-
return null
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// the single-issue read behind `spex issue show` AND `GET /api/issues/:id` — find the thread in the SAME
|
|
42
|
-
// merged, eval-remark-free read every issue surface consumes (never a second lookup path: an eval-remark
|
|
43
|
-
// thread is not an issue, so `show` can't see one either). A local id needs no forge slice; a forge id
|
|
44
|
-
// (`<host>#<n>`) reads from the caller-supplied slice (live pull on the CLI, resident cache on the server).
|
|
45
|
-
|
|
46
|
-
function renderIssue(t: Issue): string {
|
|
47
|
-
const L: string[] = []
|
|
48
|
-
L.push(`${t.concern} [${t.id}]`)
|
|
49
|
-
L.push(` ${[t.store, t.status, t.nodes.length ? `re: ${t.nodes.join(', ')}` : '', t.by ? `by ${t.by}` : '', t.created].filter(Boolean).join(' · ')}`)
|
|
50
|
-
if (t.url) L.push(` ${t.url}`)
|
|
51
|
-
if (t.evidence.length) L.push(` evidence: ${t.evidence.join(', ')}`)
|
|
52
|
-
L.push('', t.body)
|
|
53
|
-
for (const r of t.replies) {
|
|
54
|
-
L.push('', `── ${isRemark(r) ? `remark ${t.id}#${r.rid}${r.resolved ? ` (resolved by ${r.resolvedBy})` : ' (unresolved)'}` : 'reply'}: ${r.by} @ ${r.at} ──`)
|
|
55
|
-
L.push(r.body)
|
|
56
|
-
}
|
|
57
|
-
return L.join('\n')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// `spex issue <verb>` — the ONE issue surface, a noun drawer ([[cli-surface]]). `ls` is THE read over
|
|
61
|
-
// every store: the drain view a supervisor/human works from, `[--node id] [--store local|<host>] [--all]
|
|
62
|
-
// [--json]`; `show <id>` is the single-thread detail (the same read GET /api/issues/:id serves). The
|
|
63
|
-
// write verbs (open|reply — localIssues.ts) are store-routed (`open --store <host>` / a `<host>#<n>` id
|
|
64
|
-
// go through the driver); `close` is the store-routed lifecycle verb (the SAME closeIssue the dashboard's
|
|
65
|
-
// Close button calls); `promote` is the one cross-store verb; `links` is the read-only forge→spec trace
|
|
66
|
-
// (spec-forge). The list imposes NO salience ranking — replies are a signal the drain WEIGHS by judgment,
|
|
67
|
-
// never an automatic priority order. The forge slice is a LIVE pull that degrades loudly to local-only.
|
|
68
|
-
// (`nudge` left this drawer for `spex internal nudge` — only the post-merge hook calls it; the old
|
|
69
|
-
// on|off|status toggle verbs are gone — the switch is the `issues.enabled` settings key.)
|
|
70
|
-
export async function runIssues(args: string[]): Promise<number> {
|
|
71
|
-
// the drawer's READ verbs (ls/show) surface a store failure exactly as the writes do
|
|
72
|
-
// ([[issues-store-rename]]'s both-exist teeth): one clean `spex issue: <message>` line + exit 1, never a
|
|
73
|
-
// raw stack — the message carries the repair, the stack is internals. The verbs that already catch with
|
|
74
|
-
// a more specific prefix (open/reply/close/promote) return before this guard ever sees their errors.
|
|
75
|
-
try { return await issueVerbs(args) }
|
|
76
|
-
catch (e) { console.error(`spex issue: ${e instanceof Error ? e.message : e}`); return 1 }
|
|
77
|
-
}
|
|
78
|
-
async function issueVerbs(args: string[]): Promise<number> {
|
|
79
|
-
if (ISSUE_WRITE_SUBS.has(args[0])) return runIssueWrite(args)
|
|
80
|
-
if (args[0] === 'on' || args[0] === 'off' || args[0] === 'status') {
|
|
81
|
-
// v0.3.0 signpost — report the new home, never run ([[cli-surface]]: a removed spelling only points).
|
|
82
|
-
console.error(`spex: \`spex issue ${args[0]}\` was removed in v0.3.0 — the switch is the \`issues.enabled\` key in spexcode.json (edit the JSON; \`spex guide settings\` documents it, \`spex doctor\` reports its state)`)
|
|
83
|
-
return 2
|
|
84
|
-
}
|
|
85
|
-
if (args[0] === 'show') {
|
|
86
|
-
const id = args[1]
|
|
87
|
-
if (!id || id.startsWith('--')) { console.error('usage: spex issue show <issue-id> [--json] (a local id, or a forge id like github#12)'); return 2 }
|
|
88
|
-
const nodeIds = loadSpecsLite().map((s) => s.id)
|
|
89
|
-
const t = findIssue(id, id.includes('#') ? await liveForgeSlice('show') : null, nodeIds)
|
|
90
|
-
if (!t) { console.error(`spex issue show: no issue '${id}' (see \`spex issue ls --all\`)`); return 1 }
|
|
91
|
-
console.log(hasFlag(args, 'json') ? JSON.stringify(t, null, 2) : renderIssue(t))
|
|
92
|
-
return 0
|
|
93
|
-
}
|
|
94
|
-
if (args[0] === 'links') {
|
|
95
|
-
const { runIssueLinks } = await import('../../spec-forge/src/cli.js')
|
|
96
|
-
return runIssueLinks(args.slice(1))
|
|
97
|
-
}
|
|
98
|
-
if (args[0] === 'close') {
|
|
99
|
-
// the CLI leg of the ONE close verb ([[issues]] closeIssue — the same routing POST /api/issues/:id/close
|
|
100
|
-
// runs): a local id resolves the thread `landed`, a forge id (`<host>#<n>`) closes the remote issue
|
|
101
|
-
// through the driver. Lifecycle on the issue object, never node state.
|
|
102
|
-
const id = args[1]
|
|
103
|
-
if (!id || id.startsWith('--')) { console.error('usage: spex issue close <issue-id> (a local id, or a forge id like github#12)'); return 2 }
|
|
104
|
-
try {
|
|
105
|
-
const r = await closeIssue(id)
|
|
106
|
-
console.log(r.store === 'local'
|
|
107
|
-
? `closed '${id}' — local thread landed`
|
|
108
|
-
: `closed '${id}' on ${r.store}${r.url ? ` ${r.url}` : ''}`)
|
|
109
|
-
return 0
|
|
110
|
-
} catch (e) {
|
|
111
|
-
console.error(`spex issue close: ${e instanceof Error ? e.message : e}`)
|
|
112
|
-
return 1
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (args[0] === 'promote') {
|
|
116
|
-
const id = args[1]
|
|
117
|
-
if (!id || id.startsWith('--')) { console.error('usage: spex issue promote <local-issue-id>'); return 2 }
|
|
118
|
-
try {
|
|
119
|
-
const r = await promote(id)
|
|
120
|
-
console.log(`promoted '${id}' → ${r.host}#${r.number} ${r.url}\n local thread closed landed (permalink recorded in its reply trail)`)
|
|
121
|
-
return 0
|
|
122
|
-
} catch (e) {
|
|
123
|
-
console.error(`spex issue promote: ${e instanceof Error ? e.message : e}`)
|
|
124
|
-
return 1
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
if (args[0] !== 'ls') {
|
|
128
|
-
console.error(`spex issue: unknown verb '${args[0]}' — ls | show | open | reply | close | promote | links (spex help issue)`)
|
|
129
|
-
return 2
|
|
130
|
-
}
|
|
131
|
-
args = args.slice(1)
|
|
132
|
-
const nodeIds = loadSpecsLite().map((s) => s.id)
|
|
133
|
-
const forge = await liveForgeSlice('ls')
|
|
134
|
-
let issues = mergedIssues(forge, nodeIds)
|
|
135
|
-
const node = fl(args, 'node')
|
|
136
|
-
const store = fl(args, 'store')
|
|
137
|
-
if (node) issues = issues.filter((p) => p.nodes.includes(node))
|
|
138
|
-
if (store) issues = issues.filter((p) => p.store === store)
|
|
139
|
-
if (!hasFlag(args, 'all')) issues = issues.filter((p) => p.status === 'open')
|
|
140
|
-
if (hasFlag(args, 'json')) { console.log(JSON.stringify(issues, null, 2)); return 0 }
|
|
141
|
-
if (!issues.length) { console.log(node ? `no issues for node '${node}'` : 'no open issues'); return 0 }
|
|
142
|
-
console.log(`issues — ${issues.length} ${hasFlag(args, 'all') ? 'total' : 'open'}${store ? ` in '${store}'` : ''}${node ? ` for '${node}'` : ''}\n`)
|
|
143
|
-
for (const p of issues) {
|
|
144
|
-
const tags = [p.store, p.status !== 'open' ? `[${p.status}]` : '', p.nodes.length ? `re: ${p.nodes.join(', ')}` : '', p.by ? `by ${p.by}` : ''].filter(Boolean).join(' · ')
|
|
145
|
-
console.log(`• ${p.concern} [${p.id}]`)
|
|
146
|
-
console.log(` ${tags}`)
|
|
147
|
-
if (p.replies.length) console.log(` ${p.replies.length} reply(ies) in thread`)
|
|
148
|
-
if (p.url) console.log(` ${p.url}`)
|
|
149
|
-
}
|
|
150
|
-
if (!issuesEnabled()) console.log('\n(the issues workflow is OFF — set `"issues": { "enabled": true }` in spexcode.json to re-enable writes/nudges)')
|
|
151
|
-
return 0
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const VALUE_FLAGS = new Set(['--node', '--body', '--evidence', '--scenario', '--code-sha', '--store'])
|
|
155
|
-
// bare positionals, skipping flags + their values.
|
|
156
|
-
function bare(args: string[]): string[] {
|
|
157
|
-
const out: string[] = []
|
|
158
|
-
for (let i = 0; i < args.length; i++) {
|
|
159
|
-
const t = args[i]
|
|
160
|
-
if (t.startsWith('--')) { if (VALUE_FLAGS.has(t)) i++; continue }
|
|
161
|
-
out.push(t)
|
|
162
|
-
}
|
|
163
|
-
return out
|
|
164
|
-
}
|
|
165
|
-
// `--body -` reads stdin; `--body "text"` is literal; absent → undefined.
|
|
166
|
-
function readBody(args: string[]): string | undefined {
|
|
167
|
-
const v = fl(args, 'body')
|
|
168
|
-
if (v === undefined) return undefined
|
|
169
|
-
return v === '-' ? readFileSync(0, 'utf8') : v
|
|
170
|
-
}
|
|
171
|
-
// a repeatable value flag: every `--<name> <value>` pair, in order.
|
|
172
|
-
const repeated = (args: string[], name: string): string[] =>
|
|
173
|
-
args.flatMap((a, i) => (a === `--${name}` ? [args[i + 1]] : [])).filter(Boolean) as string[]
|
|
174
|
-
|
|
175
|
-
// the local-issue WRITE verbs of the issue drawer (`spex issue <verb>`): open "<concern>" [--store local|<host>] [--node id…]
|
|
176
|
-
// [--evidence hash…] [--body -|text], and the id-based reply. Store is a property of the issue,
|
|
177
|
-
// never a second command — open and reply route by it (issues.ts createIssue/replyIssue).
|
|
178
|
-
export async function runIssueWrite(args: string[]): Promise<number> {
|
|
179
|
-
const sub = args[0]
|
|
180
|
-
try {
|
|
181
|
-
if (sub === 'reply') {
|
|
182
|
-
const id = bare(args.slice(1))[0]
|
|
183
|
-
const body = readBody(args)
|
|
184
|
-
if (!id || !body) { console.error('usage: spex issue reply <issue-id> --body -|<text> [--evidence <hash>…]'); return 2 }
|
|
185
|
-
// the ONE store-routed reply verb ([[issues]]): a forge id posts a real comment through the driver,
|
|
186
|
-
// a local id commits to the store — the same command either way (dynamic import: no static cycle).
|
|
187
|
-
const r = await (await import('./loop-in.js')).replyIssueWithLoopIn(id, body, { evidence: repeated(args, 'evidence') })
|
|
188
|
-
console.log(r.store === 'local'
|
|
189
|
-
? `replied to '${id}' — ${r.replies?.length} post(s) in thread`
|
|
190
|
-
: `commented on '${id}' — ${r.url}`)
|
|
191
|
-
const s = summarizeLoopIn(r.loopIn)
|
|
192
|
-
if (s) console.log(` ${s}`)
|
|
193
|
-
return 0
|
|
194
|
-
}
|
|
195
|
-
// `open`: start a new issue — STORE-ROUTED through the one creation port ([[issues]] createIssue, the
|
|
196
|
-
// same routine POST /api/issues runs): default local commits to the trunk store; `--store <host>`
|
|
197
|
-
// creates the real forge issue through that store's driver (no promote round-trip when the concern is
|
|
198
|
-
// born forge-visible). The concern is the bare positional(s) after the sub.
|
|
199
|
-
const concern = sub === 'open' ? bare(args.slice(1)).join(' ').trim() : ''
|
|
200
|
-
if (!concern) {
|
|
201
|
-
console.error('usage: spex issue open "<concern>" [--store local|<host>] [--node <id>…] [--evidence <hash>…] [--body -|<text>]\n spex issue reply|close|promote <issue-id> …')
|
|
202
|
-
return 2
|
|
203
|
-
}
|
|
204
|
-
const r = await (await import('./issues.js')).createIssue(concern, {
|
|
205
|
-
store: fl(args, 'store'),
|
|
206
|
-
nodes: repeated(args, 'node'),
|
|
207
|
-
body: readBody(args),
|
|
208
|
-
evidence: repeated(args, 'evidence'),
|
|
209
|
-
})
|
|
210
|
-
const re = r.nodes.length ? ` (re: ${r.nodes.join(', ')})` : ''
|
|
211
|
-
console.log(r.store === 'local'
|
|
212
|
-
? `opened '${r.id}'${re} — committed to the local issue store; read it with \`spex issue ls\``
|
|
213
|
-
: `opened '${r.id}' on ${r.store}${re} — ${r.url}`)
|
|
214
|
-
return 0
|
|
215
|
-
} catch (e) {
|
|
216
|
-
console.error(`spex issue: ${e instanceof Error ? e.message : e}`)
|
|
217
|
-
return 1
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// the first positionals runIssueWrite handles — the issue drawer routes these to it. Exported so the
|
|
222
|
-
// router and the runner can never drift. (`nudge` is not here: it is machine plumbing, called only by the
|
|
223
|
-
// post-merge hook as `spex internal nudge`; the on|off|status toggle verbs died in v0.3.0 — the switch is
|
|
224
|
-
// the `issues.enabled` settings key.)
|
|
225
|
-
export const ISSUE_WRITE_SUBS = new Set(['open', 'reply'])
|
|
226
|
-
|
|
227
|
-
// ── remark CLI ([[remark-substrate]]) — CLI-first: the whole author→resolve→retract loop, no server needed ──
|
|
228
|
-
// `spex remark add <issue-id | <node> --scenario <name>> --body -|<text> [--code-sha <sha>] [--evidence <hash>…]`
|
|
229
|
-
// host = a local issue id, OR a <node> with --scenario <name>. Records targetCodeSha (default: worktree HEAD).
|
|
230
|
-
export async function runRemark(args: string[]): Promise<number> {
|
|
231
|
-
try {
|
|
232
|
-
const scenario = fl(args, 'scenario')
|
|
233
|
-
const positional = bare(args)[0]
|
|
234
|
-
const body = readBody(args)
|
|
235
|
-
if (!positional || !body) {
|
|
236
|
-
console.error('usage: spex remark add <issue-id | node --scenario name> --body -|<text> [--code-sha <sha>] [--evidence <hash>…]')
|
|
237
|
-
return 2
|
|
238
|
-
}
|
|
239
|
-
// THE FLAG DECIDES THE PARSE ([[cli-surface]] §1): `--scenario` present ⇒ the positional is a NODE id
|
|
240
|
-
// (the remark pins to that node's scenario track); absent ⇒ it is an ISSUE id. Never type-sniffed —
|
|
241
|
-
// a node id and an issue id are both bare slugs, so any "looks like" guess would misroute; the flag
|
|
242
|
-
// is the one unambiguous discriminator, and a wrong host fails loud downstream (unknown issue/node).
|
|
243
|
-
const host = scenario ? { node: positional, scenario } : { issue: positional }
|
|
244
|
-
const r = await (await import('./loop-in.js')).remarkWithLoopIn(host, body, { codeSha: fl(args, 'code-sha'), evidence: repeated(args, 'evidence') })
|
|
245
|
-
console.log(`remark ${r.ref} (against ${r.codeSha.slice(0, 7) || 'HEAD'}) — read it with \`spex issue ls --all\``)
|
|
246
|
-
const s = summarizeLoopIn(r.loopIn)
|
|
247
|
-
if (s) console.log(` ${s}`)
|
|
248
|
-
return 0
|
|
249
|
-
} catch (e) {
|
|
250
|
-
console.error(`spex remark add: ${e instanceof Error ? e.message : e}`)
|
|
251
|
-
return 1
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// `spex remark resolve <remark-ref>` — flip resolved=true (agent-only, never the author, monotonic — see resolveRemark).
|
|
256
|
-
export async function runResolve(args: string[]): Promise<number> {
|
|
257
|
-
const ref = bare(args)[0]
|
|
258
|
-
if (!ref) { console.error('usage: spex remark resolve <remark-ref> (the <thread-id>#<rid> `spex remark add` printed)'); return 2 }
|
|
259
|
-
try {
|
|
260
|
-
const by = currentSession()
|
|
261
|
-
resolveRemark(ref, by)
|
|
262
|
-
console.log(`resolved remark ${ref} — by ${by}`)
|
|
263
|
-
return 0
|
|
264
|
-
} catch (e) { console.error(`spex remark resolve: ${e instanceof Error ? e.message : e}`); return 1 }
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// `spex remark retract <remark-ref>` — the author withdraws their OWN remark, removing it (author-only — see retractRemark).
|
|
268
|
-
export async function runRetract(args: string[]): Promise<number> {
|
|
269
|
-
const ref = bare(args)[0]
|
|
270
|
-
if (!ref) { console.error('usage: spex remark retract <remark-ref>'); return 2 }
|
|
271
|
-
try {
|
|
272
|
-
retractRemark(ref, currentSession())
|
|
273
|
-
console.log(`retracted remark ${ref}`)
|
|
274
|
-
return 0
|
|
275
|
-
} catch (e) { console.error(`spex remark retract: ${e instanceof Error ? e.message : e}`); return 1 }
|
|
276
|
-
}
|