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
@@ -0,0 +1,338 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * hs settings — CLI face of the HeySpex settings capability.
4
+ * Dispatched from bin/hs.mjs. Delegates to the ONE settings core
5
+ * (vendor/heyspex-mcp/config-settings.mjs) per the three-faces principle
6
+ * ([[capability-three-faces-no-per-capability-slash]]).
7
+ *
8
+ * Usage:
9
+ * hs settings list [prefix] [--json]
10
+ * hs settings get <dotted.key> [--json]
11
+ * hs settings set <dotted.key> <value> [--json] [--confirmed-by-user]
12
+ *
13
+ * WRITE-PERMISSION GUARDRAIL (agent-settings-protocol, owner directive
14
+ * 2026-07-11): settings writes require explicit user permission. A human typing
15
+ * `hs settings set` in their own terminal IS the permission. But when this CLI
16
+ * runs inside an agent harness (Claude Code sets CLAUDECODE=1 / CLAUDE_AGENT for
17
+ * its shell tool), the write is agent-initiated: it is refused unless
18
+ * `--confirmed-by-user` is passed, and that flag may ONLY be passed after the
19
+ * user explicitly approved the exact change in the conversation. This holds
20
+ * regardless of agent_behaviors.ask_forgiveness_not_permission — that switch
21
+ * governs behaviors, never its own controls. All writes are audited to
22
+ * .heyspex/settings-history.jsonl.
23
+ */
24
+
25
+ import fs from 'node:fs';
26
+ import path from 'node:path';
27
+ import process from 'node:process';
28
+ import { pathToFileURL } from 'node:url';
29
+
30
+ import {
31
+ listConfigLeaves,
32
+ getEffectiveSetting,
33
+ setConfigLeaf,
34
+ validateSettingKey,
35
+ } from '../vendor/heyspex-mcp/config-settings.mjs';
36
+ import {
37
+ SETTINGS_REGISTRY,
38
+ getSettingEntry,
39
+ isKnownSetting,
40
+ } from '../vendor/heyspex-mcp/settings-registry.mjs';
41
+ import { getActiveConfig } from '../vendor/heyspex-mcp/vault-resolve.mjs';
42
+
43
+ const HELP = `hs settings — read/change HeySpex workflow settings (.heyspex/config.yaml at the VAULT root)
44
+
45
+ Usage:
46
+ hs settings list [prefix] [--json] List all scalar settings (optionally under a dotted prefix)
47
+ hs settings get <dotted.key> [--json] Read one setting (e.g. agent_behaviors.capture_on_idea.enabled)
48
+ hs settings set <dotted.key> <value> Change one setting (value: string | number | true | false | null)
49
+ [--confirmed-by-user] [--json]
50
+
51
+ The settings file lives at <vault root>/.heyspex/config.yaml (ADR-0009). If it is
52
+ missing, \`hs settings set\` creates it from the shipped seed template first and
53
+ then applies the change (reads never create it) — \`hs init\` seeds the same file.
54
+
55
+ Write permission (agent-settings-protocol):
56
+ A human running \`hs settings set\` directly is inherently permissioned. Inside an
57
+ agent harness (CLAUDECODE / CLAUDE_AGENT env present) the write is refused unless
58
+ --confirmed-by-user is passed — and an agent may pass it ONLY after the user
59
+ explicitly approved the exact change. Writes are audited to
60
+ .heyspex/settings-history.jsonl. Agents should prefer the MCP tool
61
+ heyspex_settings_set (two-step confirm).
62
+ `;
63
+
64
+ /**
65
+ * The vault root this face reads/writes. `bin/hs.mjs` always forwards
66
+ * `HS_VAULT_ROOT`; the last fallback (this script run directly) asks the shared
67
+ * vault resolver — NEVER this code checkout. Since the 2026-08-31 repo split the
68
+ * vault is a sibling repo, so falling back to `scripts/..` silently read/wrote a
69
+ * `.heyspex/config.yaml` the console and MCP never look at
70
+ * ([[HS-4C76-9W86-DIAG-heyspex-config-yaml-has-no-single-home]]).
71
+ */
72
+ function vaultRoot() {
73
+ return process.env.HS_VAULT_ROOT || process.env.HEYSPEX_VAULT_ROOT || getActiveConfig().repoRootAbs;
74
+ }
75
+
76
+ function isAgentHarness() {
77
+ return Boolean(
78
+ process.env.CLAUDECODE ||
79
+ process.env.CLAUDE_AGENT ||
80
+ process.env.CLAUDE_CODE_SESSION_ID ||
81
+ process.env.CURSOR_AGENT,
82
+ );
83
+ }
84
+
85
+ /**
86
+ * True when `root` is the HeySpex platform vault rather than a
87
+ * customer-provisioned one. `hs init --customer-vault` unconditionally stamps
88
+ * `template_version: <…>` into the scaffolded vault's `heyspex.yaml`
89
+ * (`spex-console/src/lib/cli/init-git-finalize.ts` `gitFinalizeHook` /
90
+ * `ensureTemplateVersionLine`) — the platform vault's own marker never
91
+ * carries that field. That stamp is the one on-disk, offline-readable signal
92
+ * that distinguishes the two without a network/account lookup (the MCP/CLI
93
+ * process is standalone, per `vendor/heyspex-mcp/vault-resolve.mjs`'s module
94
+ * doc). A vault with no `heyspex.yaml` at all (e.g. this code checkout run
95
+ * directly, with no vault marker) is treated as platform — it is not a
96
+ * customer scaffold. Registry-declared admin-only entries (e.g.
97
+ * `close_out.run_command_drift_doctor`) are hidden from `hs settings list`
98
+ * everywhere `template_version` is present ([[HS-5MNS-15XI-TASK]] AC4).
99
+ */
100
+ export function isHeyspexPlatformVault(root) {
101
+ let raw;
102
+ try {
103
+ raw = fs.readFileSync(path.join(root, 'heyspex.yaml'), 'utf8');
104
+ } catch {
105
+ return true; // no marker at all — not a customer scaffold
106
+ }
107
+ return !/^template_version:\s*\S+/m.test(raw);
108
+ }
109
+
110
+ /** How a value's `source` reads in a one-line human sentence. */
111
+ function describeSource(source) {
112
+ if (source === 'file') return 'settings file';
113
+ if (source === 'registry_default') return 'shipped default';
114
+ return 'absent';
115
+ }
116
+
117
+ /**
118
+ * Build the `hs settings list` result: every registry entry this vault ships
119
+ * (admin-only entries dropped in a non-platform vault), each carrying its
120
+ * effective value/source plus its shipped default and description, followed
121
+ * by any keys the settings file has that the registry does not declare
122
+ * (marked `unrecognised: true`) — the freeform namespaces the registry has
123
+ * not been taught yet (`agent_behaviors.*`, `mvp_mode.*`, …) land here too,
124
+ * unchanged from their pre-registry values.
125
+ * ([[HS-5MNS-15XI-TASK-show-every-declared-setting-in-the]])
126
+ *
127
+ * @param {string} root
128
+ * @param {string} [prefix] - optional dotted-key prefix filter
129
+ * @returns {{ declared: object[], unrecognised: object[] }}
130
+ */
131
+ export function buildListEntries(root, prefix, options = {}) {
132
+ const trimmedPrefix = (prefix ?? '').trim();
133
+ const matchesPrefix = (key) =>
134
+ !trimmedPrefix || key === trimmedPrefix || key.startsWith(trimmedPrefix + '.');
135
+ const platform = isHeyspexPlatformVault(root);
136
+
137
+ const declared = [];
138
+ for (const entry of SETTINGS_REGISTRY) {
139
+ if (entry.adminOnly && !platform) continue;
140
+ if (!matchesPrefix(entry.key)) continue;
141
+ const effective = getEffectiveSetting(root, entry.key, options);
142
+ declared.push({
143
+ key: entry.key,
144
+ value: effective.value,
145
+ source: effective.source,
146
+ default: entry.default,
147
+ type: entry.type,
148
+ description: entry.description,
149
+ cliFlag: entry.cliFlag,
150
+ adminOnly: entry.adminOnly,
151
+ enforced: entry.enforced,
152
+ ...(entry.type === 'enum' ? { values: entry.values } : {}),
153
+ });
154
+ }
155
+
156
+ const unrecognised = listConfigLeaves(root, options)
157
+ .filter((leaf) => !isKnownSetting(leaf.key))
158
+ .filter((leaf) => matchesPrefix(leaf.key))
159
+ .map((leaf) => ({ key: leaf.key, value: leaf.value, unrecognised: true }));
160
+
161
+ return { declared, unrecognised };
162
+ }
163
+
164
+ /**
165
+ * Build the `hs settings get <key>` result: the effective value (file value
166
+ * when present, else the registry's shipped default), which of the two it
167
+ * came from, and — for a name the registry does not declare AND that has no
168
+ * value in the file either — an explicit "not declared" report instead of a
169
+ * silent empty value. ([[HS-7W0S-15XI-TASK-return-the-effective-value-from-the]])
170
+ *
171
+ * @param {string} root
172
+ * @param {string} key
173
+ * @returns {object}
174
+ */
175
+ export function resolveGet(root, key, options = {}) {
176
+ const effective = getEffectiveSetting(root, key, options);
177
+ if (effective.source === 'absent') {
178
+ return { ok: true, key, found: false, known: false, value: null, source: 'absent' };
179
+ }
180
+ const entry = getSettingEntry(key);
181
+ return {
182
+ ok: true,
183
+ key,
184
+ found: effective.found,
185
+ known: Boolean(entry),
186
+ value: effective.value,
187
+ source: effective.source,
188
+ ...(entry ? { default: entry.default, description: entry.description } : {}),
189
+ };
190
+ }
191
+
192
+ /** Render `resolveGet`'s result as the plain-text `hs settings get` body. */
193
+ function renderGetText(result) {
194
+ if (result.source === 'absent') {
195
+ return `${result.key} is not set and is not declared in the settings registry (no shipped default to fall back to)\n`;
196
+ }
197
+ return `${result.key} = ${JSON.stringify(result.value)} [${describeSource(result.source)}]\n`;
198
+ }
199
+
200
+ /** Render `buildListEntries`'s result as the plain-text `hs settings list` body. */
201
+ function renderListText({ declared, unrecognised }) {
202
+ const lines = [];
203
+ for (const row of declared) {
204
+ lines.push(`${row.key} = ${JSON.stringify(row.value)} [${describeSource(row.source)}]`);
205
+ lines.push(` ${row.description}`);
206
+ }
207
+ if (unrecognised.length) {
208
+ if (declared.length) lines.push('');
209
+ lines.push('Unrecognised (not declared in the settings registry):');
210
+ for (const row of unrecognised) {
211
+ lines.push(` ${row.key} = ${JSON.stringify(row.value)}`);
212
+ }
213
+ }
214
+ if (!declared.length && !unrecognised.length) return 'no settings found\n';
215
+ return lines.join('\n') + '\n';
216
+ }
217
+
218
+ function parseValueToken(token) {
219
+ if (token === undefined) return undefined;
220
+ if (token === 'null') return null;
221
+ if (token === 'true') return true;
222
+ if (token === 'false') return false;
223
+ if (/^-?\d+(\.\d+)?$/.test(token)) return Number(token);
224
+ return token;
225
+ }
226
+
227
+ function out(obj, asJson, plain) {
228
+ if (asJson) process.stdout.write(JSON.stringify(obj, null, 2) + '\n');
229
+ else process.stdout.write(plain);
230
+ }
231
+
232
+ function main(argv) {
233
+ // bin/hs.mjs forwards the full argv (leading `settings` token included).
234
+ const args = argv[0] === 'settings' ? argv.slice(1) : argv.slice();
235
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
236
+ process.stdout.write(HELP);
237
+ process.exit(args.length === 0 ? 2 : 0);
238
+ }
239
+ const asJson = args.includes('--json');
240
+ const confirmedByUser = args.includes('--confirmed-by-user');
241
+ const positional = args.filter((a) => !a.startsWith('--'));
242
+ const [verb, keyArg, ...valueTokens] = positional;
243
+ const root = vaultRoot();
244
+
245
+ if (verb === 'list') {
246
+ const prefix = keyArg?.trim() || '';
247
+ const { declared, unrecognised } = buildListEntries(root, prefix);
248
+ out(
249
+ { ok: true, count: declared.length + unrecognised.length, declared, unrecognised },
250
+ asJson,
251
+ renderListText({ declared, unrecognised }),
252
+ );
253
+ process.exit(0);
254
+ }
255
+
256
+ if (verb === 'get') {
257
+ const check = validateSettingKey(keyArg ?? '');
258
+ if (!check.ok) {
259
+ process.stderr.write(`hs settings get: ${check.reason}\n`);
260
+ process.exit(2);
261
+ }
262
+ const result = resolveGet(root, keyArg);
263
+ out(result, asJson, renderGetText(result));
264
+ process.exit(0);
265
+ }
266
+
267
+ if (verb === 'set') {
268
+ const check = validateSettingKey(keyArg ?? '');
269
+ if (!check.ok) {
270
+ process.stderr.write(`hs settings set: ${check.reason}\n`);
271
+ process.exit(2);
272
+ }
273
+ if (valueTokens.length === 0) {
274
+ process.stderr.write('hs settings set: missing <value> (string | number | true | false | null)\n');
275
+ process.exit(2);
276
+ }
277
+ const value = parseValueToken(valueTokens.join(' '));
278
+
279
+ if (isAgentHarness() && !confirmedByUser) {
280
+ const msg =
281
+ `hs settings set: REFUSED — this shell is running inside an agent harness, and settings writes ` +
282
+ `require explicit user permission (agent-settings-protocol; independent of ` +
283
+ `ask_forgiveness_not_permission). Show the user the exact change and, only after they approve, ` +
284
+ `re-run with --confirmed-by-user (or use the MCP tool heyspex_settings_set, which has a ` +
285
+ `built-in confirm step).\n`;
286
+ process.stderr.write(msg);
287
+ process.exit(3);
288
+ }
289
+
290
+ const actor = isAgentHarness() ? 'agent (CLI, user-confirmed)' : 'human (CLI)';
291
+ const result = setConfigLeaf(root, keyArg, value, { actor, face: 'cli' });
292
+ if (!result.ok) {
293
+ process.stderr.write(`hs settings set: ${result.error} — ${result.message}\n`);
294
+ process.exit(1);
295
+ }
296
+ // HS-4C76 fix 3: the core seeds a missing config.yaml from the template on
297
+ // the first write instead of refusing — say so, since the user may not have
298
+ // known the file was absent (it is git-tracked at the vault root).
299
+ if (result.seeded === true) {
300
+ process.stderr.write(
301
+ `hs settings set: note — ${path.join(root, '.heyspex', 'config.yaml')} did not exist and was created from ` +
302
+ `the seed template before applying this change. Commit it with the vault (ADR-0009).\n`,
303
+ );
304
+ }
305
+ // The CLI face shares the core with heyspex_settings_set, so it inherits the
306
+ // measured `audited` flag ([[HS-IOJW-5YDH-DIAG]] sweep). A settings write with
307
+ // no audit row is a partial, and must not print as a clean success.
308
+ if (result.audited !== true) {
309
+ process.stderr.write(
310
+ `hs settings set: WARNING — the value was applied to .heyspex/config.yaml but the audit append to ` +
311
+ `.heyspex/settings-history.jsonl FAILED. The change is live and UNAUDITED; check that file is writable.\n`,
312
+ );
313
+ }
314
+ out(
315
+ { ok: true, ...result },
316
+ asJson,
317
+ `${keyArg}: ${JSON.stringify(result.previous)} → ${JSON.stringify(result.value)}${result.created ? ' (created)' : ''}${result.seeded === true ? ' (config.yaml seeded from template)' : ''}${result.audited === true ? '' : ' (UNAUDITED — audit append failed)'}\n`,
318
+ );
319
+ process.exit(0);
320
+ }
321
+
322
+ process.stderr.write(`hs settings: unknown subcommand \`${verb ?? ''}\` (expected: list | get | set)\n${HELP}`);
323
+ process.exit(2);
324
+ }
325
+
326
+ // Only auto-run when executed directly (`node scripts/hs-settings.mjs …` or via
327
+ // bin/hs.mjs's spawn) — not when a test imports this module for its exported
328
+ // helpers (buildListEntries, isHeyspexPlatformVault, …).
329
+ const isMain = (() => {
330
+ try {
331
+ return import.meta.url === pathToFileURL(process.argv[1] ?? '').href;
332
+ } catch {
333
+ return false;
334
+ }
335
+ })();
336
+ if (isMain) {
337
+ main(process.argv.slice(2));
338
+ }