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.
Files changed (352) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/README.md +21 -0
  3. package/bin/hs.mjs +1089 -104
  4. package/bin/spexcode.mjs +262 -0
  5. package/dev-factory/engine/worktree.mjs +740 -0
  6. package/dev-factory/lib/code-repo-root.mjs +67 -0
  7. package/dev-factory/lib/context-budget.mjs +84 -0
  8. package/dev-factory/lib/epic-detect.mjs +190 -0
  9. package/dev-factory/lib/fleet-queue-file.mjs +846 -0
  10. package/dev-factory/lib/fleet-queue.mjs +426 -0
  11. package/dev-factory/lib/fleet-state.mjs +14 -18
  12. package/dev-factory/lib/model-catalog.mjs +338 -0
  13. package/dev-factory/lib/seat-context.mjs +199 -0
  14. package/dev-factory/lib/spec-io.mjs +93 -0
  15. package/dev-factory/lib/sufficiency-score.mjs +8 -2
  16. package/dev-factory/lib/worktree-allocator.mjs +744 -0
  17. package/dev-factory/model-catalog.json +222 -0
  18. package/dist/cli/hs-check.mjs +1127 -103
  19. package/dist/cli/hs-claim.mjs +981 -63
  20. package/dist/cli/hs-connect.mjs +10059 -1729
  21. package/dist/cli/hs-defer.mjs +5507 -3072
  22. package/dist/cli/hs-dev.mjs +576 -0
  23. package/dist/cli/hs-env.mjs +416 -302
  24. package/dist/cli/hs-index-rebuild.mjs +7334 -0
  25. package/dist/cli/hs-index-reconcile.mjs +8138 -0
  26. package/dist/cli/hs-init.mjs +2840 -149
  27. package/dist/cli/hs-install.mjs +7214 -594
  28. package/dist/cli/hs-join.mjs +10640 -2421
  29. package/dist/cli/hs-vault-pull.mjs +8157 -6370
  30. package/dist/cli/hs-vault-push.mjs +6433 -0
  31. package/dist/cli/hs-vault.mjs +4029 -1555
  32. package/dist/cli/hs-workspace.mjs +2702 -538
  33. package/dist/cli-templates/customer-vault/specs/entity-model.md +594 -601
  34. package/dist/cli-templates/customer-vault/specs/protocols/canonical-frontmatter-templates.md +110 -177
  35. package/dist/cli-templates/customer-vault/specs/protocols/destructive-action-checklist.md +122 -0
  36. package/dist/cli-templates/customer-vault/specs/protocols/memory-protocol.md +13 -15
  37. package/dist/cli-templates/customer-vault/specs/protocols/session-close-protocol.md +91 -0
  38. package/dist/cli-templates/customer-vault/specs/protocols/spec-hierarchy.md +150 -168
  39. package/dist/cli-templates/customer-vault/specs/protocols/spec-summary-authoring.md +83 -0
  40. package/dist/cli-templates/harness-commands/claude/hs-auto.md +36 -0
  41. package/dist/cli-templates/harness-commands/claude/hs-backfill.md +28 -0
  42. package/dist/cli-templates/harness-commands/claude/hs-capture.md +62 -0
  43. package/dist/cli-templates/harness-commands/claude/hs-defer.md +29 -0
  44. package/dist/cli-templates/harness-commands/claude/hs-dev.md +20 -0
  45. package/dist/cli-templates/harness-commands/claude/hs-doctor.md +32 -0
  46. package/dist/cli-templates/harness-commands/claude/hs-ground.md +30 -0
  47. package/dist/cli-templates/harness-commands/claude/hs-handoff.md +33 -0
  48. package/dist/cli-templates/harness-commands/claude/hs-log.md +27 -0
  49. package/dist/cli-templates/harness-commands/claude/hs-next.md +29 -0
  50. package/dist/cli-templates/harness-commands/claude/hs-promote.md +70 -0
  51. package/dist/cli-templates/harness-commands/claude/hs-push.md +35 -0
  52. package/dist/cli-templates/harness-commands/claude/hs-qc.md +27 -0
  53. package/dist/cli-templates/harness-commands/claude/hs-res.md +63 -0
  54. package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -0
  55. package/dist/cli-templates/harness-commands/claude/hs-review.md +23 -0
  56. package/dist/cli-templates/harness-commands/claude/hs-view.md +28 -0
  57. package/dist/cli-templates/harness-commands/claude/kill-ports.md +32 -0
  58. package/dist/cli-templates/harness-commands/claude/prototype.md +91 -0
  59. package/dist/cli-templates/harness-commands/cursor/hs-auto.md +40 -0
  60. package/dist/cli-templates/harness-commands/cursor/hs-backfill.md +31 -0
  61. package/dist/cli-templates/harness-commands/cursor/hs-capture.md +65 -0
  62. package/dist/cli-templates/harness-commands/cursor/hs-defer.md +32 -0
  63. package/dist/cli-templates/harness-commands/cursor/hs-dev.md +24 -0
  64. package/dist/cli-templates/harness-commands/cursor/hs-doctor.md +36 -0
  65. package/dist/cli-templates/harness-commands/cursor/hs-ground.md +33 -0
  66. package/dist/cli-templates/harness-commands/cursor/hs-handoff.md +37 -0
  67. package/dist/cli-templates/harness-commands/cursor/hs-log.md +31 -0
  68. package/dist/cli-templates/harness-commands/cursor/hs-next.md +32 -0
  69. package/dist/cli-templates/harness-commands/cursor/hs-promote.md +73 -0
  70. package/dist/cli-templates/harness-commands/cursor/hs-push.md +38 -0
  71. package/dist/cli-templates/harness-commands/cursor/hs-qc.md +30 -0
  72. package/dist/cli-templates/harness-commands/cursor/hs-res.md +67 -0
  73. package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +26 -0
  74. package/dist/cli-templates/harness-commands/cursor/hs-review.md +26 -0
  75. package/dist/cli-templates/harness-commands/cursor/hs-view.md +32 -0
  76. package/dist/cli-templates/harness-commands/cursor/kill-ports.md +35 -0
  77. package/dist/cli-templates/harness-commands/cursor/prototype.md +95 -0
  78. package/docs/copilot-plugin-install.md +162 -0
  79. package/docs/driving-heyspex-from-copilot.md +165 -0
  80. package/docs/mcp-client-config.md +259 -6
  81. package/package.json +249 -124
  82. package/plugins/heyspex/.claude-plugin/plugin.json +12 -0
  83. package/plugins/heyspex/.cursor-plugin/plugin.json +15 -0
  84. package/plugins/heyspex/.mcp.json +12 -0
  85. package/plugins/heyspex/README.md +309 -0
  86. package/plugins/heyspex/bin/launch-mcp.mjs +95 -0
  87. package/plugins/heyspex/bin/run-hook.mjs +80 -0
  88. package/plugins/heyspex/hooks/cursor-hooks.json +308 -0
  89. package/plugins/heyspex/hooks/hooks.json +418 -0
  90. package/plugins/heyspex/mcp.json +13 -0
  91. package/scripts/check-mcp-freshness.mjs +17 -9
  92. package/scripts/claude-hooks/_env-vault-events.mjs +68 -0
  93. package/scripts/claude-hooks/_guardrail-events.mjs +96 -0
  94. package/scripts/claude-hooks/_guardrail-loader.mjs +494 -0
  95. package/scripts/claude-hooks/_intent-classifier-router.mjs +456 -0
  96. package/scripts/claude-hooks/_intent-classifier-semantic.mjs +356 -0
  97. package/scripts/claude-hooks/_run.mjs +413 -0
  98. package/scripts/claude-hooks/_transcript-text.mjs +60 -0
  99. package/scripts/claude-hooks/_vault-retrieval.mjs +322 -0
  100. package/scripts/claude-hooks/agent-spawn-delegation-gate.mjs +133 -0
  101. package/scripts/claude-hooks/capture-execution-gate.mjs +51 -0
  102. package/scripts/claude-hooks/capture-workflow-gate.mjs +11 -0
  103. package/scripts/claude-hooks/check-auto-memory-budget.mjs +396 -0
  104. package/scripts/claude-hooks/check-claude-md-budget.mjs +327 -0
  105. package/scripts/claude-hooks/check-mcp-freshness-hook.mjs +14 -0
  106. package/scripts/claude-hooks/claim-before-code-gate.mjs +11 -0
  107. package/scripts/claude-hooks/claim-liveness-shared.mjs +577 -0
  108. package/scripts/claude-hooks/close-terminal-on-ship.mjs +64 -0
  109. package/scripts/claude-hooks/coo-denylist-gate.mjs +11 -0
  110. package/scripts/claude-hooks/coo-guard-check.mjs +11 -0
  111. package/scripts/claude-hooks/deep-research-cost-gate.mjs +11 -0
  112. package/scripts/claude-hooks/dev-server-task-reminder.mjs +15 -0
  113. package/scripts/claude-hooks/diagnose-capture-reminder.mjs +11 -0
  114. package/scripts/claude-hooks/directive-obligation-gate.mjs +11 -0
  115. package/scripts/claude-hooks/emit-claim-status.mjs +41 -0
  116. package/scripts/claude-hooks/enforce-session-sequence.mjs +11 -0
  117. package/scripts/claude-hooks/enforce-vault-naming.mjs +11 -0
  118. package/scripts/claude-hooks/env-vault-guard.mjs +11 -0
  119. package/scripts/claude-hooks/epic-milestone-phrasing-gate.mjs +11 -0
  120. package/scripts/claude-hooks/git-identity-guard.mjs +11 -0
  121. package/scripts/claude-hooks/git-reflog-audit.mjs +15 -0
  122. package/scripts/claude-hooks/git-stash-gate.mjs +11 -0
  123. package/scripts/claude-hooks/guard-auto-memory-writes.mjs +137 -0
  124. package/scripts/claude-hooks/id-display-format-gate.mjs +11 -0
  125. package/scripts/claude-hooks/inject-communication-style.mjs +86 -0
  126. package/scripts/claude-hooks/inject-coo-seat.mjs +78 -0
  127. package/scripts/claude-hooks/inject-dev-server-awareness.mjs +11 -0
  128. package/scripts/claude-hooks/inject-doctrine.mjs +13 -0
  129. package/scripts/claude-hooks/inject-vault-context.mjs +14 -0
  130. package/scripts/claude-hooks/intent-classifier-trigger.mjs +279 -0
  131. package/scripts/claude-hooks/log-session-activity.mjs +341 -0
  132. package/scripts/claude-hooks/naughty-list-gate.mjs +11 -0
  133. package/scripts/claude-hooks/notify-status-flip.mjs +72 -0
  134. package/scripts/claude-hooks/plan-exit-ingest-gate.mjs +170 -0
  135. package/scripts/claude-hooks/plan-ingest-close-reminder.mjs +66 -0
  136. package/scripts/claude-hooks/plan-review-gate.mjs +11 -0
  137. package/scripts/claude-hooks/preflight-reminder.mjs +262 -0
  138. package/scripts/claude-hooks/protected-action-intent.mjs +221 -0
  139. package/scripts/claude-hooks/research-method-guard.mjs +398 -0
  140. package/scripts/claude-hooks/research-protocol-gate.mjs +11 -0
  141. package/scripts/claude-hooks/session-end.mjs +451 -0
  142. package/scripts/claude-hooks/settings-write-gate.mjs +11 -0
  143. package/scripts/claude-hooks/settlement-check-gate.mjs +39 -0
  144. package/scripts/claude-hooks/status-flip-detect.mjs +17 -0
  145. package/scripts/claude-hooks/terminal-close-shared.mjs +426 -0
  146. package/scripts/claude-hooks/terminal-close-watcher.mjs +122 -0
  147. package/scripts/claude-hooks/vault-mirror-catchup.mjs +11 -0
  148. package/scripts/claude-hooks/vault-write-tier-guard.mjs +11 -0
  149. package/scripts/claude-hooks/wip-checkpoint.mjs +302 -0
  150. package/scripts/cursor-hooks/manifest.mjs +281 -0
  151. package/scripts/dev-server-status.mjs +34 -13
  152. package/scripts/dev-server-stop.mjs +313 -0
  153. package/scripts/heyspex-mode.mjs +288 -0
  154. package/scripts/hs-auto-resolve.mjs +240 -0
  155. package/scripts/hs-auto-source.mjs +398 -0
  156. package/scripts/hs-auto.mjs +134 -0
  157. package/scripts/hs-capture-cli.mjs +326 -0
  158. package/scripts/hs-classifier.mjs +136 -0
  159. package/scripts/hs-companion.mjs +88 -0
  160. package/scripts/hs-gateway.mjs +115 -0
  161. package/scripts/hs-mode.mjs +125 -0
  162. package/scripts/hs-next.mjs +441 -0
  163. package/scripts/hs-settings.mjs +338 -0
  164. package/scripts/hs-view.mjs +496 -0
  165. package/scripts/hs-worktree.mjs +201 -0
  166. package/scripts/install-claude-code-hooks.mjs +272 -0
  167. package/scripts/install-cursor-hooks.mjs +471 -0
  168. package/scripts/lib/agent-env-markers.mjs +38 -0
  169. package/scripts/lib/console-url-resolver.mjs +199 -61
  170. package/scripts/lib/customer-kit.mjs +1203 -0
  171. package/scripts/lib/dev-mode.mjs +249 -32
  172. package/scripts/lib/directive-obligations.mjs +349 -0
  173. package/scripts/lib/heyspex-home.mjs +72 -0
  174. package/scripts/lib/hook-dispositions.mjs +210 -0
  175. package/scripts/lib/hook-vault-header.mjs +30 -0
  176. package/scripts/lib/hs-command.mjs +277 -0
  177. package/scripts/lib/hs-companion-settings.mjs +472 -0
  178. package/scripts/lib/hs-source-branch.mjs +196 -0
  179. package/scripts/lib/hs-source-commit.mjs +59 -5
  180. package/scripts/lib/hs-source-identity.mjs +526 -0
  181. package/scripts/lib/hs-source-log.mjs +13 -22
  182. package/scripts/lib/hs-source-preflight.mjs +18 -4
  183. package/scripts/lib/hs-source-push.mjs +386 -307
  184. package/scripts/lib/hs-worktree-args.mjs +115 -0
  185. package/scripts/lib/shared-path-helpers.mjs +134 -0
  186. package/scripts/lib/standalone-doctor.mjs +540 -3
  187. package/scripts/lib/subagent-git-lock.mjs +109 -0
  188. package/scripts/lib/template-pin.mjs +34 -0
  189. package/scripts/lib/window-placement.mjs +109 -0
  190. package/scripts/provenance-lib.mjs +91 -0
  191. package/scripts/stamp-provenance-on-edit.mjs +222 -0
  192. package/scripts/wip-ledger-health.mjs +653 -0
  193. package/spexharness/doctrine/baseline/SPEXCODE-DOCTRINE.baseline.json +29 -0
  194. package/spexharness/src/adapters/audit.mjs +197 -0
  195. package/spexharness/src/adapters/claude-code.mjs +449 -0
  196. package/spexharness/src/adapters/copilot.mjs +236 -0
  197. package/spexharness/src/adapters/detect-harness.mjs +34 -0
  198. package/spexharness/src/chat/tui/ansi.mjs +448 -0
  199. package/spexharness/src/chat/tui/palette.mjs +22 -0
  200. package/spexharness/src/chat/tui/select.mjs +208 -0
  201. package/spexharness/src/config-root.mjs +54 -0
  202. package/spexharness/src/context-budget.mjs +141 -0
  203. package/spexharness/src/dev-server-control.mjs +389 -0
  204. package/spexharness/src/doctrine/behaviour.mjs +371 -0
  205. package/spexharness/src/doctrine/corpus.mjs +733 -0
  206. package/spexharness/src/doctrine/inject.mjs +338 -0
  207. package/spexharness/src/doctrine/merge.mjs +184 -0
  208. package/spexharness/src/doctrine/sources.mjs +252 -0
  209. package/spexharness/src/doctrine/synthesize.mjs +401 -0
  210. package/spexharness/src/doctrine/vault-source.mjs +574 -0
  211. package/spexharness/src/doctrine/writer.mjs +176 -0
  212. package/spexharness/src/events.mjs +84 -0
  213. package/spexharness/src/gates/_shell-write-targets.mjs +77 -0
  214. package/spexharness/src/gates/capture-workflow-gate.mjs +202 -0
  215. package/spexharness/src/gates/claim-before-code-gate.decide.mjs +33 -0
  216. package/spexharness/src/gates/claim-before-code-gate.mjs +129 -0
  217. package/spexharness/src/gates/deep-research-cost-gate.mjs +275 -0
  218. package/spexharness/src/gates/diagnose-capture-reminder.mjs +112 -0
  219. package/spexharness/src/gates/directive-obligation-gate.decide.mjs +132 -0
  220. package/spexharness/src/gates/directive-obligation-gate.mjs +183 -0
  221. package/spexharness/src/gates/enforce-session-sequence.mjs +895 -0
  222. package/spexharness/src/gates/enforce-vault-naming.mjs +215 -0
  223. package/spexharness/src/gates/epic-milestone-phrasing-gate.mjs +233 -0
  224. package/spexharness/src/gates/git-identity-guard.decide.mjs +436 -0
  225. package/spexharness/src/gates/git-identity-guard.mjs +61 -0
  226. package/spexharness/src/gates/git-reflog-audit.mjs +151 -0
  227. package/spexharness/src/gates/git-stash-gate.decide.mjs +361 -0
  228. package/spexharness/src/gates/git-stash-gate.mjs +159 -0
  229. package/spexharness/src/gates/id-display-format-gate.mjs +190 -0
  230. package/spexharness/src/gates/inject-doctrine-gate.mjs +89 -0
  231. package/spexharness/src/gates/inject-vault-context.mjs +239 -0
  232. package/spexharness/src/gates/naughty-list-gate.mjs +213 -0
  233. package/spexharness/src/gates/plan-review-gate.mjs +233 -0
  234. package/spexharness/src/gates/preflight-reminder-gate.mjs +265 -0
  235. package/spexharness/src/gates/research-protocol-gate.mjs +175 -0
  236. package/spexharness/src/gates/settings-write-gate.decide.mjs +96 -0
  237. package/spexharness/src/gates/settings-write-gate.mjs +104 -0
  238. package/spexharness/src/gates/vault-mirror-catchup.mjs +124 -0
  239. package/spexharness/src/gates/vault-write-tier-guard.decide.mjs +125 -0
  240. package/spexharness/src/gates/vault-write-tier-guard.mjs +42 -0
  241. package/spexharness/src/git-reflog-audit.mjs +294 -0
  242. package/spexharness/src/intent-classifier.mjs +196 -0
  243. package/spexharness/src/intent-directive.mjs +626 -0
  244. package/spexharness/src/profile/learn.mjs +551 -0
  245. package/spexharness/src/profile/proposals.mjs +357 -0
  246. package/spexharness/src/profile/vault-inclusion.mjs +386 -0
  247. package/spexharness/src/redact.mjs +151 -0
  248. package/spexharness/src/rule-table.mjs +849 -0
  249. package/spexharness/src/seat-context.mjs +122 -0
  250. package/spexharness/src/session-bootstrap.mjs +512 -0
  251. package/spexharness/src/session-record.mjs +815 -0
  252. package/spexharness/src/token-inventory.mjs +207 -0
  253. package/vendor/heyspex-mcp/account-switch.mjs +96 -0
  254. package/vendor/heyspex-mcp/alignment-gate.mjs +315 -1
  255. package/vendor/heyspex-mcp/blocker-resolver.mjs +37 -2
  256. package/vendor/heyspex-mcp/breakdown-ladder.mjs +119 -4
  257. package/vendor/heyspex-mcp/breakdown-source.mjs +271 -0
  258. package/vendor/heyspex-mcp/breakdown-writer.mjs +23 -3
  259. package/vendor/heyspex-mcp/capture-buffer-patches.mjs +77 -8
  260. package/vendor/heyspex-mcp/capture-channel.mjs +55 -5
  261. package/vendor/heyspex-mcp/capture-console-client.mjs +117 -3
  262. package/vendor/heyspex-mcp/capture-focus.mjs +1061 -31
  263. package/vendor/heyspex-mcp/capture-outbox.mjs +15 -5
  264. package/vendor/heyspex-mcp/capture-sources.mjs +195 -0
  265. package/vendor/heyspex-mcp/capture-tools.mjs +1264 -0
  266. package/vendor/heyspex-mcp/claim-tools.mjs +1147 -0
  267. package/vendor/heyspex-mcp/cli-verbs.mjs +2074 -0
  268. package/vendor/heyspex-mcp/cli.mjs +207 -15524
  269. package/vendor/heyspex-mcp/close-branch-report.mjs +102 -0
  270. package/vendor/heyspex-mcp/cloud-tool-surface.mjs +128 -0
  271. package/vendor/heyspex-mcp/cloud-vault-writes.mjs +602 -0
  272. package/vendor/heyspex-mcp/config-seed.yaml +15 -0
  273. package/vendor/heyspex-mcp/config-settings.mjs +290 -7
  274. package/vendor/heyspex-mcp/console-fetch.mjs +822 -17
  275. package/vendor/heyspex-mcp/console-transport.mjs +172 -0
  276. package/vendor/heyspex-mcp/credentials.mjs +585 -0
  277. package/vendor/heyspex-mcp/defer-spec.mjs +44 -4
  278. package/vendor/heyspex-mcp/deferred-reclaim.mjs +29 -3
  279. package/vendor/heyspex-mcp/design-handlers.mjs +31 -0
  280. package/vendor/heyspex-mcp/design-tools.mjs +4 -1
  281. package/vendor/heyspex-mcp/dev-factory-bridge.mjs +4 -4
  282. package/vendor/heyspex-mcp/dev-mode-core.mjs +45 -0
  283. package/vendor/heyspex-mcp/dev-tools.mjs +131 -0
  284. package/vendor/heyspex-mcp/diagnose-handlers.mjs +54 -0
  285. package/vendor/heyspex-mcp/events-tools.mjs +207 -0
  286. package/vendor/heyspex-mcp/filing-tools.mjs +723 -0
  287. package/vendor/heyspex-mcp/fleet-handlers.mjs +37 -0
  288. package/vendor/heyspex-mcp/fleet-queue-tools.mjs +71 -15
  289. package/vendor/heyspex-mcp/focus-tools.mjs +190 -0
  290. package/vendor/heyspex-mcp/folder-trust-store.mjs +60 -0
  291. package/vendor/heyspex-mcp/http-transport.mjs +302 -0
  292. package/vendor/heyspex-mcp/list-tools.mjs +257 -0
  293. package/vendor/heyspex-mcp/login-handoff.mjs +15 -1
  294. package/vendor/heyspex-mcp/mcp-config.mjs +107 -0
  295. package/vendor/heyspex-mcp/memory-tools.mjs +523 -0
  296. package/vendor/heyspex-mcp/mvp-mode.mjs +53 -6
  297. package/vendor/heyspex-mcp/obligation-backstop.mjs +103 -0
  298. package/vendor/heyspex-mcp/occupied-keys.mjs +142 -0
  299. package/vendor/heyspex-mcp/on-deck-brief.mjs +3377 -0
  300. package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -0
  301. package/vendor/heyspex-mcp/package-root.mjs +32 -0
  302. package/vendor/heyspex-mcp/peer-presence.mjs +8 -1
  303. package/vendor/heyspex-mcp/plan-ground.mjs +621 -652
  304. package/vendor/heyspex-mcp/plan-push.mjs +908 -22
  305. package/vendor/heyspex-mcp/plan-review.mjs +124 -30
  306. package/vendor/heyspex-mcp/preflight-gate.mjs +0 -0
  307. package/vendor/heyspex-mcp/procedure-handlers.mjs +327 -0
  308. package/vendor/heyspex-mcp/procedure-tools.mjs +1181 -970
  309. package/vendor/heyspex-mcp/promote-capture.mjs +388 -69
  310. package/vendor/heyspex-mcp/promote-diagnose.mjs +74 -0
  311. package/vendor/heyspex-mcp/promote-research-to-diagnose.mjs +9 -2
  312. package/vendor/heyspex-mcp/promote-research.mjs +666 -53
  313. package/vendor/heyspex-mcp/promotion-helpers.mjs +251 -0
  314. package/vendor/heyspex-mcp/prompts.mjs +1460 -0
  315. package/vendor/heyspex-mcp/read-path.mjs +191 -15
  316. package/vendor/heyspex-mcp/receipt-shape.mjs +146 -0
  317. package/vendor/heyspex-mcp/recipe-handlers.mjs +117 -0
  318. package/vendor/heyspex-mcp/regen-tasks.mjs +210 -3
  319. package/vendor/heyspex-mcp/register-spec.mjs +266 -54
  320. package/vendor/heyspex-mcp/request-context.mjs +83 -0
  321. package/vendor/heyspex-mcp/research-focus.mjs +207 -4
  322. package/vendor/heyspex-mcp/research-handlers.mjs +625 -0
  323. package/vendor/heyspex-mcp/research-tools.mjs +4 -4
  324. package/vendor/heyspex-mcp/response-budget.mjs +348 -0
  325. package/vendor/heyspex-mcp/review-focus.mjs +25 -1
  326. package/vendor/heyspex-mcp/roadmap-default.mjs +70 -0
  327. package/vendor/heyspex-mcp/search-specs.mjs +280 -0
  328. package/vendor/heyspex-mcp/seat-block-ledger.mjs +113 -0
  329. package/vendor/heyspex-mcp/seat-identity.mjs +2 -6
  330. package/vendor/heyspex-mcp/session-owner.mjs +109 -0
  331. package/vendor/heyspex-mcp/session-tools.mjs +162 -0
  332. package/vendor/heyspex-mcp/settings-registry.mjs +232 -0
  333. package/vendor/heyspex-mcp/settings-tools.mjs +85 -12
  334. package/vendor/heyspex-mcp/spec-edit-tools.mjs +453 -0
  335. package/vendor/heyspex-mcp/spec-id-lib.mjs +93 -17
  336. package/vendor/heyspex-mcp/split-research.mjs +304 -56
  337. package/vendor/heyspex-mcp/stdio-rpc.mjs +22 -0
  338. package/vendor/heyspex-mcp/submit-for-review.mjs +150 -7
  339. package/vendor/heyspex-mcp/summary-contract.mjs +105 -0
  340. package/vendor/heyspex-mcp/summary-write-tools.mjs +228 -0
  341. package/vendor/heyspex-mcp/symptom-query.mjs +146 -0
  342. package/vendor/heyspex-mcp/test-helpers.mjs +123 -1
  343. package/vendor/heyspex-mcp/tool-catalog.mjs +2819 -0
  344. package/vendor/heyspex-mcp/tool-dispatch.mjs +657 -0
  345. package/vendor/heyspex-mcp/tool-helpers.mjs +325 -0
  346. package/vendor/heyspex-mcp/validate-linkage.mjs +414 -27
  347. package/vendor/heyspex-mcp/vault-io.mjs +720 -0
  348. package/vendor/heyspex-mcp/vault-less-endpoints.mjs +52 -0
  349. package/vendor/heyspex-mcp/vault-resolve.mjs +554 -68
  350. package/vendor/heyspex-mcp/verify-reproduction.mjs +270 -30
  351. package/vendor/heyspex-mcp/whoami.mjs +92 -0
  352. package/vendor/heyspex-mcp/write-outbox.mjs +512 -0
