heyspex 0.1.0 → 0.2.0

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 (322) hide show
  1. package/README.md +21 -0
  2. package/bin/hs.mjs +931 -98
  3. package/bin/spexcode.mjs +262 -0
  4. package/dev-factory/engine/worktree.mjs +740 -0
  5. package/dev-factory/lib/code-repo-root.mjs +67 -0
  6. package/dev-factory/lib/context-budget.mjs +84 -0
  7. package/dev-factory/lib/epic-detect.mjs +190 -0
  8. package/dev-factory/lib/fleet-queue-file.mjs +846 -0
  9. package/dev-factory/lib/fleet-queue.mjs +426 -0
  10. package/dev-factory/lib/fleet-state.mjs +14 -18
  11. package/dev-factory/lib/model-catalog.mjs +338 -0
  12. package/dev-factory/lib/seat-context.mjs +199 -0
  13. package/dev-factory/lib/spec-io.mjs +93 -0
  14. package/dev-factory/lib/sufficiency-score.mjs +8 -2
  15. package/dev-factory/lib/worktree-allocator.mjs +744 -0
  16. package/dev-factory/model-catalog.json +222 -0
  17. package/dist/cli/hs-check.mjs +1085 -103
  18. package/dist/cli/hs-claim.mjs +936 -63
  19. package/dist/cli/hs-connect.mjs +9786 -1910
  20. package/dist/cli/hs-defer.mjs +5267 -3053
  21. package/dist/cli/hs-dev.mjs +564 -0
  22. package/dist/cli/hs-env.mjs +385 -299
  23. package/dist/cli/hs-index-rebuild.mjs +7129 -0
  24. package/dist/cli/hs-index-reconcile.mjs +7852 -0
  25. package/dist/cli/hs-init.mjs +777 -138
  26. package/dist/cli/hs-install.mjs +6583 -485
  27. package/dist/cli/hs-join.mjs +10137 -2368
  28. package/dist/cli/hs-vault-pull.mjs +4659 -5882
  29. package/dist/cli/hs-vault.mjs +3793 -1537
  30. package/dist/cli/hs-workspace.mjs +2550 -524
  31. package/dist/cli-templates/customer-vault/specs/entity-model.md +594 -601
  32. package/dist/cli-templates/customer-vault/specs/protocols/canonical-frontmatter-templates.md +110 -177
  33. package/dist/cli-templates/customer-vault/specs/protocols/destructive-action-checklist.md +122 -0
  34. package/dist/cli-templates/customer-vault/specs/protocols/memory-protocol.md +13 -15
  35. package/dist/cli-templates/customer-vault/specs/protocols/session-close-protocol.md +91 -0
  36. package/dist/cli-templates/customer-vault/specs/protocols/spec-hierarchy.md +150 -168
  37. package/dist/cli-templates/customer-vault/specs/protocols/spec-summary-authoring.md +83 -0
  38. package/dist/cli-templates/harness-commands/claude/hs-auto.md +36 -0
  39. package/dist/cli-templates/harness-commands/claude/hs-backfill.md +28 -0
  40. package/dist/cli-templates/harness-commands/claude/hs-capture.md +62 -0
  41. package/dist/cli-templates/harness-commands/claude/hs-defer.md +29 -0
  42. package/dist/cli-templates/harness-commands/claude/hs-dev.md +20 -0
  43. package/dist/cli-templates/harness-commands/claude/hs-doctor.md +32 -0
  44. package/dist/cli-templates/harness-commands/claude/hs-ground.md +28 -0
  45. package/dist/cli-templates/harness-commands/claude/hs-handoff.md +33 -0
  46. package/dist/cli-templates/harness-commands/claude/hs-log.md +27 -0
  47. package/dist/cli-templates/harness-commands/claude/hs-next.md +29 -0
  48. package/dist/cli-templates/harness-commands/claude/hs-promote.md +70 -0
  49. package/dist/cli-templates/harness-commands/claude/hs-push.md +35 -0
  50. package/dist/cli-templates/harness-commands/claude/hs-qc.md +27 -0
  51. package/dist/cli-templates/harness-commands/claude/hs-res.md +63 -0
  52. package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -0
  53. package/dist/cli-templates/harness-commands/claude/hs-review.md +23 -0
  54. package/dist/cli-templates/harness-commands/claude/hs-view.md +26 -0
  55. package/dist/cli-templates/harness-commands/claude/kill-ports.md +32 -0
  56. package/dist/cli-templates/harness-commands/claude/prototype.md +91 -0
  57. package/dist/cli-templates/harness-commands/cursor/hs-auto.md +40 -0
  58. package/dist/cli-templates/harness-commands/cursor/hs-backfill.md +31 -0
  59. package/dist/cli-templates/harness-commands/cursor/hs-capture.md +65 -0
  60. package/dist/cli-templates/harness-commands/cursor/hs-defer.md +32 -0
  61. package/dist/cli-templates/harness-commands/cursor/hs-dev.md +24 -0
  62. package/dist/cli-templates/harness-commands/cursor/hs-doctor.md +36 -0
  63. package/dist/cli-templates/harness-commands/cursor/hs-ground.md +31 -0
  64. package/dist/cli-templates/harness-commands/cursor/hs-handoff.md +37 -0
  65. package/dist/cli-templates/harness-commands/cursor/hs-log.md +31 -0
  66. package/dist/cli-templates/harness-commands/cursor/hs-next.md +32 -0
  67. package/dist/cli-templates/harness-commands/cursor/hs-promote.md +73 -0
  68. package/dist/cli-templates/harness-commands/cursor/hs-push.md +38 -0
  69. package/dist/cli-templates/harness-commands/cursor/hs-qc.md +30 -0
  70. package/dist/cli-templates/harness-commands/cursor/hs-res.md +67 -0
  71. package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +26 -0
  72. package/dist/cli-templates/harness-commands/cursor/hs-review.md +26 -0
  73. package/dist/cli-templates/harness-commands/cursor/hs-view.md +30 -0
  74. package/dist/cli-templates/harness-commands/cursor/kill-ports.md +35 -0
  75. package/dist/cli-templates/harness-commands/cursor/prototype.md +95 -0
  76. package/docs/mcp-client-config.md +259 -6
  77. package/package.json +231 -124
  78. package/plugins/heyspex/.claude-plugin/plugin.json +12 -0
  79. package/plugins/heyspex/.cursor-plugin/plugin.json +15 -0
  80. package/plugins/heyspex/.mcp.json +12 -0
  81. package/plugins/heyspex/bin/launch-mcp.mjs +95 -0
  82. package/plugins/heyspex/bin/run-hook.mjs +62 -0
  83. package/plugins/heyspex/hooks/cursor-hooks.json +227 -0
  84. package/plugins/heyspex/hooks/hooks.json +361 -0
  85. package/plugins/heyspex/mcp.json +13 -0
  86. package/scripts/check-mcp-freshness.mjs +17 -9
  87. package/scripts/claude-hooks/_env-vault-events.mjs +68 -0
  88. package/scripts/claude-hooks/_guardrail-events.mjs +96 -0
  89. package/scripts/claude-hooks/_guardrail-loader.mjs +494 -0
  90. package/scripts/claude-hooks/_intent-classifier-router.mjs +410 -0
  91. package/scripts/claude-hooks/_intent-classifier-semantic.mjs +351 -0
  92. package/scripts/claude-hooks/_run.mjs +120 -0
  93. package/scripts/claude-hooks/_transcript-text.mjs +60 -0
  94. package/scripts/claude-hooks/_vault-retrieval.mjs +322 -0
  95. package/scripts/claude-hooks/agent-spawn-delegation-gate.mjs +133 -0
  96. package/scripts/claude-hooks/capture-workflow-gate.mjs +11 -0
  97. package/scripts/claude-hooks/check-auto-memory-budget.mjs +396 -0
  98. package/scripts/claude-hooks/check-claude-md-budget.mjs +327 -0
  99. package/scripts/claude-hooks/check-mcp-freshness-hook.mjs +14 -0
  100. package/scripts/claude-hooks/claim-before-code-gate.mjs +11 -0
  101. package/scripts/claude-hooks/claim-liveness-shared.mjs +575 -0
  102. package/scripts/claude-hooks/close-terminal-on-ship.mjs +64 -0
  103. package/scripts/claude-hooks/coo-denylist-gate.mjs +11 -0
  104. package/scripts/claude-hooks/coo-guard-check.mjs +11 -0
  105. package/scripts/claude-hooks/deep-research-cost-gate.mjs +11 -0
  106. package/scripts/claude-hooks/dev-server-task-reminder.mjs +15 -0
  107. package/scripts/claude-hooks/emit-claim-status.mjs +41 -0
  108. package/scripts/claude-hooks/enforce-session-sequence.mjs +11 -0
  109. package/scripts/claude-hooks/enforce-vault-naming.mjs +11 -0
  110. package/scripts/claude-hooks/env-vault-guard.mjs +11 -0
  111. package/scripts/claude-hooks/epic-milestone-phrasing-gate.mjs +11 -0
  112. package/scripts/claude-hooks/git-identity-guard.mjs +11 -0
  113. package/scripts/claude-hooks/git-reflog-audit.mjs +15 -0
  114. package/scripts/claude-hooks/git-stash-gate.mjs +11 -0
  115. package/scripts/claude-hooks/guard-auto-memory-writes.mjs +137 -0
  116. package/scripts/claude-hooks/id-display-format-gate.mjs +11 -0
  117. package/scripts/claude-hooks/inject-communication-style.mjs +66 -0
  118. package/scripts/claude-hooks/inject-coo-seat.mjs +78 -0
  119. package/scripts/claude-hooks/inject-dev-server-awareness.mjs +11 -0
  120. package/scripts/claude-hooks/inject-doctrine.mjs +13 -0
  121. package/scripts/claude-hooks/inject-vault-context.mjs +14 -0
  122. package/scripts/claude-hooks/intent-classifier-trigger.mjs +247 -0
  123. package/scripts/claude-hooks/log-session-activity.mjs +341 -0
  124. package/scripts/claude-hooks/naughty-list-gate.mjs +11 -0
  125. package/scripts/claude-hooks/notify-status-flip.mjs +72 -0
  126. package/scripts/claude-hooks/plan-exit-ingest-gate.mjs +170 -0
  127. package/scripts/claude-hooks/plan-ingest-close-reminder.mjs +66 -0
  128. package/scripts/claude-hooks/plan-review-gate.mjs +11 -0
  129. package/scripts/claude-hooks/preflight-reminder.mjs +262 -0
  130. package/scripts/claude-hooks/protected-action-intent.mjs +221 -0
  131. package/scripts/claude-hooks/research-method-guard.mjs +398 -0
  132. package/scripts/claude-hooks/research-protocol-gate.mjs +11 -0
  133. package/scripts/claude-hooks/session-end.mjs +449 -0
  134. package/scripts/claude-hooks/settings-write-gate.mjs +11 -0
  135. package/scripts/claude-hooks/settlement-check-gate.mjs +39 -0
  136. package/scripts/claude-hooks/status-flip-detect.mjs +17 -0
  137. package/scripts/claude-hooks/terminal-close-shared.mjs +426 -0
  138. package/scripts/claude-hooks/terminal-close-watcher.mjs +122 -0
  139. package/scripts/claude-hooks/wip-checkpoint.mjs +298 -0
  140. package/scripts/cursor-hooks/manifest.mjs +235 -0
  141. package/scripts/dev-server-status.mjs +34 -13
  142. package/scripts/dev-server-stop.mjs +313 -0
  143. package/scripts/heyspex-mode.mjs +268 -0
  144. package/scripts/hs-auto-resolve.mjs +240 -0
  145. package/scripts/hs-auto-source.mjs +398 -0
  146. package/scripts/hs-auto.mjs +134 -0
  147. package/scripts/hs-capture-cli.mjs +326 -0
  148. package/scripts/hs-classifier.mjs +136 -0
  149. package/scripts/hs-companion.mjs +88 -0
  150. package/scripts/hs-gateway.mjs +115 -0
  151. package/scripts/hs-mode.mjs +125 -0
  152. package/scripts/hs-next.mjs +441 -0
  153. package/scripts/hs-settings.mjs +338 -0
  154. package/scripts/hs-view.mjs +333 -0
  155. package/scripts/hs-worktree.mjs +201 -0
  156. package/scripts/install-claude-code-hooks.mjs +270 -0
  157. package/scripts/install-cursor-hooks.mjs +471 -0
  158. package/scripts/lib/agent-env-markers.mjs +38 -0
  159. package/scripts/lib/console-url-resolver.mjs +197 -60
  160. package/scripts/lib/customer-kit.mjs +886 -0
  161. package/scripts/lib/dev-mode.mjs +244 -28
  162. package/scripts/lib/heyspex-home.mjs +72 -0
  163. package/scripts/lib/hs-command.mjs +277 -0
  164. package/scripts/lib/hs-companion-settings.mjs +472 -0
  165. package/scripts/lib/hs-source-commit.mjs +59 -5
  166. package/scripts/lib/hs-source-identity.mjs +526 -0
  167. package/scripts/lib/hs-source-log.mjs +11 -21
  168. package/scripts/lib/hs-source-push.mjs +107 -58
  169. package/scripts/lib/hs-worktree-args.mjs +115 -0
  170. package/scripts/lib/shared-path-helpers.mjs +134 -0
  171. package/scripts/lib/standalone-doctor.mjs +540 -3
  172. package/scripts/lib/subagent-git-lock.mjs +109 -0
  173. package/scripts/lib/template-pin.mjs +34 -0
  174. package/scripts/provenance-lib.mjs +91 -0
  175. package/scripts/stamp-provenance-on-edit.mjs +222 -0
  176. package/scripts/wip-ledger-health.mjs +653 -0
  177. package/spexharness/doctrine/baseline/SPEXCODE-DOCTRINE.baseline.json +29 -0
  178. package/spexharness/src/adapters/audit.mjs +197 -0
  179. package/spexharness/src/adapters/claude-code.mjs +441 -0
  180. package/spexharness/src/chat/tui/ansi.mjs +448 -0
  181. package/spexharness/src/chat/tui/palette.mjs +22 -0
  182. package/spexharness/src/chat/tui/select.mjs +208 -0
  183. package/spexharness/src/config-root.mjs +54 -0
  184. package/spexharness/src/context-budget.mjs +141 -0
  185. package/spexharness/src/dev-server-control.mjs +389 -0
  186. package/spexharness/src/doctrine/behaviour.mjs +371 -0
  187. package/spexharness/src/doctrine/corpus.mjs +733 -0
  188. package/spexharness/src/doctrine/inject.mjs +338 -0
  189. package/spexharness/src/doctrine/merge.mjs +184 -0
  190. package/spexharness/src/doctrine/sources.mjs +252 -0
  191. package/spexharness/src/doctrine/synthesize.mjs +401 -0
  192. package/spexharness/src/doctrine/vault-source.mjs +574 -0
  193. package/spexharness/src/doctrine/writer.mjs +176 -0
  194. package/spexharness/src/events.mjs +84 -0
  195. package/spexharness/src/gates/capture-workflow-gate.mjs +202 -0
  196. package/spexharness/src/gates/claim-before-code-gate.decide.mjs +33 -0
  197. package/spexharness/src/gates/claim-before-code-gate.mjs +129 -0
  198. package/spexharness/src/gates/deep-research-cost-gate.mjs +274 -0
  199. package/spexharness/src/gates/enforce-session-sequence.mjs +895 -0
  200. package/spexharness/src/gates/enforce-vault-naming.mjs +215 -0
  201. package/spexharness/src/gates/epic-milestone-phrasing-gate.mjs +233 -0
  202. package/spexharness/src/gates/git-identity-guard.decide.mjs +436 -0
  203. package/spexharness/src/gates/git-identity-guard.mjs +61 -0
  204. package/spexharness/src/gates/git-reflog-audit.mjs +151 -0
  205. package/spexharness/src/gates/git-stash-gate.decide.mjs +361 -0
  206. package/spexharness/src/gates/git-stash-gate.mjs +159 -0
  207. package/spexharness/src/gates/id-display-format-gate.mjs +190 -0
  208. package/spexharness/src/gates/inject-doctrine-gate.mjs +89 -0
  209. package/spexharness/src/gates/inject-vault-context.mjs +239 -0
  210. package/spexharness/src/gates/naughty-list-gate.mjs +213 -0
  211. package/spexharness/src/gates/plan-review-gate.mjs +233 -0
  212. package/spexharness/src/gates/preflight-reminder-gate.mjs +265 -0
  213. package/spexharness/src/gates/research-protocol-gate.mjs +175 -0
  214. package/spexharness/src/gates/settings-write-gate.decide.mjs +96 -0
  215. package/spexharness/src/gates/settings-write-gate.mjs +104 -0
  216. package/spexharness/src/git-reflog-audit.mjs +294 -0
  217. package/spexharness/src/intent-classifier.mjs +194 -0
  218. package/spexharness/src/intent-directive.mjs +541 -0
  219. package/spexharness/src/profile/learn.mjs +551 -0
  220. package/spexharness/src/profile/proposals.mjs +357 -0
  221. package/spexharness/src/profile/vault-inclusion.mjs +386 -0
  222. package/spexharness/src/redact.mjs +151 -0
  223. package/spexharness/src/rule-table.mjs +819 -0
  224. package/spexharness/src/seat-context.mjs +122 -0
  225. package/spexharness/src/session-bootstrap.mjs +512 -0
  226. package/spexharness/src/session-record.mjs +815 -0
  227. package/spexharness/src/token-inventory.mjs +207 -0
  228. package/vendor/heyspex-mcp/account-switch.mjs +95 -0
  229. package/vendor/heyspex-mcp/alignment-gate.mjs +315 -1
  230. package/vendor/heyspex-mcp/blocker-resolver.mjs +37 -2
  231. package/vendor/heyspex-mcp/breakdown-ladder.mjs +119 -4
  232. package/vendor/heyspex-mcp/breakdown-source.mjs +271 -0
  233. package/vendor/heyspex-mcp/breakdown-writer.mjs +23 -3
  234. package/vendor/heyspex-mcp/capture-buffer-patches.mjs +46 -5
  235. package/vendor/heyspex-mcp/capture-channel.mjs +55 -5
  236. package/vendor/heyspex-mcp/capture-console-client.mjs +80 -1
  237. package/vendor/heyspex-mcp/capture-focus.mjs +1035 -29
  238. package/vendor/heyspex-mcp/capture-outbox.mjs +5 -1
  239. package/vendor/heyspex-mcp/capture-tools.mjs +1219 -0
  240. package/vendor/heyspex-mcp/claim-tools.mjs +1124 -0
  241. package/vendor/heyspex-mcp/cli-verbs.mjs +2076 -0
  242. package/vendor/heyspex-mcp/cli.mjs +201 -15524
  243. package/vendor/heyspex-mcp/cloud-tool-surface.mjs +128 -0
  244. package/vendor/heyspex-mcp/cloud-vault-writes.mjs +412 -0
  245. package/vendor/heyspex-mcp/config-seed.yaml +15 -0
  246. package/vendor/heyspex-mcp/config-settings.mjs +290 -7
  247. package/vendor/heyspex-mcp/console-fetch.mjs +657 -16
  248. package/vendor/heyspex-mcp/console-transport.mjs +166 -0
  249. package/vendor/heyspex-mcp/credentials.mjs +584 -0
  250. package/vendor/heyspex-mcp/defer-spec.mjs +44 -4
  251. package/vendor/heyspex-mcp/deferred-reclaim.mjs +29 -3
  252. package/vendor/heyspex-mcp/design-handlers.mjs +31 -0
  253. package/vendor/heyspex-mcp/design-tools.mjs +4 -1
  254. package/vendor/heyspex-mcp/dev-factory-bridge.mjs +4 -4
  255. package/vendor/heyspex-mcp/dev-mode-core.mjs +45 -0
  256. package/vendor/heyspex-mcp/dev-tools.mjs +124 -0
  257. package/vendor/heyspex-mcp/diagnose-handlers.mjs +54 -0
  258. package/vendor/heyspex-mcp/events-tools.mjs +207 -0
  259. package/vendor/heyspex-mcp/filing-tools.mjs +688 -0
  260. package/vendor/heyspex-mcp/fleet-handlers.mjs +37 -0
  261. package/vendor/heyspex-mcp/fleet-queue-tools.mjs +69 -14
  262. package/vendor/heyspex-mcp/focus-tools.mjs +190 -0
  263. package/vendor/heyspex-mcp/folder-trust-store.mjs +59 -0
  264. package/vendor/heyspex-mcp/http-transport.mjs +300 -0
  265. package/vendor/heyspex-mcp/list-tools.mjs +257 -0
  266. package/vendor/heyspex-mcp/login-handoff.mjs +15 -1
  267. package/vendor/heyspex-mcp/mcp-config.mjs +94 -0
  268. package/vendor/heyspex-mcp/memory-tools.mjs +523 -0
  269. package/vendor/heyspex-mcp/mvp-mode.mjs +53 -6
  270. package/vendor/heyspex-mcp/occupied-keys.mjs +141 -0
  271. package/vendor/heyspex-mcp/on-deck-brief.mjs +3360 -0
  272. package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -0
  273. package/vendor/heyspex-mcp/package-root.mjs +32 -0
  274. package/vendor/heyspex-mcp/peer-presence.mjs +8 -1
  275. package/vendor/heyspex-mcp/plan-ground.mjs +621 -652
  276. package/vendor/heyspex-mcp/plan-push.mjs +906 -21
  277. package/vendor/heyspex-mcp/plan-review.mjs +124 -30
  278. package/vendor/heyspex-mcp/preflight-gate.mjs +0 -0
  279. package/vendor/heyspex-mcp/procedure-handlers.mjs +325 -0
  280. package/vendor/heyspex-mcp/procedure-tools.mjs +540 -351
  281. package/vendor/heyspex-mcp/promote-capture.mjs +386 -69
  282. package/vendor/heyspex-mcp/promote-diagnose.mjs +74 -0
  283. package/vendor/heyspex-mcp/promote-research-to-diagnose.mjs +9 -2
  284. package/vendor/heyspex-mcp/promote-research.mjs +660 -53
  285. package/vendor/heyspex-mcp/promotion-helpers.mjs +251 -0
  286. package/vendor/heyspex-mcp/prompts.mjs +1460 -0
  287. package/vendor/heyspex-mcp/read-path.mjs +29 -9
  288. package/vendor/heyspex-mcp/receipt-shape.mjs +146 -0
  289. package/vendor/heyspex-mcp/recipe-handlers.mjs +117 -0
  290. package/vendor/heyspex-mcp/regen-tasks.mjs +210 -3
  291. package/vendor/heyspex-mcp/register-spec.mjs +266 -54
  292. package/vendor/heyspex-mcp/request-context.mjs +59 -0
  293. package/vendor/heyspex-mcp/research-focus.mjs +207 -4
  294. package/vendor/heyspex-mcp/research-handlers.mjs +623 -0
  295. package/vendor/heyspex-mcp/research-tools.mjs +4 -4
  296. package/vendor/heyspex-mcp/response-budget.mjs +348 -0
  297. package/vendor/heyspex-mcp/review-focus.mjs +25 -1
  298. package/vendor/heyspex-mcp/search-specs.mjs +280 -0
  299. package/vendor/heyspex-mcp/seat-block-ledger.mjs +113 -0
  300. package/vendor/heyspex-mcp/seat-identity.mjs +2 -6
  301. package/vendor/heyspex-mcp/session-owner.mjs +108 -0
  302. package/vendor/heyspex-mcp/session-tools.mjs +152 -0
  303. package/vendor/heyspex-mcp/settings-registry.mjs +232 -0
  304. package/vendor/heyspex-mcp/settings-tools.mjs +85 -12
  305. package/vendor/heyspex-mcp/spec-edit-tools.mjs +446 -0
  306. package/vendor/heyspex-mcp/spec-id-lib.mjs +93 -17
  307. package/vendor/heyspex-mcp/split-research.mjs +301 -56
  308. package/vendor/heyspex-mcp/stdio-rpc.mjs +22 -0
  309. package/vendor/heyspex-mcp/submit-for-review.mjs +132 -6
  310. package/vendor/heyspex-mcp/summary-contract.mjs +105 -0
  311. package/vendor/heyspex-mcp/summary-write-tools.mjs +224 -0
  312. package/vendor/heyspex-mcp/symptom-query.mjs +146 -0
  313. package/vendor/heyspex-mcp/test-helpers.mjs +108 -1
  314. package/vendor/heyspex-mcp/tool-catalog.mjs +2813 -0
  315. package/vendor/heyspex-mcp/tool-dispatch.mjs +639 -0
  316. package/vendor/heyspex-mcp/tool-helpers.mjs +325 -0
  317. package/vendor/heyspex-mcp/validate-linkage.mjs +414 -27
  318. package/vendor/heyspex-mcp/vault-io.mjs +724 -0
  319. package/vendor/heyspex-mcp/vault-less-endpoints.mjs +52 -0
  320. package/vendor/heyspex-mcp/vault-resolve.mjs +366 -68
  321. package/vendor/heyspex-mcp/verify-reproduction.mjs +270 -30
  322. package/vendor/heyspex-mcp/whoami.mjs +91 -0
