heyspex 0.1.0 → 0.2.1
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/.claude-plugin/marketplace.json +14 -0
- package/README.md +21 -0
- package/bin/hs.mjs +1089 -104
- package/bin/spexcode.mjs +262 -0
- package/dev-factory/engine/worktree.mjs +740 -0
- package/dev-factory/lib/code-repo-root.mjs +67 -0
- package/dev-factory/lib/context-budget.mjs +84 -0
- package/dev-factory/lib/epic-detect.mjs +190 -0
- package/dev-factory/lib/fleet-queue-file.mjs +846 -0
- package/dev-factory/lib/fleet-queue.mjs +426 -0
- package/dev-factory/lib/fleet-state.mjs +14 -18
- package/dev-factory/lib/model-catalog.mjs +338 -0
- package/dev-factory/lib/seat-context.mjs +199 -0
- package/dev-factory/lib/spec-io.mjs +93 -0
- package/dev-factory/lib/sufficiency-score.mjs +8 -2
- package/dev-factory/lib/worktree-allocator.mjs +744 -0
- package/dev-factory/model-catalog.json +222 -0
- package/dist/cli/hs-check.mjs +1127 -103
- package/dist/cli/hs-claim.mjs +981 -63
- package/dist/cli/hs-connect.mjs +10059 -1729
- package/dist/cli/hs-defer.mjs +5507 -3072
- package/dist/cli/hs-dev.mjs +576 -0
- package/dist/cli/hs-env.mjs +416 -302
- package/dist/cli/hs-index-rebuild.mjs +7334 -0
- package/dist/cli/hs-index-reconcile.mjs +8138 -0
- package/dist/cli/hs-init.mjs +2840 -149
- package/dist/cli/hs-install.mjs +7214 -594
- package/dist/cli/hs-join.mjs +10640 -2421
- package/dist/cli/hs-vault-pull.mjs +8157 -6370
- package/dist/cli/hs-vault-push.mjs +6433 -0
- package/dist/cli/hs-vault.mjs +4029 -1555
- package/dist/cli/hs-workspace.mjs +2702 -538
- package/dist/cli-templates/customer-vault/specs/entity-model.md +594 -601
- package/dist/cli-templates/customer-vault/specs/protocols/canonical-frontmatter-templates.md +110 -177
- package/dist/cli-templates/customer-vault/specs/protocols/destructive-action-checklist.md +122 -0
- package/dist/cli-templates/customer-vault/specs/protocols/memory-protocol.md +13 -15
- package/dist/cli-templates/customer-vault/specs/protocols/session-close-protocol.md +91 -0
- package/dist/cli-templates/customer-vault/specs/protocols/spec-hierarchy.md +150 -168
- package/dist/cli-templates/customer-vault/specs/protocols/spec-summary-authoring.md +83 -0
- package/dist/cli-templates/harness-commands/claude/hs-auto.md +36 -0
- package/dist/cli-templates/harness-commands/claude/hs-backfill.md +28 -0
- package/dist/cli-templates/harness-commands/claude/hs-capture.md +62 -0
- package/dist/cli-templates/harness-commands/claude/hs-defer.md +29 -0
- package/dist/cli-templates/harness-commands/claude/hs-dev.md +20 -0
- package/dist/cli-templates/harness-commands/claude/hs-doctor.md +32 -0
- package/dist/cli-templates/harness-commands/claude/hs-ground.md +30 -0
- package/dist/cli-templates/harness-commands/claude/hs-handoff.md +33 -0
- package/dist/cli-templates/harness-commands/claude/hs-log.md +27 -0
- package/dist/cli-templates/harness-commands/claude/hs-next.md +29 -0
- package/dist/cli-templates/harness-commands/claude/hs-promote.md +70 -0
- package/dist/cli-templates/harness-commands/claude/hs-push.md +35 -0
- package/dist/cli-templates/harness-commands/claude/hs-qc.md +27 -0
- package/dist/cli-templates/harness-commands/claude/hs-res.md +63 -0
- package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -0
- package/dist/cli-templates/harness-commands/claude/hs-review.md +23 -0
- package/dist/cli-templates/harness-commands/claude/hs-view.md +28 -0
- package/dist/cli-templates/harness-commands/claude/kill-ports.md +32 -0
- package/dist/cli-templates/harness-commands/claude/prototype.md +91 -0
- package/dist/cli-templates/harness-commands/cursor/hs-auto.md +40 -0
- package/dist/cli-templates/harness-commands/cursor/hs-backfill.md +31 -0
- package/dist/cli-templates/harness-commands/cursor/hs-capture.md +65 -0
- package/dist/cli-templates/harness-commands/cursor/hs-defer.md +32 -0
- package/dist/cli-templates/harness-commands/cursor/hs-dev.md +24 -0
- package/dist/cli-templates/harness-commands/cursor/hs-doctor.md +36 -0
- package/dist/cli-templates/harness-commands/cursor/hs-ground.md +33 -0
- package/dist/cli-templates/harness-commands/cursor/hs-handoff.md +37 -0
- package/dist/cli-templates/harness-commands/cursor/hs-log.md +31 -0
- package/dist/cli-templates/harness-commands/cursor/hs-next.md +32 -0
- package/dist/cli-templates/harness-commands/cursor/hs-promote.md +73 -0
- package/dist/cli-templates/harness-commands/cursor/hs-push.md +38 -0
- package/dist/cli-templates/harness-commands/cursor/hs-qc.md +30 -0
- package/dist/cli-templates/harness-commands/cursor/hs-res.md +67 -0
- package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +26 -0
- package/dist/cli-templates/harness-commands/cursor/hs-review.md +26 -0
- package/dist/cli-templates/harness-commands/cursor/hs-view.md +32 -0
- package/dist/cli-templates/harness-commands/cursor/kill-ports.md +35 -0
- package/dist/cli-templates/harness-commands/cursor/prototype.md +95 -0
- package/docs/copilot-plugin-install.md +162 -0
- package/docs/driving-heyspex-from-copilot.md +165 -0
- package/docs/mcp-client-config.md +259 -6
- package/package.json +249 -124
- package/plugins/heyspex/.claude-plugin/plugin.json +12 -0
- package/plugins/heyspex/.cursor-plugin/plugin.json +15 -0
- package/plugins/heyspex/.mcp.json +12 -0
- package/plugins/heyspex/README.md +309 -0
- package/plugins/heyspex/bin/launch-mcp.mjs +95 -0
- package/plugins/heyspex/bin/run-hook.mjs +80 -0
- package/plugins/heyspex/hooks/cursor-hooks.json +308 -0
- package/plugins/heyspex/hooks/hooks.json +418 -0
- package/plugins/heyspex/mcp.json +13 -0
- package/scripts/check-mcp-freshness.mjs +17 -9
- package/scripts/claude-hooks/_env-vault-events.mjs +68 -0
- package/scripts/claude-hooks/_guardrail-events.mjs +96 -0
- package/scripts/claude-hooks/_guardrail-loader.mjs +494 -0
- package/scripts/claude-hooks/_intent-classifier-router.mjs +456 -0
- package/scripts/claude-hooks/_intent-classifier-semantic.mjs +356 -0
- package/scripts/claude-hooks/_run.mjs +413 -0
- package/scripts/claude-hooks/_transcript-text.mjs +60 -0
- package/scripts/claude-hooks/_vault-retrieval.mjs +322 -0
- package/scripts/claude-hooks/agent-spawn-delegation-gate.mjs +133 -0
- package/scripts/claude-hooks/capture-execution-gate.mjs +51 -0
- package/scripts/claude-hooks/capture-workflow-gate.mjs +11 -0
- package/scripts/claude-hooks/check-auto-memory-budget.mjs +396 -0
- package/scripts/claude-hooks/check-claude-md-budget.mjs +327 -0
- package/scripts/claude-hooks/check-mcp-freshness-hook.mjs +14 -0
- package/scripts/claude-hooks/claim-before-code-gate.mjs +11 -0
- package/scripts/claude-hooks/claim-liveness-shared.mjs +577 -0
- package/scripts/claude-hooks/close-terminal-on-ship.mjs +64 -0
- package/scripts/claude-hooks/coo-denylist-gate.mjs +11 -0
- package/scripts/claude-hooks/coo-guard-check.mjs +11 -0
- package/scripts/claude-hooks/deep-research-cost-gate.mjs +11 -0
- package/scripts/claude-hooks/dev-server-task-reminder.mjs +15 -0
- package/scripts/claude-hooks/diagnose-capture-reminder.mjs +11 -0
- package/scripts/claude-hooks/directive-obligation-gate.mjs +11 -0
- package/scripts/claude-hooks/emit-claim-status.mjs +41 -0
- package/scripts/claude-hooks/enforce-session-sequence.mjs +11 -0
- package/scripts/claude-hooks/enforce-vault-naming.mjs +11 -0
- package/scripts/claude-hooks/env-vault-guard.mjs +11 -0
- package/scripts/claude-hooks/epic-milestone-phrasing-gate.mjs +11 -0
- package/scripts/claude-hooks/git-identity-guard.mjs +11 -0
- package/scripts/claude-hooks/git-reflog-audit.mjs +15 -0
- package/scripts/claude-hooks/git-stash-gate.mjs +11 -0
- package/scripts/claude-hooks/guard-auto-memory-writes.mjs +137 -0
- package/scripts/claude-hooks/id-display-format-gate.mjs +11 -0
- package/scripts/claude-hooks/inject-communication-style.mjs +86 -0
- package/scripts/claude-hooks/inject-coo-seat.mjs +78 -0
- package/scripts/claude-hooks/inject-dev-server-awareness.mjs +11 -0
- package/scripts/claude-hooks/inject-doctrine.mjs +13 -0
- package/scripts/claude-hooks/inject-vault-context.mjs +14 -0
- package/scripts/claude-hooks/intent-classifier-trigger.mjs +279 -0
- package/scripts/claude-hooks/log-session-activity.mjs +341 -0
- package/scripts/claude-hooks/naughty-list-gate.mjs +11 -0
- package/scripts/claude-hooks/notify-status-flip.mjs +72 -0
- package/scripts/claude-hooks/plan-exit-ingest-gate.mjs +170 -0
- package/scripts/claude-hooks/plan-ingest-close-reminder.mjs +66 -0
- package/scripts/claude-hooks/plan-review-gate.mjs +11 -0
- package/scripts/claude-hooks/preflight-reminder.mjs +262 -0
- package/scripts/claude-hooks/protected-action-intent.mjs +221 -0
- package/scripts/claude-hooks/research-method-guard.mjs +398 -0
- package/scripts/claude-hooks/research-protocol-gate.mjs +11 -0
- package/scripts/claude-hooks/session-end.mjs +451 -0
- package/scripts/claude-hooks/settings-write-gate.mjs +11 -0
- package/scripts/claude-hooks/settlement-check-gate.mjs +39 -0
- package/scripts/claude-hooks/status-flip-detect.mjs +17 -0
- package/scripts/claude-hooks/terminal-close-shared.mjs +426 -0
- package/scripts/claude-hooks/terminal-close-watcher.mjs +122 -0
- package/scripts/claude-hooks/vault-mirror-catchup.mjs +11 -0
- package/scripts/claude-hooks/vault-write-tier-guard.mjs +11 -0
- package/scripts/claude-hooks/wip-checkpoint.mjs +302 -0
- package/scripts/cursor-hooks/manifest.mjs +281 -0
- package/scripts/dev-server-status.mjs +34 -13
- package/scripts/dev-server-stop.mjs +313 -0
- package/scripts/heyspex-mode.mjs +288 -0
- package/scripts/hs-auto-resolve.mjs +240 -0
- package/scripts/hs-auto-source.mjs +398 -0
- package/scripts/hs-auto.mjs +134 -0
- package/scripts/hs-capture-cli.mjs +326 -0
- package/scripts/hs-classifier.mjs +136 -0
- package/scripts/hs-companion.mjs +88 -0
- package/scripts/hs-gateway.mjs +115 -0
- package/scripts/hs-mode.mjs +125 -0
- package/scripts/hs-next.mjs +441 -0
- package/scripts/hs-settings.mjs +338 -0
- package/scripts/hs-view.mjs +496 -0
- package/scripts/hs-worktree.mjs +201 -0
- package/scripts/install-claude-code-hooks.mjs +272 -0
- package/scripts/install-cursor-hooks.mjs +471 -0
- package/scripts/lib/agent-env-markers.mjs +38 -0
- package/scripts/lib/console-url-resolver.mjs +199 -61
- package/scripts/lib/customer-kit.mjs +1203 -0
- package/scripts/lib/dev-mode.mjs +249 -32
- package/scripts/lib/directive-obligations.mjs +349 -0
- package/scripts/lib/heyspex-home.mjs +72 -0
- package/scripts/lib/hook-dispositions.mjs +210 -0
- package/scripts/lib/hook-vault-header.mjs +30 -0
- package/scripts/lib/hs-command.mjs +277 -0
- package/scripts/lib/hs-companion-settings.mjs +472 -0
- package/scripts/lib/hs-source-branch.mjs +196 -0
- package/scripts/lib/hs-source-commit.mjs +59 -5
- package/scripts/lib/hs-source-identity.mjs +526 -0
- package/scripts/lib/hs-source-log.mjs +13 -22
- package/scripts/lib/hs-source-preflight.mjs +18 -4
- package/scripts/lib/hs-source-push.mjs +386 -307
- package/scripts/lib/hs-worktree-args.mjs +115 -0
- package/scripts/lib/shared-path-helpers.mjs +134 -0
- package/scripts/lib/standalone-doctor.mjs +540 -3
- package/scripts/lib/subagent-git-lock.mjs +109 -0
- package/scripts/lib/template-pin.mjs +34 -0
- package/scripts/lib/window-placement.mjs +109 -0
- package/scripts/provenance-lib.mjs +91 -0
- package/scripts/stamp-provenance-on-edit.mjs +222 -0
- package/scripts/wip-ledger-health.mjs +653 -0
- package/spexharness/doctrine/baseline/SPEXCODE-DOCTRINE.baseline.json +29 -0
- package/spexharness/src/adapters/audit.mjs +197 -0
- package/spexharness/src/adapters/claude-code.mjs +449 -0
- package/spexharness/src/adapters/copilot.mjs +236 -0
- package/spexharness/src/adapters/detect-harness.mjs +34 -0
- package/spexharness/src/chat/tui/ansi.mjs +448 -0
- package/spexharness/src/chat/tui/palette.mjs +22 -0
- package/spexharness/src/chat/tui/select.mjs +208 -0
- package/spexharness/src/config-root.mjs +54 -0
- package/spexharness/src/context-budget.mjs +141 -0
- package/spexharness/src/dev-server-control.mjs +389 -0
- package/spexharness/src/doctrine/behaviour.mjs +371 -0
- package/spexharness/src/doctrine/corpus.mjs +733 -0
- package/spexharness/src/doctrine/inject.mjs +338 -0
- package/spexharness/src/doctrine/merge.mjs +184 -0
- package/spexharness/src/doctrine/sources.mjs +252 -0
- package/spexharness/src/doctrine/synthesize.mjs +401 -0
- package/spexharness/src/doctrine/vault-source.mjs +574 -0
- package/spexharness/src/doctrine/writer.mjs +176 -0
- package/spexharness/src/events.mjs +84 -0
- package/spexharness/src/gates/_shell-write-targets.mjs +77 -0
- package/spexharness/src/gates/capture-workflow-gate.mjs +202 -0
- package/spexharness/src/gates/claim-before-code-gate.decide.mjs +33 -0
- package/spexharness/src/gates/claim-before-code-gate.mjs +129 -0
- package/spexharness/src/gates/deep-research-cost-gate.mjs +275 -0
- package/spexharness/src/gates/diagnose-capture-reminder.mjs +112 -0
- package/spexharness/src/gates/directive-obligation-gate.decide.mjs +132 -0
- package/spexharness/src/gates/directive-obligation-gate.mjs +183 -0
- package/spexharness/src/gates/enforce-session-sequence.mjs +895 -0
- package/spexharness/src/gates/enforce-vault-naming.mjs +215 -0
- package/spexharness/src/gates/epic-milestone-phrasing-gate.mjs +233 -0
- package/spexharness/src/gates/git-identity-guard.decide.mjs +436 -0
- package/spexharness/src/gates/git-identity-guard.mjs +61 -0
- package/spexharness/src/gates/git-reflog-audit.mjs +151 -0
- package/spexharness/src/gates/git-stash-gate.decide.mjs +361 -0
- package/spexharness/src/gates/git-stash-gate.mjs +159 -0
- package/spexharness/src/gates/id-display-format-gate.mjs +190 -0
- package/spexharness/src/gates/inject-doctrine-gate.mjs +89 -0
- package/spexharness/src/gates/inject-vault-context.mjs +239 -0
- package/spexharness/src/gates/naughty-list-gate.mjs +213 -0
- package/spexharness/src/gates/plan-review-gate.mjs +233 -0
- package/spexharness/src/gates/preflight-reminder-gate.mjs +265 -0
- package/spexharness/src/gates/research-protocol-gate.mjs +175 -0
- package/spexharness/src/gates/settings-write-gate.decide.mjs +96 -0
- package/spexharness/src/gates/settings-write-gate.mjs +104 -0
- package/spexharness/src/gates/vault-mirror-catchup.mjs +124 -0
- package/spexharness/src/gates/vault-write-tier-guard.decide.mjs +125 -0
- package/spexharness/src/gates/vault-write-tier-guard.mjs +42 -0
- package/spexharness/src/git-reflog-audit.mjs +294 -0
- package/spexharness/src/intent-classifier.mjs +196 -0
- package/spexharness/src/intent-directive.mjs +626 -0
- package/spexharness/src/profile/learn.mjs +551 -0
- package/spexharness/src/profile/proposals.mjs +357 -0
- package/spexharness/src/profile/vault-inclusion.mjs +386 -0
- package/spexharness/src/redact.mjs +151 -0
- package/spexharness/src/rule-table.mjs +849 -0
- package/spexharness/src/seat-context.mjs +122 -0
- package/spexharness/src/session-bootstrap.mjs +512 -0
- package/spexharness/src/session-record.mjs +815 -0
- package/spexharness/src/token-inventory.mjs +207 -0
- package/vendor/heyspex-mcp/account-switch.mjs +96 -0
- package/vendor/heyspex-mcp/alignment-gate.mjs +315 -1
- package/vendor/heyspex-mcp/blocker-resolver.mjs +37 -2
- package/vendor/heyspex-mcp/breakdown-ladder.mjs +119 -4
- package/vendor/heyspex-mcp/breakdown-source.mjs +271 -0
- package/vendor/heyspex-mcp/breakdown-writer.mjs +23 -3
- package/vendor/heyspex-mcp/capture-buffer-patches.mjs +77 -8
- package/vendor/heyspex-mcp/capture-channel.mjs +55 -5
- package/vendor/heyspex-mcp/capture-console-client.mjs +117 -3
- package/vendor/heyspex-mcp/capture-focus.mjs +1061 -31
- package/vendor/heyspex-mcp/capture-outbox.mjs +15 -5
- package/vendor/heyspex-mcp/capture-sources.mjs +195 -0
- package/vendor/heyspex-mcp/capture-tools.mjs +1264 -0
- package/vendor/heyspex-mcp/claim-tools.mjs +1147 -0
- package/vendor/heyspex-mcp/cli-verbs.mjs +2074 -0
- package/vendor/heyspex-mcp/cli.mjs +207 -15524
- package/vendor/heyspex-mcp/close-branch-report.mjs +102 -0
- package/vendor/heyspex-mcp/cloud-tool-surface.mjs +128 -0
- package/vendor/heyspex-mcp/cloud-vault-writes.mjs +602 -0
- package/vendor/heyspex-mcp/config-seed.yaml +15 -0
- package/vendor/heyspex-mcp/config-settings.mjs +290 -7
- package/vendor/heyspex-mcp/console-fetch.mjs +822 -17
- package/vendor/heyspex-mcp/console-transport.mjs +172 -0
- package/vendor/heyspex-mcp/credentials.mjs +585 -0
- package/vendor/heyspex-mcp/defer-spec.mjs +44 -4
- package/vendor/heyspex-mcp/deferred-reclaim.mjs +29 -3
- package/vendor/heyspex-mcp/design-handlers.mjs +31 -0
- package/vendor/heyspex-mcp/design-tools.mjs +4 -1
- package/vendor/heyspex-mcp/dev-factory-bridge.mjs +4 -4
- package/vendor/heyspex-mcp/dev-mode-core.mjs +45 -0
- package/vendor/heyspex-mcp/dev-tools.mjs +131 -0
- package/vendor/heyspex-mcp/diagnose-handlers.mjs +54 -0
- package/vendor/heyspex-mcp/events-tools.mjs +207 -0
- package/vendor/heyspex-mcp/filing-tools.mjs +723 -0
- package/vendor/heyspex-mcp/fleet-handlers.mjs +37 -0
- package/vendor/heyspex-mcp/fleet-queue-tools.mjs +71 -15
- package/vendor/heyspex-mcp/focus-tools.mjs +190 -0
- package/vendor/heyspex-mcp/folder-trust-store.mjs +60 -0
- package/vendor/heyspex-mcp/http-transport.mjs +302 -0
- package/vendor/heyspex-mcp/list-tools.mjs +257 -0
- package/vendor/heyspex-mcp/login-handoff.mjs +15 -1
- package/vendor/heyspex-mcp/mcp-config.mjs +107 -0
- package/vendor/heyspex-mcp/memory-tools.mjs +523 -0
- package/vendor/heyspex-mcp/mvp-mode.mjs +53 -6
- package/vendor/heyspex-mcp/obligation-backstop.mjs +103 -0
- package/vendor/heyspex-mcp/occupied-keys.mjs +142 -0
- package/vendor/heyspex-mcp/on-deck-brief.mjs +3377 -0
- package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -0
- package/vendor/heyspex-mcp/package-root.mjs +32 -0
- package/vendor/heyspex-mcp/peer-presence.mjs +8 -1
- package/vendor/heyspex-mcp/plan-ground.mjs +621 -652
- package/vendor/heyspex-mcp/plan-push.mjs +908 -22
- package/vendor/heyspex-mcp/plan-review.mjs +124 -30
- package/vendor/heyspex-mcp/preflight-gate.mjs +0 -0
- package/vendor/heyspex-mcp/procedure-handlers.mjs +327 -0
- package/vendor/heyspex-mcp/procedure-tools.mjs +1181 -970
- package/vendor/heyspex-mcp/promote-capture.mjs +388 -69
- package/vendor/heyspex-mcp/promote-diagnose.mjs +74 -0
- package/vendor/heyspex-mcp/promote-research-to-diagnose.mjs +9 -2
- package/vendor/heyspex-mcp/promote-research.mjs +666 -53
- package/vendor/heyspex-mcp/promotion-helpers.mjs +251 -0
- package/vendor/heyspex-mcp/prompts.mjs +1460 -0
- package/vendor/heyspex-mcp/read-path.mjs +191 -15
- package/vendor/heyspex-mcp/receipt-shape.mjs +146 -0
- package/vendor/heyspex-mcp/recipe-handlers.mjs +117 -0
- package/vendor/heyspex-mcp/regen-tasks.mjs +210 -3
- package/vendor/heyspex-mcp/register-spec.mjs +266 -54
- package/vendor/heyspex-mcp/request-context.mjs +83 -0
- package/vendor/heyspex-mcp/research-focus.mjs +207 -4
- package/vendor/heyspex-mcp/research-handlers.mjs +625 -0
- package/vendor/heyspex-mcp/research-tools.mjs +4 -4
- package/vendor/heyspex-mcp/response-budget.mjs +348 -0
- package/vendor/heyspex-mcp/review-focus.mjs +25 -1
- package/vendor/heyspex-mcp/roadmap-default.mjs +70 -0
- package/vendor/heyspex-mcp/search-specs.mjs +280 -0
- package/vendor/heyspex-mcp/seat-block-ledger.mjs +113 -0
- package/vendor/heyspex-mcp/seat-identity.mjs +2 -6
- package/vendor/heyspex-mcp/session-owner.mjs +109 -0
- package/vendor/heyspex-mcp/session-tools.mjs +162 -0
- package/vendor/heyspex-mcp/settings-registry.mjs +232 -0
- package/vendor/heyspex-mcp/settings-tools.mjs +85 -12
- package/vendor/heyspex-mcp/spec-edit-tools.mjs +453 -0
- package/vendor/heyspex-mcp/spec-id-lib.mjs +93 -17
- package/vendor/heyspex-mcp/split-research.mjs +304 -56
- package/vendor/heyspex-mcp/stdio-rpc.mjs +22 -0
- package/vendor/heyspex-mcp/submit-for-review.mjs +150 -7
- package/vendor/heyspex-mcp/summary-contract.mjs +105 -0
- package/vendor/heyspex-mcp/summary-write-tools.mjs +228 -0
- package/vendor/heyspex-mcp/symptom-query.mjs +146 -0
- package/vendor/heyspex-mcp/test-helpers.mjs +123 -1
- package/vendor/heyspex-mcp/tool-catalog.mjs +2819 -0
- package/vendor/heyspex-mcp/tool-dispatch.mjs +657 -0
- package/vendor/heyspex-mcp/tool-helpers.mjs +325 -0
- package/vendor/heyspex-mcp/validate-linkage.mjs +414 -27
- package/vendor/heyspex-mcp/vault-io.mjs +720 -0
- package/vendor/heyspex-mcp/vault-less-endpoints.mjs +52 -0
- package/vendor/heyspex-mcp/vault-resolve.mjs +554 -68
- package/vendor/heyspex-mcp/verify-reproduction.mjs +270 -30
- package/vendor/heyspex-mcp/whoami.mjs +92 -0
- package/vendor/heyspex-mcp/write-outbox.mjs +512 -0
|
@@ -21,7 +21,24 @@
|
|
|
21
21
|
|
|
22
22
|
import { execFileSync } from 'node:child_process';
|
|
23
23
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync } from 'node:fs';
|
|
24
|
-
import { dirname, join } from 'node:path';
|
|
24
|
+
import { dirname, join, isAbsolute, resolve, sep } from 'node:path';
|
|
25
|
+
import { assertPathUnderRoot } from '../../scripts/lib/shared-path-helpers.mjs';
|
|
26
|
+
// Cloud-mode vault WRITES ([[HS-BYU4-CWPX-TASK-promotion-writes-go-through-the-console]]).
|
|
27
|
+
// Regen has no create-first/link-second reorder — nothing it writes links to a
|
|
28
|
+
// basename another write in the same batch mints — but the same rule applies:
|
|
29
|
+
// a `writeFileSync` under `specs/` in cloud mode is a split brain.
|
|
30
|
+
import {
|
|
31
|
+
createSpecViaConsole,
|
|
32
|
+
updateSpecViaConsole,
|
|
33
|
+
stripServerMintedFields,
|
|
34
|
+
} from './cloud-vault-writes.mjs';
|
|
35
|
+
import {
|
|
36
|
+
resolveWriteModeFromDeps,
|
|
37
|
+
splitRawSpecForConsole,
|
|
38
|
+
cloudWriteFailureResult,
|
|
39
|
+
cloudModeUnsupportedWrite,
|
|
40
|
+
} from './promotion-helpers.mjs';
|
|
41
|
+
|
|
25
42
|
|
|
26
43
|
const TERMINAL_STATUSES = new Set([
|
|
27
44
|
'closed',
|
|
@@ -49,6 +66,11 @@ export function softDeleteToTrash(vaultRoot, relPath, bucket = 'misc') {
|
|
|
49
66
|
if (!existsSync(abs)) return { ok: false, error: 'not_found', source: relPath };
|
|
50
67
|
const basename = relPath.split(/[\\/]/).pop() || `${timestamp()}-spec.md`;
|
|
51
68
|
const trashDir = join(vaultRoot, 'specs', '.trash', bucket);
|
|
69
|
+
try {
|
|
70
|
+
assertPathUnderRoot(vaultRoot, trashDir, 'regen-tasks write');
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return { ok: false, error: 'BAD_VAULT_ROOT', source: relPath, message: err.message };
|
|
73
|
+
}
|
|
52
74
|
mkdirSync(trashDir, { recursive: true });
|
|
53
75
|
const dest = join(trashDir, `${timestamp()}-${basename}`);
|
|
54
76
|
renameSync(abs, dest);
|
|
@@ -136,7 +158,77 @@ function epicSlugFromRel(relPath) {
|
|
|
136
158
|
*
|
|
137
159
|
* Both modes return `{ ok, mode, task, epic, brief?, commit_result? }`.
|
|
138
160
|
*/
|
|
139
|
-
|
|
161
|
+
/**
|
|
162
|
+
* The cloud twin of the `.trash/` soft-delete — EXPLICIT DEGRADE.
|
|
163
|
+
*
|
|
164
|
+
* `softDeleteToTrash` renames a file into `specs/.trash/<bucket>/`, which is
|
|
165
|
+
* not a spec of any type the console models (no TYPE_TO_FOLDER entry, no id,
|
|
166
|
+
* no frontmatter contract), so there is no POST/PUT route that could carry it.
|
|
167
|
+
* In cloud mode the replacement still happens — `PUT /api/specs/:id` overwrites
|
|
168
|
+
* the body and the console keeps its own version history — but the local
|
|
169
|
+
* `.trash/` copy the [[destructive-action-checklist]] recovery procedure names
|
|
170
|
+
* does not exist. That is REPORTED on every affected entry rather than
|
|
171
|
+
* silently skipped, so the caller knows which recovery path applies.
|
|
172
|
+
*/
|
|
173
|
+
function cloudTrashDegrade(relPath) {
|
|
174
|
+
return cloudModeUnsupportedWrite(
|
|
175
|
+
`specs/.trash/… (soft-delete of ${relPath})`,
|
|
176
|
+
'a trash copy is not a spec of any type the console models, so there is no route to write it; the replacement itself still landed through PUT /api/specs/:id and the console keeps its own version history',
|
|
177
|
+
{ recovery: 'Restore the previous body from the console\'s spec history rather than from a local .trash/ file.' },
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Replace one existing spec's body through the console.
|
|
183
|
+
* `new_body` is the agent-authored full markdown (frontmatter + body), the
|
|
184
|
+
* same string the disk path writes verbatim.
|
|
185
|
+
*/
|
|
186
|
+
async function putBodyViaConsole(specId, newBody, cloudDeps) {
|
|
187
|
+
const { frontmatter, body } = splitRawSpecForConsole(newBody);
|
|
188
|
+
return updateSpecViaConsole({ ...cloudDeps, specId, frontmatter, body });
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Cloud-mode `executeRegenTask` commit. Same result shape as the disk path
|
|
193
|
+
* plus `write_mode: 'cloud'` and the `.trash/` degrade note.
|
|
194
|
+
*/
|
|
195
|
+
async function regenTaskCommitViaConsole({ taskSummary, epicSummary, new_body, retire_reason, cloudDeps }) {
|
|
196
|
+
let res;
|
|
197
|
+
try {
|
|
198
|
+
res = await putBodyViaConsole(taskSummary.id, new_body, cloudDeps);
|
|
199
|
+
} catch (err) {
|
|
200
|
+
return {
|
|
201
|
+
ok: false,
|
|
202
|
+
...cloudWriteFailureResult(err, {
|
|
203
|
+
step: { kind: 'update', type: 'task', spec_id: taskSummary.id },
|
|
204
|
+
completed: [],
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
ok: true,
|
|
210
|
+
mode: 'commit',
|
|
211
|
+
write_mode: 'cloud',
|
|
212
|
+
task: { id: res.specId ?? taskSummary.id, rel_path: res.relPath ?? taskSummary.rel_path },
|
|
213
|
+
retired_to: null,
|
|
214
|
+
retire_reason: retire_reason || null,
|
|
215
|
+
epic: epicSummary ? { id: epicSummary.id } : null,
|
|
216
|
+
cloud_mode_unsupported_writes: [cloudTrashDegrade(taskSummary.rel_path ?? taskSummary.id)],
|
|
217
|
+
message:
|
|
218
|
+
`Replaced the body of ${taskSummary.id} through the console (cloud write mode — nothing was written to local disk). ` +
|
|
219
|
+
'No local .trash/ copy was made; recover the previous body from the console\'s spec history.',
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function executeRegenTask(vaultRoot, { task_id, commit = false, new_body, retire_reason, loadTask, writeMode, consoleFetch, consoleUrl }) {
|
|
224
|
+
// Vault WRITE mode ([[HS-BYU4-CWPX-TASK-promotion-writes-go-through-the-console]]),
|
|
225
|
+
// resolved ONCE by the caller and defaulting to `local`. This function stays
|
|
226
|
+
// SYNCHRONOUS on the local path on purpose — `spec-edit-tools.mjs` consumes
|
|
227
|
+
// its return value synchronously — and returns a Promise only in cloud mode,
|
|
228
|
+
// which a cloud-aware caller awaits (awaiting the plain object the local
|
|
229
|
+
// path returns is a no-op, so one call site serves both).
|
|
230
|
+
const cloudWriteMode = resolveWriteModeFromDeps({ writeMode });
|
|
231
|
+
const cloudDeps = { consoleFetch, consoleUrl };
|
|
140
232
|
if (!task_id) {
|
|
141
233
|
return { ok: false, error: 'MISSING_TASK_ID', message: 'task_id is required' };
|
|
142
234
|
}
|
|
@@ -159,6 +251,15 @@ export function executeRegenTask(vaultRoot, { task_id, commit = false, new_body,
|
|
|
159
251
|
message: 'commit: true requires non-empty new_body',
|
|
160
252
|
};
|
|
161
253
|
}
|
|
254
|
+
if (cloudWriteMode === 'cloud') {
|
|
255
|
+
return regenTaskCommitViaConsole({
|
|
256
|
+
taskSummary,
|
|
257
|
+
epicSummary,
|
|
258
|
+
new_body,
|
|
259
|
+
retire_reason,
|
|
260
|
+
cloudDeps,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
162
263
|
if (!taskSummary.rel_path) {
|
|
163
264
|
return { ok: false, error: 'NO_REL_PATH', task_id };
|
|
164
265
|
}
|
|
@@ -172,6 +273,11 @@ export function executeRegenTask(vaultRoot, { task_id, commit = false, new_body,
|
|
|
172
273
|
// it — that's an agent error and surfaces as a malformed spec at the
|
|
173
274
|
// next /hs-next.
|
|
174
275
|
const destAbs = join(vaultRoot, taskSummary.rel_path);
|
|
276
|
+
try {
|
|
277
|
+
assertPathUnderRoot(vaultRoot, dirname(destAbs), 'regen-tasks write');
|
|
278
|
+
} catch (err) {
|
|
279
|
+
return { ok: false, error: 'BAD_VAULT_ROOT', task_id, message: err.message };
|
|
280
|
+
}
|
|
175
281
|
mkdirSync(dirname(destAbs), { recursive: true });
|
|
176
282
|
writeFileSync(destAbs, new_body, 'utf8');
|
|
177
283
|
return {
|
|
@@ -222,7 +328,93 @@ export function executeRegenTask(vaultRoot, { task_id, commit = false, new_body,
|
|
|
222
328
|
* The tool is deliberately deterministic — the LLM thinking happens between
|
|
223
329
|
* brief mode and commit mode in the calling agent.
|
|
224
330
|
*/
|
|
225
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Cloud-mode `executeRegenTasksForEpic` commit — the same two entry shapes the
|
|
333
|
+
* disk path takes, routed through the console:
|
|
334
|
+
*
|
|
335
|
+
* `{ id, new_body, retire_reason }` → `PUT /api/specs/:id` (replace in place;
|
|
336
|
+
* no local `.trash/` copy — reported, see {@link cloudTrashDegrade}).
|
|
337
|
+
* `{ new_id, body, rel_path }` → `POST /api/specs` (the caller-supplied
|
|
338
|
+
* `new_id`/`rel_path` are IGNORED: the console mints the id, the family
|
|
339
|
+
* and the filename, so nothing is hand-picked — HS-BYU4 AC3. The minted
|
|
340
|
+
* id is reported back in `wrote[]`.)
|
|
341
|
+
*/
|
|
342
|
+
async function regenTasksForEpicCommitViaConsole({ epicSummary, task_specs, loadTask, cloudDeps }) {
|
|
343
|
+
const retired = [];
|
|
344
|
+
const wrote = [];
|
|
345
|
+
const errors = [];
|
|
346
|
+
const unsupported = [];
|
|
347
|
+
for (const entry of task_specs) {
|
|
348
|
+
if (entry && typeof entry === 'object' && entry.id && typeof entry.new_body === 'string') {
|
|
349
|
+
const target = loadSpecRecord(loadTask, entry.id);
|
|
350
|
+
const specId = target?.id || target?.frontmatter?.id || entry.id;
|
|
351
|
+
try {
|
|
352
|
+
const res = await putBodyViaConsole(specId, entry.new_body, cloudDeps);
|
|
353
|
+
retired.push({ id: entry.id, trash_path: null, retire_reason: entry.retire_reason || null });
|
|
354
|
+
unsupported.push(cloudTrashDegrade(target?.relPath || target?.rel_path || entry.id));
|
|
355
|
+
wrote.push({ id: res.specId ?? specId, rel_path: res.relPath ?? null });
|
|
356
|
+
} catch (err) {
|
|
357
|
+
errors.push({
|
|
358
|
+
id: entry.id,
|
|
359
|
+
...cloudWriteFailureResult(err, {
|
|
360
|
+
step: { kind: 'update', type: 'task', spec_id: specId },
|
|
361
|
+
completed: wrote,
|
|
362
|
+
}),
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
} else if (entry && typeof entry === 'object' && entry.new_id && typeof entry.body === 'string') {
|
|
366
|
+
const { frontmatter, body } = splitRawSpecForConsole(entry.body);
|
|
367
|
+
const cleaned = stripServerMintedFields(frontmatter);
|
|
368
|
+
try {
|
|
369
|
+
const created = await createSpecViaConsole({
|
|
370
|
+
...cloudDeps,
|
|
371
|
+
type: cleaned.type ?? frontmatter.type ?? 'task',
|
|
372
|
+
name: cleaned.name ?? frontmatter.name ?? String(entry.new_id),
|
|
373
|
+
summary: cleaned.summary ?? null,
|
|
374
|
+
frontmatter: cleaned,
|
|
375
|
+
body,
|
|
376
|
+
});
|
|
377
|
+
wrote.push({
|
|
378
|
+
id: created.specId,
|
|
379
|
+
rel_path: created.relPath,
|
|
380
|
+
requested_id: entry.new_id,
|
|
381
|
+
note:
|
|
382
|
+
'The console minted this id/filename server-side; the caller-supplied `new_id`/`rel_path` were not used (file keys are never hand-picked).',
|
|
383
|
+
});
|
|
384
|
+
} catch (err) {
|
|
385
|
+
errors.push({
|
|
386
|
+
new_id: entry.new_id,
|
|
387
|
+
...cloudWriteFailureResult(err, {
|
|
388
|
+
step: { kind: 'create', type: 'task', name: entry.new_id },
|
|
389
|
+
completed: wrote,
|
|
390
|
+
}),
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
errors.push({ entry, error: 'INVALID_SHAPE' });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return {
|
|
398
|
+
ok: errors.length === 0,
|
|
399
|
+
mode: 'commit',
|
|
400
|
+
write_mode: 'cloud',
|
|
401
|
+
epic: { id: epicSummary.id },
|
|
402
|
+
retired,
|
|
403
|
+
wrote,
|
|
404
|
+
errors,
|
|
405
|
+
bucket: null,
|
|
406
|
+
...(unsupported.length > 0 ? { cloud_mode_unsupported_writes: unsupported } : {}),
|
|
407
|
+
message:
|
|
408
|
+
`Stage-1-2-3 commit for ${epicSummary.id} through the console: replaced ${retired.length}, wrote ${wrote.length}, errors ${errors.length}. ` +
|
|
409
|
+
'Cloud write mode — nothing was written to local disk and no .trash/ copies were made; recover previous bodies from the console\'s spec history.',
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function executeRegenTasksForEpic(vaultRoot, { epic_id, commit = false, task_specs, loadTask, writeMode, consoleFetch, consoleUrl }) {
|
|
414
|
+
// Same once-per-call resolution + sync-unless-cloud contract as
|
|
415
|
+
// {@link executeRegenTask} above.
|
|
416
|
+
const cloudWriteMode = resolveWriteModeFromDeps({ writeMode });
|
|
417
|
+
const cloudDeps = { consoleFetch, consoleUrl };
|
|
226
418
|
if (!epic_id) {
|
|
227
419
|
return { ok: false, error: 'MISSING_EPIC_ID', message: 'epic_id is required' };
|
|
228
420
|
}
|
|
@@ -255,6 +447,9 @@ export function executeRegenTasksForEpic(vaultRoot, { epic_id, commit = false, t
|
|
|
255
447
|
message: 'commit: true requires task_specs: [{ id, new_body, retire_reason } | { new_id, body, rel_path }]',
|
|
256
448
|
};
|
|
257
449
|
}
|
|
450
|
+
if (cloudWriteMode === 'cloud') {
|
|
451
|
+
return regenTasksForEpicCommitViaConsole({ epicSummary, task_specs, loadTask, cloudDeps });
|
|
452
|
+
}
|
|
258
453
|
const bucket = epicSlugFromRel(epicSummary.rel_path);
|
|
259
454
|
const retired = [];
|
|
260
455
|
const wrote = [];
|
|
@@ -273,6 +468,12 @@ export function executeRegenTasksForEpic(vaultRoot, { epic_id, commit = false, t
|
|
|
273
468
|
continue;
|
|
274
469
|
}
|
|
275
470
|
const abs = join(vaultRoot, rel);
|
|
471
|
+
try {
|
|
472
|
+
assertPathUnderRoot(vaultRoot, dirname(abs), 'regen-tasks write');
|
|
473
|
+
} catch (err) {
|
|
474
|
+
errors.push({ id: entry.id, error: 'BAD_VAULT_ROOT', message: err.message });
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
276
477
|
mkdirSync(dirname(abs), { recursive: true });
|
|
277
478
|
writeFileSync(abs, entry.new_body, 'utf8');
|
|
278
479
|
retired.push({ id: entry.id, trash_path: del.trash_path, retire_reason: entry.retire_reason || null });
|
|
@@ -283,6 +484,12 @@ export function executeRegenTasksForEpic(vaultRoot, { epic_id, commit = false, t
|
|
|
283
484
|
errors.push({ new_id: entry.new_id, error: 'CONFLICT', rel_path: entry.rel_path });
|
|
284
485
|
continue;
|
|
285
486
|
}
|
|
487
|
+
try {
|
|
488
|
+
assertPathUnderRoot(vaultRoot, dirname(abs), 'regen-tasks write');
|
|
489
|
+
} catch (err) {
|
|
490
|
+
errors.push({ new_id: entry.new_id, error: 'BAD_VAULT_ROOT', message: err.message });
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
286
493
|
mkdirSync(dirname(abs), { recursive: true });
|
|
287
494
|
writeFileSync(abs, entry.body, 'utf8');
|
|
288
495
|
wrote.push({ id: entry.new_id, rel_path: entry.rel_path });
|