@@ -13,47 +13,106 @@
13
13
  * documented the drift that causes. This module is the ONE implementation;
14
14
  * all five now import/delegate to it.
15
15
  *
16
- * Precedence (cloud-first — an explicit override always wins over ambient
17
- * discovery, and a paired cloud console outranks a stale local dev-server
18
- * discovery file):
19
- * 1. `HEYSPEX_CONSOLE_URL` env (legacy-cockpit: `HEYSPEX_COCKPIT_URL`)
16
+ * MODE-AWARE precedence ([[HS-VOJ7-YL1C-DIAG-console-url-resolver-ignores-dev-mode]];
17
+ * it also closes [[HS-3UZS-EKLJ-DIAG-a-brand-new-team-member-s-one-command]]
18
+ * Gap 1 — a fresh clone with nothing configured resolves to the production
19
+ * console instead of guessing localhost, because the default mode is prod).
20
+ * The resolved dev mode (`scripts/lib/dev-mode.mjs` `resolveDevMode`: env →
21
+ * `~/.heyspex/dev-mode.json` → default prod) decides whether the repo's
22
+ * discovery file is even eligible, because that file is an ADMIN-LOCAL
23
+ * artifact: cloud is the default reliance for every HeySpex customer, and
24
+ * local reliance exists only for HeySpex admins developing HeySpex. A stale
25
+ * localhost pointer must never outrank the resolved cloud console.
26
+ *
27
+ * 1. `HEYSPEX_CONSOLE_URL` env
20
28
  * 2. `console_url:` in `~/.heyspex/credentials.yaml` — written by
