@webpresso/agent-kit 3.1.28 → 3.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.

Potentially problematic release.


This version of @webpresso/agent-kit might be problematic. Click here for more details.

Files changed (329) hide show
  1. package/README.md +53 -15
  2. package/bin/_run.js +179 -19
  3. package/catalog/AGENTS.md.tpl +6 -6
  4. package/catalog/agent/agents/implementer.md +45 -0
  5. package/catalog/agent/rules/ci-cost-local-first.md +139 -0
  6. package/catalog/agent/rules/ci-test-perf.md +5 -1
  7. package/catalog/agent/rules/cmd-execution.md +9 -0
  8. package/catalog/agent/rules/parallel-orchestration-quota.md +100 -0
  9. package/catalog/agent/rules/pre-implementation.md +30 -2
  10. package/catalog/agent/rules/supported-agent-clis.md +9 -0
  11. package/catalog/agent/rules/test-scan-perf.md +80 -0
  12. package/catalog/agent/rules/typescript-version.md +50 -0
  13. package/catalog/agent/rules/workflow-skills-routing.md +4 -2
  14. package/catalog/agent/skills/codex/SKILL.md +25 -1
  15. package/catalog/agent/skills/fix/SKILL.md +3 -0
  16. package/catalog/agent/skills/verify/SKILL.md +22 -2
  17. package/catalog/docs/templates/blueprint.md +1 -1
  18. package/dist/esm/audit/agents.js +1 -0
  19. package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +12 -0
  20. package/dist/esm/audit/blueprint-lifecycle-sql.js +23 -2
  21. package/dist/esm/audit/blueprint-pr-coverage.js +72 -7
  22. package/dist/esm/audit/ci-guardrails-wiring.d.ts +22 -0
  23. package/dist/esm/audit/ci-guardrails-wiring.js +90 -0
  24. package/dist/esm/audit/ci-test-perf.js +30 -0
  25. package/dist/esm/audit/command-surface.js +4 -2
  26. package/dist/esm/audit/host-substitution-risk.d.ts +2 -0
  27. package/dist/esm/audit/host-substitution-risk.js +256 -0
  28. package/dist/esm/audit/registry.d.ts +4 -4
  29. package/dist/esm/audit/registry.js +11 -1
  30. package/dist/esm/audit/roadmap-links.js +6 -0
  31. package/dist/esm/audit/test-scan-perf.d.ts +18 -0
  32. package/dist/esm/audit/test-scan-perf.js +275 -0
  33. package/dist/esm/audit/toolchain-isolation.js +1 -2
  34. package/dist/esm/audit/typescript-version.d.ts +2 -0
  35. package/dist/esm/audit/typescript-version.js +123 -0
  36. package/dist/esm/blueprint/core/parser.js +43 -1
  37. package/dist/esm/blueprint/core/validation/criteria.d.ts +14 -0
  38. package/dist/esm/blueprint/core/validation/criteria.js +41 -2
  39. package/dist/esm/blueprint/core/validation/state.js +25 -14
  40. package/dist/esm/blueprint/db/migrations/run.js +4 -2
  41. package/dist/esm/blueprint/lifecycle/audit.d.ts +20 -0
  42. package/dist/esm/blueprint/lifecycle/audit.js +65 -10
  43. package/dist/esm/blueprint/lifecycle/canonicalize.d.ts +6 -0
  44. package/dist/esm/blueprint/lifecycle/canonicalize.js +135 -0
  45. package/dist/esm/blueprint/lifecycle/engine.d.ts +9 -0
  46. package/dist/esm/blueprint/lifecycle/engine.js +53 -6
  47. package/dist/esm/blueprint/lifecycle/local.d.ts +2 -1
  48. package/dist/esm/blueprint/lifecycle/local.js +19 -3
  49. package/dist/esm/blueprint/lifecycle/review-provenance.d.ts +6 -0
  50. package/dist/esm/blueprint/lifecycle/review-provenance.js +118 -12
  51. package/dist/esm/blueprint/markdown/helpers.js +6 -2
  52. package/dist/esm/blueprint/service/BlueprintCreationService.d.ts +1 -0
  53. package/dist/esm/blueprint/service/BlueprintCreationService.js +53 -4
  54. package/dist/esm/blueprint/service/blueprint-tech-debt-links.js +16 -2
  55. package/dist/esm/blueprint/trust/command-runner.d.ts +26 -0
  56. package/dist/esm/blueprint/trust/command-runner.js +148 -0
  57. package/dist/esm/blueprint/trust/gates.d.ts +7 -0
  58. package/dist/esm/blueprint/trust/gates.js +20 -0
  59. package/dist/esm/blueprint/trust/promotion.d.ts +8 -0
  60. package/dist/esm/blueprint/trust/promotion.js +62 -112
  61. package/dist/esm/blueprint/trust/scaffold.d.ts +19 -0
  62. package/dist/esm/blueprint/trust/scaffold.js +64 -0
  63. package/dist/esm/blueprint/trust/validator.d.ts +1 -0
  64. package/dist/esm/blueprint/trust/validator.js +7 -1
  65. package/dist/esm/blueprint/utils/archive.js +27 -5
  66. package/dist/esm/blueprint/utils/document-paths.d.ts +18 -0
  67. package/dist/esm/blueprint/utils/document-paths.js +45 -12
  68. package/dist/esm/build/cli-mcp-parity.js +10 -0
  69. package/dist/esm/ci/act-replay.js +110 -7
  70. package/dist/esm/ci/act-runner.d.ts +4 -0
  71. package/dist/esm/ci/act-runner.js +85 -26
  72. package/dist/esm/ci/act-worktree-git.d.ts +11 -0
  73. package/dist/esm/ci/act-worktree-git.js +219 -0
  74. package/dist/esm/cli/bundle/commands/blueprint.d.ts +1 -0
  75. package/dist/esm/cli/bundle/commands/blueprint.js +1 -0
  76. package/dist/esm/cli/cli.d.ts +1 -1
  77. package/dist/esm/cli/cli.js +34 -0
  78. package/dist/esm/cli/commands/agent-launch.d.ts +6 -1
  79. package/dist/esm/cli/commands/agent-launch.js +82 -4
  80. package/dist/esm/cli/commands/audit-core.d.ts +1 -1
  81. package/dist/esm/cli/commands/audit-core.js +8 -1
  82. package/dist/esm/cli/commands/audit.js +20 -5
  83. package/dist/esm/cli/commands/blueprint/execution.js +18 -6
  84. package/dist/esm/cli/commands/blueprint/mutations.js +83 -47
  85. package/dist/esm/cli/commands/blueprint/router-dispatch.d.ts +2 -1
  86. package/dist/esm/cli/commands/blueprint/router-dispatch.js +20 -1
  87. package/dist/esm/cli/commands/blueprint/router-output.d.ts +21 -0
  88. package/dist/esm/cli/commands/blueprint/router-output.js +48 -17
  89. package/dist/esm/cli/commands/blueprint/router.d.ts +7 -0
  90. package/dist/esm/cli/commands/blueprint/router.js +40 -3
  91. package/dist/esm/cli/commands/ci-preflight.d.ts +13 -2
  92. package/dist/esm/cli/commands/ci-preflight.js +6 -3
  93. package/dist/esm/cli/commands/ci.d.ts +8 -1
  94. package/dist/esm/cli/commands/ci.js +80 -21
  95. package/dist/esm/cli/commands/compile.js +5 -31
  96. package/dist/esm/cli/commands/dash/delivery-status.d.ts +1 -0
  97. package/dist/esm/cli/commands/dash/delivery-status.js +11 -4
  98. package/dist/esm/cli/commands/dash/keymap.js +1 -0
  99. package/dist/esm/cli/commands/dash/launch-preferences.d.ts +15 -0
  100. package/dist/esm/cli/commands/dash/launch-preferences.js +46 -17
  101. package/dist/esm/cli/commands/dash/plan-once-label.d.ts +7 -0
  102. package/dist/esm/cli/commands/dash/plan-once-label.js +5 -0
  103. package/dist/esm/cli/commands/dash/plan-once-membership.d.ts +67 -0
  104. package/dist/esm/cli/commands/dash/plan-once-membership.js +151 -0
  105. package/dist/esm/cli/commands/dash/plan-once-merge.d.ts +143 -0
  106. package/dist/esm/cli/commands/dash/plan-once-merge.js +238 -0
  107. package/dist/esm/cli/commands/dash/plan-once.d.ts +22 -2
  108. package/dist/esm/cli/commands/dash/plan-once.js +41 -4
  109. package/dist/esm/cli/commands/dash/tui/attention-hud.d.ts +9 -0
  110. package/dist/esm/cli/commands/dash/tui/attention-hud.js +9 -0
  111. package/dist/esm/cli/commands/dash/tui/chat-bridge.d.ts +41 -0
  112. package/dist/esm/cli/commands/dash/tui/chat-bridge.js +73 -0
  113. package/dist/esm/cli/commands/dash/tui/chat-mode.d.ts +47 -0
  114. package/dist/esm/cli/commands/dash/tui/chat-mode.js +98 -0
  115. package/dist/esm/cli/commands/dash/tui/frame.d.ts +3 -0
  116. package/dist/esm/cli/commands/dash/tui/frame.js +3 -1
  117. package/dist/esm/cli/commands/dash/tui/palette.d.ts +1 -1
  118. package/dist/esm/cli/commands/dash/tui/palette.js +14 -0
  119. package/dist/esm/cli/commands/dash/tui/runtime.js +239 -4
  120. package/dist/esm/cli/commands/dash/tui/state.d.ts +41 -0
  121. package/dist/esm/cli/commands/dash/tui/state.js +257 -4
  122. package/dist/esm/cli/commands/doctor.js +5 -0
  123. package/dist/esm/cli/commands/format.js +0 -2
  124. package/dist/esm/cli/commands/hook.d.ts +5 -0
  125. package/dist/esm/cli/commands/hook.js +15 -9
  126. package/dist/esm/cli/commands/init/config.d.ts +0 -1
  127. package/dist/esm/cli/commands/init/config.js +3 -6
  128. package/dist/esm/cli/commands/init/convergence-apply.d.ts +24 -0
  129. package/dist/esm/cli/commands/init/convergence-apply.js +221 -0
  130. package/dist/esm/cli/commands/init/convergence-state.d.ts +13 -0
  131. package/dist/esm/cli/commands/init/convergence-state.js +54 -0
  132. package/dist/esm/cli/commands/init/convergence.d.ts +23 -0
  133. package/dist/esm/cli/commands/init/convergence.js +57 -0
  134. package/dist/esm/cli/commands/init/git-convergence.d.ts +19 -0
  135. package/dist/esm/cli/commands/init/git-convergence.js +168 -0
  136. package/dist/esm/cli/commands/init/gitignore-patcher.js +2 -0
  137. package/dist/esm/cli/commands/init/grok-privacy-smoke.d.ts +52 -0
  138. package/dist/esm/cli/commands/init/grok-privacy-smoke.js +91 -0
  139. package/dist/esm/cli/commands/init/host-native-proof.d.ts +18 -0
  140. package/dist/esm/cli/commands/init/host-native-proof.js +88 -0
  141. package/dist/esm/cli/commands/init/host-visibility.d.ts +2 -2
  142. package/dist/esm/cli/commands/init/host-visibility.js +94 -5
  143. package/dist/esm/cli/commands/init/index.d.ts +1 -0
  144. package/dist/esm/cli/commands/init/index.js +326 -173
  145. package/dist/esm/cli/commands/init/mcp-spec.d.ts +57 -0
  146. package/dist/esm/cli/commands/init/mcp-spec.js +273 -0
  147. package/dist/esm/cli/commands/init/merge.d.ts +1 -0
  148. package/dist/esm/cli/commands/init/merge.js +30 -1
  149. package/dist/esm/cli/commands/init/plugin-cache-prune.d.ts +0 -3
  150. package/dist/esm/cli/commands/init/plugin-cache-prune.js +0 -1
  151. package/dist/esm/cli/commands/init/scaffold-agents-md.d.ts +1 -1
  152. package/dist/esm/cli/commands/init/scaffold-agents-md.js +9 -3
  153. package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +11 -0
  154. package/dist/esm/cli/commands/init/scaffold-base-kit.js +56 -1
  155. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.d.ts +5 -6
  156. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.js +6 -13
  157. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.d.ts +14 -8
  158. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.js +41 -24
  159. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.d.ts +2 -0
  160. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +51 -23
  161. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.d.ts +0 -2
  162. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.js +0 -2
  163. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.d.ts +6 -3
  164. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.js +39 -26
  165. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.d.ts +12 -31
  166. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +297 -173
  167. package/dist/esm/cli/commands/init/scaffolders/file-transaction.d.ts +7 -0
  168. package/dist/esm/cli/commands/init/scaffolders/file-transaction.js +58 -0
  169. package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.d.ts +38 -0
  170. package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.js +73 -0
  171. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.d.ts +21 -0
  172. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.js +559 -63
  173. package/dist/esm/cli/commands/init/untracked-collision.d.ts +14 -0
  174. package/dist/esm/cli/commands/init/untracked-collision.js +42 -0
  175. package/dist/esm/cli/commands/logs.d.ts +15 -0
  176. package/dist/esm/cli/commands/logs.js +192 -3
  177. package/dist/esm/cli/commands/opencode-rotate.d.ts +49 -0
  178. package/dist/esm/cli/commands/opencode-rotate.js +135 -0
  179. package/dist/esm/cli/commands/public-readiness.d.ts +11 -0
  180. package/dist/esm/cli/commands/public-readiness.js +42 -0
  181. package/dist/esm/cli/commands/quality-log-store.d.ts +1 -0
  182. package/dist/esm/cli/commands/quality-log-store.js +187 -51
  183. package/dist/esm/cli/commands/review.d.ts +35 -3
  184. package/dist/esm/cli/commands/review.js +734 -217
  185. package/dist/esm/cli/commands/run-wait.d.ts +2 -0
  186. package/dist/esm/cli/commands/run-wait.js +122 -0
  187. package/dist/esm/cli/commands/secrets.d.ts +1 -0
  188. package/dist/esm/cli/commands/secrets.js +4 -1
  189. package/dist/esm/cli/commands/setup-help.js +1 -1
  190. package/dist/esm/cli/commands/setup-repair-help.js +1 -1
  191. package/dist/esm/cli/commands/worktree/router-dispatch.js +13 -8
  192. package/dist/esm/cli/direct-provider-launch.js +31 -3
  193. package/dist/esm/cli/optional-tool-freshness.d.ts +27 -0
  194. package/dist/esm/cli/optional-tool-freshness.js +219 -9
  195. package/dist/esm/daemon/domains/git-actions.d.ts +29 -0
  196. package/dist/esm/daemon/domains/git-actions.js +136 -0
  197. package/dist/esm/daemon/domains/run-registry-interop.d.ts +16 -0
  198. package/dist/esm/daemon/domains/run-registry-interop.js +45 -0
  199. package/dist/esm/daemon/domains/sessions-search.d.ts +11 -0
  200. package/dist/esm/daemon/domains/sessions-search.js +29 -0
  201. package/dist/esm/daemon/handlers/blueprints-handlers.d.ts +5 -0
  202. package/dist/esm/daemon/handlers/blueprints-handlers.js +36 -0
  203. package/dist/esm/daemon/handlers/deploy-handlers.d.ts +6 -0
  204. package/dist/esm/daemon/handlers/deploy-handlers.js +5 -0
  205. package/dist/esm/daemon/handlers/fleet-handlers.d.ts +15 -0
  206. package/dist/esm/daemon/handlers/fleet-handlers.js +91 -0
  207. package/dist/esm/daemon/handlers/git-handlers.d.ts +6 -0
  208. package/dist/esm/daemon/handlers/git-handlers.js +27 -0
  209. package/dist/esm/daemon/handlers/product.d.ts +7 -0
  210. package/dist/esm/daemon/handlers/product.js +10 -119
  211. package/dist/esm/daemon/handlers/sessions-handlers.d.ts +12 -0
  212. package/dist/esm/daemon/handlers/sessions-handlers.js +31 -0
  213. package/dist/esm/daemon/handlers/shared.d.ts +5 -0
  214. package/dist/esm/daemon/handlers/shared.js +16 -0
  215. package/dist/esm/daemon/methods.d.ts +8 -1
  216. package/dist/esm/daemon/methods.js +7 -0
  217. package/dist/esm/daemon/protocol/contract.d.ts +43 -0
  218. package/dist/esm/daemon/protocol/contract.js +26 -0
  219. package/dist/esm/daemon/protocol/index.d.ts +1 -1
  220. package/dist/esm/daemon/protocol/index.js +1 -1
  221. package/dist/esm/hooks/__conformance__/matrix.d.ts +6 -0
  222. package/dist/esm/hooks/__conformance__/matrix.js +137 -0
  223. package/dist/esm/hooks/conformance/batch.js +5 -0
  224. package/dist/esm/hooks/doctor.d.ts +15 -0
  225. package/dist/esm/hooks/doctor.js +79 -8
  226. package/dist/esm/hooks/permission-request/index.js +9 -3
  227. package/dist/esm/hooks/permission-request/policy.d.ts +9 -0
  228. package/dist/esm/hooks/permission-request/policy.js +13 -0
  229. package/dist/esm/hooks/pretool-guard/dev-routing.d.ts +9 -0
  230. package/dist/esm/hooks/pretool-guard/dev-routing.js +41 -5
  231. package/dist/esm/hooks/pretool-guard/logger.d.ts +7 -0
  232. package/dist/esm/hooks/pretool-guard/logger.js +16 -0
  233. package/dist/esm/hooks/pretool-guard/runner.d.ts +6 -0
  234. package/dist/esm/hooks/pretool-guard/runner.js +68 -16
  235. package/dist/esm/hooks/pretool-guard/validators/blueprint.js +30 -10
  236. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +58 -4
  237. package/dist/esm/hooks/pretool-guard/validators/index.d.ts +7 -0
  238. package/dist/esm/hooks/pretool-guard/validators/index.js +21 -0
  239. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +0 -1
  240. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +8 -5
  241. package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +19 -0
  242. package/dist/esm/hooks/pretool-guard/validators/path-contract.js +25 -8
  243. package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.d.ts +9 -7
  244. package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.js +126 -14
  245. package/dist/esm/hooks/shared/guard-outcome.d.ts +149 -0
  246. package/dist/esm/hooks/shared/guard-outcome.js +215 -0
  247. package/dist/esm/hooks/shared/hook-bootstrap.d.ts +26 -0
  248. package/dist/esm/hooks/shared/hook-bootstrap.js +64 -1
  249. package/dist/esm/hooks/shared/types.d.ts +8 -5
  250. package/dist/esm/hooks/shared/types.js +23 -8
  251. package/dist/esm/hooks/stop/qa-changed-files.d.ts +11 -0
  252. package/dist/esm/hooks/stop/qa-changed-files.js +74 -0
  253. package/dist/esm/mcp/blueprint/_shared/lifecycle.js +14 -1
  254. package/dist/esm/mcp/blueprint/handlers/document-mutations.js +78 -4
  255. package/dist/esm/mcp/blueprint/handlers/review-log.js +8 -1
  256. package/dist/esm/mcp/blueprint/handlers/task-advance.js +113 -54
  257. package/dist/esm/mcp/blueprint/handlers/task-verify.js +39 -19
  258. package/dist/esm/mcp/blueprint/registration.js +3 -2
  259. package/dist/esm/mcp/server.d.ts +1 -0
  260. package/dist/esm/mcp/server.js +27 -0
  261. package/dist/esm/mcp/tools/_names.d.ts +1 -1
  262. package/dist/esm/mcp/tools/_names.js +5 -0
  263. package/dist/esm/mcp/tools/_registry.js +10 -0
  264. package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
  265. package/dist/esm/mcp/tools/_shared/result.js +44 -1
  266. package/dist/esm/mcp/tools/audit.d.ts +5 -1
  267. package/dist/esm/mcp/tools/audit.js +40 -0
  268. package/dist/esm/mcp/tools/audits.d.ts +4 -0
  269. package/dist/esm/mcp/tools/ci-act.js +9 -11
  270. package/dist/esm/mcp/tools/ci-preflight.d.ts +50 -0
  271. package/dist/esm/mcp/tools/ci-preflight.js +183 -0
  272. package/dist/esm/mcp/tools/pr-upsert.js +39 -1
  273. package/dist/esm/mcp/tools/review-run.d.ts +28 -0
  274. package/dist/esm/mcp/tools/review-run.js +216 -0
  275. package/dist/esm/mcp/tools/run-wait.d.ts +86 -0
  276. package/dist/esm/mcp/tools/run-wait.js +593 -0
  277. package/dist/esm/mcp/tools/session-id.d.ts +3 -0
  278. package/dist/esm/mcp/tools/session-id.js +45 -0
  279. package/dist/esm/mcp/tools/session-info.d.ts +3 -0
  280. package/dist/esm/mcp/tools/session-info.js +49 -0
  281. package/dist/esm/output-transforms/audit.d.ts +23 -0
  282. package/dist/esm/output-transforms/audit.js +47 -0
  283. package/dist/esm/output-transforms/index.js +2 -0
  284. package/dist/esm/paths/state-root.js +3 -0
  285. package/dist/esm/review/authority.js +30 -7
  286. package/dist/esm/review/availability.d.ts +22 -0
  287. package/dist/esm/review/availability.js +123 -23
  288. package/dist/esm/review/delivery-verifier.d.ts +27 -0
  289. package/dist/esm/review/delivery-verifier.js +115 -0
  290. package/dist/esm/review/events.d.ts +3 -2
  291. package/dist/esm/review/events.js +23 -3
  292. package/dist/esm/review/execution/adapters.js +26 -9
  293. package/dist/esm/review/execution/output-policy.d.ts +2 -0
  294. package/dist/esm/review/execution/output-policy.js +12 -0
  295. package/dist/esm/review/execution/review-checkout.js +87 -6
  296. package/dist/esm/review/execution/supervisor.js +5 -0
  297. package/dist/esm/review/execution/types.d.ts +8 -0
  298. package/dist/esm/review/opencode-account.d.ts +24 -0
  299. package/dist/esm/review/opencode-account.js +68 -0
  300. package/dist/esm/review/opencode-auth.d.ts +33 -0
  301. package/dist/esm/review/opencode-auth.js +79 -0
  302. package/dist/esm/review/subject.d.ts +27 -0
  303. package/dist/esm/review/subject.js +179 -32
  304. package/dist/esm/runtime/executor.d.ts +1 -0
  305. package/dist/esm/runtime/executor.js +2 -1
  306. package/dist/esm/runtime/opencode-account-materializer.d.ts +34 -0
  307. package/dist/esm/runtime/opencode-account-materializer.js +33 -0
  308. package/dist/esm/secret-gate/runner.d.ts +1 -0
  309. package/dist/esm/secret-gate/runner.js +4 -1
  310. package/dist/esm/status/snapshot.js +30 -19
  311. package/dist/esm/test/duration-sequencer.d.ts +20 -0
  312. package/dist/esm/test/duration-sequencer.js +54 -0
  313. package/dist/esm/test/shard-durations.json +922 -0
  314. package/dist/esm/test/worker-budget.d.ts +6 -0
  315. package/dist/esm/test/worker-budget.js +59 -1
  316. package/dist/esm/test-helpers/global-setup.d.ts +1 -1
  317. package/dist/esm/test-helpers/global-setup.js +68 -24
  318. package/dist/esm/ultragoal/service.d.ts +7 -0
  319. package/dist/esm/ultragoal/service.js +42 -2
  320. package/dist/esm/utils/write-json-file.js +3 -1
  321. package/dist/esm/worktrees/codex-project-trust.d.ts +15 -0
  322. package/dist/esm/worktrees/codex-project-trust.js +56 -0
  323. package/dist/esm/worktrees/current.d.ts +1 -0
  324. package/dist/esm/worktrees/current.js +1 -0
  325. package/dist/esm/worktrees/project-agent-surfaces.d.ts +1 -0
  326. package/dist/esm/worktrees/project-agent-surfaces.js +2 -1
  327. package/dist/esm/worktrees/registry.d.ts +8 -0
  328. package/dist/esm/worktrees/registry.js +18 -3
  329. package/package.json +18 -15
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Guardrail: keep `wp audit guardrails` wired into a repo's own CI.
3
+ *
4
+ * `wp audit guardrails` is the delivery vehicle for every guardrail that ships
5
+ * inside the suite (e.g. `typescript-version` from #810). A consumer inherits a
6
+ * new guardrail automatically on their next agent-kit bump ONLY IF their CI
7
+ * still invokes `wp audit guardrails`. If that step is deleted, the whole suite
8
+ * silently stops running in CI and new guardrails never reach the consumer.
9
+ *
10
+ * This audit is dogfood / defense-in-depth — NOT the delivery guarantee. It
11
+ * cannot run if the very invariant it checks is already broken (a CI with no
12
+ * guardrails step never executes this audit in CI). The actual self-healing
13
+ * guarantee is the managed inject-by-content-absence repair in
14
+ * `scaffold-base-kit.ts` (`ensureGuardrailsCiStep`), which re-inserts the step
15
+ * on every `wp setup`. This audit's value is LOCAL: it is registered as
16
+ * affected-safe + MCP-visible, so `wp audit guardrails --affected` (pre-commit /
17
+ * IDE) catches the drift on the developer's machine even when CI has drifted.
18
+ *
19
+ * Modeled on the self-CI checks in `ci-test-perf.ts`.
20
+ */
21
+ import type { RepoAuditResult } from "./repo-guardrails.js";
22
+ export declare function auditCiGuardrailsWiring(rootDirectory?: string): RepoAuditResult;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Guardrail: keep `wp audit guardrails` wired into a repo's own CI.
3
+ *
4
+ * `wp audit guardrails` is the delivery vehicle for every guardrail that ships
5
+ * inside the suite (e.g. `typescript-version` from #810). A consumer inherits a
6
+ * new guardrail automatically on their next agent-kit bump ONLY IF their CI
7
+ * still invokes `wp audit guardrails`. If that step is deleted, the whole suite
8
+ * silently stops running in CI and new guardrails never reach the consumer.
9
+ *
10
+ * This audit is dogfood / defense-in-depth — NOT the delivery guarantee. It
11
+ * cannot run if the very invariant it checks is already broken (a CI with no
12
+ * guardrails step never executes this audit in CI). The actual self-healing
13
+ * guarantee is the managed inject-by-content-absence repair in
14
+ * `scaffold-base-kit.ts` (`ensureGuardrailsCiStep`), which re-inserts the step
15
+ * on every `wp setup`. This audit's value is LOCAL: it is registered as
16
+ * affected-safe + MCP-visible, so `wp audit guardrails --affected` (pre-commit /
17
+ * IDE) catches the drift on the developer's machine even when CI has drifted.
18
+ *
19
+ * Modeled on the self-CI checks in `ci-test-perf.ts`.
20
+ */
21
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
22
+ import { join, relative } from "node:path";
23
+ const WORKFLOW_DIR = ".github/workflows";
24
+ const WORKFLOW_FILE_PATTERN = /\.(ya?ml)$/iu;
25
+ /** The guardrails invocation, keyed on the command itself (not the `wp` prefix
26
+ * nor a marker comment) so `wp audit guardrails`, `./bin/wp audit guardrails`,
27
+ * and the `--affected`/`--full` variants all count as wired. */
28
+ const GUARDRAILS_INVOCATION_PATTERN = /\baudit guardrails\b/u;
29
+ /**
30
+ * Lines that run the default test suite — the signal that a workflow is a
31
+ * quality-CI pipeline that owes a guardrails step. Mirrors the notion of a
32
+ * test-running workflow used by `ci-test-perf.ts`; kept local so the two audits
33
+ * stay independent.
34
+ */
35
+ const TEST_RUN_PATTERN = /(?:\bvp\s+run\s+test\b|\bpnpm\s+(?:run\s+)?test\b|\bnpm\s+(?:run\s+)?test\b|\bbun\s+(?:run\s+)?test\b|\bwp\s+test\b|\bvitest\s+run\b)/iu;
36
+ function walkWorkflowFiles(dir) {
37
+ if (!existsSync(dir))
38
+ return [];
39
+ const files = [];
40
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
41
+ const fullPath = join(dir, entry.name);
42
+ if (entry.isDirectory()) {
43
+ files.push(...walkWorkflowFiles(fullPath));
44
+ continue;
45
+ }
46
+ if (entry.isFile() && WORKFLOW_FILE_PATTERN.test(entry.name)) {
47
+ files.push(fullPath);
48
+ }
49
+ }
50
+ return files;
51
+ }
52
+ export function auditCiGuardrailsWiring(rootDirectory = process.cwd()) {
53
+ const workflowsRoot = join(rootDirectory, WORKFLOW_DIR);
54
+ const files = walkWorkflowFiles(workflowsRoot);
55
+ const testWorkflows = [];
56
+ let anyWorkflowWiresGuardrails = false;
57
+ for (const file of files) {
58
+ const content = readFileSync(file, "utf8");
59
+ if (GUARDRAILS_INVOCATION_PATTERN.test(content))
60
+ anyWorkflowWiresGuardrails = true;
61
+ if (TEST_RUN_PATTERN.test(content)) {
62
+ testWorkflows.push(relative(rootDirectory, file).replace(/\\/gu, "/"));
63
+ }
64
+ }
65
+ // No quality-CI pipeline (no workflow runs the default test suite) → nothing
66
+ // to enforce; a repo without agent-kit CI is not "drifted".
67
+ const violations = [];
68
+ if (testWorkflows.length > 0 && !anyWorkflowWiresGuardrails) {
69
+ for (const workflow of testWorkflows) {
70
+ violations.push({
71
+ file: workflow,
72
+ severity: "error",
73
+ ruleId: "ci-guardrails-wiring",
74
+ message: `${workflow} runs the test suite but no workflow invokes \`wp audit guardrails\`. ` +
75
+ `Guardrails (e.g. typescript-version) reach this repo only while CI runs ` +
76
+ `\`wp audit guardrails\`. Re-run \`wp setup\` to restore the managed CI step.`,
77
+ });
78
+ }
79
+ }
80
+ return {
81
+ ok: violations.length === 0,
82
+ title: "CI guardrails wiring",
83
+ checked: files.length,
84
+ sources: files.map((file) => ({
85
+ path: relative(rootDirectory, file).replace(/\\/gu, "/"),
86
+ kind: "workflow",
87
+ })),
88
+ violations,
89
+ };
90
+ }
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import { existsSync, readdirSync, readFileSync } from "node:fs";
13
13
  import { join, relative } from "node:path";
14
+ import { parse as parseYaml } from "yaml";
14
15
  const WORKFLOW_DIR = ".github/workflows";
15
16
  const WORKFLOW_FILE_PATTERN = /\.(ya?ml)$/iu;
16
17
  /** Steps/jobs that intentionally serialize workers (mutation, Stryker, etc.). */
@@ -26,6 +27,16 @@ const SETUP_VP_CACHE_TRUE_PATTERN = /^\s*cache:\s*(?:true|pnpm|npm)\b/mu;
26
27
  const PACKAGE_INSTALL_PATTERN = /(?:\bvp\s+install\b|\bpnpm\s+install\b|\bnpm\s+ci\b|\bnpm\s+install\b|\bbun\s+install\b)/u;
27
28
  // Opt-out: put this comment on the same line or the line immediately above a serial force.
28
29
  const ALLOW_COMMENT_PATTERN = /ci-test-perf-allow(?:-serial)?\b/iu;
30
+ const AGENT_KIT_SELF_CI_PATH = ".github/workflows/ci.agent-kit.yml";
31
+ function readWorkflowJob(content, jobName) {
32
+ try {
33
+ const parsed = parseYaml(content);
34
+ return parsed.jobs?.[jobName];
35
+ }
36
+ catch {
37
+ return;
38
+ }
39
+ }
29
40
  function walkWorkflowFiles(dir) {
30
41
  if (!existsSync(dir))
31
42
  return [];
@@ -112,6 +123,25 @@ function findViolations(root, file) {
112
123
  `Cold installs inflate test job wall-clock without adding coverage.`,
113
124
  });
114
125
  }
