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
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* symptom-query.mjs — turn a SYMPTOM SENTENCE into the small set of bounded
|
|
3
|
+
* queries `GET /api/search` can actually answer. Pure: no imports, no I/O, no
|
|
4
|
+
* console, so both the MCP tool and the console's own route suite can drive it.
|
|
5
|
+
*
|
|
6
|
+
* WHY THIS IS NOT "just pass the sentence through"
|
|
7
|
+
* ------------------------------------------------
|
|
8
|
+
* The console's ranked path is `websearch_to_tsquery('english', $q)`, and
|
|
9
|
+
* unquoted words in a websearch query are AND-ed. A real bug report —
|
|
10
|
+
*
|
|
11
|
+
* "row-level security policies exist but are not enforced at runtime;
|
|
12
|
+
* the database connection bypasses tenant isolation"
|
|
13
|
+
*
|
|
14
|
+
* — is ~12 content words AND-ed together, which matches NOTHING in any vault,
|
|
15
|
+
* then falls through to the trigram near-miss on `name`, which also matches
|
|
16
|
+
* nothing. The endpoint answers honestly ("searched, zero hits") and the agent
|
|
17
|
+
* concludes the symptom was never filed, files a duplicate, and the two
|
|
18
|
+
* existing specs stay invisible. That is [[HS-YFLS]] AC2.
|
|
19
|
+
*
|
|
20
|
+
* So a symptom search is a handful of ANGLES, not one query:
|
|
21
|
+
*
|
|
22
|
+
* phrase — the sentence verbatim (AND). Rarely hits; when it does, it is
|
|
23
|
+
* the highest-precision answer there is, so it is asked first.
|
|
24
|
+
* bigrams — the adjacent salient pairs, quoted, OR-ed. "tenant isolation"
|
|
25
|
+
* and "row-level security" are CONCEPTS; a quoted phrase makes
|
|
26
|
+
* `ts_rank_cd` reward the document that contains the concept over
|
|
27
|
+
* one that merely mentions both words a page apart.
|
|
28
|
+
* terms — every salient term, OR-ed. The recall floor. A document that
|
|
29
|
+
* matches eight of the twelve terms outranks one that matches two
|
|
30
|
+
* without any extra scoring on our side, because `ts_rank_cd`
|
|
31
|
+
* already counts matched lexemes and their density.
|
|
32
|
+
*
|
|
33
|
+
* Nothing here is a reranker and nothing is semantic — the substrate is
|
|
34
|
+
* lexical by decision ([[retrieval-substrate-lexical-not-embeddings-gate-b-no]]).
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Words that carry no retrieval signal in a bug report. Deliberately larger
|
|
39
|
+
* than a generic English stoplist: the vocabulary of a SYMPTOM ("happens",
|
|
40
|
+
* "should", "instead", "error", "issue") is noise when every spec in the vault
|
|
41
|
+
* is about something going wrong.
|
|
42
|
+
*/
|
|
43
|
+
const STOPWORDS = new Set([
|
|
44
|
+
'a', 'an', 'the', 'and', 'or', 'but', 'not', 'nor', 'for', 'to', 'in', 'on', 'at', 'of',
|
|
45
|
+
'with', 'without', 'from', 'by', 'as', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
46
|
+
'do', 'does', 'did', 'has', 'have', 'had', 'can', 'cannot', 'could', 'will', 'would',
|
|
47
|
+
'should', 'shall', 'may', 'might', 'must', 'this', 'that', 'these', 'those', 'it', 'its',
|
|
48
|
+
'we', 'our', 'you', 'your', 'they', 'them', 'their', 'there', 'here', 'when', 'where',
|
|
49
|
+
'what', 'which', 'who', 'whom', 'how', 'why', 'all', 'any', 'some', 'only', 'also',
|
|
50
|
+
'still', 'then', 'than', 'so', 'if', 'else', 'into', 'onto', 'out', 'up', 'down', 'over',
|
|
51
|
+
'under', 'again', 'more', 'most', 'much', 'very', 'just', 'now', 'get', 'gets', 'got',
|
|
52
|
+
// symptom filler — true of every bug, so it discriminates between none of them
|
|
53
|
+
'bug', 'issue', 'problem', 'error', 'fail', 'fails', 'failed', 'failing', 'broken',
|
|
54
|
+
'wrong', 'happens', 'happening', 'instead', 'expected', 'actual', 'repro', 'steps',
|
|
55
|
+
'seems', 'looks', 'like', 'never', 'always', 'sometimes', 'exist', 'exists',
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
/** Minimum length for a token to count as salient (drops `is`, `an`, `ok`, `x`). */
|
|
59
|
+
const MIN_TERM_LENGTH = 3;
|
|
60
|
+
|
|
61
|
+
/** Hard ceiling on salient terms — a 400-word paste must not become a 400-term OR. */
|
|
62
|
+
export const DEFAULT_MAX_TERMS = 12;
|
|
63
|
+
|
|
64
|
+
/** Hard ceiling on quoted bigram phrases. */
|
|
65
|
+
export const DEFAULT_MAX_BIGRAMS = 6;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Split a symptom sentence into ordered, de-duplicated content terms.
|
|
69
|
+
* Hyphens and underscores are KEPT inside a word (`row-level`, `vault_id`,
|
|
70
|
+
* `HS-WRUQ`) because those are the highest-signal tokens a spec vault has;
|
|
71
|
+
* everything else becomes a separator.
|
|
72
|
+
*/
|
|
73
|
+
export function extractSymptomTerms(text, { maxTerms = DEFAULT_MAX_TERMS } = {}) {
|
|
74
|
+
if (typeof text !== 'string' || !text.trim()) return [];
|
|
75
|
+
const raw = text
|
|
76
|
+
.toLowerCase()
|
|
77
|
+
.replace(/[^a-z0-9_-]+/g, ' ')
|
|
78
|
+
.split(' ')
|
|
79
|
+
.map((t) => t.replace(/^[-_]+|[-_]+$/g, ''))
|
|
80
|
+
.filter(Boolean);
|
|
81
|
+
|
|
82
|
+
const ordered = [];
|
|
83
|
+
const seen = new Set();
|
|
84
|
+
for (const token of raw) {
|
|
85
|
+
if (token.length < MIN_TERM_LENGTH) continue;
|
|
86
|
+
if (STOPWORDS.has(token)) continue;
|
|
87
|
+
if (/^\d+$/.test(token)) continue;
|
|
88
|
+
if (seen.has(token)) continue;
|
|
89
|
+
seen.add(token);
|
|
90
|
+
ordered.push(token);
|
|
91
|
+
}
|
|
92
|
+
if (ordered.length <= maxTerms) return ordered;
|
|
93
|
+
|
|
94
|
+
// Over the cap: keep the most SALIENT terms, then restore reading order so
|
|
95
|
+
// the bigram angle below still pairs words that were adjacent in the report.
|
|
96
|
+
// Saliency is length plus a bonus for a compound (`row-level`, `vault_id`) —
|
|
97
|
+
// a crude rarity proxy, but one that needs no corpus statistics and cannot
|
|
98
|
+
// go stale.
|
|
99
|
+
const salience = (t) => t.length + (/[-_]/.test(t) ? 4 : 0);
|
|
100
|
+
const keep = new Set(
|
|
101
|
+
[...ordered]
|
|
102
|
+
.sort((a, b) => salience(b) - salience(a) || ordered.indexOf(a) - ordered.indexOf(b))
|
|
103
|
+
.slice(0, maxTerms),
|
|
104
|
+
);
|
|
105
|
+
return ordered.filter((t) => keep.has(t));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** `["tenant","isolation","neon"]` → `['"tenant isolation"', '"isolation neon"']`. */
|
|
109
|
+
export function buildBigrams(terms, { maxBigrams = DEFAULT_MAX_BIGRAMS } = {}) {
|
|
110
|
+
const pairs = [];
|
|
111
|
+
for (let i = 0; i + 1 < terms.length && pairs.length < maxBigrams; i += 1) {
|
|
112
|
+
pairs.push(`${terms[i]} ${terms[i + 1]}`);
|
|
113
|
+
}
|
|
114
|
+
return pairs;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The angles to ask `GET /api/search`, most precise first.
|
|
119
|
+
*
|
|
120
|
+
* Returns `{ terms, queries: [{ label, q }] }`. Queries are de-duplicated by
|
|
121
|
+
* `q`, so a one-word symptom collapses to a single request rather than three
|
|
122
|
+
* identical ones. An input with no salient terms at all (punctuation, pure
|
|
123
|
+
* stopwords) yields `queries: []` — the caller must treat that as "nothing
|
|
124
|
+
* searchable was asked", never as "nothing is filed".
|
|
125
|
+
*/
|
|
126
|
+
export function buildSymptomQueries(text, { maxTerms = DEFAULT_MAX_TERMS, maxBigrams = DEFAULT_MAX_BIGRAMS } = {}) {
|
|
127
|
+
const phrase = typeof text === 'string' ? text.trim().replace(/\s+/g, ' ') : '';
|
|
128
|
+
const terms = extractSymptomTerms(phrase, { maxTerms });
|
|
129
|
+
const queries = [];
|
|
130
|
+
const pushed = new Set();
|
|
131
|
+
const push = (label, q) => {
|
|
132
|
+
if (!q || pushed.has(q)) return;
|
|
133
|
+
pushed.add(q);
|
|
134
|
+
queries.push({ label, q });
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
if (terms.length > 0) {
|
|
138
|
+
// Precision first: the sentence as written, AND-ed by websearch_to_tsquery.
|
|
139
|
+
if (phrase) push('phrase', phrase);
|
|
140
|
+
const bigrams = buildBigrams(terms, { maxBigrams });
|
|
141
|
+
if (bigrams.length > 0) push('bigrams', bigrams.map((b) => `"${b}"`).join(' or '));
|
|
142
|
+
push('terms', terms.join(' or '));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return { phrase, terms, queries };
|
|
146
|
+
}
|
|
@@ -2,9 +2,120 @@
|
|
|
2
2
|
* Shared test helpers for the vendor MCP round-trip suites.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { tmpdir } from 'node:os';
|
|
6
8
|
import { join } from 'node:path';
|
|
7
9
|
|
|
10
|
+
import { resetActiveConfigCache } from './vault-resolve.mjs';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A hermetic `{ account, vault }` scope for tests that drive the REAL console
|
|
14
|
+
* transport ([[HS-MVG4-WW9R-TASK-mcp-and-hs-name-account-vault-on-every]]).
|
|
15
|
+
*
|
|
16
|
+
* Since invariant 2 the transport refuses LOCALLY (no fetch) when the cwd
|
|
17
|
+
* resolves to an unregistered root or the machine has no configured account.
|
|
18
|
+
* A test that hits a stand-in console through `consoleFetch` with the default
|
|
19
|
+
* header resolvers therefore depends on the machine it runs on — registered
|
|
20
|
+
* here, unregistered on CI — unless it pins both facts. This helper pins them:
|
|
21
|
+
*
|
|
22
|
+
* - a temp HOME (`HOME` + `USERPROFILE`, what `os.homedir()` reads) holding
|
|
23
|
+
* `~/.heyspex/registry.json` with the roots the test names,
|
|
24
|
+
* - `HS_ACCOUNT_ID` (tier 1 of session-owner.mjs) as the configured account,
|
|
25
|
+
* - optionally `HEYSPEX_VAULT_ROOT` pointed at a registered root,
|
|
26
|
+
* - `CLAUDE_PROJECT_DIR` (the resolver's cwd base) pointed at that root —
|
|
27
|
+
* or at the temp home when none is given — so the resolver's walk starts
|
|
28
|
+
* inside the fixture and never climbs through the ambient checkout. The
|
|
29
|
+
* walk (tier 2) outranks `HEYSPEX_VAULT_ROOT` (tier 3, [[HS-VVNQ]]), so a
|
|
30
|
+
* satellite pin in the repo the suite is run FROM (heyspex-app's own
|
|
31
|
+
* `.mcp.json` since 2026-10-10) would otherwise silently replace the
|
|
32
|
+
* root a test pinned, and the machine's registry pointer (tier 4) would
|
|
33
|
+
* otherwise answer for a test that pinned nothing.
|
|
34
|
+
*
|
|
35
|
+
* `registerRoot(root)` adds a row for a root a test mints later (its own temp
|
|
36
|
+
* vault) and resets the memoized resolver so the next request sees it. Call
|
|
37
|
+
* `restore()` in `after`/`afterEach`. Nothing here touches the real profile.
|
|
38
|
+
*
|
|
39
|
+
* Row ids are UUIDs (what the console mints): the wire gate treats a non-UUID
|
|
40
|
+
* registry id as a legacy slug and looks for the repo's heyspex.yaml
|
|
41
|
+
* `vault_id` instead — a slug row with no marker is refused, by design.
|
|
42
|
+
*
|
|
43
|
+
* @param {{ accountId?: string, vaultId?: string, repoRootAbs?: string, activeVaultId?: string | null }} [opts]
|
|
44
|
+
* `repoRootAbs`: register this root as `vaultId` and set `HEYSPEX_VAULT_ROOT` to it.
|
|
45
|
+
* `activeVaultId`: the registry's active pointer (defaults to `vaultId` when a root is registered).
|
|
46
|
+
*/
|
|
47
|
+
export function installScopedConsoleEnv({
|
|
48
|
+
accountId = 'acct_test',
|
|
49
|
+
vaultId = randomUUID(),
|
|
50
|
+
repoRootAbs,
|
|
51
|
+
activeVaultId,
|
|
52
|
+
} = {}) {
|
|
53
|
+
const ENV_KEYS = ['HOME', 'USERPROFILE', 'HS_ACCOUNT_ID', 'HEYSPEX_VAULT_ROOT', 'CLAUDE_PROJECT_DIR', 'HEYSPEX_MCP_TOKEN'];
|
|
54
|
+
const saved = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]]));
|
|
55
|
+
const home = mkdtempSync(join(tmpdir(), 'hs-scoped-home-'));
|
|
56
|
+
// The registry lives under the HeySpex home: HEYSPEX_HOME when a test set one, else the scoped HOME.
|
|
57
|
+
const registryHome = process.env.HEYSPEX_HOME?.trim() || home;
|
|
58
|
+
const registryDir = join(registryHome, '.heyspex');
|
|
59
|
+
mkdirSync(registryDir, { recursive: true });
|
|
60
|
+
const registryPath = join(registryDir, 'registry.json');
|
|
61
|
+
// Registry schema v2 (HS-RXLG): the pointer is the signed-in account's row.
|
|
62
|
+
const registry = {
|
|
63
|
+
schema_version: 2,
|
|
64
|
+
current_account_id: accountId,
|
|
65
|
+
accounts: {
|
|
66
|
+
[accountId]: {
|
|
67
|
+
active_vault_id: activeVaultId ?? (repoRootAbs ? vaultId : null),
|
|
68
|
+
active_workspace_id: null,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
workspaces: [],
|
|
72
|
+
vaults: [],
|
|
73
|
+
};
|
|
74
|
+
const flush = () => {
|
|
75
|
+
writeFileSync(registryPath, JSON.stringify(registry, null, 2));
|
|
76
|
+
resetActiveConfigCache();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const registerRoot = (root, id) => {
|
|
80
|
+
const rowId = id ?? randomUUID();
|
|
81
|
+
registry.vaults = registry.vaults.filter((v) => v.id !== rowId && v.repo_root_abs !== root);
|
|
82
|
+
registry.vaults.push({ id: rowId, repo_root_abs: root, account_id: accountId });
|
|
83
|
+
flush();
|
|
84
|
+
return rowId;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
process.env.HOME = home;
|
|
88
|
+
process.env.USERPROFILE = home;
|
|
89
|
+
process.env.HS_ACCOUNT_ID = accountId;
|
|
90
|
+
// The scoped registry row is bound to this account (machine-local binding), so the
|
|
91
|
+
// machine must hold a sign-in for it; an env bearer stands in for the credentials file.
|
|
92
|
+
process.env.HEYSPEX_MCP_TOKEN ||= 'hsmcp_scoped_test_token';
|
|
93
|
+
// Fence the resolver's walk inside the fixture (see the doc comment above).
|
|
94
|
+
process.env.CLAUDE_PROJECT_DIR = repoRootAbs ?? home;
|
|
95
|
+
if (repoRootAbs) {
|
|
96
|
+
registerRoot(repoRootAbs, vaultId);
|
|
97
|
+
process.env.HEYSPEX_VAULT_ROOT = repoRootAbs;
|
|
98
|
+
} else {
|
|
99
|
+
flush();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
home,
|
|
104
|
+
accountId,
|
|
105
|
+
vaultId,
|
|
106
|
+
registryPath,
|
|
107
|
+
registerRoot,
|
|
108
|
+
restore() {
|
|
109
|
+
for (const k of ENV_KEYS) {
|
|
110
|
+
if (saved[k] === undefined) delete process.env[k];
|
|
111
|
+
else process.env[k] = saved[k];
|
|
112
|
+
}
|
|
113
|
+
resetActiveConfigCache();
|
|
114
|
+
rmSync(home, { recursive: true, force: true });
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
8
119
|
/**
|
|
9
120
|
* Mirror into a temp vault every real-repo file that
|
|
10
121
|
* `scripts/validate-vault-ids.mjs` needs to run in isolation.
|
|
@@ -19,6 +130,13 @@ import { join } from 'node:path';
|
|
|
19
130
|
* id-suffix-shape rule, compiled from protocol frontmatter), so that file must be
|
|
20
131
|
* mirrored too or the engine import dangles.
|
|
21
132
|
*
|
|
133
|
+
* Post repo-split, `scripts/lib/resolve-validate-root.mjs` (copied wholesale as
|
|
134
|
+
* part of `scripts/`) also imports `vendor/heyspex-mcp/vault-resolve.mjs` by a
|
|
135
|
+
* relative path OUTSIDE `scripts/` — that file must be mirrored too, or the
|
|
136
|
+
* copied validator dangles with MODULE_NOT_FOUND the moment it computes its
|
|
137
|
+
* own default root. `vault-resolve.mjs` itself has no further local-file
|
|
138
|
+
* imports (node builtins only), so this is a single extra copy, not a chain.
|
|
139
|
+
*
|
|
22
140
|
* Single source of truth: the next dependency the validator grows is a one-line
|
|
23
141
|
* add here, not a silent breakage in every round-trip test.
|
|
24
142
|
*
|
|
@@ -28,6 +146,10 @@ import { join } from 'node:path';
|
|
|
28
146
|
export function mirrorValidatorDeps(repoRoot, root) {
|
|
29
147
|
cpSync(join(repoRoot, 'scripts'), join(root, 'scripts'), { recursive: true });
|
|
30
148
|
|
|
149
|
+
const vaultResolveRel = join('vendor', 'heyspex-mcp', 'vault-resolve.mjs');
|
|
150
|
+
mkdirSync(join(root, 'vendor', 'heyspex-mcp'), { recursive: true });
|
|
151
|
+
cpSync(join(repoRoot, vaultResolveRel), join(root, vaultResolveRel));
|
|
152
|
+
|
|
31
153
|
const indexerRel = join('spex-console', 'src', 'lib', 'indexer');
|
|
32
154
|
mkdirSync(join(root, indexerRel), { recursive: true });
|
|
33
155
|
for (const file of [
|