21
- * `hs mcp pair <code>` when a machine pairs with a deployed console,
22
- * and by `hs dev local` (owner-only) when the owner's OWN machine
23
- * overrides to `http://localhost:3000` — that write is rung 2, so it
24
- * wins over the rung-4 default below without needing rung 1
25
- * 3. `.heyspex/console-url` discovery file in the repo (legacy-cockpit `cockpit-url`)
29
+ * `hs mcp pair <code>` / `hs login` / `hs dev mode:<...>`.
30
+ * **Skipped when the resolved reliance is `cloud` and the value is a
31
+ * loopback address** (localhost / 127.0.0.1 / ::1): `hs dev mode:local`
32
+ * writes `http://localhost:3000` here, and a later hand-edit of the mode
33
+ * file to prod left that stale pointer outranking the derived
34
+ * production console — every cloud call then went to a dev server the
35
+ * machine no longer runs. Logged once to stderr; the env override above
36
+ * is still honored verbatim (an explicit loopback env is operator intent,
37
+ * e.g. the stand-in consoles the test suites bind).
38
+ * 3. `.heyspex/console-url` discovery file in the repo
26
39
  * — written by the local dev-server launcher
27
- * (`spex-console/scripts/ensure-next-dev.mjs`), ephemeral per session
28
- * 4. `https://app.heyspex.com` (the cloud console — [[HS-3UZS-EKLJ-DIAG-a-brand-new-team-member-s-one-command]]
29
- * Gap 1: a fresh clone with none of the above set has no way to
30
- * discover the production console, and used to silently guess
31
- * localhost instead, which for anyone but the owner is unreachable and
32
- * degrades every registration to registry.json-only. The owner's own
33
- * daily local tooling is unaffected — rung 2 above always wins for them.)
40
+ * (`spex-console/scripts/ensure-next-dev.mjs`), ephemeral per session.
41
+ * **Consulted ONLY when the resolved reliance is `local`.**
42
+ * 4. The DERIVED console URL for the resolved mode — `deriveSemantics()`:
43
+ * prod / dev+cloud → `https://app.heyspex.com`, dev+local →
44
+ * `http://localhost:3000`. Never a hard-coded literal.
45
+ *
46
+ * Steps 1 and 2 are explicit operator intent, so they still win in both
47
+ * reliances. Local reliance behaves exactly as it did before this change
48
+ * (discovery file, then the localhost default, including `strict`).
34
49
  *
