peaks-loop 4.1.2 → 4.1.3

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 (323) hide show
  1. package/.claude-plugin/marketplace.json +136 -47
  2. package/CHANGELOG.md +56 -0
  3. package/README-en.md +1 -1
  4. package/README.md +1 -1
  5. package/contracts/readonly-argv-whitelist.json +211 -0
  6. package/dist/cli/commands/audit-artifact-runners.d.ts +16 -0
  7. package/dist/cli/commands/audit-artifact-runners.js +170 -0
  8. package/dist/cli/commands/audit-command-shared.d.ts +97 -0
  9. package/dist/cli/commands/audit-command-shared.js +60 -0
  10. package/dist/cli/commands/audit-commands.d.ts +7 -31
  11. package/dist/cli/commands/audit-commands.js +64 -473
  12. package/dist/cli/commands/audit-goal-runners.d.ts +17 -0
  13. package/dist/cli/commands/audit-goal-runners.js +114 -0
  14. package/dist/cli/commands/audit-red-lines-runners.d.ts +11 -0
  15. package/dist/cli/commands/audit-red-lines-runners.js +43 -0
  16. package/dist/cli/commands/audit-refusal-data.d.ts +23 -0
  17. package/dist/cli/commands/audit-refusal-data.js +69 -0
  18. package/dist/cli/commands/audit-static-runners.d.ts +13 -0
  19. package/dist/cli/commands/audit-static-runners.js +139 -0
  20. package/dist/cli/commands/await-runners.d.ts +11 -0
  21. package/dist/cli/commands/await-runners.js +148 -0
  22. package/dist/cli/commands/code-auto-compact-command.d.ts +3 -0
  23. package/dist/cli/commands/code-auto-compact-command.js +124 -0
  24. package/dist/cli/commands/code-auto-compact-envelope.d.ts +22 -0
  25. package/dist/cli/commands/code-auto-compact-envelope.js +39 -0
  26. package/dist/cli/commands/code-context-audit-command.d.ts +3 -0
  27. package/dist/cli/commands/code-context-audit-command.js +68 -0
  28. package/dist/cli/commands/code-context-now-command.d.ts +3 -0
  29. package/dist/cli/commands/code-context-now-command.js +124 -0
  30. package/dist/cli/commands/code-context-now-envelope.d.ts +66 -0
  31. package/dist/cli/commands/code-context-now-envelope.js +136 -0
  32. package/dist/cli/commands/code-context-now-mapping.d.ts +27 -0
  33. package/dist/cli/commands/code-context-now-mapping.js +43 -0
  34. package/dist/cli/commands/code-emit-handoff-command.d.ts +3 -0
  35. package/dist/cli/commands/code-emit-handoff-command.js +99 -0
  36. package/dist/cli/commands/code-gate-step-08-command.d.ts +3 -0
  37. package/dist/cli/commands/code-gate-step-08-command.js +139 -0
  38. package/dist/cli/commands/code-post-compact-detect-command.d.ts +3 -0
  39. package/dist/cli/commands/code-post-compact-detect-command.js +50 -0
  40. package/dist/cli/commands/code-runtime-commands.d.ts +9 -43
  41. package/dist/cli/commands/code-runtime-commands.js +20 -672
  42. package/dist/cli/commands/code-runtime-session.d.ts +1 -0
  43. package/dist/cli/commands/code-runtime-session.js +15 -0
  44. package/dist/cli/commands/compact-command.d.ts +6 -2
  45. package/dist/cli/commands/compact-command.js +12 -559
  46. package/dist/cli/commands/compact-dry-run-command.d.ts +3 -0
  47. package/dist/cli/commands/compact-dry-run-command.js +87 -0
  48. package/dist/cli/commands/compact-force-command.d.ts +3 -0
  49. package/dist/cli/commands/compact-force-command.js +98 -0
  50. package/dist/cli/commands/compact-harness-window-command.d.ts +3 -0
  51. package/dist/cli/commands/compact-harness-window-command.js +174 -0
  52. package/dist/cli/commands/compact-history-command.d.ts +3 -0
  53. package/dist/cli/commands/compact-history-command.js +89 -0
  54. package/dist/cli/commands/compact-read-commands.d.ts +3 -0
  55. package/dist/cli/commands/compact-read-commands.js +123 -0
  56. package/dist/cli/commands/compact-settle-command.d.ts +3 -0
  57. package/dist/cli/commands/compact-settle-command.js +130 -0
  58. package/dist/cli/commands/compact-shared.d.ts +9 -0
  59. package/dist/cli/commands/compact-shared.js +26 -0
  60. package/dist/cli/commands/core/skill-command.d.ts +1 -44
  61. package/dist/cli/commands/core/skill-command.js +13 -541
  62. package/dist/cli/commands/core/skill-context-verdict.d.ts +38 -0
  63. package/dist/cli/commands/core/skill-context-verdict.js +63 -0
  64. package/dist/cli/commands/core/skill-generated-config-notice.d.ts +41 -0
  65. package/dist/cli/commands/core/skill-generated-config-notice.js +75 -0
  66. package/dist/cli/commands/core/skill-heartbeat-commands.d.ts +3 -0
  67. package/dist/cli/commands/core/skill-heartbeat-commands.js +50 -0
  68. package/dist/cli/commands/core/skill-presence-commands.d.ts +3 -0
  69. package/dist/cli/commands/core/skill-presence-commands.js +123 -0
  70. package/dist/cli/commands/core/skill-presence-housekeeping-commands.d.ts +3 -0
  71. package/dist/cli/commands/core/skill-presence-housekeeping-commands.js +165 -0
  72. package/dist/cli/commands/core/skill-registry-commands.d.ts +3 -0
  73. package/dist/cli/commands/core/skill-registry-commands.js +117 -0
  74. package/dist/cli/commands/core/skill-runbook-command.d.ts +3 -0
  75. package/dist/cli/commands/core/skill-runbook-command.js +29 -0
  76. package/dist/cli/commands/dispatch-command-spec.d.ts +2 -0
  77. package/dist/cli/commands/dispatch-command-spec.js +62 -0
  78. package/dist/cli/commands/dispatch-commands.js +159 -775
  79. package/dist/cli/commands/dispatch-detached-branch.d.ts +3 -0
  80. package/dist/cli/commands/dispatch-detached-branch.js +58 -0
  81. package/dist/cli/commands/dispatch-envelope.d.ts +36 -0
  82. package/dist/cli/commands/dispatch-envelope.js +104 -0
  83. package/dist/cli/commands/dispatch-isolation-lease.d.ts +17 -0
  84. package/dist/cli/commands/dispatch-isolation-lease.js +149 -0
  85. package/dist/cli/commands/dispatch-preflight.d.ts +7 -0
  86. package/dist/cli/commands/dispatch-preflight.js +105 -0
  87. package/dist/cli/commands/dispatch-prompt-blocks.d.ts +10 -0
  88. package/dist/cli/commands/dispatch-prompt-blocks.js +56 -0
  89. package/dist/cli/commands/dispatch-prompt-composition.d.ts +30 -0
  90. package/dist/cli/commands/dispatch-prompt-composition.js +171 -0
  91. package/dist/cli/commands/dispatch-record-write.d.ts +24 -0
  92. package/dist/cli/commands/dispatch-record-write.js +96 -0
  93. package/dist/cli/commands/dispatch-tool-call.d.ts +15 -0
  94. package/dist/cli/commands/dispatch-tool-call.js +128 -0
  95. package/dist/cli/commands/evolution-command-shared.d.ts +78 -0
  96. package/dist/cli/commands/evolution-command-shared.js +107 -0
  97. package/dist/cli/commands/evolution-commands.d.ts +11 -1
  98. package/dist/cli/commands/evolution-commands.js +19 -350
  99. package/dist/cli/commands/evolution-evaluate-command.d.ts +24 -0
  100. package/dist/cli/commands/evolution-evaluate-command.js +138 -0
  101. package/dist/cli/commands/evolution-propose-command.d.ts +23 -0
  102. package/dist/cli/commands/evolution-propose-command.js +145 -0
  103. package/dist/cli/commands/evolution-status-command.d.ts +17 -0
  104. package/dist/cli/commands/evolution-status-command.js +41 -0
  105. package/dist/cli/commands/evolution-verdict-commands.d.ts +30 -0
  106. package/dist/cli/commands/evolution-verdict-commands.js +100 -0
  107. package/dist/cli/commands/finalize-accumulator.d.ts +44 -0
  108. package/dist/cli/commands/finalize-accumulator.js +55 -0
  109. package/dist/cli/commands/finalize-branches.d.ts +34 -0
  110. package/dist/cli/commands/finalize-branches.js +119 -0
  111. package/dist/cli/commands/finalize-runners.d.ts +3 -0
  112. package/dist/cli/commands/finalize-runners.js +92 -0
  113. package/dist/cli/commands/finalize-selection.d.ts +65 -0
  114. package/dist/cli/commands/finalize-selection.js +35 -0
  115. package/dist/cli/commands/gate-commands.js +26 -8
  116. package/dist/cli/commands/job-checkpoint-commands.d.ts +3 -0
  117. package/dist/cli/commands/job-checkpoint-commands.js +157 -0
  118. package/dist/cli/commands/job-command-shared.d.ts +109 -0
  119. package/dist/cli/commands/job-command-shared.js +72 -0
  120. package/dist/cli/commands/job-commands.d.ts +4 -64
  121. package/dist/cli/commands/job-commands.js +42 -552
  122. package/dist/cli/commands/job-cost-check-command.d.ts +3 -0
  123. package/dist/cli/commands/job-cost-check-command.js +41 -0
  124. package/dist/cli/commands/job-init-status-commands.d.ts +3 -0
  125. package/dist/cli/commands/job-init-status-commands.js +149 -0
  126. package/dist/cli/commands/job-run-commands.d.ts +3 -0
  127. package/dist/cli/commands/job-run-commands.js +97 -0
  128. package/dist/cli/commands/job-state-root.d.ts +35 -0
  129. package/dist/cli/commands/job-state-root.js +76 -0
  130. package/dist/cli/commands/loop-eval-capture-index.d.ts +4 -0
  131. package/dist/cli/commands/loop-eval-capture-index.js +44 -0
  132. package/dist/cli/commands/loop-eval-commands.d.ts +8 -5
  133. package/dist/cli/commands/loop-eval-commands.js +12 -626
  134. package/dist/cli/commands/loop-eval-eval-command.d.ts +3 -0
  135. package/dist/cli/commands/loop-eval-eval-command.js +168 -0
  136. package/dist/cli/commands/loop-eval-monotonic-command.d.ts +3 -0
  137. package/dist/cli/commands/loop-eval-monotonic-command.js +90 -0
  138. package/dist/cli/commands/loop-eval-parents.d.ts +7 -0
  139. package/dist/cli/commands/loop-eval-parents.js +20 -0
  140. package/dist/cli/commands/loop-eval-run-code.d.ts +7 -0
  141. package/dist/cli/commands/loop-eval-run-code.js +40 -0
  142. package/dist/cli/commands/loop-eval-run-command.d.ts +3 -0
  143. package/dist/cli/commands/loop-eval-run-command.js +113 -0
  144. package/dist/cli/commands/loop-eval-spec-commands.d.ts +3 -0
  145. package/dist/cli/commands/loop-eval-spec-commands.js +165 -0
  146. package/dist/cli/commands/loop-eval-spec-lint-command.d.ts +3 -0
  147. package/dist/cli/commands/loop-eval-spec-lint-command.js +42 -0
  148. package/dist/cli/commands/loop-eval-workflow-commands.d.ts +3 -0
  149. package/dist/cli/commands/loop-eval-workflow-commands.js +141 -0
  150. package/dist/cli/commands/mcp-commands.d.ts +10 -0
  151. package/dist/cli/commands/mcp-commands.js +157 -0
  152. package/dist/cli/commands/request-command-options.d.ts +49 -0
  153. package/dist/cli/commands/request-command-options.js +1 -0
  154. package/dist/cli/commands/request-commands.d.ts +3 -9
  155. package/dist/cli/commands/request-commands.js +17 -522
  156. package/dist/cli/commands/request-init-command.d.ts +3 -0
  157. package/dist/cli/commands/request-init-command.js +100 -0
  158. package/dist/cli/commands/request-lint-command.d.ts +3 -0
  159. package/dist/cli/commands/request-lint-command.js +50 -0
  160. package/dist/cli/commands/request-list-command.d.ts +10 -0
  161. package/dist/cli/commands/request-list-command.js +53 -0
  162. package/dist/cli/commands/request-repair-status-command.d.ts +3 -0
  163. package/dist/cli/commands/request-repair-status-command.js +61 -0
  164. package/dist/cli/commands/request-show-command.d.ts +3 -0
  165. package/dist/cli/commands/request-show-command.js +56 -0
  166. package/dist/cli/commands/request-transition-command.d.ts +3 -0
  167. package/dist/cli/commands/request-transition-command.js +122 -0
  168. package/dist/cli/commands/request-transition-failures.d.ts +8 -0
  169. package/dist/cli/commands/request-transition-failures.js +90 -0
  170. package/dist/cli/commands/request-transition-hooks.d.ts +50 -0
  171. package/dist/cli/commands/request-transition-hooks.js +115 -0
  172. package/dist/cli/commands/request-transition-preflight.d.ts +10 -0
  173. package/dist/cli/commands/request-transition-preflight.js +107 -0
  174. package/dist/cli/commands/scan-command-shared.d.ts +96 -0
  175. package/dist/cli/commands/scan-command-shared.js +83 -0
  176. package/dist/cli/commands/scan-commands.d.ts +3 -2
  177. package/dist/cli/commands/scan-commands.js +23 -463
  178. package/dist/cli/commands/scan-inventory-commands.d.ts +3 -0
  179. package/dist/cli/commands/scan-inventory-commands.js +96 -0
  180. package/dist/cli/commands/scan-project-commands.d.ts +3 -0
  181. package/dist/cli/commands/scan-project-commands.js +65 -0
  182. package/dist/cli/commands/scan-scope-commands.d.ts +3 -0
  183. package/dist/cli/commands/scan-scope-commands.js +149 -0
  184. package/dist/cli/commands/scan-scope-helpers.d.ts +8 -0
  185. package/dist/cli/commands/scan-scope-helpers.js +54 -0
  186. package/dist/cli/commands/scan-structural-commands.d.ts +3 -0
  187. package/dist/cli/commands/scan-structural-commands.js +113 -0
  188. package/dist/cli/commands/share-commands.d.ts +12 -68
  189. package/dist/cli/commands/share-commands.js +47 -556
  190. package/dist/cli/commands/share-error-hints.d.ts +14 -0
  191. package/dist/cli/commands/share-error-hints.js +38 -0
  192. package/dist/cli/commands/share-identity.d.ts +13 -0
  193. package/dist/cli/commands/share-identity.js +22 -0
  194. package/dist/cli/commands/share-record-paths.d.ts +37 -0
  195. package/dist/cli/commands/share-record-paths.js +68 -0
  196. package/dist/cli/commands/share-runners.d.ts +3 -0
  197. package/dist/cli/commands/share-runners.js +158 -0
  198. package/dist/cli/commands/shared-read-runners.d.ts +3 -0
  199. package/dist/cli/commands/shared-read-runners.js +51 -0
  200. package/dist/cli/commands/slice-check-command.d.ts +3 -0
  201. package/dist/cli/commands/slice-check-command.js +54 -0
  202. package/dist/cli/commands/slice-commands.d.ts +2 -22
  203. package/dist/cli/commands/slice-commands.js +18 -517
  204. package/dist/cli/commands/slice-decompose-artifacts.d.ts +18 -0
  205. package/dist/cli/commands/slice-decompose-artifacts.js +79 -0
  206. package/dist/cli/commands/slice-decompose-command.d.ts +3 -0
  207. package/dist/cli/commands/slice-decompose-command.js +123 -0
  208. package/dist/cli/commands/slice-list-commands.d.ts +3 -0
  209. package/dist/cli/commands/slice-list-commands.js +182 -0
  210. package/dist/cli/commands/slice-pick-command.d.ts +3 -0
  211. package/dist/cli/commands/slice-pick-command.js +60 -0
  212. package/dist/cli/commands/slice-plan-command.d.ts +24 -0
  213. package/dist/cli/commands/slice-plan-command.js +111 -0
  214. package/dist/cli/commands/workflow-commands.d.ts +10 -1
  215. package/dist/cli/commands/workflow-commands.js +6 -594
  216. package/dist/cli/commands/workflow-gate-commands.d.ts +3 -0
  217. package/dist/cli/commands/workflow-gate-commands.js +116 -0
  218. package/dist/cli/commands/workflow-plan-helpers.d.ts +48 -0
  219. package/dist/cli/commands/workflow-plan-helpers.js +103 -0
  220. package/dist/cli/commands/workflow-planning-commands.d.ts +3 -0
  221. package/dist/cli/commands/workflow-planning-commands.js +56 -0
  222. package/dist/cli/commands/workflow-swarm-actions.d.ts +7 -0
  223. package/dist/cli/commands/workflow-swarm-actions.js +109 -0
  224. package/dist/cli/commands/workflow-swarm-commands.d.ts +3 -0
  225. package/dist/cli/commands/workflow-swarm-commands.js +138 -0
  226. package/dist/cli/commands/workflow-tech-actions.d.ts +10 -0
  227. package/dist/cli/commands/workflow-tech-actions.js +150 -0
  228. package/dist/cli/commands/workspace/init-actions.d.ts +10 -0
  229. package/dist/cli/commands/workspace/init-actions.js +199 -0
  230. package/dist/cli/commands/workspace/init-codegraph-stake.d.ts +10 -0
  231. package/dist/cli/commands/workspace/init-codegraph-stake.js +54 -0
  232. package/dist/cli/commands/workspace/init-command.d.ts +8 -124
  233. package/dist/cli/commands/workspace/init-command.js +59 -623
  234. package/dist/cli/commands/workspace/init-context.d.ts +58 -0
  235. package/dist/cli/commands/workspace/init-context.js +121 -0
  236. package/dist/cli/commands/workspace/init-envelope.d.ts +3 -0
  237. package/dist/cli/commands/workspace/init-envelope.js +34 -0
  238. package/dist/cli/commands/workspace/init-failures.d.ts +3 -0
  239. package/dist/cli/commands/workspace/init-failures.js +84 -0
  240. package/dist/cli/commands/workspace/init-hooks-decision.d.ts +24 -0
  241. package/dist/cli/commands/workspace/init-hooks-decision.js +189 -0
  242. package/dist/cli/commands/workspace/init-options.d.ts +102 -0
  243. package/dist/cli/commands/workspace/init-options.js +1 -0
  244. package/dist/cli/commands/worktree-lease-commands.d.ts +10 -6
  245. package/dist/cli/commands/worktree-lease-commands.js +42 -512
  246. package/dist/cli/commands/worktree-lease-gc-command.d.ts +12 -0
  247. package/dist/cli/commands/worktree-lease-gc-command.js +117 -0
  248. package/dist/cli/commands/worktree-lease-git.d.ts +22 -0
  249. package/dist/cli/commands/worktree-lease-git.js +48 -0
  250. package/dist/cli/commands/worktree-lease-list-command.d.ts +12 -0
  251. package/dist/cli/commands/worktree-lease-list-command.js +100 -0
  252. package/dist/cli/commands/worktree-lease-load.d.ts +37 -0
  253. package/dist/cli/commands/worktree-lease-load.js +28 -0
  254. package/dist/cli/commands/worktree-lease-release-command.d.ts +13 -0
  255. package/dist/cli/commands/worktree-lease-release-command.js +105 -0
  256. package/dist/cli/commands/worktree-lease-renew-command.d.ts +11 -0
  257. package/dist/cli/commands/worktree-lease-renew-command.js +99 -0
  258. package/dist/cli/commands/worktree-lease-session.d.ts +22 -0
  259. package/dist/cli/commands/worktree-lease-session.js +29 -0
  260. package/dist/cli/commands/worktree-lease-spawn-command.d.ts +11 -0
  261. package/dist/cli/commands/worktree-lease-spawn-command.js +119 -0
  262. package/dist/cli/commands/worktree-lease-status-command.d.ts +11 -0
  263. package/dist/cli/commands/worktree-lease-status-command.js +86 -0
  264. package/dist/cli/commands/worktree-lease-store.d.ts +19 -0
  265. package/dist/cli/commands/worktree-lease-store.js +24 -0
  266. package/dist/cli/program.js +5 -0
  267. package/dist/services/distribution/mcp-install-runner.d.ts +21 -0
  268. package/dist/services/distribution/mcp-install-runner.js +59 -0
  269. package/dist/services/distribution/mcp-install.d.ts +95 -0
  270. package/dist/services/distribution/mcp-install.js +179 -0
  271. package/dist/services/distribution/plugin-manifest.d.ts +97 -0
  272. package/dist/services/distribution/plugin-manifest.js +126 -0
  273. package/dist/services/hooks/mcp-surface-gate.d.ts +19 -0
  274. package/dist/services/hooks/mcp-surface-gate.js +87 -0
  275. package/dist/services/ide/adapters/claude-code-adapter.d.ts +4 -35
  276. package/dist/services/ide/adapters/claude-code-adapter.js +48 -171
  277. package/dist/services/ide/adapters/claude-code-local-state.d.ts +28 -0
  278. package/dist/services/ide/adapters/claude-code-local-state.js +112 -0
  279. package/dist/services/ide/adapters/claude-code-model-window.d.ts +37 -0
  280. package/dist/services/ide/adapters/claude-code-model-window.js +113 -0
  281. package/dist/services/ide/ide-mcp-install-types.d.ts +78 -0
  282. package/dist/services/ide/ide-mcp-install-types.js +104 -0
  283. package/dist/services/ide/ide-types.d.ts +45 -1
  284. package/dist/services/ide/mcp-tool-matcher.d.ts +34 -0
  285. package/dist/services/ide/mcp-tool-matcher.js +84 -0
  286. package/dist/services/lint/npx-resolver.js +7 -0
  287. package/dist/services/mcp/cli-executor.d.ts +36 -0
  288. package/dist/services/mcp/cli-executor.js +97 -0
  289. package/dist/services/mcp/json-rpc.d.ts +81 -0
  290. package/dist/services/mcp/json-rpc.js +116 -0
  291. package/dist/services/mcp/memory-tool.d.ts +3 -0
  292. package/dist/services/mcp/memory-tool.js +62 -0
  293. package/dist/services/mcp/server-main.d.ts +1 -0
  294. package/dist/services/mcp/server-main.js +66 -0
  295. package/dist/services/mcp/server.d.ts +22 -0
  296. package/dist/services/mcp/server.js +152 -0
  297. package/dist/services/mcp/surface.d.ts +62 -0
  298. package/dist/services/mcp/surface.js +198 -0
  299. package/dist/services/mcp/tool-core.d.ts +42 -0
  300. package/dist/services/mcp/tool-core.js +137 -0
  301. package/dist/services/mcp/tools.d.ts +13 -0
  302. package/dist/services/mcp/tools.js +58 -0
  303. package/dist/services/readonly-surface/argv-guard.d.ts +32 -0
  304. package/dist/services/readonly-surface/argv-guard.js +164 -0
  305. package/dist/services/readonly-surface/readonly-whitelist.d.ts +147 -0
  306. package/dist/services/readonly-surface/readonly-whitelist.js +107 -0
  307. package/dist/services/readonly-surface/whitelist-generator.d.ts +64 -0
  308. package/dist/services/readonly-surface/whitelist-generator.js +212 -0
  309. package/dist/services/skills/hooks-codegate-superpowers.d.ts +1 -0
  310. package/dist/services/skills/hooks-codegate-superpowers.js +26 -0
  311. package/dist/services/skills/hooks-settings-service.js +10 -2
  312. package/package.json +17 -6
  313. package/scripts/install-skills-bundles.mjs +233 -0
  314. package/scripts/install-skills-fs.mjs +148 -0
  315. package/scripts/install-skills-ide.mjs +279 -0
  316. package/scripts/install-skills-output-style-default.mjs +196 -0
  317. package/scripts/install-skills-output-styles.mjs +121 -0
  318. package/scripts/install-skills-report.mjs +42 -0
  319. package/scripts/install-skills-user-config.mjs +198 -0
  320. package/scripts/install-skills.mjs +36 -1066
  321. package/scripts/watch-tree.mjs +140 -0
  322. package/scripts/watch.mjs +4 -126
  323. package/skills/peaks-status/SKILL.md +31 -13
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Parameter-injection guard for the read-only surface.
3
+ *
4
+ * THE ATTACK. An argv template has placeholder slots (`request show <rid>`). If a
5
+ * placeholder value is pasted into a command LINE, the value `--apply` stops being
6
+ * a request id and becomes a flag - the semantics of the call are inverted by its
7
+ * own data. Two independent defences, both required (spec §8.1):
8
+ *
9
+ * 1. TYPE WHITELIST - every placeholder declares a type, and the value must
10
+ * satisfy it. No type admits a leading `-`, so a flag-shaped value is never a
11
+ * legal value of any placeholder.
12
+ * 2. ARRAY PASSING - `buildArgv` returns `string[]`. The caller passes the array
13
+ * to the process API with shell parsing disabled (`readonlySpawnOptions`), so
14
+ * no value is ever re-tokenized by a shell.
15
+ *
16
+ * Defence 2 alone is not enough: `spawn(..., {shell:false})` still hands `--apply`
17
+ * to the CLI as a real flag. Defence 1 alone is not enough: a caller that joins
18
+ * the array into a string reintroduces the shell. Hence both.
19
+ */
20
+ import { isAbsolute } from 'node:path';
21
+ /** Fallback pattern for a `slug` placeholder that declares none. */
22
+ const DEFAULT_SLUG_PATTERN = '^[a-z0-9][a-z0-9-]*$';
23
+ /** Upper bound on any single placeholder value, whatever its type. */
24
+ export const READONLY_VALUE_MAX_LENGTH = 200;
25
+ /** The process options that keep the array from being re-parsed by a shell. */
26
+ export function readonlySpawnOptions() {
27
+ return { shell: false };
28
+ }
29
+ function reject(param, code, message) {
30
+ return { ok: false, param, code, message };
31
+ }
32
+ /**
33
+ * Control characters, matched by Unicode category rather than by a literal range:
34
+ * a hand-written `\x00-\x1f` class is a lint error (`no-control-regex`) precisely
35
+ * because such a range in a pattern is usually a bug, and `\p{Cc}` says what is
36
+ * meant without spelling out code points.
37
+ */
38
+ function hasControlCharacter(value) {
39
+ return /\p{Cc}/u.test(value);
40
+ }
41
+ /**
42
+ * The rules that hold for EVERY type, before any type-specific rule runs. A
43
+ * leading `-` is refused here, so no type can carry a flag into the argv.
44
+ */
45
+ function precheckCommon(param, raw) {
46
+ if (typeof raw !== 'string') {
47
+ return reject(param, 'NOT_A_STRING', `Parameter ${param} must be a string.`);
48
+ }
49
+ if (raw.length === 0)
50
+ return reject(param, 'EMPTY', `Parameter ${param} must not be empty.`);
51
+ if (raw.length > READONLY_VALUE_MAX_LENGTH) {
52
+ return reject(param, 'TOO_LONG', `Parameter ${param} exceeds ${READONLY_VALUE_MAX_LENGTH} characters.`);
53
+ }
54
+ if (raw.startsWith('-')) {
55
+ return reject(param, 'FLAG_SHAPED', `Parameter ${param} must not look like a flag: ${raw}`);
56
+ }
57
+ if (hasControlCharacter(raw)) {
58
+ return reject(param, 'CONTROL_CHARACTER', `Parameter ${param} must not contain control characters.`);
59
+ }
60
+ return { ok: true, value: raw };
61
+ }
62
+ function checkToken(param, value) {
63
+ if (/\s/.test(value)) {
64
+ return reject(param, 'WHITESPACE', `Parameter ${param} must be a single token.`);
65
+ }
66
+ return { ok: true, value };
67
+ }
68
+ function checkSlug(param, value, spec) {
69
+ const asToken = checkToken(param, value);
70
+ if (!asToken.ok)
71
+ return asToken;
72
+ const pattern = new RegExp(spec.pattern ?? DEFAULT_SLUG_PATTERN);
73
+ if (!pattern.test(value)) {
74
+ return reject(param, 'PATTERN_MISMATCH', `Parameter ${param} must match ${pattern.source}: ${value}`);
75
+ }
76
+ return { ok: true, value };
77
+ }
78
+ function checkEnum(param, value, spec) {
79
+ if (spec.values === undefined || !spec.values.includes(value)) {
80
+ return reject(param, 'NOT_IN_ENUM', `Parameter ${param} must be one of: ${(spec.values ?? []).join(', ')}`);
81
+ }
82
+ return { ok: true, value };
83
+ }
84
+ function checkInteger(param, value, spec) {
85
+ if (!/^[0-9]+$/.test(value)) {
86
+ return reject(param, 'NOT_AN_INTEGER', `Parameter ${param} must be an integer: ${value}`);
87
+ }
88
+ const parsed = Number.parseInt(value, 10);
89
+ const min = spec.min ?? 0;
90
+ const max = spec.max ?? Number.MAX_SAFE_INTEGER;
91
+ if (parsed < min || parsed > max) {
92
+ return reject(param, 'OUT_OF_RANGE', `Parameter ${param} must be between ${min} and ${max}.`);
93
+ }
94
+ return { ok: true, value };
95
+ }
96
+ function checkPath(param, value) {
97
+ // Spaces are legal in a path and irrelevant under array passing; the absolute
98
+ // check is what keeps `--apply` and a bare word out.
99
+ if (!isAbsolute(value)) {
100
+ return reject(param, 'NOT_ABSOLUTE', `Parameter ${param} must be an absolute path.`);
101
+ }
102
+ return { ok: true, value };
103
+ }
104
+ const TYPE_CHECKS = {
105
+ token: (param, value) => checkToken(param, value),
106
+ slug: (param, value, spec) => checkSlug(param, value, spec),
107
+ enum: (param, value, spec) => checkEnum(param, value, spec),
108
+ integer: (param, value, spec) => checkInteger(param, value, spec),
109
+ path: (param, value) => checkPath(param, value)
110
+ };
111
+ /** Validate one placeholder value against its spec. */
112
+ export function validatePlaceholderValue(param, spec, raw) {
113
+ const prechecked = precheckCommon(param, raw);
114
+ if (!prechecked.ok)
115
+ return prechecked;
116
+ return TYPE_CHECKS[spec.type](param, prechecked.value, spec);
117
+ }
118
+ function missingParam(param) {
119
+ return reject(param, 'EMPTY', `Parameter ${param} was not supplied.`);
120
+ }
121
+ /** A value is required for every placeholder present in the template. */
122
+ function resolveParamValue(param, declared, values) {
123
+ if (declared === undefined)
124
+ return missingParam(param);
125
+ const supplied = values[param];
126
+ // Every placeholder in this surface is required (introspected), and a missing
127
+ // OPTIONAL value could only be honoured by also dropping the flag literal the
128
+ // loop has already pushed. Refusing is the honest answer.
129
+ if (supplied === undefined)
130
+ return missingParam(param);
131
+ return validatePlaceholderValue(param, declared, supplied);
132
+ }
133
+ function unknownParams(entry, values) {
134
+ for (const name of Object.keys(values)) {
135
+ if (!(name in entry.params)) {
136
+ return reject(name, 'NOT_A_STRING', `Entry ${entry.id} declares no parameter ${name}.`);
137
+ }
138
+ }
139
+ return undefined;
140
+ }
141
+ /**
142
+ * Render a whitelist entry into a concrete argv ARRAY.
143
+ *
144
+ * The output is never a string: literals and validated values are pushed as
145
+ * separate elements, so no value can contribute token boundaries. A parameter the
146
+ * entry does not declare is refused rather than appended.
147
+ */
148
+ export function buildArgv(entry, values) {
149
+ const unexpected = unknownParams(entry, values);
150
+ if (unexpected !== undefined)
151
+ return unexpected;
152
+ const argv = [];
153
+ for (const segment of entry.argv) {
154
+ if (segment.kind === 'literal') {
155
+ argv.push(segment.value);
156
+ continue;
157
+ }
158
+ const resolved = resolveParamValue(segment.name, entry.params[segment.name], values);
159
+ if (!resolved.ok)
160
+ return resolved;
161
+ argv.push(resolved.value);
162
+ }
163
+ return { ok: true, argv };
164
+ }
@@ -0,0 +1,147 @@
1
+ import { z } from 'zod';
2
+ /** Where the generator writes the artifact, relative to the package root. */
3
+ export declare const READONLY_WHITELIST_RELATIVE_PATH = "contracts/readonly-argv-whitelist.json";
4
+ declare const PlaceholderSpecSchema: z.ZodObject<{
5
+ type: z.ZodEnum<{
6
+ enum: "enum";
7
+ path: "path";
8
+ token: "token";
9
+ slug: "slug";
10
+ integer: "integer";
11
+ }>;
12
+ pattern: z.ZodOptional<z.ZodString>;
13
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
14
+ min: z.ZodOptional<z.ZodNumber>;
15
+ max: z.ZodOptional<z.ZodNumber>;
16
+ default: z.ZodOptional<z.ZodNumber>;
17
+ binding: z.ZodObject<{
18
+ kind: z.ZodEnum<{
19
+ option: "option";
20
+ positional: "positional";
21
+ }>;
22
+ token: z.ZodString;
23
+ required: z.ZodBoolean;
24
+ }, z.core.$strip>;
25
+ constraintSource: z.ZodEnum<{
26
+ introspected: "introspected";
27
+ handwritten: "handwritten";
28
+ }>;
29
+ }, z.core.$strip>;
30
+ declare const EntrySchema: z.ZodObject<{
31
+ id: z.ZodString;
32
+ tool: z.ZodString;
33
+ commandPath: z.ZodArray<z.ZodString>;
34
+ argv: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
35
+ kind: z.ZodLiteral<"literal">;
36
+ value: z.ZodString;
37
+ }, z.core.$strip>, z.ZodObject<{
38
+ kind: z.ZodLiteral<"param">;
39
+ name: z.ZodString;
40
+ }, z.core.$strip>]>>;
41
+ params: z.ZodRecord<z.ZodString, z.ZodObject<{
42
+ type: z.ZodEnum<{
43
+ enum: "enum";
44
+ path: "path";
45
+ token: "token";
46
+ slug: "slug";
47
+ integer: "integer";
48
+ }>;
49
+ pattern: z.ZodOptional<z.ZodString>;
50
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
51
+ min: z.ZodOptional<z.ZodNumber>;
52
+ max: z.ZodOptional<z.ZodNumber>;
53
+ default: z.ZodOptional<z.ZodNumber>;
54
+ binding: z.ZodObject<{
55
+ kind: z.ZodEnum<{
56
+ option: "option";
57
+ positional: "positional";
58
+ }>;
59
+ token: z.ZodString;
60
+ required: z.ZodBoolean;
61
+ }, z.core.$strip>;
62
+ constraintSource: z.ZodEnum<{
63
+ introspected: "introspected";
64
+ handwritten: "handwritten";
65
+ }>;
66
+ }, z.core.$strip>>;
67
+ introspection: z.ZodObject<{
68
+ optionTokens: z.ZodArray<z.ZodString>;
69
+ positionalCount: z.ZodNumber;
70
+ }, z.core.$strip>;
71
+ }, z.core.$strip>;
72
+ declare const WhitelistSchema: z.ZodObject<{
73
+ schemaVersion: z.ZodLiteral<1>;
74
+ source: z.ZodString;
75
+ readOnlyDefinition: z.ZodString;
76
+ entries: z.ZodArray<z.ZodObject<{
77
+ id: z.ZodString;
78
+ tool: z.ZodString;
79
+ commandPath: z.ZodArray<z.ZodString>;
80
+ argv: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
81
+ kind: z.ZodLiteral<"literal">;
82
+ value: z.ZodString;
83
+ }, z.core.$strip>, z.ZodObject<{
84
+ kind: z.ZodLiteral<"param">;
85
+ name: z.ZodString;
86
+ }, z.core.$strip>]>>;
87
+ params: z.ZodRecord<z.ZodString, z.ZodObject<{
88
+ type: z.ZodEnum<{
89
+ enum: "enum";
90
+ path: "path";
91
+ token: "token";
92
+ slug: "slug";
93
+ integer: "integer";
94
+ }>;
95
+ pattern: z.ZodOptional<z.ZodString>;
96
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
97
+ min: z.ZodOptional<z.ZodNumber>;
98
+ max: z.ZodOptional<z.ZodNumber>;
99
+ default: z.ZodOptional<z.ZodNumber>;
100
+ binding: z.ZodObject<{
101
+ kind: z.ZodEnum<{
102
+ option: "option";
103
+ positional: "positional";
104
+ }>;
105
+ token: z.ZodString;
106
+ required: z.ZodBoolean;
107
+ }, z.core.$strip>;
108
+ constraintSource: z.ZodEnum<{
109
+ introspected: "introspected";
110
+ handwritten: "handwritten";
111
+ }>;
112
+ }, z.core.$strip>>;
113
+ introspection: z.ZodObject<{
114
+ optionTokens: z.ZodArray<z.ZodString>;
115
+ positionalCount: z.ZodNumber;
116
+ }, z.core.$strip>;
117
+ }, z.core.$strip>>;
118
+ }, z.core.$strip>;
119
+ export type PlaceholderSpec = z.infer<typeof PlaceholderSpecSchema>;
120
+ export type ReadOnlyWhitelistEntry = z.infer<typeof EntrySchema>;
121
+ export type ReadOnlyWhitelist = z.infer<typeof WhitelistSchema>;
122
+ /** Absolute path of the generated artifact for a package root. */
123
+ export declare function resolveReadOnlyWhitelistPath(root?: string): string;
124
+ /** Parse + validate the artifact text. Throws a zod error when the shape drifts. */
125
+ export declare function parseReadOnlyWhitelist(text: string): ReadOnlyWhitelist;
126
+ /** Read + validate the artifact. The only supported way to obtain it. */
127
+ export declare function loadReadOnlyWhitelist(root?: string): ReadOnlyWhitelist;
128
+ /** The param names an entry expects, in argv order. */
129
+ export declare function paramNamesOf(entry: ReadOnlyWhitelistEntry): string[];
130
+ /**
131
+ * The tool names the surface declares, in first-appearance order.
132
+ *
133
+ * This is the pre-tool interceptor's view of "what may be called", and it is
134
+ * computed HERE rather than in the MCP module on purpose: the interceptor must
135
+ * keep working when `src/services/mcp/` is deleted (spec §1), so it cannot reach
136
+ * into it for the answer. Grouping the entries by their `tool` field is the whole
137
+ * computation, and both readers do it from the same DATA.
138
+ */
139
+ export declare function toolIdsOf(whitelist: ReadOnlyWhitelist): string[];
140
+ /**
141
+ * Match a CONCRETE argv against the entries. A param slot consumes exactly one
142
+ * token, so `--apply` in a param slot still MATCHES here - refusing it is the
143
+ * validator's job (`argv-guard.ts`), not the matcher's. Keeping the two separate
144
+ * is what stops a rejected value from silently re-routing to another entry.
145
+ */
146
+ export declare function matchReadOnlyEntry(whitelist: ReadOnlyWhitelist, argv: readonly string[]): ReadOnlyWhitelistEntry | undefined;
147
+ export {};
@@ -0,0 +1,107 @@
1
+ /**
2
+ * The read-only argv whitelist, as DATA.
3
+ *
4
+ * WHY THIS IS A LOADER AND NOT AN IMPORT. The generated whitelist is read by two
5
+ * consumers that must survive the removal of the MCP module (spec §1): the
6
+ * pre-tool interceptor and, later, the MCP server. If either `import`ed the
7
+ * generated artifact it would become a static edge between them, and deleting
8
+ * the MCP module would break the gate. So the artifact stays a `.json` file and
9
+ * every reader goes through the filesystem. `tests/unit/standards/no-mcp-source-import.test.ts`
10
+ * pins that no module may `import` it.
11
+ *
12
+ * The shape is `{ schemaVersion, source, readOnlyDefinition, entries[] }`. Each
13
+ * entry is a full argv template (flags included) plus typed placeholders - the
14
+ * key is the WHOLE argv, never the top-level verb, because each named command
15
+ * family mixes read and write subcommands.
16
+ */
17
+ import { readFileSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { z } from 'zod';
20
+ import { repoRoot } from 'peaks-loop-shared/paths';
21
+ /** Where the generator writes the artifact, relative to the package root. */
22
+ export const READONLY_WHITELIST_RELATIVE_PATH = 'contracts/readonly-argv-whitelist.json';
23
+ const PlaceholderBindingSchema = z.object({
24
+ /** `option` when the value is the argument of a flag, `positional` otherwise. */
25
+ kind: z.enum(['option', 'positional']),
26
+ /** The flag token (`--role`) or the positional name (`request-id`). */
27
+ token: z.string().min(1),
28
+ required: z.boolean()
29
+ });
30
+ const PlaceholderSpecSchema = z.object({
31
+ type: z.enum(['slug', 'enum', 'token', 'integer', 'path']),
32
+ pattern: z.string().min(1).optional(),
33
+ values: z.array(z.string().min(1)).min(1).optional(),
34
+ min: z.number().int().optional(),
35
+ max: z.number().int().optional(),
36
+ default: z.number().int().optional(),
37
+ /**
38
+ * Where the placeholder lives and whether the REGISTRY makes it mandatory.
39
+ * A placeholder present in the template is always supplied a value; this
40
+ * field carries the introspected fact, not the template's demand.
41
+ */
42
+ binding: PlaceholderBindingSchema,
43
+ /** `introspected` when the registry supplied the constraint, else `handwritten`. */
44
+ constraintSource: z.enum(['introspected', 'handwritten'])
45
+ });
46
+ const ArgvSegmentSchema = z.union([
47
+ z.object({ kind: z.literal('literal'), value: z.string().min(1) }),
48
+ z.object({ kind: z.literal('param'), name: z.string().min(1) })
49
+ ]);
50
+ const EntrySchema = z.object({
51
+ id: z.string().min(1),
52
+ tool: z.string().min(1),
53
+ commandPath: z.array(z.string().min(1)).min(1),
54
+ argv: z.array(ArgvSegmentSchema).min(1),
55
+ params: z.record(z.string(), PlaceholderSpecSchema),
56
+ introspection: z.object({
57
+ optionTokens: z.array(z.string().min(1)),
58
+ positionalCount: z.number().int().gte(0)
59
+ })
60
+ });
61
+ const WhitelistSchema = z.object({
62
+ schemaVersion: z.literal(1),
63
+ source: z.string().min(1),
64
+ readOnlyDefinition: z.string().min(1),
65
+ entries: z.array(EntrySchema).min(1)
66
+ });
67
+ /** Absolute path of the generated artifact for a package root. */
68
+ export function resolveReadOnlyWhitelistPath(root = repoRoot) {
69
+ return join(root, READONLY_WHITELIST_RELATIVE_PATH);
70
+ }
71
+ /** Parse + validate the artifact text. Throws a zod error when the shape drifts. */
72
+ export function parseReadOnlyWhitelist(text) {
73
+ return WhitelistSchema.parse(JSON.parse(text));
74
+ }
75
+ /** Read + validate the artifact. The only supported way to obtain it. */
76
+ export function loadReadOnlyWhitelist(root = repoRoot) {
77
+ return parseReadOnlyWhitelist(readFileSync(resolveReadOnlyWhitelistPath(root), 'utf8'));
78
+ }
79
+ /** The param names an entry expects, in argv order. */
80
+ export function paramNamesOf(entry) {
81
+ return entry.argv.flatMap((segment) => (segment.kind === 'param' ? [segment.name] : []));
82
+ }
83
+ /**
84
+ * The tool names the surface declares, in first-appearance order.
85
+ *
86
+ * This is the pre-tool interceptor's view of "what may be called", and it is
87
+ * computed HERE rather than in the MCP module on purpose: the interceptor must
88
+ * keep working when `src/services/mcp/` is deleted (spec §1), so it cannot reach
89
+ * into it for the answer. Grouping the entries by their `tool` field is the whole
90
+ * computation, and both readers do it from the same DATA.
91
+ */
92
+ export function toolIdsOf(whitelist) {
93
+ return [...new Set(whitelist.entries.map((entry) => entry.tool))];
94
+ }
95
+ /**
96
+ * Match a CONCRETE argv against the entries. A param slot consumes exactly one
97
+ * token, so `--apply` in a param slot still MATCHES here - refusing it is the
98
+ * validator's job (`argv-guard.ts`), not the matcher's. Keeping the two separate
99
+ * is what stops a rejected value from silently re-routing to another entry.
100
+ */
101
+ export function matchReadOnlyEntry(whitelist, argv) {
102
+ return whitelist.entries.find((entry) => {
103
+ if (entry.argv.length !== argv.length)
104
+ return false;
105
+ return entry.argv.every((segment, index) => segment.kind === 'literal' ? segment.value === argv[index] : true);
106
+ });
107
+ }
@@ -0,0 +1,64 @@
1
+ import type { Command } from 'commander';
2
+ import { z } from 'zod';
3
+ import { type ReadOnlyWhitelist } from './readonly-whitelist.js';
4
+ /** The hand-authored input, relative to the package root. */
5
+ export declare const READONLY_SURFACE_RELATIVE_PATH = "contracts/readonly-surface.json";
6
+ /** The schema version of the artifact this module emits. */
7
+ export declare const READONLY_WHITELIST_SCHEMA_VERSION = 1;
8
+ declare const SurfaceEntrySchema: z.ZodObject<{
9
+ id: z.ZodString;
10
+ commandPath: z.ZodArray<z.ZodString>;
11
+ argv: z.ZodArray<z.ZodString>;
12
+ params: z.ZodRecord<z.ZodString, z.ZodObject<{
13
+ type: z.ZodEnum<{
14
+ enum: "enum";
15
+ path: "path";
16
+ token: "token";
17
+ slug: "slug";
18
+ integer: "integer";
19
+ }>;
20
+ pattern: z.ZodOptional<z.ZodString>;
21
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ min: z.ZodOptional<z.ZodNumber>;
23
+ max: z.ZodOptional<z.ZodNumber>;
24
+ default: z.ZodOptional<z.ZodNumber>;
25
+ }, z.core.$strip>>;
26
+ }, z.core.$strip>;
27
+ export declare const ReadOnlySurfaceSchema: z.ZodObject<{
28
+ schemaVersion: z.ZodLiteral<1>;
29
+ readOnlyDefinition: z.ZodString;
30
+ note: z.ZodDefault<z.ZodArray<z.ZodString>>;
31
+ tools: z.ZodArray<z.ZodObject<{
32
+ tool: z.ZodString;
33
+ entries: z.ZodArray<z.ZodObject<{
34
+ id: z.ZodString;
35
+ commandPath: z.ZodArray<z.ZodString>;
36
+ argv: z.ZodArray<z.ZodString>;
37
+ params: z.ZodRecord<z.ZodString, z.ZodObject<{
38
+ type: z.ZodEnum<{
39
+ enum: "enum";
40
+ path: "path";
41
+ token: "token";
42
+ slug: "slug";
43
+ integer: "integer";
44
+ }>;
45
+ pattern: z.ZodOptional<z.ZodString>;
46
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
47
+ min: z.ZodOptional<z.ZodNumber>;
48
+ max: z.ZodOptional<z.ZodNumber>;
49
+ default: z.ZodOptional<z.ZodNumber>;
50
+ }, z.core.$strip>>;
51
+ }, z.core.$strip>>;
52
+ }, z.core.$strip>>;
53
+ }, z.core.$strip>;
54
+ export type ReadOnlySurface = z.infer<typeof ReadOnlySurfaceSchema>;
55
+ export type ReadOnlySurfaceEntry = z.infer<typeof SurfaceEntrySchema>;
56
+ /** Build the artifact object from a surface declaration and a live program. */
57
+ export declare function generateReadOnlyWhitelist(surface: ReadOnlySurface, program: Command): ReadOnlyWhitelist;
58
+ /** Byte-stable serialization: two runs over the same input MUST match. */
59
+ export declare function serializeReadOnlyWhitelist(whitelist: ReadOnlyWhitelist): string;
60
+ /** Read + validate the hand-authored surface declaration. */
61
+ export declare function loadReadOnlySurface(root?: string): ReadOnlySurface;
62
+ /** Absolute path of the generated artifact. */
63
+ export declare function readonlyWhitelistPath(root?: string): string;
64
+ export {};