126
+ if (relPath === AGENT_KIT_SELF_CI_PATH) {
127
+ const testJob = readWorkflowJob(content, "test");
128
+ const supervisorSteps = testJob?.steps?.filter((step) => typeof step.run === "string" && step.run.includes("bun scripts/run-vitest-projects.ts"));
129
+ const hasConcurrentLane = content.includes("WP_VITEST_PROJECT_MODE: concurrent");
130
+ const hasSerialLane = content.includes("WP_VITEST_PROJECT_MODE: serial");
131
+ if ((supervisorSteps?.length ?? 0) < 2 || !hasConcurrentLane || !hasSerialLane) {
132
+ violations.push({
133
+ file: relPath,
134
+ message: `${relPath}: agent-kit self-CI must run concurrent Test shards and the isolated serial lane ` +
135
+ `through scripts/run-vitest-projects.ts so project concurrency and owned-process cleanup stay enforced.`,
136
+ });
137
+ }
138
+ if (testJob?.["timeout-minutes"] !== 5) {
139
+ violations.push({
140
+ file: relPath,
141
+ message: `${relPath}: agent-kit self-CI Test job must declare timeout-minutes: 5.`,
142
+ });
143
+ }
144
+ }
115
145
  return violations;
116
146
  }
117
147
  export function auditCiTestPerf(rootDirectory = process.cwd()) {
@@ -23,6 +23,7 @@ export function auditCommandSurface(root) {
23
23
  const verifySkillPath = path.join(root, "catalog/agent/skills/verify/SKILL.md");
24
24
  const codexVerifyPath = path.join(root, "packages/codex-plugin/skills/verify/SKILL.md");
25
25
  const claudeVerifyPath = path.join(root, "packages/claude-plugin/skills/verify/SKILL.md");
26
+ const opencodeVerifyPath = path.join(root, "packages/opencode-plugin/skills/verify/SKILL.md");
26
27
  const hookGuidancePath = path.join(root, "src/hooks/pretool-guard/dev-routing.ts");
27
28
  const requiredFiles = [
28
29
  cliPath,
@@ -35,6 +36,7 @@ export function auditCommandSurface(root) {
35
36
  verifySkillPath,
36
37
  codexVerifyPath,
37
38
  claudeVerifyPath,
39
+ opencodeVerifyPath,
38
40
  hookGuidancePath,
39
41
  ];
40
42
  for (const file of requiredFiles) {
@@ -65,8 +67,8 @@ export function auditCommandSurface(root) {
65
67
  if (!contains(mcpPrWaitPath, "buildStatusSnapshot")) {
66
68
  findings.push(violation("src/mcp/tools/pr-wait.ts", "MCP ready wait does not use the shared snapshot evaluator"));
67
69
  }
68
- for (const file of [verifySkillPath, codexVerifyPath, claudeVerifyPath]) {
69
- if (!contains(file, "wp review gate <blueprint-slug> --target HEAD --json")) {
70
+ for (const file of [verifySkillPath, codexVerifyPath, claudeVerifyPath, opencodeVerifyPath]) {
71
+ if (!contains(file, "wp review gate <blueprint-slug> --purpose delivery --target HEAD --json")) {
70
72
  findings.push(violation(path.relative(root, file), "missing executable review-gate lifecycle guidance"));
71
73
  }
72
74
  }
@@ -0,0 +1,2 @@
1
+ import type { RepoAuditResult } from "./repo-guardrails.js";
2
+ export declare function auditHostSubstitutionRisk(rootDirectory?: string): RepoAuditResult;
@@ -0,0 +1,256 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ import { readTrustedJsonFile } from "#shared-utils/read-json-file.js";
5
+ const AGENT_KIT_PACKAGE = "@webpresso/agent-kit";
6
+ const SCORECARD_REL = "docs/host-substitution-scorecard.md";
7
+ const BASELINES_REL = "maintainers/host-baselines";
8
+ const SCORECARD_HEADERS = [
9
+ "capability",
10
+ "class",
11
+ "substitution risk",
12
+ "observed native overlap",
13
+ "repo-owned invariant",
14
+ "independent verifier",
15
+ "blueprints",
16
+ "investment",
17
+ ];
18
+ const CLASS_VALUES = new Set(["core", "bridge", "utility"]);
19
+ const RISK_VALUES = new Set(["low", "medium", "high"]);
20
+ const INVESTMENT_VALUES = new Set(["invest", "maintain", "minimize"]);
21
+ const SURFACE_STATUS_VALUES = new Set(["full", "partial", "none", "in-progress"]);
22
+ function violation(file, message) {
23
+ return { file, message };
24
+ }
25
+ function isRecord(value) {
26
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27
+ }
28
+ function packageName(root) {
29
+ try {
30
+ const parsed = readTrustedJsonFile(path.join(root, "package.json"));
31
+ return typeof parsed.name === "string" ? parsed.name : null;
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ function splitMarkdownRow(line) {
38
+ return line
39
+ .trim()
40
+ .replace(/^\|/u, "")
41
+ .replace(/\|$/u, "")
42
+ .split("|")
43
+ .map((cell) => cell.trim());
44
+ }
45
+ function parseScorecard(markdown) {
46
+ const lines = markdown.split(/\r?\n/u);
47
+ const rows = [];
48
+ const errors = [];
49
+ for (let index = 0; index < lines.length - 1; index += 1) {
50
+ const header = splitMarkdownRow(lines[index] ?? "").map((cell) => cell.toLowerCase());
51
+ if (header.join("|") !== SCORECARD_HEADERS.join("|"))
52
+ continue;
53
+ const separator = lines[index + 1] ?? "";
54
+ if (!/^\s*\|[\s:|-]+\|\s*$/u.test(separator)) {
55
+ errors.push("scorecard table header must be followed by a markdown separator row");
56
+ continue;
57
+ }
58
+ for (let rowIndex = index + 2; rowIndex < lines.length; rowIndex += 1) {
59
+ const line = lines[rowIndex] ?? "";
60
+ if (!line.trimStart().startsWith("|"))
61
+ break;
62
+ const cells = splitMarkdownRow(line);
63
+ if (cells.length !== SCORECARD_HEADERS.length) {
64
+ errors.push(`scorecard row ${rowIndex + 1} has ${cells.length} cells`);
65
+ continue;
66
+ }
67
+ rows.push(Object.fromEntries(SCORECARD_HEADERS.map((key, i) => [key, cells[i] ?? ""])));
68
+ }
69
+ return { rows, errors };
70
+ }
71
+ errors.push(`missing scorecard table with headers: ${SCORECARD_HEADERS.join(" | ")}`);
72
+ return { rows, errors };
73
+ }
74
+ function cleanToken(value) {
75
+ return value.replace(/^`|`$/gu, "").trim();
76
+ }
77
+ function splitCellList(value) {
78
+ return value
79
+ .split(/(?:<br\s*\/?>|,)/iu)
80
+ .map((item) => cleanToken(item))
81
+ .filter((item) => item.length > 0 && item !== "--" && item.toLowerCase() !== "none");
82
+ }
83
+ function scanBlueprintIds(root) {
84
+ const ids = new Set();
85
+ const base = path.join(root, "blueprints");
86
+ if (!existsSync(base))
87
+ return ids;
88
+ for (const status of ["draft", "planned", "in-progress", "completed", "archived", "parked"]) {
89
+ const statusDir = path.join(base, status);
90
+ if (!existsSync(statusDir))
91
+ continue;
92
+ for (const entry of readdirSync(statusDir)) {
93
+ if (entry.startsWith("."))
94
+ continue;
95
+ const absolute = path.join(statusDir, entry);
96
+ if (entry.endsWith(".md")) {
97
+ ids.add(`${status}/${entry.replace(/\.md$/u, "")}`);
98
+ continue;
99
+ }
100
+ if (statSync(absolute).isDirectory() && existsSync(path.join(absolute, "_overview.md"))) {
101
+ ids.add(`${status}/${entry}`);
102
+ }
103
+ }
104
+ }
105
+ return ids;
106
+ }
107
+ function activeBlueprintIds(root) {
108
+ const ids = new Set();
109
+ for (const id of scanBlueprintIds(root)) {
110
+ if (id.startsWith("planned/") || id.startsWith("in-progress/"))
111
+ ids.add(id);
112
+ }
113
+ return ids;
114
+ }
115
+ function validateScorecard(root) {
116
+ const scorecardPath = path.join(root, SCORECARD_REL);
117
+ if (!existsSync(scorecardPath)) {
118
+ return { checked: 1, violations: [violation(SCORECARD_REL, "scorecard file is missing")] };
119
+ }
120
+ const parsed = parseScorecard(readFileSync(scorecardPath, "utf8"));
121
+ const violations = parsed.errors.map((message) => violation(SCORECARD_REL, message));
122
+ const seenCapabilities = new Set();
123
+ const allBlueprintIds = scanBlueprintIds(root);
124
+ const active = activeBlueprintIds(root);
125
+ const activeCoverage = new Map();
126
+ for (const id of active)
127
+ activeCoverage.set(id, 0);
128
+ for (const [index, row] of parsed.rows.entries()) {
129
+ const rowLabel = `row ${index + 1}`;
130
+ const capability = cleanToken(row.capability ?? "");
131
+ if (!/^[a-z][a-z0-9-]*$/u.test(capability)) {
132
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: capability must be a stable kebab-case id`));
133
+ }
134
+ else if (seenCapabilities.has(capability)) {
135
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: duplicate capability ${capability}`));
136
+ }
137
+ seenCapabilities.add(capability);
138
+ const kind = cleanToken(row.class ?? "");
139
+ if (!CLASS_VALUES.has(kind)) {
140
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: class must be core, bridge, or utility`));
141
+ }
142
+ const risk = cleanToken(row["substitution risk"] ?? "");
143
+ if (!RISK_VALUES.has(risk)) {
144
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: substitution risk must be low, medium, or high`));
145
+ }
146
+ const investment = cleanToken(row.investment ?? "");
147
+ if (!INVESTMENT_VALUES.has(investment)) {
148
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: investment must be invest, maintain, or minimize`));
149
+ }
150
+ for (const verifier of splitCellList(row["independent verifier"] ?? "")) {
151
+ if (!verifier.startsWith("repo:"))
152
+ continue;
153
+ const verifierPath = verifier.slice("repo:".length);
154
+ if (!existsSync(path.join(root, verifierPath))) {
155
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: verifier path missing: ${verifier}`));
156
+ }
157
+ }
158
+ for (const blueprint of splitCellList(row.blueprints ?? "")) {
159
+ if (!/^(?:draft|planned|in-progress|completed|archived|parked)\/[a-z0-9][a-z0-9-]*$/u.test(blueprint)) {
160
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: invalid blueprint reference ${blueprint}`));
161
+ continue;
162
+ }
163
+ if (!allBlueprintIds.has(blueprint)) {
164
+ violations.push(violation(SCORECARD_REL, `${rowLabel}: blueprint reference does not exist: ${blueprint}`));
165
+ }
166
+ if (activeCoverage.has(blueprint)) {
167
+ activeCoverage.set(blueprint, (activeCoverage.get(blueprint) ?? 0) + 1);
168
+ }
169
+ }
170
+ }
171
+ for (const [id, count] of activeCoverage) {
172
+ if (count !== 1) {
173
+ violations.push(violation(SCORECARD_REL, `active blueprint ${id} must be covered exactly once in scorecard blueprints column; found ${count}`));
174
+ }
175
+ }
176
+ return { checked: parsed.rows.length + activeCoverage.size, violations };
177
+ }
178
+ function validateHostBaseline(root, relPath) {
179
+ const violations = [];
180
+ const value = parseYaml(readFileSync(path.join(root, relPath), "utf8"));
181
+ if (!isRecord(value))
182
+ return [violation(relPath, "host baseline must be a YAML object")];
183
+ for (const key of ["host", "cli"]) {
184
+ if (typeof value[key] !== "string" || value[key].trim() === "") {
185
+ violations.push(violation(relPath, `${key} must be a non-empty string`));
186
+ }
187
+ }
188
+ for (const key of ["last_implemented", "last_observed"]) {
189
+ const record = value[key];
190
+ if (!isRecord(record)) {
191
+ violations.push(violation(relPath, `${key} must be an object`));
192
+ continue;
193
+ }
194
+ for (const child of ["version", "date"]) {
195
+ if (typeof record[child] !== "string" || record[child].trim() === "") {
196
+ violations.push(violation(relPath, `${key}.${child} must be a non-empty string`));
197
+ }
198
+ }
199
+ }
200
+ const sources = value.sources;
201
+ const docs = isRecord(sources) ? sources.docs : undefined;
202
+ if (!Array.isArray(docs) ||
203
+ docs.some((item) => typeof item !== "string" || !item.startsWith("https://"))) {
204
+ violations.push(violation(relPath, "sources.docs must be an array of https URLs"));
205
+ }
206
+ const surfaces = value.surfaces;
207
+ if (!isRecord(surfaces)) {
208
+ violations.push(violation(relPath, "surfaces must be an object"));
209
+ }
210
+ else {
211
+ for (const [name, raw] of Object.entries(surfaces)) {
212
+ if (!isRecord(raw)) {
213
+ violations.push(violation(relPath, `surfaces.${name} must be an object`));
214
+ continue;
215
+ }
216
+ if (typeof raw.status !== "string" || !SURFACE_STATUS_VALUES.has(raw.status)) {
217
+ violations.push(violation(relPath, `surfaces.${name}.status must be full, partial, none, or in-progress`));
218
+ }
219
+ if (typeof raw.notes !== "string" || raw.notes.trim() === "") {
220
+ violations.push(violation(relPath, `surfaces.${name}.notes must be a non-empty string`));
221
+ }
222
+ }
223
+ }
224
+ return violations;
225
+ }
226
+ function validateHostBaselines(root) {
227
+ const dir = path.join(root, BASELINES_REL);
228
+ if (!existsSync(dir)) {
229
+ return {
230
+ checked: 1,
231
+ violations: [violation(BASELINES_REL, "host baselines directory missing")],
232
+ };
233
+ }
234
+ const files = readdirSync(dir)
235
+ .filter((entry) => entry.endsWith(".yaml"))
236
+ .map((entry) => path.join(BASELINES_REL, entry));
237
+ return {
238
+ checked: files.length,
239
+ violations: files.flatMap((file) => validateHostBaseline(root, file)),
240
+ };
241
+ }
242
+ export function auditHostSubstitutionRisk(rootDirectory = process.cwd()) {
243
+ const root = path.resolve(rootDirectory);
244
+ const title = "Host substitution risk";
245
+ if (packageName(root) !== AGENT_KIT_PACKAGE)
246
+ return { ok: true, title, checked: 0, violations: [] };
247
+ const scorecard = validateScorecard(root);
248
+ const baselines = validateHostBaselines(root);
249
+ const violations = [...scorecard.violations, ...baselines.violations];
250
+ return {
251
+ ok: violations.length === 0,
252
+ title,
253
+ checked: scorecard.checked + baselines.checked,
254
+ violations,
255
+ };
256
+ }
@@ -14,11 +14,11 @@ export interface AuditKindDescriptor {
14
14
  }
15
15
  export declare const SCRIPT_AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e"];
16
16
  export declare const SPECIAL_AUDIT_KIND_IDS: readonly ["bundle-budget", "commit-message", "blueprint-pr-coverage", "mutation", "guardrails", "quality"];
17
- export declare const REPO_AUDIT_KIND_IDS: readonly ["catalog-drift", "package-surface", "command-surface", "reference-parity-matrix", "blueprint-readme-drift", "blueprint-lifecycle", "blueprint-trust", "roadmap-links", "docs-frontmatter", "agents", "vision", "tech-debt", "supported-agent-clis", "no-relative-parent-imports", "no-link-protocol", "no-relative-package-scripts", "test-isolation", "bucket-boundary", "skill-sizes", "broken-refs", "memory-rotation", "gitignore-agent-surfaces", "memory-unified", "compile-drift", "no-legacy-cli-bin", "architecture-drift", "cloudflare-deploy-contract", "toolchain-isolation", "absolute-path-policy", "no-first-party-mjs", "outside-review-runtime-ownership", "no-math-random", "agent-cost", "blueprint-db-consistency", "tech-debt-cadence", "cross-repo-correlation", "ai-contracts", "atomic-state-writes", "hook-surface", "hook-vendor-drift", "session-memory-hardcut", "open-source-licenses", "secrets-policy", "no-dev-vars", "secret-provider-quarantine", "github-actions-secrets", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "worktree-main-ownership", "sast", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "legacy-workflow-identity", "rules", "skills"];
17
+ export declare const REPO_AUDIT_KIND_IDS: readonly ["catalog-drift", "package-surface", "command-surface", "reference-parity-matrix", "blueprint-readme-drift", "blueprint-lifecycle", "blueprint-trust", "roadmap-links", "docs-frontmatter", "agents", "vision", "tech-debt", "supported-agent-clis", "no-relative-parent-imports", "no-link-protocol", "no-relative-package-scripts", "test-isolation", "bucket-boundary", "skill-sizes", "broken-refs", "memory-rotation", "gitignore-agent-surfaces", "memory-unified", "compile-drift", "no-legacy-cli-bin", "architecture-drift", "cloudflare-deploy-contract", "toolchain-isolation", "absolute-path-policy", "no-first-party-mjs", "outside-review-runtime-ownership", "no-math-random", "agent-cost", "blueprint-db-consistency", "tech-debt-cadence", "cross-repo-correlation", "ai-contracts", "atomic-state-writes", "hook-surface", "hook-vendor-drift", "session-memory-hardcut", "open-source-licenses", "secrets-policy", "no-dev-vars", "secret-provider-quarantine", "github-actions-secrets", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "ci-guardrails-wiring", "test-scan-perf", "worktree-main-ownership", "sast", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "host-substitution-risk", "legacy-workflow-identity", "rules", "skills", "typescript-version"];
18
18
  export declare const AUDIT_KIND_DESCRIPTORS: readonly AuditKindDescriptor[];
19
- export declare const AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", ...("absolute-path-policy" | "agent-cost" | "agents" | "ai-contracts" | "architecture-drift" | "atomic-state-writes" | "blueprint-db-consistency" | "blueprint-lifecycle" | "blueprint-pr-coverage" | "blueprint-readme-drift" | "blueprint-trust" | "broken-refs" | "bucket-boundary" | "bundle-budget" | "catalog-drift" | "ci-test-perf" | "cloudflare-deploy-contract" | "command-surface" | "commit-message" | "compile-drift" | "consumer-agent-kit-dependency" | "cross-repo-correlation" | "docs-frontmatter" | "github-actions-secrets" | "gitignore-agent-surfaces" | "guardrails" | "harness-overlay-evidence" | "harness-surfaces" | "hook-surface" | "hook-vendor-drift" | "legacy-workflow-identity" | "memory-rotation" | "memory-unified" | "mutation" | "no-dev-vars" | "no-first-party-mjs" | "no-legacy-cli-bin" | "no-link-protocol" | "no-math-random" | "no-relative-package-scripts" | "no-relative-parent-imports" | "open-source-licenses" | "outside-review-runtime-ownership" | "package-surface" | "quality" | "reference-parity-matrix" | "roadmap-links" | "rules" | "sast" | "secret-provider-quarantine" | "secrets-config" | "secrets-policy" | "security-quality-regressions" | "session-memory-hardcut" | "skill-sizes" | "skills" | "supported-agent-clis" | "tech-debt" | "tech-debt-cadence" | "test-isolation" | "toolchain-isolation" | "vision" | "weakness-mining" | "worktree-main-ownership")[]];
20
- export declare const MCP_AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "session-memory-hardcut", "worktree-main-ownership", "sast"];
21
- export declare const AFFECTED_SAFE_AUDIT_KIND_IDS: readonly ["blueprint-readme-drift", "blueprint-lifecycle", "bucket-boundary", "skill-sizes", "broken-refs", "no-dev-vars", "absolute-path-policy", "secret-provider-quarantine", "secrets-config", "docs-frontmatter", "no-relative-parent-imports", "no-link-protocol", "no-first-party-mjs", "no-math-random"];
19
+ export declare const AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", ...("absolute-path-policy" | "agent-cost" | "agents" | "ai-contracts" | "architecture-drift" | "atomic-state-writes" | "blueprint-db-consistency" | "blueprint-lifecycle" | "blueprint-pr-coverage" | "blueprint-readme-drift" | "blueprint-trust" | "broken-refs" | "bucket-boundary" | "bundle-budget" | "catalog-drift" | "ci-guardrails-wiring" | "ci-test-perf" | "cloudflare-deploy-contract" | "command-surface" | "commit-message" | "compile-drift" | "consumer-agent-kit-dependency" | "cross-repo-correlation" | "docs-frontmatter" | "github-actions-secrets" | "gitignore-agent-surfaces" | "guardrails" | "harness-overlay-evidence" | "harness-surfaces" | "hook-surface" | "hook-vendor-drift" | "host-substitution-risk" | "legacy-workflow-identity" | "memory-rotation" | "memory-unified" | "mutation" | "no-dev-vars" | "no-first-party-mjs" | "no-legacy-cli-bin" | "no-link-protocol" | "no-math-random" | "no-relative-package-scripts" | "no-relative-parent-imports" | "open-source-licenses" | "outside-review-runtime-ownership" | "package-surface" | "quality" | "reference-parity-matrix" | "roadmap-links" | "rules" | "sast" | "secret-provider-quarantine" | "secrets-config" | "secrets-policy" | "security-quality-regressions" | "session-memory-hardcut" | "skill-sizes" | "skills" | "supported-agent-clis" | "tech-debt" | "tech-debt-cadence" | "test-isolation" | "test-scan-perf" | "toolchain-isolation" | "typescript-version" | "vision" | "weakness-mining" | "worktree-main-ownership")[]];
20
+ export declare const MCP_AUDIT_KIND_IDS: readonly ["test-smells", "tph-e2e", "agents", "catalog-drift", "package-surface", "reference-parity-matrix", "docs-frontmatter", "blueprint-readme-drift", "blueprint-pr-coverage", "blueprint-lifecycle", "blueprint-trust", "architecture-drift", "cloudflare-deploy-contract", "absolute-path-policy", "no-first-party-mjs", "no-math-random", "roadmap-links", "bundle-budget", "commit-message", "tech-debt", "supported-agent-clis", "hook-surface", "harness-surfaces", "weakness-mining", "harness-overlay-evidence", "host-substitution-risk", "ai-contracts", "atomic-state-writes", "no-relative-package-scripts", "toolchain-isolation", "open-source-licenses", "secrets-policy", "no-dev-vars", "github-actions-secrets", "secret-provider-quarantine", "security-quality-regressions", "secrets-config", "consumer-agent-kit-dependency", "ci-test-perf", "test-scan-perf", "session-memory-hardcut", "worktree-main-ownership", "typescript-version", "ci-guardrails-wiring", "sast"];
21
+ export declare const AFFECTED_SAFE_AUDIT_KIND_IDS: readonly ["blueprint-readme-drift", "blueprint-lifecycle", "bucket-boundary", "skill-sizes", "broken-refs", "no-dev-vars", "absolute-path-policy", "secret-provider-quarantine", "secrets-config", "docs-frontmatter", "no-relative-parent-imports", "no-link-protocol", "no-first-party-mjs", "no-math-random", "test-scan-perf", "ci-guardrails-wiring"];
22
22
  export type AuditKindId = (typeof AUDIT_KIND_IDS)[number];
23
23
  export type RepoAuditKindId = (typeof REPO_AUDIT_KIND_IDS)[number];
24
24
  export type MCPAuditKindId = (typeof MCP_AUDIT_KIND_IDS)[number];
@@ -16,6 +16,8 @@ const affectedSafeKinds = [
16
16
  "no-link-protocol",
17
17
  "no-first-party-mjs",
18
18
  "no-math-random",
19
+ "test-scan-perf",
20
+ "ci-guardrails-wiring",
19
21
  ];
20
22
  const mcpKindIds = [
21
23
  "test-smells",
@@ -43,6 +45,7 @@ const mcpKindIds = [
43
45
  "harness-surfaces",
44
46
  "weakness-mining",
45
47
  "harness-overlay-evidence",
48
+ "host-substitution-risk",
46
49
  "ai-contracts",
47
50
  "atomic-state-writes",
48
51
  "no-relative-package-scripts",
@@ -56,8 +59,11 @@ const mcpKindIds = [
56
59
  "secrets-config",
57
60
  "consumer-agent-kit-dependency",
58
61
  "ci-test-perf",
62
+ "test-scan-perf",
59
63
  "session-memory-hardcut",
60
64
  "worktree-main-ownership",
65
+ "typescript-version",
66
+ "ci-guardrails-wiring",
61
67
  "sast",
62
68
  ];
63
69
  const affectedSafe = new Set(affectedSafeKinds);
@@ -130,14 +136,18 @@ const repoKinds = [
130
136
  "secrets-config",
131
137
  "consumer-agent-kit-dependency",
132
138
  "ci-test-perf",
139
+ "ci-guardrails-wiring",
140
+ "test-scan-perf",
133
141
  "worktree-main-ownership",
134
142
  "sast",
135
143
  "harness-surfaces",
136
144
  "weakness-mining",
137
145
  "harness-overlay-evidence",
146
+ "host-substitution-risk",
138
147
  "legacy-workflow-identity",
139
148
  "rules",
140
149
  "skills",
150
+ "typescript-version",
141
151
  ];
142
152
  function descriptor(id, kindClass) {
143
153
  return {
@@ -148,7 +158,7 @@ function descriptor(id, kindClass) {
148
158
  gateClass: signalKinds.has(id) ? "signal" : "blocking",
149
159
  scopeSafety: affectedSafe.has(id) ? "affected-safe" : "full-scan-only",
150
160
  summaryLabel: id === "sast" ? "SAST" : id,
151
- ...(id === "sast" ? { includedInGuardrails: false } : {}),
161
+ ...(["sast", "host-substitution-risk"].includes(id) ? { includedInGuardrails: false } : {}),
152
162
  ...(["blueprint-readme-drift", "docs-frontmatter"].includes(id) ? { fixable: true } : {}),
153
163
  };
154
164
  }
@@ -58,7 +58,13 @@ export function auditRoadmapLinks(rootDirectory = process.cwd(), options = {}) {
58
58
  message: "Parent-roadmap execution-wave maps may list local child blueprints only; move cross-repo references to Cross-Plan References and use GitHub links there",
59
59
  });
60
60
  }
61
+ // Archived parent-roadmaps are non-executable program records. They may
62
+ // document completed children without a live execution-wave map or local
63
+ // children still declaring parent_roadmap. Do not fail CI on that residue.
61
64
  if (waveMapChildren.size === 0 && localChildren.length === 0) {
65
+ if (roadmap.status === "archived") {
66
+ continue;
67
+ }
62
68
  violations.push({
63
69
  file: roadmap.file,
64
70
  message: "Roadmap declares no children in its wave map",
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Guardrail: keep tests from silently growing multi-second / multi-ten-second
3
+ * full-repo filesystem scans, and from "fixing" that cost with elevated
4
+ * per-test timeouts.
5
+ *
6
+ * The private-UI cutover anti-regression suite originally walked the monorepo
7
+ * with readdirSync/statSync/readFileSync and needed a 30s timeout. Prefer
8
+ * `git grep` (tracked files) or a bounded fixture tree instead.
9
+ *
10
+ * Opt-out: `// test-scan-perf-allow` on the same line or previous line as the
11
+ * walk/timeout site, or `// test-scan-perf-allow-file` anywhere in the file.
12
+ */
13
+ import type { RepoAuditResult, RepoAuditViolation } from "./repo-guardrails.js";
14
+ export declare function isTestScanPerfTargetPath(relativePath: string): boolean;
15
+ export declare function findTestScanPerfViolationsInText(relativePath: string, text: string): RepoAuditViolation[];
16
+ export declare function auditTestScanPerf(rootDirectory?: string, options?: {
17
+ affectedFiles?: readonly string[];
18
+ }): RepoAuditResult;