@@ -12,6 +12,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
12
12
  if (typeof require !== "undefined") return require.apply(this, arguments);
13
13
  throw Error('Dynamic require of "' + x + '" is not supported');
14
14
  });
15
+ var __esm = (fn, res) => function __init() {
16
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
17
+ };
15
18
  var __commonJS = (cb, mod2) => function __require2() {
16
19
  return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
17
20
  };
@@ -109,8 +112,8 @@ var require_main = __commonJS({
109
112
  "node_modules/dotenv/lib/main.js"(exports, module) {
110
113
  "use strict";
111
114
  var fs = __require("fs");
112
- var path6 = __require("path");
113
- var os = __require("os");
115
+ var path7 = __require("path");
116
+ var os2 = __require("os");
114
117
  var crypto3 = __require("crypto");
115
118
  var packageJson = require_package();
116
119
  var version = packageJson.version;
@@ -225,7 +228,7 @@ var require_main = __commonJS({
225
228
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
226
229
  }
227
230
  } else {
228
- possibleVaultPath = path6.resolve(process.cwd(), ".env.vault");
231
+ possibleVaultPath = path7.resolve(process.cwd(), ".env.vault");
229
232
  }
230
233
  if (fs.existsSync(possibleVaultPath)) {
231
234
  return possibleVaultPath;
@@ -233,7 +236,7 @@ var require_main = __commonJS({
233
236
  return null;
234
237
  }
235
238
  function _resolveHome(envPath) {
236
- return envPath[0] === "~" ? path6.join(os.homedir(), envPath.slice(1)) : envPath;
239
+ return envPath[0] === "~" ? path7.join(os2.homedir(), envPath.slice(1)) : envPath;
237
240
  }
238
241
  function _configVault(options) {
239
242
  const debug = Boolean(options && options.debug);
@@ -250,7 +253,7 @@ var require_main = __commonJS({
250
253
  return { parsed };
251
254
  }
252
255
  function configDotenv(options) {
253
- const dotenvPath2 = path6.resolve(process.cwd(), ".env");
256
+ const dotenvPath2 = path7.resolve(process.cwd(), ".env");
254
257
  let encoding = "utf8";
255
258
  const debug = Boolean(options && options.debug);
256
259
  const quiet = options && "quiet" in options ? options.quiet : true;
@@ -274,13 +277,13 @@ var require_main = __commonJS({
274
277
  }
275
278
  let lastError;
276
279
  const parsedAll = {};
277
- for (const path7 of optionPaths) {
280
+ for (const path8 of optionPaths) {
278
281
  try {
279
- const parsed = DotenvModule.parse(fs.readFileSync(path7, { encoding }));
282
+ const parsed = DotenvModule.parse(fs.readFileSync(path8, { encoding }));
280
283
  DotenvModule.populate(parsedAll, parsed, options);
281
284
  } catch (e) {
282
285
  if (debug) {
283
- _debug(`Failed to load ${path7} ${e.message}`);
286
+ _debug(`Failed to load ${path8} ${e.message}`);
284
287
  }
285
288
  lastError = e;
286
289
  }
@@ -295,7 +298,7 @@ var require_main = __commonJS({
295
298
  const shortPaths = [];
296
299
  for (const filePath of optionPaths) {
297
300
  try {
298
- const relative = path6.relative(process.cwd(), filePath);
301
+ const relative = path7.relative(process.cwd(), filePath);
299
302
  shortPaths.push(relative);
300
303
  } catch (e) {
301
304
  if (debug) {
@@ -472,17 +475,17 @@ var require_visit = __commonJS({
472
475
  visit.BREAK = BREAK;
473
476
  visit.SKIP = SKIP;
474
477
  visit.REMOVE = REMOVE;
475
- function visit_(key, node, visitor, path6) {
476
- const ctrl = callVisitor(key, node, visitor, path6);
478
+ function visit_(key, node, visitor, path7) {
479
+ const ctrl = callVisitor(key, node, visitor, path7);
477
480
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
478
- replaceNode(key, path6, ctrl);
479
- return visit_(key, ctrl, visitor, path6);
481
+ replaceNode(key, path7, ctrl);
482
+ return visit_(key, ctrl, visitor, path7);
480
483
  }
481
484
  if (typeof ctrl !== "symbol") {
482
485
  if (identity.isCollection(node)) {
483
- path6 = Object.freeze(path6.concat(node));
486
+ path7 = Object.freeze(path7.concat(node));
484
487
  for (let i = 0; i < node.items.length; ++i) {
485
- const ci = visit_(i, node.items[i], visitor, path6);
488
+ const ci = visit_(i, node.items[i], visitor, path7);
486
489
  if (typeof ci === "number")
487
490
  i = ci - 1;
488
491
  else if (ci === BREAK)
@@ -493,13 +496,13 @@ var require_visit = __commonJS({
493
496
  }
494
497
  }
495
498
  } else if (identity.isPair(node)) {
496
- path6 = Object.freeze(path6.concat(node));
497
- const ck = visit_("key", node.key, visitor, path6);
499
+ path7 = Object.freeze(path7.concat(node));
500
+ const ck = visit_("key", node.key, visitor, path7);
498
501
  if (ck === BREAK)
499
502
  return BREAK;
500
503
  else if (ck === REMOVE)
501
504
  node.key = null;
502
- const cv = visit_("value", node.value, visitor, path6);
505
+ const cv = visit_("value", node.value, visitor, path7);
503
506
  if (cv === BREAK)
504
507
  return BREAK;
505
508
  else if (cv === REMOVE)
@@ -520,17 +523,17 @@ var require_visit = __commonJS({
520
523
  visitAsync.BREAK = BREAK;
521
524
  visitAsync.SKIP = SKIP;
522
525
  visitAsync.REMOVE = REMOVE;
523
- async function visitAsync_(key, node, visitor, path6) {
524
- const ctrl = await callVisitor(key, node, visitor, path6);
526
+ async function visitAsync_(key, node, visitor, path7) {
527
+ const ctrl = await callVisitor(key, node, visitor, path7);
525
528
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
526
- replaceNode(key, path6, ctrl);
527
- return visitAsync_(key, ctrl, visitor, path6);
529
+ replaceNode(key, path7, ctrl);
530
+ return visitAsync_(key, ctrl, visitor, path7);
528
531
  }
529
532
  if (typeof ctrl !== "symbol") {
530
533
  if (identity.isCollection(node)) {
531
- path6 = Object.freeze(path6.concat(node));
534
+ path7 = Object.freeze(path7.concat(node));
532
535
  for (let i = 0; i < node.items.length; ++i) {
533
- const ci = await visitAsync_(i, node.items[i], visitor, path6);
536
+ const ci = await visitAsync_(i, node.items[i], visitor, path7);
534
537
  if (typeof ci === "number")
535
538
  i = ci - 1;
536
539
  else if (ci === BREAK)
@@ -541,13 +544,13 @@ var require_visit = __commonJS({
541
544
  }
542
545
  }
543
546
  } else if (identity.isPair(node)) {
544
- path6 = Object.freeze(path6.concat(node));
545
- const ck = await visitAsync_("key", node.key, visitor, path6);
547
+ path7 = Object.freeze(path7.concat(node));
548
+ const ck = await visitAsync_("key", node.key, visitor, path7);
546
549
  if (ck === BREAK)
547
550
  return BREAK;
548
551
  else if (ck === REMOVE)
549
552
  node.key = null;
550
- const cv = await visitAsync_("value", node.value, visitor, path6);
553
+ const cv = await visitAsync_("value", node.value, visitor, path7);
551
554
  if (cv === BREAK)
552
555
  return BREAK;
553
556
  else if (cv === REMOVE)
@@ -574,23 +577,23 @@ var require_visit = __commonJS({
574
577
  }
575
578
  return visitor;
576
579
  }
577
- function callVisitor(key, node, visitor, path6) {
580
+ function callVisitor(key, node, visitor, path7) {
578
581
  if (typeof visitor === "function")
579
- return visitor(key, node, path6);
582
+ return visitor(key, node, path7);
580
583
  if (identity.isMap(node))
581
- return visitor.Map?.(key, node, path6);
584
+ return visitor.Map?.(key, node, path7);
582
585
  if (identity.isSeq(node))
583
- return visitor.Seq?.(key, node, path6);
586
+ return visitor.Seq?.(key, node, path7);
584
587
  if (identity.isPair(node))
585
- return visitor.Pair?.(key, node, path6);
588
+ return visitor.Pair?.(key, node, path7);
586
589
  if (identity.isScalar(node))
587
- return visitor.Scalar?.(key, node, path6);
590
+ return visitor.Scalar?.(key, node, path7);
588
591
  if (identity.isAlias(node))
589
- return visitor.Alias?.(key, node, path6);
592
+ return visitor.Alias?.(key, node, path7);
590
593
  return void 0;
591
594
  }
592
- function replaceNode(key, path6, node) {
593
- const parent = path6[path6.length - 1];
595
+ function replaceNode(key, path7, node) {
596
+ const parent = path7[path7.length - 1];
594
597
  if (identity.isCollection(parent)) {
595
598
  parent.items[key] = node;
596
599
  } else if (identity.isPair(parent)) {
@@ -1200,10 +1203,10 @@ var require_Collection = __commonJS({
1200
1203
  var createNode = require_createNode();
1201
1204
  var identity = require_identity();
1202
1205
  var Node = require_Node();
1203
- function collectionFromPath(schema, path6, value) {
1206
+ function collectionFromPath(schema, path7, value) {
1204
1207
  let v = value;
1205
- for (let i = path6.length - 1; i >= 0; --i) {
1206
- const k = path6[i];
1208
+ for (let i = path7.length - 1; i >= 0; --i) {
1209
+ const k = path7[i];
1207
1210
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
1208
1211
  const a = [];
1209
1212
  a[k] = v;
@@ -1222,7 +1225,7 @@ var require_Collection = __commonJS({
1222
1225
  sourceObjects: /* @__PURE__ */ new Map()
1223
1226
  });
1224
1227
  }
1225
- var isEmptyPath = (path6) => path6 == null || typeof path6 === "object" && !!path6[Symbol.iterator]().next().done;
1228
+ var isEmptyPath = (path7) => path7 == null || typeof path7 === "object" && !!path7[Symbol.iterator]().next().done;
1226
1229
  var Collection = class extends Node.NodeBase {
1227
1230
  constructor(type, schema) {
1228
1231
  super(type);
@@ -1252,11 +1255,11 @@ var require_Collection = __commonJS({
1252
1255
  * be a Pair instance or a `{ key, value }` object, which may not have a key
1253
1256
  * that already exists in the map.
1254
1257
  */
1255
- addIn(path6, value) {
1256
- if (isEmptyPath(path6))
1258
+ addIn(path7, value) {
1259
+ if (isEmptyPath(path7))
1257
1260
  this.add(value);
1258
1261
  else {
1259
- const [key, ...rest] = path6;
1262
+ const [key, ...rest] = path7;
1260
1263
  const node = this.get(key, true);
1261
1264
  if (identity.isCollection(node))
1262
1265
  node.addIn(rest, value);
@@ -1270,8 +1273,8 @@ var require_Collection = __commonJS({
1270
1273
  * Removes a value from the collection.
1271
1274
  * @returns `true` if the item was found and removed.
1272
1275
  */
1273
- deleteIn(path6) {
1274
- const [key, ...rest] = path6;
1276
+ deleteIn(path7) {
1277
+ const [key, ...rest] = path7;
1275
1278
  if (rest.length === 0)
1276
1279
  return this.delete(key);
1277
1280
  const node = this.get(key, true);
@@ -1285,8 +1288,8 @@ var require_Collection = __commonJS({
1285
1288
  * scalar values from their surrounding node; to disable set `keepScalar` to
1286
1289
  * `true` (collections are always returned intact).
1287
1290
  */
1288
- getIn(path6, keepScalar) {
1289
- const [key, ...rest] = path6;
1291
+ getIn(path7, keepScalar) {
1292
+ const [key, ...rest] = path7;
1290
1293
  const node = this.get(key, true);
1291
1294
  if (rest.length === 0)
1292
1295
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -1304,8 +1307,8 @@ var require_Collection = __commonJS({
1304
1307
  /**
1305
1308
  * Checks if the collection includes a value with the key `key`.
1306
1309
  */
1307
- hasIn(path6) {
1308
- const [key, ...rest] = path6;
1310
+ hasIn(path7) {
1311
+ const [key, ...rest] = path7;
1309
1312
  if (rest.length === 0)
1310
1313
  return this.has(key);
1311
1314
  const node = this.get(key, true);
@@ -1315,8 +1318,8 @@ var require_Collection = __commonJS({
1315
1318
  * Sets a value in this collection. For `!!set`, `value` needs to be a
1316
1319
  * boolean to add/remove the item from the set.
1317
1320
  */
1318
- setIn(path6, value) {
1319
- const [key, ...rest] = path6;
1321
+ setIn(path7, value) {
1322
+ const [key, ...rest] = path7;
1320
1323
  if (rest.length === 0) {
1321
1324
  this.set(key, value);
1322
1325
  } else {
@@ -3831,9 +3834,9 @@ var require_Document = __commonJS({
3831
3834
  this.contents.add(value);
3832
3835
  }
3833
3836
  /** Adds a value to the document. */
3834
- addIn(path6, value) {
3837
+ addIn(path7, value) {
3835
3838
  if (assertCollection(this.contents))
3836
- this.contents.addIn(path6, value);
3839
+ this.contents.addIn(path7, value);
3837
3840
  }
3838
3841
  /**
3839
3842
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3908,14 +3911,14 @@ var require_Document = __commonJS({
3908
3911
  * Removes a value from the document.
3909
3912
  * @returns `true` if the item was found and removed.
3910
3913
  */
3911
- deleteIn(path6) {
3912
- if (Collection.isEmptyPath(path6)) {
3914
+ deleteIn(path7) {
3915
+ if (Collection.isEmptyPath(path7)) {
3913
3916
  if (this.contents == null)
3914
3917
  return false;
3915
3918
  this.contents = null;
3916
3919
  return true;
3917
3920
  }
3918
- return assertCollection(this.contents) ? this.contents.deleteIn(path6) : false;
3921
+ return assertCollection(this.contents) ? this.contents.deleteIn(path7) : false;
3919
3922
  }
3920
3923
  /**
3921
3924
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3930,10 +3933,10 @@ var require_Document = __commonJS({
3930
3933
  * scalar values from their surrounding node; to disable set `keepScalar` to
3931
3934
  * `true` (collections are always returned intact).
3932
3935
  */
3933
- getIn(path6, keepScalar) {
3934
- if (Collection.isEmptyPath(path6))
3936
+ getIn(path7, keepScalar) {
3937
+ if (Collection.isEmptyPath(path7))
3935
3938
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
3936
- return identity.isCollection(this.contents) ? this.contents.getIn(path6, keepScalar) : void 0;
3939
+ return identity.isCollection(this.contents) ? this.contents.getIn(path7, keepScalar) : void 0;
3937
3940
  }
3938
3941
  /**
3939
3942
  * Checks if the document includes a value with the key `key`.
@@ -3944,10 +3947,10 @@ var require_Document = __commonJS({
3944
3947
  /**
3945
3948
  * Checks if the document includes a value at `path`.
3946
3949
  */
3947
- hasIn(path6) {
3948
- if (Collection.isEmptyPath(path6))
3950
+ hasIn(path7) {
3951
+ if (Collection.isEmptyPath(path7))
3949
3952
  return this.contents !== void 0;
3950
- return identity.isCollection(this.contents) ? this.contents.hasIn(path6) : false;
3953
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path7) : false;
3951
3954
  }
3952
3955
  /**
3953
3956
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3964,13 +3967,13 @@ var require_Document = __commonJS({
3964
3967
  * Sets a value in this document. For `!!set`, `value` needs to be a
3965
3968
  * boolean to add/remove the item from the set.
3966
3969
  */
3967
- setIn(path6, value) {
3968
- if (Collection.isEmptyPath(path6)) {
3970
+ setIn(path7, value) {
3971
+ if (Collection.isEmptyPath(path7)) {
3969
3972
  this.contents = value;
3970
3973
  } else if (this.contents == null) {
3971
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path6), value);
3974
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path7), value);
3972
3975
  } else if (assertCollection(this.contents)) {
3973
- this.contents.setIn(path6, value);
3976
+ this.contents.setIn(path7, value);
3974
3977
  }
3975
3978
  }
3976
3979
  /**
@@ -4356,10 +4359,10 @@ var require_resolve_block_map = __commonJS({
4356
4359
  let offset = bm.offset;
4357
4360
  let commentEnd = null;
4358
4361
  for (const collItem of bm.items) {
4359
- const { start, key, sep, value } = collItem;
4362
+ const { start, key, sep: sep2, value } = collItem;
4360
4363
  const keyProps = resolveProps.resolveProps(start, {
4361
4364
  indicator: "explicit-key-ind",
4362
- next: key ?? sep?.[0],
4365
+ next: key ?? sep2?.[0],
4363
4366
  offset,
4364
4367
  onError,
4365
4368
  parentIndent: bm.indent,
@@ -4373,7 +4376,7 @@ var require_resolve_block_map = __commonJS({
4373
4376
  else if ("indent" in key && key.indent !== bm.indent)
4374
4377
  onError(offset, "BAD_INDENT", startColMsg);
4375
4378
  }
4376
- if (!keyProps.anchor && !keyProps.tag && !sep) {
4379
+ if (!keyProps.anchor && !keyProps.tag && !sep2) {
4377
4380
  commentEnd = keyProps.end;
4378
4381
  if (keyProps.comment) {
4379
4382
  if (map.comment)
@@ -4397,7 +4400,7 @@ var require_resolve_block_map = __commonJS({
4397
4400
  ctx.atKey = false;
4398
4401
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
4399
4402
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
4400
- const valueProps = resolveProps.resolveProps(sep ?? [], {
4403
+ const valueProps = resolveProps.resolveProps(sep2 ?? [], {
4401
4404
  indicator: "map-value-ind",
4402
4405
  next: value,
4403
4406
  offset: keyNode.range[2],
@@ -4413,7 +4416,7 @@ var require_resolve_block_map = __commonJS({
4413
4416
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
4414
4417
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
4415
4418
  }
4416
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
4419
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep2, null, valueProps, onError);
4417
4420
  if (ctx.schema.compat)
4418
4421
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
4419
4422
  offset = valueNode.range[2];
@@ -4504,7 +4507,7 @@ var require_resolve_end = __commonJS({
4504
4507
  let comment = "";
4505
4508
  if (end) {
4506
4509
  let hasSpace = false;
4507
- let sep = "";
4510
+ let sep2 = "";
4508
4511
  for (const token of end) {
4509
4512
  const { source, type } = token;
4510
4513
  switch (type) {
@@ -4518,13 +4521,13 @@ var require_resolve_end = __commonJS({
4518
4521
  if (!comment)
4519
4522
  comment = cb;
4520
4523
  else
4521
- comment += sep + cb;
4522
- sep = "";
4524
+ comment += sep2 + cb;
4525
+ sep2 = "";
4523
4526
  break;
4524
4527
  }
4525
4528
  case "newline":
4526
4529
  if (comment)
4527
- sep += source;
4530
+ sep2 += source;
4528
4531
  hasSpace = true;
4529
4532
  break;
4530
4533
  default:
@@ -4567,18 +4570,18 @@ var require_resolve_flow_collection = __commonJS({
4567
4570
  let offset = fc.offset + fc.start.source.length;
4568
4571
  for (let i = 0; i < fc.items.length; ++i) {
4569
4572
  const collItem = fc.items[i];
4570
- const { start, key, sep, value } = collItem;
4573
+ const { start, key, sep: sep2, value } = collItem;
4571
4574
  const props = resolveProps.resolveProps(start, {
4572
4575
  flow: fcName,
4573
4576
  indicator: "explicit-key-ind",
4574
- next: key ?? sep?.[0],
4577
+ next: key ?? sep2?.[0],
4575
4578
  offset,
4576
4579
  onError,
4577
4580
  parentIndent: fc.indent,
4578
4581
  startOnNewline: false
4579
4582
  });
4580
4583
  if (!props.found) {
4581
- if (!props.anchor && !props.tag && !sep && !value) {
4584
+ if (!props.anchor && !props.tag && !sep2 && !value) {
4582
4585
  if (i === 0 && props.comma)
4583
4586
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
4584
4587
  else if (i < fc.items.length - 1)
@@ -4632,8 +4635,8 @@ var require_resolve_flow_collection = __commonJS({
4632
4635
  }
4633
4636
  }
4634
4637
  }
4635
- if (!isMap && !sep && !props.found) {
4636
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep, null, props, onError);
4638
+ if (!isMap && !sep2 && !props.found) {
4639
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep2, null, props, onError);
4637
4640
  coll.items.push(valueNode);
4638
4641
  offset = valueNode.range[2];
4639
4642
  if (isBlock(value))
@@ -4645,7 +4648,7 @@ var require_resolve_flow_collection = __commonJS({
4645
4648
  if (isBlock(key))
4646
4649
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
4647
4650
  ctx.atKey = false;
4648
- const valueProps = resolveProps.resolveProps(sep ?? [], {
4651
+ const valueProps = resolveProps.resolveProps(sep2 ?? [], {
4649
4652
  flow: fcName,
4650
4653
  indicator: "map-value-ind",
4651
4654
  next: value,
@@ -4656,8 +4659,8 @@ var require_resolve_flow_collection = __commonJS({
4656
4659
  });
4657
4660
  if (valueProps.found) {
4658
4661
  if (!isMap && !props.found && ctx.options.strict) {
4659
- if (sep)
4660
- for (const st of sep) {
4662
+ if (sep2)
4663
+ for (const st of sep2) {
4661
4664
  if (st === valueProps.found)
4662
4665
  break;
4663
4666
  if (st.type === "newline") {
@@ -4674,7 +4677,7 @@ var require_resolve_flow_collection = __commonJS({
4674
4677
  else
4675
4678
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
4676
4679
  }
4677
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError) : null;
4680
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep2, null, valueProps, onError) : null;
4678
4681
  if (valueNode) {
4679
4682
  if (isBlock(value))
4680
4683
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -4854,7 +4857,7 @@ var require_resolve_block_scalar = __commonJS({
4854
4857
  chompStart = i + 1;
4855
4858
  }
4856
4859
  let value = "";
4857
- let sep = "";
4860
+ let sep2 = "";
4858
4861
  let prevMoreIndented = false;
4859
4862
  for (let i = 0; i < contentStart; ++i)
4860
4863
  value += lines[i][0].slice(trimIndent) + "\n";
@@ -4871,24 +4874,24 @@ var require_resolve_block_scalar = __commonJS({
4871
4874
  indent = "";
4872
4875
  }
4873
4876
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
4874
- value += sep + indent.slice(trimIndent) + content;
4875
- sep = "\n";
4877
+ value += sep2 + indent.slice(trimIndent) + content;
4878
+ sep2 = "\n";
4876
4879
  } else if (indent.length > trimIndent || content[0] === " ") {
4877
- if (sep === " ")
4878
- sep = "\n";
4879
- else if (!prevMoreIndented && sep === "\n")
4880
- sep = "\n\n";
4881
- value += sep + indent.slice(trimIndent) + content;
4882
- sep = "\n";
4880
+ if (sep2 === " ")
4881
+ sep2 = "\n";
4882
+ else if (!prevMoreIndented && sep2 === "\n")
4883
+ sep2 = "\n\n";
4884
+ value += sep2 + indent.slice(trimIndent) + content;
4885
+ sep2 = "\n";
4883
4886
  prevMoreIndented = true;
4884
4887
  } else if (content === "") {
4885
- if (sep === "\n")
4888
+ if (sep2 === "\n")
4886
4889
  value += "\n";
4887
4890
  else
4888
- sep = "\n";
4891
+ sep2 = "\n";
4889
4892
  } else {
4890
- value += sep + content;
4891
- sep = " ";
4893
+ value += sep2 + content;
4894
+ sep2 = " ";
4892
4895
  prevMoreIndented = false;
4893
4896
  }
4894
4897
  }
@@ -5070,25 +5073,25 @@ var require_resolve_flow_scalar = __commonJS({
5070
5073
  if (!match)
5071
5074
  return source;
5072
5075
  let res = match[1];
5073
- let sep = " ";
5076
+ let sep2 = " ";
5074
5077
  let pos = first.lastIndex;
5075
5078
  line.lastIndex = pos;
5076
5079
  while (match = line.exec(source)) {
5077
5080
  if (match[1] === "") {
5078
- if (sep === "\n")
5079
- res += sep;
5081
+ if (sep2 === "\n")
5082
+ res += sep2;
5080
5083
  else
5081
- sep = "\n";
5084
+ sep2 = "\n";
5082
5085
  } else {
5083
- res += sep + match[1];
5084
- sep = " ";
5086
+ res += sep2 + match[1];
5087
+ sep2 = " ";
5085
5088
  }
5086
5089
  pos = line.lastIndex;
5087
5090
  }
5088
5091
  const last = /[ \t]*(.*)/sy;
5089
5092
  last.lastIndex = pos;
5090
5093
  match = last.exec(source);
5091
- return res + sep + (match?.[1] ?? "");
5094
+ return res + sep2 + (match?.[1] ?? "");
5092
5095
  }
5093
5096
  function doubleQuotedValue(source, onError) {
5094
5097
  let res = "";
@@ -5898,14 +5901,14 @@ var require_cst_stringify = __commonJS({
5898
5901
  }
5899
5902
  }
5900
5903
  }
5901
- function stringifyItem({ start, key, sep, value }) {
5904
+ function stringifyItem({ start, key, sep: sep2, value }) {
5902
5905
  let res = "";
5903
5906
  for (const st of start)
5904
5907
  res += st.source;
5905
5908
  if (key)
5906
5909
  res += stringifyToken(key);
5907
- if (sep)
5908
- for (const st of sep)
5910
+ if (sep2)
5911
+ for (const st of sep2)
5909
5912
  res += st.source;
5910
5913
  if (value)
5911
5914
  res += stringifyToken(value);
@@ -5930,9 +5933,9 @@ var require_cst_visit = __commonJS({
5930
5933
  visit.BREAK = BREAK;
5931
5934
  visit.SKIP = SKIP;
5932
5935
  visit.REMOVE = REMOVE;
5933
- visit.itemAtPath = (cst, path6) => {
5936
+ visit.itemAtPath = (cst, path7) => {
5934
5937
  let item = cst;
5935
- for (const [field, index] of path6) {
5938
+ for (const [field, index] of path7) {
5936
5939
  const tok = item?.[field];
5937
5940
  if (tok && "items" in tok) {
5938
5941
  item = tok.items[index];
@@ -5941,23 +5944,23 @@ var require_cst_visit = __commonJS({
5941
5944
  }
5942
5945
  return item;
5943
5946
  };
5944
- visit.parentCollection = (cst, path6) => {
5945
- const parent = visit.itemAtPath(cst, path6.slice(0, -1));
5946
- const field = path6[path6.length - 1][0];
5947
+ visit.parentCollection = (cst, path7) => {
5948
+ const parent = visit.itemAtPath(cst, path7.slice(0, -1));
5949
+ const field = path7[path7.length - 1][0];
5947
5950
  const coll = parent?.[field];
5948
5951
  if (coll && "items" in coll)
5949
5952
  return coll;
5950
5953
  throw new Error("Parent collection not found");
5951
5954
  };
5952
- function _visit(path6, item, visitor) {
5953
- let ctrl = visitor(item, path6);
5955
+ function _visit(path7, item, visitor) {
5956
+ let ctrl = visitor(item, path7);
5954
5957
  if (typeof ctrl === "symbol")
5955
5958
  return ctrl;
5956
5959
  for (const field of ["key", "value"]) {
5957
5960
  const token = item[field];
5958
5961
  if (token && "items" in token) {
5959
5962
  for (let i = 0; i < token.items.length; ++i) {
5960
- const ci = _visit(Object.freeze(path6.concat([[field, i]])), token.items[i], visitor);
5963
+ const ci = _visit(Object.freeze(path7.concat([[field, i]])), token.items[i], visitor);
5961
5964
  if (typeof ci === "number")
5962
5965
  i = ci - 1;
5963
5966
  else if (ci === BREAK)
@@ -5968,10 +5971,10 @@ var require_cst_visit = __commonJS({
5968
5971
  }
5969
5972
  }
5970
5973
  if (typeof ctrl === "function" && field === "key")
5971
- ctrl = ctrl(item, path6);
5974
+ ctrl = ctrl(item, path7);
5972
5975
  }
5973
5976
  }
5974
- return typeof ctrl === "function" ? ctrl(item, path6) : ctrl;
5977
+ return typeof ctrl === "function" ? ctrl(item, path7) : ctrl;
5975
5978
  }
5976
5979
  exports.visit = visit;
5977
5980
  }
@@ -7072,18 +7075,18 @@ var require_parser = __commonJS({
7072
7075
  if (this.type === "map-value-ind") {
7073
7076
  const prev = getPrevProps(this.peek(2));
7074
7077
  const start = getFirstKeyStartProps(prev);
7075
- let sep;
7078
+ let sep2;
7076
7079
  if (scalar.end) {
7077
- sep = scalar.end;
7078
- sep.push(this.sourceToken);
7080
+ sep2 = scalar.end;
7081
+ sep2.push(this.sourceToken);
7079
7082
  delete scalar.end;
7080
7083
  } else
7081
- sep = [this.sourceToken];
7084
+ sep2 = [this.sourceToken];
7082
7085
  const map = {
7083
7086
  type: "block-map",
7084
7087
  offset: scalar.offset,
7085
7088
  indent: scalar.indent,
7086
- items: [{ start, key: scalar, sep }]
7089
+ items: [{ start, key: scalar, sep: sep2 }]
7087
7090
  };
7088
7091
  this.onKeyLine = true;
7089
7092
  this.stack[this.stack.length - 1] = map;
@@ -7236,15 +7239,15 @@ var require_parser = __commonJS({
7236
7239
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
7237
7240
  const start2 = getFirstKeyStartProps(it.start);
7238
7241
  const key = it.key;
7239
- const sep = it.sep;
7240
- sep.push(this.sourceToken);
7242
+ const sep2 = it.sep;
7243
+ sep2.push(this.sourceToken);
7241
7244
  delete it.key;
7242
7245
  delete it.sep;
7243
7246
  this.stack.push({
7244
7247
  type: "block-map",
7245
7248
  offset: this.offset,
7246
7249
  indent: this.indent,
7247
- items: [{ start: start2, key, sep }]
7250
+ items: [{ start: start2, key, sep: sep2 }]
7248
7251
  });
7249
7252
  } else if (start.length > 0) {
7250
7253
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -7438,13 +7441,13 @@ var require_parser = __commonJS({
7438
7441
  const prev = getPrevProps(parent);
7439
7442
  const start = getFirstKeyStartProps(prev);
7440
7443
  fixFlowSeqItems(fc);
7441
- const sep = fc.end.splice(1, fc.end.length);
7442
- sep.push(this.sourceToken);
7444
+ const sep2 = fc.end.splice(1, fc.end.length);
7445
+ sep2.push(this.sourceToken);
7443
7446
  const map = {
7444
7447
  type: "block-map",
7445
7448
  offset: fc.offset,
7446
7449
  indent: fc.indent,
7447
- items: [{ start, key: fc, sep }]
7450
+ items: [{ start, key: fc, sep: sep2 }]
7448
7451
  };
7449
7452
  this.onKeyLine = true;
7450
7453
  this.stack[this.stack.length - 1] = map;
@@ -9826,11 +9829,11 @@ var require_baseGet = __commonJS({
9826
9829
  "use strict";
9827
9830
  var castPath = require_castPath();
9828
9831
  var toKey = require_toKey();
9829
- function baseGet(object, path6) {
9830
- path6 = castPath(path6, object);
9831
- var index = 0, length = path6.length;
9832
+ function baseGet(object, path7) {
9833
+ path7 = castPath(path7, object);
9834
+ var index = 0, length = path7.length;
9832
9835
  while (object != null && index < length) {
9833
- object = object[toKey(path6[index++])];
9836
+ object = object[toKey(path7[index++])];
9834
9837
  }
9835
9838
  return index && index == length ? object : void 0;
9836
9839
  }
@@ -9843,8 +9846,8 @@ var require_get = __commonJS({
9843
9846
  "node_modules/lodash/get.js"(exports, module) {
9844
9847
  "use strict";
9845
9848
  var baseGet = require_baseGet();
9846
- function get2(object, path6, defaultValue) {
9847
- var result = object == null ? void 0 : baseGet(object, path6);
9849
+ function get2(object, path7, defaultValue) {
9850
+ var result = object == null ? void 0 : baseGet(object, path7);
9848
9851
  return result === void 0 ? defaultValue : result;
9849
9852
  }
9850
9853
  module.exports = get2;
@@ -21774,13 +21777,52 @@ var require_lib2 = __commonJS({
21774
21777
  }
21775
21778
  });
21776
21779
 
21780
+ // vendor/heyspex-mcp/credentials.mjs
21781
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync4, renameSync as renameSync4, writeFileSync as writeFileSync4 } from "node:fs";
21782
+ import os, { homedir as homedir3 } from "node:os";
21783
+ import { dirname, join as join5, resolve as resolve2 } from "node:path";
21784
+ var init_credentials = __esm({
21785
+ "vendor/heyspex-mcp/credentials.mjs"() {
21786
+ "use strict";
21787
+ }
21788
+ });
21789
+
21790
+ // scripts/lib/dev-mode.mjs
21791
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
21792
+ import { homedir as homedir4 } from "node:os";
21793
+ import { join as join6 } from "node:path";
21794
+ var init_dev_mode = __esm({
21795
+ "scripts/lib/dev-mode.mjs"() {
21796
+ "use strict";
21797
+ init_credentials();
21798
+ }
21799
+ });
21800
+
21777
21801
  // spex-console/bin/hs-env.ts
21778
21802
  import { spawn } from "node:child_process";
21779
- import { existsSync as existsSync6 } from "node:fs";
21803
+ import { existsSync as existsSync9 } from "node:fs";
21780
21804
  import { networkInterfaces } from "node:os";
21781
- import path5 from "node:path";
21782
- import process2 from "node:process";
21783
- import { fileURLToPath } from "node:url";
21805
+ import path6 from "node:path";
21806
+ import process3 from "node:process";
21807
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
21808
+
21809
+ // scripts/lib/shared-path-helpers.mjs
21810
+ import { isAbsolute, resolve, sep } from "node:path";
21811
+ function resolveCodeRoot({
21812
+ explicit,
21813
+ packageRoot,
21814
+ vaultRoot,
21815
+ env = process.env
21816
+ } = {}) {
21817
+ const fromExplicit = typeof explicit === "string" ? explicit.trim() : "";
21818
+ if (fromExplicit) return fromExplicit;
21819
+ const fromEnv = typeof env?.HS_PKG_ROOT === "string" ? env.HS_PKG_ROOT.trim() : "";
21820
+ if (fromEnv) return fromEnv;
21821
+ const fromPackage = typeof packageRoot === "string" ? packageRoot.trim() : "";
21822
+ if (fromPackage) return fromPackage;
21823
+ const fromVault = typeof vaultRoot === "string" ? vaultRoot.trim() : "";
21824
+ return fromVault;
21825
+ }
21784
21826
 
21785
21827
  // spex-console/src/lib/env-vault/audit.ts
21786
21828
  import { appendFileSync } from "node:fs";
@@ -24685,20 +24727,20 @@ async function doRun(args, deps) {
24685
24727
  }
24686
24728
  const spawnCommand = useShell ? [quoteProgramForCmd(command), ...rest.map(quoteForCmd)].join(" ") : command;
24687
24729
  const spawnArgs = useShell ? [] : rest;
24688
- return await new Promise((resolve) => {
24730
+ return await new Promise((resolve5) => {
24689
24731
  const child = deps.spawn(spawnCommand, spawnArgs, {
24690
24732
  stdio: "inherit",
24691
24733
  env: { ...deps.env, ...decrypted },
24692
24734
  ...useShell ? { shell: true } : {}
24693
24735
  });
24694
24736
  child.on("error", (err) => {
24695
- resolve({
24737
+ resolve5({
24696
24738
  code: EXIT.RUNTIME,
24697
24739
  message: `hs env run: failed to spawn ${command}: ${err.message}`
24698
24740
  });
24699
24741
  });
24700
24742
  child.on("exit", (code, signal) => {
24701
- resolve({ code: signal ? EXIT.RUNTIME : code ?? EXIT.OK });
24743
+ resolve5({ code: signal ? EXIT.RUNTIME : code ?? EXIT.OK });
24702
24744
  });
24703
24745
  });
24704
24746
  }
@@ -25990,12 +26032,12 @@ async function runVerifyStep(command, deps) {
25990
26032
  });
25991
26033
  if (resolved.kind === "empty") return { code: EXIT.OK };
25992
26034
  if (resolved.kind === "unsafe") return { code: EXIT.RUNTIME, error: resolved.reason };
25993
- return await new Promise((resolve) => {
26035
+ return await new Promise((resolve5) => {
25994
26036
  let settled = false;
25995
26037
  const done = (r) => {
25996
26038
  if (!settled) {
25997
26039
  settled = true;
25998
- resolve(r);
26040
+ resolve5(r);
25999
26041
  }
26000
26042
  };
26001
26043
  const child = deps.spawn(resolved.command, resolved.args, {
@@ -26247,17 +26289,17 @@ import { spawnSync as spawnSync2 } from "node:child_process";
26247
26289
  import { randomBytes as randomBytes5 } from "node:crypto";
26248
26290
  import {
26249
26291
  chmodSync,
26250
- existsSync as existsSync5,
26251
- mkdirSync as mkdirSync4,
26292
+ existsSync as existsSync8,
26293
+ mkdirSync as mkdirSync7,
26252
26294
  readdirSync,
26253
- readFileSync as readFileSync6,
26254
- renameSync as renameSync4,
26295
+ readFileSync as readFileSync11,
26296
+ renameSync as renameSync6,
26255
26297
  statSync as statSync3,
26256
26298
  unlinkSync as unlinkSync3,
26257
- writeFileSync as writeFileSync4
26299
+ writeFileSync as writeFileSync7
26258
26300
  } from "node:fs";
26259
- import { homedir as homedir5 } from "node:os";
26260
- import path4 from "node:path";
26301
+ import { homedir as homedir10 } from "node:os";
26302
+ import path5 from "node:path";
26261
26303
 
26262
26304
  // node_modules/sops-age/dist/index.js
26263
26305
  var import_dotenv = __toESM(require_main(), 1);
@@ -26741,8 +26783,8 @@ function getErrorMap() {
26741
26783
 
26742
26784
  // node_modules/zod/v3/helpers/parseUtil.js
26743
26785
  var makeIssue = (params) => {
26744
- const { data, path: path6, errorMaps, issueData } = params;
26745
- const fullPath = [...path6, ...issueData.path || []];
26786
+ const { data, path: path7, errorMaps, issueData } = params;
26787
+ const fullPath = [...path7, ...issueData.path || []];
26746
26788
  const fullIssue = {
26747
26789
  ...issueData,
26748
26790
  path: fullPath
@@ -26858,11 +26900,11 @@ var errorUtil;
26858
26900
 
26859
26901
  // node_modules/zod/v3/types.js
26860
26902
  var ParseInputLazyPath = class {
26861
- constructor(parent, value, path6, key) {
26903
+ constructor(parent, value, path7, key) {
26862
26904
  this._cachedPath = [];
26863
26905
  this.parent = parent;
26864
26906
  this.data = value;
26865
- this._path = path6;
26907
+ this._path = path7;
26866
26908
  this._key = key;
26867
26909
  }
26868
26910
  get path() {
@@ -34931,18 +34973,18 @@ import { homedir as homedir2, platform } from "node:os";
34931
34973
  import { exec } from "node:child_process";
34932
34974
  import { promisify } from "node:util";
34933
34975
  var import_sshpk = __toESM(require_lib2(), 1);
34934
- async function loadFromFile(path6) {
34976
+ async function loadFromFile(path7) {
34935
34977
  if (globalThis.Deno) {
34936
- return Deno.readTextFile(path6);
34978
+ return Deno.readTextFile(path7);
34937
34979
  }
34938
34980
  if (globalThis.Bun) {
34939
- return Bun.file(path6).text();
34981
+ return Bun.file(path7).text();
34940
34982
  }
34941
34983
  if (typeof process !== "undefined" && process.versions?.node) {
34942
34984
  const fs = await import("fs/promises");
34943
- return fs.readFile(path6, "utf-8");
34985
+ return fs.readFile(path7, "utf-8");
34944
34986
  }
34945
- throw new Error(`Unable to determine method to load file "${path6}"`);
34987
+ throw new Error(`Unable to determine method to load file "${path7}"`);
34946
34988
  }
34947
34989
  function isSopsInput(value) {
34948
34990
  if (!value) {
@@ -35050,13 +35092,13 @@ async function parseSops(input, sopsFileType) {
35050
35092
  });
35051
35093
  }
35052
35094
  }
35053
- async function loadSopsFile(path6, sopsFileType) {
35095
+ async function loadSopsFile(path7, sopsFileType) {
35054
35096
  try {
35055
- const content = await loadFromFile(path6);
35097
+ const content = await loadFromFile(path7);
35056
35098
  return await parseSops(content, sopsFileType);
35057
35099
  } catch (err) {
35058
35100
  throw new Error(
35059
- `Failed to load SOPS file '${path6}': ${err.message}`,
35101
+ `Failed to load SOPS file '${path7}': ${err.message}`,
35060
35102
  {
35061
35103
  cause: err
35062
35104
  }
@@ -35473,15 +35515,15 @@ async function getSopsEncryptionKey(sops, secretKeys) {
35473
35515
  ${errors.join("\n")}`
35474
35516
  );
35475
35517
  }
35476
- function path2gopath(path6) {
35477
- return `${path6.filter((x) => !/^\d+$/.test(x)).join(":")}:`;
35518
+ function path2gopath(path7) {
35519
+ return `${path7.filter((x) => !/^\d+$/.test(x)).join(":")}:`;
35478
35520
  }
35479
- function decryptSOPSValue(ciphertext, decryptionKey, path6) {
35521
+ function decryptSOPSValue(ciphertext, decryptionKey, path7) {
35480
35522
  if (!ciphertext) {
35481
35523
  return "";
35482
35524
  }
35483
35525
  const encryptedValue = parse(ciphertext);
35484
- const aad = path2gopath(path6);
35526
+ const aad = path2gopath(path7);
35485
35527
  let decrypted;
35486
35528
  try {
35487
35529
  decrypted = decryptAesGcm(
@@ -35491,22 +35533,22 @@ function decryptSOPSValue(ciphertext, decryptionKey, path6) {
35491
35533
  );
35492
35534
  } catch (err) {
35493
35535
  throw new Error(
35494
- `AES-GCM decryption failed at path ${JSON.stringify(path6)} for value "${ciphertext}": ${err instanceof Error ? err.message : String(err)}`
35536
+ `AES-GCM decryption failed at path ${JSON.stringify(path7)} for value "${ciphertext}": ${err instanceof Error ? err.message : String(err)}`
35495
35537
  );
35496
35538
  }
35497
35539
  const decryptedValue = new TextDecoder().decode(decrypted);
35498
35540
  return convertDecryptedValue(decryptedValue, encryptedValue.datatype);
35499
35541
  }
35500
- function decryptObject(obj, decryptionKey, path6 = []) {
35542
+ function decryptObject(obj, decryptionKey, path7 = []) {
35501
35543
  if (typeof obj !== "object" || obj === null) {
35502
35544
  return obj;
35503
35545
  }
35504
35546
  for (const key of Object.keys(obj)) {
35505
35547
  const value = obj[key];
35506
35548
  if (typeof value === "string" && value.startsWith("ENC[AES256_GCM,data:")) {
35507
- obj[key] = decryptSOPSValue(value, decryptionKey, [...path6, key]);
35549
+ obj[key] = decryptSOPSValue(value, decryptionKey, [...path7, key]);
35508
35550
  } else if (typeof value === "object") {
35509
- obj[key] = decryptObject(value, decryptionKey, [...path6, key]);
35551
+ obj[key] = decryptObject(value, decryptionKey, [...path7, key]);
35510
35552
  }
35511
35553
  }
35512
35554
  return obj;
@@ -35578,69 +35620,72 @@ async function decryptSops(inputOrOptions, options) {
35578
35620
  import { randomUUID } from "node:crypto";
35579
35621
 
35580
35622
  // scripts/lib/console-url-resolver.mjs
35581
- import { readFileSync as readFileSync4 } from "node:fs";
35582
- import { homedir as homedir3 } from "node:os";
35583
- import { join as join5 } from "node:path";
35584
- var DEFAULT_CONSOLE_URL = "https://app.heyspex.com";
35585
- function trimTrailingSlash(url) {
35586
- return url.replace(/\/+$/, "");
35587
- }
35588
- function readCredentialsConsoleUrl({ homeDir = homedir3() } = {}) {
35623
+ init_dev_mode();
35624
+ import { readFileSync as readFileSync6 } from "node:fs";
35625
+ import { homedir as homedir5 } from "node:os";
35626
+ import { join as join7 } from "node:path";
35627
+
35628
+ // spex-console/src/lib/cli/control-shared.ts
35629
+ import path4 from "node:path";
35630
+
35631
+ // scripts/lib/hs-command.mjs
35632
+ import { existsSync as existsSync5 } from "node:fs";
35633
+ import { delimiter, dirname as dirname2, join as join8 } from "node:path";
35634
+ import { fileURLToPath } from "node:url";
35635
+ var HS_BIN_NAME = "hs";
35636
+ var HS_DISPATCHER_PATH = (() => {
35589
35637
  try {
35590
- const raw = readFileSync4(join5(homeDir, ".heyspex", "credentials.yaml"), "utf8");
35591
- const match = raw.match(/^console_url:\s*["']?([^"'\r\n#]+)/m);
35592
- const value = match?.[1]?.trim();
35593
- return value && value.length > 0 ? trimTrailingSlash(value) : null;
35638
+ const here = dirname2(fileURLToPath(import.meta.url));
35639
+ return join8(dirname2(dirname2(here)), "bin", "hs.mjs");
35594
35640
  } catch {
35595
35641
  return null;
35596
35642
  }
35597
- }
35598
- function readDiscoveryFileConsoleUrl(repoRoot) {
35599
- if (!repoRoot) return null;
35600
- for (const name of [
35601
- "console-url",
35602
- "cockpit-url"
35603
- /* legacy-cockpit */
35604
- ]) {
35605
- try {
35606
- const discovery = readFileSync4(join5(repoRoot, ".heyspex", name), "utf8").trim();
35607
- if (discovery.length > 0) return trimTrailingSlash(discovery);
35608
- } catch {
35609
- }
35610
- }
35611
- return null;
35612
- }
35613
- var ConsoleUrlUnresolvedError = class extends Error {
35614
- constructor() {
35615
- super(
35616
- `resolveConsoleUrl: no HEYSPEX_CONSOLE_URL/HEYSPEX_COCKPIT_URL env, no console_url: in ~/.heyspex/credentials.yaml, and no .heyspex/console-url discovery file \u2014 refusing to silently fall back to the ${DEFAULT_CONSOLE_URL} default in strict mode.`
35617
- );
35618
- this.name = "ConsoleUrlUnresolvedError";
35619
- }
35620
- };
35621
- function resolveConsoleUrl({
35622
- repoRoot,
35623
- env = process.env,
35624
- homeDir = homedir3(),
35625
- strict = false
35626
- } = {}) {
35627
- const envUrl = (env.HEYSPEX_CONSOLE_URL ?? env.HEYSPEX_COCKPIT_URL)?.trim();
35628
- if (envUrl) return trimTrailingSlash(envUrl);
35629
- const credentialsUrl = readCredentialsConsoleUrl({ homeDir });
35630
- if (credentialsUrl) return credentialsUrl;
35631
- const discoveryUrl = readDiscoveryFileConsoleUrl(repoRoot);
35632
- if (discoveryUrl) return discoveryUrl;
35633
- if (strict) throw new ConsoleUrlUnresolvedError();
35634
- return DEFAULT_CONSOLE_URL;
35635
- }
35643
+ })();
35644
+ function shellQuote(p) {
35645
+ return /[\\\s]/.test(p) ? `"${p}"` : p;
35646
+ }
35647
+ var HS_DISPATCHER_PREFIX = HS_DISPATCHER_PATH ? `node ${shellQuote(HS_DISPATCHER_PATH)}` : HS_BIN_NAME;
35648
+
35649
+ // vendor/heyspex-mcp/console-fetch.mjs
35650
+ init_credentials();
35651
+ import { readFileSync as readFileSync9 } from "node:fs";
35652
+ import { homedir as homedir8 } from "node:os";
35653
+ import { join as join11 } from "node:path";
35654
+
35655
+ // vendor/heyspex-mcp/session-owner.mjs
35656
+ init_credentials();
35657
+ import { readFileSync as readFileSync7 } from "node:fs";
35658
+ import { homedir as homedir6 } from "node:os";
35659
+ import { join as join9 } from "node:path";
35660
+
35661
+ // vendor/heyspex-mcp/vault-less-endpoints.mjs
35662
+ var VAULT_LESS_ENDPOINTS = Object.freeze([
35663
+ "* /api/mcp/session",
35664
+ "* /api/mcp/pairing-codes",
35665
+ "POST /api/vaults",
35666
+ "GET /api/vaults",
35667
+ "POST /api/workspaces",
35668
+ "GET /api/workspaces",
35669
+ "* /api/admin/dev-mode"
35670
+ ]);
35671
+
35672
+ // vendor/heyspex-mcp/vault-resolve.mjs
35673
+ import { existsSync as existsSync6, readFileSync as readFileSync8 } from "node:fs";
35674
+ import { homedir as homedir7, tmpdir } from "node:os";
35675
+ import { dirname as dirname3, join as join10, resolve as resolve3 } from "node:path";
35676
+
35677
+ // vendor/heyspex-mcp/console-fetch.mjs
35678
+ var SCOPE_REFUSAL_CODES = Object.freeze(["VAULT_SCOPE_MISMATCH", "ACCOUNT_MISMATCH", "VAULT_NOT_REGISTERED"]);
35636
35679
 
35637
35680
  // spex-console/src/lib/cli/control-shared.ts
35638
- import { readFileSync as readFileSync5 } from "node:fs";
35639
- import { homedir as homedir4 } from "node:os";
35640
- import { join as join6 } from "node:path";
35681
+ init_credentials();
35682
+
35683
+ // spex-console/src/lib/vault-registry/registry-file.ts
35684
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync10, renameSync as renameSync5, writeFileSync as writeFileSync6 } from "node:fs";
35685
+ import { homedir as homedir9 } from "node:os";
35686
+ import { dirname as dirname4, join as join12, resolve as resolve4 } from "node:path";
35641
35687
 
35642
35688
  // spex-console/src/lib/cli/init.ts
35643
- var DEFAULT_CONSOLE_URL2 = resolveConsoleUrl();
35644
35689
  function parseVaultId(content) {
35645
35690
  const m = content.match(/^vault_id:\s*(.+?)\s*$/m);
35646
35691
  if (!m) return null;
@@ -35652,27 +35697,38 @@ var HELP2 = [
35652
35697
  "Usage:",
35653
35698
  " hs init [--console-url <url>] [--vault-root <path>] [--force] [--json]",
35654
35699
  " hs init --customer-vault <dir> [--console-url <url>] [--principles <all|none|a,b>]",
35655
- " [--vault-name <name>] [--no-git] [--json]",
35700
+ " [--vault-name <name>] [--git] [--json]",
35656
35701
  "",
35657
35702
  "Write the top-level heyspex.yaml vault marker (schema_version, console_url,",
35658
- "vault_root, vault_id) \u2014 the committed file the console / web companion read",
35703
+ "vault_root, vault_id; `hs connect` also records `account:`, the account id the",
35704
+ "repo was connected under) \u2014 the committed file the console / web companion read",
35659
35705
  "to bootstrap a vault. Idempotent: an existing marker is left untouched unless",
35660
35706
  "--force, EXCEPT a missing vault_id is backfilled in place either way (backward",
35661
35707
  "compatible \u2014 no schema_version bump). vault_id is reused exactly when already",
35662
35708
  "present; a fresh one is minted only when absent.",
35663
- "Does not modify .heyspex/config.yaml or its templates (ADR-0009).",
35709
+ "Also scaffolds the vault_root folder and seeds .heyspex/config.yaml (the",
35710
+ "HeySpex workflow settings, ADR-0009) from the shipped template",
35711
+ "(vendor/heyspex-mcp/config-seed.yaml) when that file is absent. An existing",
35712
+ ".heyspex/config.yaml is never rewritten \u2014 not even with --force; change its",
35713
+ "values with `hs settings set <key> <value>`.",
35664
35714
  "",
35665
35715
  "--customer-vault <dir> scaffolds a REAL customer vault at <dir> instead: the",
35666
- "specs/ folder tree, heyspex.yaml, and every row of the template shipping",
35667
- "manifest (spex-console/src/lib/cli/template-manifest.ts) \u2014 universal docs",
35716
+ "specs/ folder tree, heyspex.yaml, the seeded .heyspex/config.yaml, and every",
35717
+ "row of the template shipping manifest",
35718
+ "(spex-console/src/lib/cli/template-manifest.ts) \u2014 universal docs",
35668
35719
  "copied verbatim, template-shape docs written as author-prompt skeletons \u2014",
35669
- "plus a generated CLAUDE.md, the kept-principles index, and (unless --no-git)",
35670
- "one initial `git init` + commit pinning the template version. Refuses a",
35671
- "non-empty <dir> with a plain error. See init.customer-vault.ts.",
35720
+ "plus a generated CLAUDE.md, the kept-principles index, and the template_version",
35721
+ "pin; with --git, one initial `git init` + commit. Rerunnable: a <dir> that already",
35722
+ "holds heyspex.yaml and an empty/placeholder-only specs/ is accepted, existing",
35723
+ "files are never overwritten (an existing CLAUDE.md gets a CLAUDE.md.template",
35724
+ "beside it), and the result lists each manifest row as created or kept. Refuses a",
35725
+ "non-empty <dir> without heyspex.yaml, or a specs/ holding managed specs.",
35726
+ "See init.customer-vault.ts.",
35672
35727
  "",
35673
35728
  "Flags:",
35674
- " --console-url <url> console_url value (default: $HEYSPEX_CONSOLE_URL or",
35675
- " https://console.heyspex.local).",
35729
+ " --console-url <url> console_url value (default: the mode-aware console --",
35730
+ " $HEYSPEX_CONSOLE_URL, else the signed-in console, else",
35731
+ " https://app.heyspex.com in prod mode).",
35676
35732
  " --vault-root <path> vault_root value (default: specs/).",
35677
35733
  " --customer-vault <dir> Scaffold a new customer vault at <dir> (see above).",
35678
35734
  " --principles <all|none|a,b> Which universal principle docs to ship",
@@ -35680,8 +35736,9 @@ var HELP2 = [
35680
35736
  " keep/skip prompt per principle. Omitted + no TTY: all.",
35681
35737
  " --vault-name <name> Display name for the scaffolded vault (--customer-vault",
35682
35738
  " only; default: <dir>'s basename).",
35683
- " --no-git Skip git init + the initial commit (--customer-vault only).",
35684
- " --force Overwrite an existing heyspex.yaml.",
35739
+ " --git Also run git init + one initial commit (--customer-vault only;",
35740
+ " default: no git). --no-git is accepted as a no-op.",
35741
+ " --force Overwrite an existing heyspex.yaml (never .heyspex/config.yaml).",
35685
35742
  " --json Emit a machine-readable JSON result.",
35686
35743
  " --help, -h Show this help.",
35687
35744
  "",
@@ -35697,8 +35754,11 @@ function scopedProfileName(profileName, vaultId) {
35697
35754
  const short = vaultId.replace(/[^A-Za-z0-9]/g, "").slice(0, 8).toUpperCase();
35698
35755
  return short.length === 0 ? profileName : `${profileName}__V${short}`;
35699
35756
  }
35757
+ function sanitizedProfileToken(profileName) {
35758
+ return profileName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
35759
+ }
35700
35760
  function keysEnvVarName(profileName) {
35701
- return ENV_VAR_PREFIX + profileName.toUpperCase();
35761
+ return ENV_VAR_PREFIX + sanitizedProfileToken(profileName);
35702
35762
  }
35703
35763
  function looksLikePrivateKey(value) {
35704
35764
  if (typeof value !== "string") return false;
@@ -35736,7 +35796,7 @@ function upsertKeysLine(contentOrNull, profileName, privateKey, vaultId) {
35736
35796
  const matchesProfile = (raw) => {
35737
35797
  const bare = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
35738
35798
  const m = KEYS_LINE.exec(bare);
35739
- return m !== null && m[1].toUpperCase() === effective.toUpperCase();
35799
+ return m !== null && m[1].toUpperCase() === sanitizedProfileToken(effective);
35740
35800
  };
35741
35801
  const lines = [];
35742
35802
  let replaced = false;
@@ -35758,7 +35818,7 @@ function upsertKeysLine(contentOrNull, profileName, privateKey, vaultId) {
35758
35818
  }
35759
35819
  function existingKeyInSlot(contentOrNull, profileName, vaultId) {
35760
35820
  const effective = scopedProfileName(profileName, vaultId);
35761
- return parseKeysFile(contentOrNull ?? "")[effective.toLowerCase()] ?? null;
35821
+ return parseKeysFile(contentOrNull ?? "")[sanitizedProfileToken(effective).toLowerCase()] ?? null;
35762
35822
  }
35763
35823
  function dateStamp(when) {
35764
35824
  return when.toISOString().slice(0, 10).replace(/-/g, "");
@@ -35820,7 +35880,7 @@ function resolvePrivateKey(args) {
35820
35880
  if (!source.content) continue;
35821
35881
  const parsed = parseKeysFile(source.content);
35822
35882
  for (const candidate of candidateProfileNames(args)) {
35823
- const fromFile = parsed[candidate.toLowerCase()];
35883
+ const fromFile = parsed[sanitizedProfileToken(candidate).toLowerCase()];
35824
35884
  if (!fromFile) continue;
35825
35885
  if (!looksLikePrivateKey(fromFile)) {
35826
35886
  throw new EnvVaultConfigError(
@@ -35969,23 +36029,23 @@ function isExpiredDate(expires, today = todayIso()) {
35969
36029
  return expires !== null && today > expires;
35970
36030
  }
35971
36031
  function envDir(vaultRoot) {
35972
- return path4.join(vaultRoot, ".heyspex", "env");
36032
+ return path5.join(vaultRoot, ".heyspex", "env");
35973
36033
  }
35974
36034
  function profilePath(vaultRoot, name) {
35975
- return path4.join(envDir(vaultRoot), `${name}.env`);
36035
+ return path5.join(envDir(vaultRoot), `${name}.env`);
35976
36036
  }
35977
36037
  function keysPath(vaultRoot) {
35978
- return path4.join(vaultRoot, ".heyspex", "env.keys");
36038
+ return path5.join(vaultRoot, ".heyspex", "env.keys");
35979
36039
  }
35980
36040
  function homeKeysPath() {
35981
- return path4.join(process.env.HEYSPEX_ENV_KEYS_HOME || homedir5(), ".heyspex", "env.keys");
36041
+ return path5.join(process.env.HEYSPEX_ENV_KEYS_HOME || homedir10(), ".heyspex", "env.keys");
35982
36042
  }
35983
36043
  function dotenvPath(vaultRoot) {
35984
- return path4.join(vaultRoot, ".env");
36044
+ return path5.join(vaultRoot, ".env");
35985
36045
  }
35986
36046
  function readOrNull(file) {
35987
36047
  try {
35988
- return readFileSync6(file, "utf-8");
36048
+ return readFileSync11(file, "utf-8");
35989
36049
  } catch {
35990
36050
  return null;
35991
36051
  }
@@ -35999,7 +36059,7 @@ function renameWithRetry(tmp, file) {
35999
36059
  const retryable = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES"]);
36000
36060
  for (let attempt = 0; ; attempt++) {
36001
36061
  try {
36002
- renameSync4(tmp, file);
36062
+ renameSync6(tmp, file);
36003
36063
  return;
36004
36064
  } catch (err) {
36005
36065
  const code = err.code ?? "";
@@ -36016,15 +36076,15 @@ function unlinkQuiet(file) {
36016
36076
  }
36017
36077
  function atomicWrite(file, content, mode = 420) {
36018
36078
  const secret = mode === SECRET_MODE;
36019
- const dir = path4.dirname(file);
36020
- mkdirSync4(dir, { recursive: true, ...secret ? { mode: SECRET_DIR_MODE } : {} });
36021
- const tmp = path4.join(
36079
+ const dir = path5.dirname(file);
36080
+ mkdirSync7(dir, { recursive: true, ...secret ? { mode: SECRET_DIR_MODE } : {} });
36081
+ const tmp = path5.join(
36022
36082
  dir,
36023
- `.${path4.basename(file)}.${process.pid}.${randomBytes5(4).toString("hex")}.tmp`
36083
+ `.${path5.basename(file)}.${process.pid}.${randomBytes5(4).toString("hex")}.tmp`
36024
36084
  );
36025
36085
  let renamed = false;
36026
36086
  try {
36027
- writeFileSync4(tmp, content, { encoding: "utf-8", mode });
36087
+ writeFileSync7(tmp, content, { encoding: "utf-8", mode });
36028
36088
  if (secret) chmodOwnerOnly(tmp);
36029
36089
  renameWithRetry(tmp, file);
36030
36090
  renamed = true;
@@ -36038,11 +36098,11 @@ var LOCK_RETRY_MS3 = 50;
36038
36098
  var LOCK_STALE_MS3 = 5e3;
36039
36099
  function withFileLock(file, fn) {
36040
36100
  const lock = `${file}.lock`;
36041
- mkdirSync4(path4.dirname(file), { recursive: true, mode: SECRET_DIR_MODE });
36101
+ mkdirSync7(path5.dirname(file), { recursive: true, mode: SECRET_DIR_MODE });
36042
36102
  let held = false;
36043
36103
  for (let attempt = 0; attempt < LOCK_RETRIES && !held; attempt++) {
36044
36104
  try {
36045
- writeFileSync4(lock, `${process.pid}
36105
+ writeFileSync7(lock, `${process.pid}
36046
36106
  `, { flag: "wx" });
36047
36107
  held = true;
36048
36108
  } catch (err) {
@@ -36091,7 +36151,7 @@ function writeHomeKeyLine(profileName, privateKey, vaultId) {
36091
36151
  }
36092
36152
  function readVaultId(vaultRoot) {
36093
36153
  try {
36094
- const raw = readOrNull(path4.join(vaultRoot, "heyspex.yaml"));
36154
+ const raw = readOrNull(path5.join(vaultRoot, "heyspex.yaml"));
36095
36155
  return raw === null ? null : parseVaultId(raw);
36096
36156
  } catch {
36097
36157
  return null;
@@ -36234,7 +36294,7 @@ function legacyDecryptAllSync(vaultRoot, name) {
36234
36294
  }
36235
36295
  function initProfile(vaultRoot, name = DEFAULT_PROFILE2, opts = {}) {
36236
36296
  const pFile = profilePath(vaultRoot, name);
36237
- if (existsSync5(pFile) && !opts.force) {
36297
+ if (existsSync8(pFile) && !opts.force) {
36238
36298
  throw new EnvVaultConfigError(
36239
36299
  `Env profile "${name}" already exists at ${pFile}. Pass --force to re-key it (this discards existing values and mints a new keypair).`
36240
36300
  );
@@ -36620,7 +36680,7 @@ function removeGrant(vaultRoot, profileName, name, opts = {}) {
36620
36680
  }
36621
36681
  async function exportProfile(vaultRoot, name = DEFAULT_PROFILE2, opts = {}) {
36622
36682
  const target = dotenvPath(vaultRoot);
36623
- if (existsSync5(target) && !opts.force) {
36683
+ if (existsSync8(target) && !opts.force) {
36624
36684
  throw new EnvVaultConfigError(
36625
36685
  `${target} already exists. Pass --force to overwrite it (it is disposable \u2014 the encrypted profile is the system of record).`
36626
36686
  );
@@ -36632,10 +36692,10 @@ async function exportProfile(vaultRoot, name = DEFAULT_PROFILE2, opts = {}) {
36632
36692
  return { path: target };
36633
36693
  }
36634
36694
  function resolveVaultPath(vaultRoot, filePath) {
36635
- const root = path4.resolve(vaultRoot);
36636
- const resolved = path4.resolve(root, filePath);
36637
- const rel = path4.relative(root, resolved);
36638
- if (path4.isAbsolute(filePath) || path4.isAbsolute(rel) || rel === ".." || rel.startsWith(`..${path4.sep}`)) {
36695
+ const root = path5.resolve(vaultRoot);
36696
+ const resolved = path5.resolve(root, filePath);
36697
+ const rel = path5.relative(root, resolved);
36698
+ if (path5.isAbsolute(filePath) || path5.isAbsolute(rel) || rel === ".." || rel.startsWith(`..${path5.sep}`)) {
36639
36699
  throw new EnvVaultConfigError(
36640
36700
  `Refusing to touch "${filePath}" \u2014 it resolves outside the vault root (${root}). Vault file paths must stay inside the repo (no "..", no absolute paths).`
36641
36701
  );
@@ -36649,7 +36709,7 @@ function writeTextFile(vaultRoot, filePath, content) {
36649
36709
  atomicWrite(resolveVaultPath(vaultRoot, filePath), content, SECRET_MODE);
36650
36710
  }
36651
36711
  function pathExists(vaultRoot, filePath) {
36652
- return existsSync5(resolveVaultPath(vaultRoot, filePath));
36712
+ return existsSync8(resolveVaultPath(vaultRoot, filePath));
36653
36713
  }
36654
36714
  function fileMtime(vaultRoot, filePath) {
36655
36715
  const resolved = resolveVaultPath(vaultRoot, filePath);
@@ -36683,7 +36743,7 @@ function listRepoSourceFiles(vaultRoot) {
36683
36743
  for (const entry of entries) {
36684
36744
  const childRel = rel === "" ? entry.name : `${rel}/${entry.name}`;
36685
36745
  if (entry.isDirectory()) {
36686
- if (!WALK_SKIP_DIRS.has(entry.name)) walk(path4.join(dir, entry.name), childRel);
36746
+ if (!WALK_SKIP_DIRS.has(entry.name)) walk(path5.join(dir, entry.name), childRel);
36687
36747
  } else if (entry.isFile()) {
36688
36748
  out.push(childRel);
36689
36749
  }
@@ -36709,7 +36769,7 @@ function isKeysFileGitignored(vaultRoot) {
36709
36769
  if (res.status === 1) return false;
36710
36770
  } catch {
36711
36771
  }
36712
- const gitignore = readOrNull(path4.join(vaultRoot, ".gitignore"));
36772
+ const gitignore = readOrNull(path5.join(vaultRoot, ".gitignore"));
36713
36773
  if (gitignore === null) return false;
36714
36774
  const ignorePatterns = /* @__PURE__ */ new Set([
36715
36775
  ".heyspex/env.keys",
@@ -36739,16 +36799,44 @@ async function httpPostJson(url, body) {
36739
36799
  return { status: res.status, body: parsed };
36740
36800
  }
36741
36801
 
36802
+ // spex-console/bin/run-entry.ts
36803
+ import process2 from "node:process";
36804
+ var BinExit = class extends Error {
36805
+ code;
36806
+ constructor(code) {
36807
+ super(`exit ${code}`);
36808
+ this.name = "BinExit";
36809
+ this.code = code;
36810
+ }
36811
+ };
36812
+ function runEntry(name, main2, options = {}) {
36813
+ const { fallbackCode = 1, unhandledLabel = "unhandled" } = options;
36814
+ void (async () => {
36815
+ try {
36816
+ await main2();
36817
+ } catch (err) {
36818
+ if (err instanceof BinExit) {
36819
+ process2.exitCode = err.code;
36820
+ return;
36821
+ }
36822
+ const message = err instanceof Error ? err.message : String(err);
36823
+ process2.stderr.write(`${name}: ${unhandledLabel}: ${message}
36824
+ `);
36825
+ process2.exitCode = fallbackCode;
36826
+ }
36827
+ })();
36828
+ }
36829
+
36742
36830
  // spex-console/bin/hs-env.ts
36743
36831
  function hsSelfCommand() {
36744
- const here = path5.dirname(fileURLToPath(import.meta.url));
36745
- const pkgRoot = process2.env.HS_PKG_ROOT?.trim();
36832
+ const here = path6.dirname(fileURLToPath2(import.meta.url));
36833
+ const pkgRoot = resolveCodeRoot({});
36746
36834
  const candidates = [
36747
- ...pkgRoot ? [path5.join(pkgRoot, "bin", "hs.mjs")] : [],
36748
- path5.resolve(here, "..", "..", "bin", "hs.mjs")
36835
+ ...pkgRoot ? [path6.join(pkgRoot, "bin", "hs.mjs")] : [],
36836
+ path6.resolve(here, "..", "..", "bin", "hs.mjs")
36749
36837
  ];
36750
- const launcher = candidates.find((c) => existsSync6(c));
36751
- return launcher ? [process2.execPath, launcher] : null;
36838
+ const launcher = candidates.find((c) => existsSync9(c));
36839
+ return launcher ? [process3.execPath, launcher] : null;
36752
36840
  }
36753
36841
  var VIRTUAL_ADAPTER = /nordlynx|tailscale|zerotier|hamachi|wireguard|openvpn|proton|tap-|tun\d|vethernet|\bwsl\b|hyper-v|docker|vmware|virtualbox|vbox|utun|bridge/i;
36754
36842
  function lanCandidates() {
@@ -36773,36 +36861,39 @@ function lanIp() {
36773
36861
  return lanCandidates()[0]?.address ?? null;
36774
36862
  }
36775
36863
  function readStdin() {
36776
- if (process2.stdin.isTTY) {
36777
- const eof = process2.platform === "win32" ? "Ctrl+Z then Enter" : "Ctrl+D";
36778
- process2.stderr.write(`Paste the value, press Enter, then ${eof} to finish (Ctrl+C cancels):
36864
+ if (process3.stdin.isTTY) {
36865
+ const eof = process3.platform === "win32" ? "Ctrl+Z then Enter" : "Ctrl+D";
36866
+ process3.stderr.write(`Paste the value, press Enter, then ${eof} to finish (Ctrl+C cancels):
36779
36867
  `);
36780
36868
  }
36781
- return new Promise((resolve, reject) => {
36869
+ return new Promise((resolve5, reject) => {
36782
36870
  const chunks = [];
36783
- process2.stdin.on("data", (c) => chunks.push(c));
36784
- process2.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
36785
- process2.stdin.on("error", reject);
36871
+ process3.stdin.on("data", (c) => chunks.push(c));
36872
+ process3.stdin.on("end", () => resolve5(Buffer.concat(chunks).toString("utf-8")));
36873
+ process3.stdin.on("error", reject);
36786
36874
  });
36787
36875
  }
36788
36876
  async function main() {
36789
- const vaultRoot = process2.env.HS_VAULT_ROOT;
36877
+ const vaultRoot = process3.env.HS_VAULT_ROOT;
36790
36878
  if (!vaultRoot) {
36791
- process2.stderr.write(
36879
+ process3.stderr.write(
36792
36880
  "hs env: HS_VAULT_ROOT is not set (the dispatcher must resolve and pass it).\n"
36793
36881
  );
36794
- process2.exit(EXIT.USAGE);
36882
+ process3.exitCode = EXIT.USAGE;
36883
+ return;
36795
36884
  }
36796
- const parsed = parseEnvArgs(process2.argv.slice(3));
36885
+ const parsed = parseEnvArgs(process3.argv.slice(3));
36797
36886
  if ("help" in parsed) {
36798
- process2.stdout.write(`${HELP}
36887
+ process3.stdout.write(`${HELP}
36799
36888
  `);
36800
- process2.exit(EXIT.OK);
36889
+ process3.exitCode = EXIT.OK;
36890
+ return;
36801
36891
  }
36802
36892
  if ("error" in parsed) {
36803
- process2.stderr.write(`hs env: ${parsed.error.message}
36893
+ process3.stderr.write(`hs env: ${parsed.error.message}
36804
36894
  `);
36805
- process2.exit(parsed.error.code);
36895
+ process3.exitCode = parsed.error.code;
36896
+ return;
36806
36897
  }
36807
36898
  const result = await runEnv(parsed.args, {
36808
36899
  vaultRoot,
@@ -36817,29 +36908,24 @@ async function main() {
36817
36908
  // `resolveVerifyCommand`) so no manifest text is shell-interpolated.
36818
36909
  ...options.shell === true ? { shell: true } : {}
36819
36910
  }),
36820
- stdout: (s) => process2.stdout.write(s),
36821
- stderr: (s) => process2.stderr.write(s),
36822
- env: process2.env,
36911
+ stdout: (s) => process3.stdout.write(s),
36912
+ stderr: (s) => process3.stderr.write(s),
36913
+ env: process3.env,
36823
36914
  audit: (event) => void appendEnvVaultAudit(vaultRoot, event),
36824
36915
  readStdin,
36825
- sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
36916
+ sleep: (ms) => new Promise((resolve5) => setTimeout(resolve5, ms)),
36826
36917
  httpPostJson,
36827
36918
  pairingConsoleCandidates: defaultPairingConsoleCandidates,
36828
36919
  lanIp,
36829
36920
  lanCandidates,
36830
- platform: process2.platform,
36921
+ platform: process3.platform,
36831
36922
  hsSelfCommand: hsSelfCommand()
36832
36923
  });
36833
36924
  if (result.message) {
36834
- const sink = result.code === EXIT.OK ? process2.stdout : process2.stderr;
36925
+ const sink = result.code === EXIT.OK ? process3.stdout : process3.stderr;
36835
36926
  sink.write(`${result.message}
36836
36927
  `);
36837
36928
  }
36838
- process2.exit(result.code);
36929
+ process3.exitCode = result.code;
36839
36930
  }
36840
- main().catch((err) => {
36841
- const message = err instanceof Error ? err.message : String(err);
36842
- process2.stderr.write(`hs env: unhandled: ${message}
36843
- `);
36844
- process2.exit(EXIT.RUNTIME);
36845
- });
36931
+ runEntry("hs env", main, { fallbackCode: EXIT.RUNTIME });