35
- * Plain Node ESM, zero deps beyond `node:fs`/`node:os`/`node:path` — every
36
- * consumer (vendor MCP server, Claude-hook scripts, dev-factory dispatchers)
37
- * can import this directly with no build step and no risk of pulling in a
38
- * dependency that isn't installed in their execution context.
50
+ * Plain Node ESM, zero deps beyond `node:fs`/`node:os`/`node:path` (the one
51
+ * import, `./dev-mode.mjs`, obeys the same rule) — every consumer (vendor MCP
52
+ * server, Claude-hook scripts, dev-factory dispatchers) can import this
53
+ * directly with no build step and no risk of pulling in a dependency that
54
+ * isn't installed in their execution context. Stays SYNCHRONOUS and does zero
55
+ * network I/O: it runs on every console request.
39
56
  */
57
+ import { heyspexHome } from './heyspex-home.mjs';
40
58
  import { readFileSync } from 'node:fs';
41
59
  import { homedir } from 'node:os';
42
60
  import { join } from 'node:path';
43
61
 
62
+ import { CLOUD_CONSOLE_URL, LOCAL_CONSOLE_URL, resolveDevMode } from './dev-mode.mjs';
63
+
44
64
  /**
45
- * The rung-4 fallback when nothing else resolves — the cloud console, so a
46
- * fresh clone reaches production instead of guessing localhost. Literal
47
- * mirror of `CLOUD_CONSOLE_URL` (`spex-console/src/lib/dev-mode.ts`): this
48
- * file stays dependency-free plain Node (see module doc), so it cannot
49
- * import that TS module — keep the two literals in sync by hand.
65
+ * The last-resort console URL for LOCAL reliance only (cloud reliance falls
66
+ * back to the derived cloud console instead). Re-exported from
67
+ * `dev-mode.mjs` so there is exactly one localhost literal in the codebase.
50
68
  */
51
- export const DEFAULT_CONSOLE_URL = 'https://app.heyspex.com';
69
+ export const DEFAULT_CONSOLE_URL = LOCAL_CONSOLE_URL;
52
70
 
53
71
  function trimTrailingSlash(url) {
54
72
  return url.replace(/\/+$/, '');
55
73
  }
56
74
 
75
+ /** Host names that can only ever name THIS machine's own dev console. */
76
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0']);
77
+
78
+ /**
79
+ * True when `url` points at a loopback host — a console that lives on this
80
+ * machine, which a cloud-reliance session has no business talking to. Never
81
+ * throws: an unparseable value is simply "not loopback" and falls through to
82
+ * the same handling it had before.
83
+ */
84
+ export function isLoopbackConsoleUrl(url) {
85
+ if (typeof url !== 'string' || !url) return false;
86
+ try {
87
+ return LOOPBACK_HOSTS.has(new URL(url).hostname.toLowerCase());
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+
93
+ // Once per process: the resolver runs on every console request, and a stale
94
+ // pointer repeating itself on each call would bury the one line that matters.
95
+ let staleLoopbackCredentialsWarned = false;
96
+
97
+ /** Test seam — re-arm the once-per-process stderr notice. */
98
+ export function resetConsoleUrlResolverWarnings() {
99
+ staleLoopbackCredentialsWarned = false;
100
+ }
101
+
102
+ function warnStaleLoopbackCredentialsOnce(credentialsUrl, derivedUrl, { log }) {
103
+ if (staleLoopbackCredentialsWarned) return;
104
+ staleLoopbackCredentialsWarned = true;
105
+ try {
106
+ log(
107
+ `[heyspex] ignoring console_url ${credentialsUrl} from ~/.heyspex/credentials.yaml: ` +
108
+ `the resolved reliance is cloud, and a loopback console cannot serve it — using ${derivedUrl} ` +
109
+ '(set HEYSPEX_CONSOLE_URL to override explicitly, or run `hs dev mode:local` to go back to a local console).\n',
110
+ );
111
+ } catch {
112
+ // A logging failure must never break URL resolution.
113
+ }
114
+ }
115
+
57
116
  /**
58
117
  * Read `console_url:` out of `~/.heyspex/credentials.yaml` with a targeted
59
118
  * regex rather than a full YAML parse — mirrors the same
@@ -62,10 +121,10 @@ function trimTrailingSlash(url) {
62
121
  * consumers (some of which run standalone, outside the npm workspace's
63
122
  * hoisted `node_modules`) can call it with zero new dependencies.
64
123
  */
65
- export function readCredentialsConsoleUrl({ homeDir = homedir() } = {}) {
124
+ export function readCredentialsConsoleUrl({ homeDir = heyspexHome(), readFile = defaultReadFile } = {}) {
66
125
  try {
67
- const raw = readFileSync(join(homeDir, '.heyspex', 'credentials.yaml'), 'utf8');
68
- const match = raw.match(/^console_url:\s*["']?([^"'\r\n#]+)/m);
126
+ const raw = readFile(join(homeDir, '.heyspex', 'credentials.yaml'));
127
+ const match = String(raw ?? '').match(/^console_url:\s*["']?([^"'\r\n#]+)/m);
69
128
  const value = match?.[1]?.trim();
70
129
  return value && value.length > 0 ? trimTrailingSlash(value) : null;
71
130
  } catch {
@@ -74,49 +133,92 @@ export function readCredentialsConsoleUrl({ homeDir = homedir() } = {}) {
74
133
  }
75
134
  }
76
135
 
77
- /** Read the repo's `.heyspex/console-url` (or legacy-cockpit `cockpit-url`) discovery file. */
78
- export function readDiscoveryFileConsoleUrl(repoRoot) {
136
+ /** Default IO for the two file rungs — `readFileSync` utf8; tests inject their own. */
137
+ function defaultReadFile(p) {
138
+ return readFileSync(p, 'utf8');
139
+ }
140
+
141
+ /**
142
+ * Read the repo's `.heyspex/console-url` discovery file. `readDiscovery` is
143
+ * the seam the `hs` bins already inject (a `(path) => string | null` reader);
144
+ * it defaults to the real file read.
145
+ */
146
+ export function readDiscoveryFileConsoleUrl(repoRoot, { readDiscovery = defaultReadFile } = {}) {
79
147
  if (!repoRoot) return null;
80
- for (const name of ['console-url', 'cockpit-url' /* legacy-cockpit */]) {
81
- // legacy-cockpit: pre-rename launchers only wrote cockpit-url — keep resolving it.
82
- try {
83
- const discovery = readFileSync(join(repoRoot, '.heyspex', name), 'utf8').trim();
84
- if (discovery.length > 0) return trimTrailingSlash(discovery);
85
- } catch {
86
- // Missing or unreadable — try the next candidate.
87
- }
148
+ try {
149
+ const discovery = String(readDiscovery(join(repoRoot, '.heyspex', 'console-url')) ?? '').trim();
150
+ if (discovery.length > 0) return trimTrailingSlash(discovery);
151
+ } catch {
152
+ // Missing or unreadable — no discovery-file override.
88
153
  }
89
154
  return null;
90
155
  }
91
156
 
92
157
  /**
93
- * Thrown by {@link resolveConsoleUrl} in `strict` mode when nothing in the
94
- * precedence chain (env → credentials file → discovery file) resolves —
95
- * i.e. the caller is about to guess `DEFAULT_CONSOLE_URL` instead of knowing
96
- * the real console URL ([[HS-OQ34-G59F-DIAG-console-url-silently-defaults-to]]:
97
- * "not knowing the port produces a guess, not an error").
158
+ * Thrown by {@link resolveConsoleUrl} in `strict` mode when the resolved
159
+ * reliance is `local` and nothing in the precedence chain (env → credentials
160
+ * file → discovery file) resolves — i.e. the caller is about to guess a
161
+ * localhost PORT instead of knowing the real console URL
162
+ * ([[HS-OQ34-G59F-DIAG-console-url-silently-defaults-to]]: "not knowing the
163
+ * port produces a guess, not an error").
164
+ *
165
+ * Cloud reliance never throws: the derived cloud console
166
+ * (`https://app.heyspex.com`) is a resolved answer, not a guess
167
+ * ([[HS-VOJ7-YL1C-DIAG-console-url-resolver-ignores-dev-mode]]).
98
168
  */
99
169
  export class ConsoleUrlUnresolvedError extends Error {
100
170
  constructor() {
101
171
  super(
102
- 'resolveConsoleUrl: no HEYSPEX_CONSOLE_URL/HEYSPEX_COCKPIT_URL env, no console_url: in ' + // legacy-cockpit env name
103
- '~/.heyspex/credentials.yaml, and no .heyspex/console-url discovery file — refusing to ' +
104
- `silently fall back to the ${DEFAULT_CONSOLE_URL} default in strict mode.`,
172
+ 'resolveConsoleUrl: local reliance with no HEYSPEX_CONSOLE_URL env, ' +
173
+ 'no console_url: in ~/.heyspex/credentials.yaml, and no .heyspex/console-url discovery ' +
174
+ 'file — refusing to silently fall back to the localhost:3000 default in strict mode.',
105
175
  );
106
176
  this.name = 'ConsoleUrlUnresolvedError';
107
177
  }
108
178
  }
109
179
 
180
+ /**
181
+ * The resolved dev mode, read synchronously and with zero network I/O:
182
+ * `resolveDevMode` consults env → `~/.heyspex/dev-mode.json` → default prod,
183
+ * and never talks to Neon when `cloudSetting` is left undefined (as here).
184
+ * Fail-open: any unexpected failure degrades to the legacy local answer so a
185
+ * hook script can never be broken by a malformed mode record.
186
+ */
187
+ function resolveModeEnvelope({ env, homeDir }) {
188
+ try {
189
+ const resolved = resolveDevMode({ env, homeDir });
190
+ return {
191
+ reliance: resolved.reliance === 'cloud' ? 'cloud' : 'local',
192
+ consoleUrl: resolved.consoleUrl || DEFAULT_CONSOLE_URL,
193
+ };
194
+ } catch {
195
+ return { reliance: 'local', consoleUrl: DEFAULT_CONSOLE_URL };
196
+ }
197
+ }
198
+
110
199
  /**
111
200
  * Resolve the console base URL (no trailing slash) per the precedence above.
112
201
  * Every input is injectable so callers/tests can run hermetically:
113
- * - `repoRoot` — needed only for step 3 (discovery file); omit if the
114
- * caller has no vault root to check (env/credentials-only resolution).
115
- * - `env` — defaults to `process.env`.
116
- * - `homeDir` — defaults to `os.homedir()`.
202
+ * - `repoRoot` — needed only for step 3 (discovery file, local reliance
203
+ * only); omit if the caller has no vault root to check.
204
+ * - `env` — defaults to `process.env`. Also feeds the mode resolver, so
205
+ * `HEYSPEX_DEV_MODE` / `HEYSPEX_DEV_RELIANCE` are honored here too.
206
+ * - `homeDir` — defaults to `os.homedir()`. Source of both
207
+ * `credentials.yaml` and the machine-local `dev-mode.json` record.
117
208
  * - `strict` — when `true`, throw {@link ConsoleUrlUnresolvedError} instead
118
- * of returning `DEFAULT_CONSOLE_URL` when nothing resolves. Opt-in only —
209
+ * of guessing the localhost default in LOCAL reliance. Opt-in only —
119
210
  * default `false` preserves every existing caller's fail-open behavior.
211
+ * - `devMode` — optional pre-resolved `{ reliance, consoleUrl }` envelope,
212
+ * a test/caller seam so a consumer that already resolved the mode does
213
+ * not re-read `dev-mode.json`.
214
+ * - `log` — where the once-per-process "ignoring stale loopback
215
+ * credentials" notice goes. Defaults to stderr (stdout is the MCP
216
+ * JSON-RPC channel and must stay clean); tests inject a collector.
217
+ * - `readFile` / `readDiscovery` — IO seams for the credentials rung and
218
+ * the discovery-file rung ([[HS-HL0D-WW9R-TASK-share-one-bearer-reader-and-one-console]]):
219
+ * the `hs` bins inject these through `resolveSpexConsoleUrl`
220
+ * (spex-console/src/lib/cli/defer.ts), which is now a thin call into
221
+ * THIS function instead of a second, non-mode-aware copy of it.
120
222
  *
121
223
  * Non-strict (default): never throws — every read is wrapped and falls
122
224
  * through to the next step, so a caller in a fail-open context (a
@@ -127,26 +229,62 @@ export class ConsoleUrlUnresolvedError extends Error {
127
229
  * @param {object} [options]
128
230
  * @param {string} [options.repoRoot] - needed only for step 3 (discovery file); omit if the
129
231
  * caller has no vault root to check (env/credentials-only resolution).
130
- * @param {NodeJS.ProcessEnv} [options.env] - defaults to `process.env`.
232
+ * @param {NodeJS.ProcessEnv | Record<string, string | undefined>} [options.env] - defaults to `process.env`.
131
233
  * @param {string} [options.homeDir] - defaults to `os.homedir()`.
132
234
  * @param {boolean} [options.strict] - throw {@link ConsoleUrlUnresolvedError} instead of
133
235
  * returning `DEFAULT_CONSOLE_URL` when nothing resolves. Default `false`.
236
+ * @param {{ reliance: string, consoleUrl: string }} [options.devMode] - pre-resolved mode envelope.
237
+ * @param {(line: string) => void} [options.log] - sink for the once-per-process stale-loopback notice.
238
+ * @param {(path: string) => string} [options.readFile] - reads `~/.heyspex/credentials.yaml`.
239
+ * @param {(path: string) => string | null} [options.readDiscovery] - reads `<repoRoot>/.heyspex/console-url`.
240
+ * @returns {string}
134
241
  */
135
242
  export function resolveConsoleUrl({
136
243
  repoRoot,
137
244
  env = process.env,
138
- homeDir = homedir(),
245
+ homeDir = heyspexHome(),
139
246
  strict = false,
247
+ devMode,
248
+ log = (line) => process.stderr.write(line),
249
+ readFile = defaultReadFile,
250
+ readDiscovery = defaultReadFile,
140
251
  } = {}) {
141
- const envUrl = (env.HEYSPEX_CONSOLE_URL ?? env.HEYSPEX_COCKPIT_URL)?.trim(); // legacy-cockpit env
252
+ const envUrl = env.HEYSPEX_CONSOLE_URL?.trim();
142
253
  if (envUrl) return trimTrailingSlash(envUrl);
143
254
 
144
- const credentialsUrl = readCredentialsConsoleUrl({ homeDir });
145
- if (credentialsUrl) return credentialsUrl;
255
+ // Resolved before step 2 now: the credentials rung is mode-aware. Still
256
+ // synchronous, still zero network I/O (see resolveModeEnvelope).
257
+ const mode = devMode ?? resolveModeEnvelope({ env, homeDir });
258
+ const cloud = mode.reliance === 'cloud';
146
259
 
147
- const discoveryUrl = readDiscoveryFileConsoleUrl(repoRoot);
148
- if (discoveryUrl) return discoveryUrl;
260
+ // Derived answer for the resolved mode. A cloud-reliance mode record that
261
+ // still carries a loopback `console_url` (a hand-edited `dev-mode.json`) is
262
+ // the same stale pointer in a different file, so it gets the same treatment:
263
+ // cloud derives the production console, never a localhost guess.
264
+ const derivedUrl = trimTrailingSlash(
265
+ cloud && isLoopbackConsoleUrl(mode.consoleUrl)
266
+ ? CLOUD_CONSOLE_URL
267
+ : mode.consoleUrl || DEFAULT_CONSOLE_URL,
268
+ );
269
+
270
+ const credentialsUrl = readCredentialsConsoleUrl({ homeDir, readFile });
271
+ if (credentialsUrl) {
272
+ if (cloud && isLoopbackConsoleUrl(credentialsUrl)) {
273
+ warnStaleLoopbackCredentialsOnce(credentialsUrl, derivedUrl, { log });
274
+ } else {
275
+ return credentialsUrl;
276
+ }
277
+ }
278
+
279
+ // Step 3 is ADMIN-LOCAL: the repo discovery file points at a local Next.js
280
+ // dev server, which a cloud-reliance machine has no business talking to
281
+ // (and which is routinely stale). Cloud reliance skips straight to the
282
+ // derived cloud console.
283
+ if (!cloud) {
284
+ const discoveryUrl = readDiscoveryFileConsoleUrl(repoRoot, { readDiscovery });
285
+ if (discoveryUrl) return discoveryUrl;
286
+ if (strict) throw new ConsoleUrlUnresolvedError();
287
+ }
149
288
 
150
- if (strict) throw new ConsoleUrlUnresolvedError();
151
- return DEFAULT_CONSOLE_URL;
289
+ return derivedUrl;
152
290
  }