@soleur/opencode 0.0.0-stage → 3.354.2

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 (832) 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 +660 -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 +29 -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 +361 -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 +171 -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 +818 -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 +411 -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 +509 -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 +115 -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 +165 -0
  247. package/scripts/sync-opencode-adapter.ts +498 -0
  248. package/scripts/sync-pr-behind.sh +647 -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 +67 -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 +143 -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 +120 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -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 +670 -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 +331 -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 +141 -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 +1620 -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-evidence-comment.md +36 -0
  674. package/skills/review/references/review-todo-structure.md +165 -0
  675. package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
  676. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  677. package/skills/review/references/ultrathink-phases.md +98 -0
  678. package/skills/review/references/wfs.md +6 -0
  679. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  680. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  681. package/skills/review/scripts/fix-round-seats.sh +197 -0
  682. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  683. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  684. package/skills/review/test/fix-round-seats.test.sh +237 -0
  685. package/skills/review/workflows/README.md +147 -0
  686. package/skills/review/workflows/review.workflow.js +667 -0
  687. package/skills/schedule/SKILL.md +796 -0
  688. package/skills/seo-aeo/SKILL.md +139 -0
  689. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  690. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  691. package/skills/ship/SKILL.md +3023 -0
  692. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  693. package/skills/ship/references/affected-gate-contract.md +115 -0
  694. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  695. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  696. package/skills/ship/references/cleanup-merged-archival.md +39 -0
  697. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  698. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  699. package/skills/ship/references/decision-challenges-render.md +71 -0
  700. package/skills/ship/references/delegated-act-authoring-form.md +7 -0
  701. package/skills/ship/references/detached-battery-verdict.md +13 -0
  702. package/skills/ship/references/epic-close-sweep.md +62 -0
  703. package/skills/ship/references/feature-tweet-draft.md +42 -0
  704. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  705. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  706. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  707. package/skills/ship/references/operator-holds.md +179 -0
  708. package/skills/ship/references/pipeline-tally-render.md +43 -0
  709. package/skills/ship/references/pr-overlap.md +153 -0
  710. package/skills/ship/references/queue-mode.md +7 -0
  711. package/skills/ship/references/ready-run-wait.md +36 -0
  712. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  713. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  714. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  715. package/skills/ship/references/supabase-column-probe.md +13 -0
  716. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  717. package/skills/ship/scripts/battery-owed.sh +403 -0
  718. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  719. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  720. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  721. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  722. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  723. package/skills/skill-creator/SKILL.md +299 -0
  724. package/skills/skill-creator/references/api-security.md +248 -0
  725. package/skills/skill-creator/references/authoring-levers.md +110 -0
  726. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  727. package/skills/skill-creator/references/best-practices.md +431 -0
  728. package/skills/skill-creator/references/common-patterns.md +639 -0
  729. package/skills/skill-creator/references/core-principles.md +193 -0
  730. package/skills/skill-creator/references/executable-code.md +188 -0
  731. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  732. package/skills/skill-creator/references/official-spec.md +193 -0
  733. package/skills/skill-creator/references/recommended-structure.md +180 -0
  734. package/skills/skill-creator/references/skill-structure.md +396 -0
  735. package/skills/skill-creator/references/using-scripts.md +122 -0
  736. package/skills/skill-creator/references/using-templates.md +120 -0
  737. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  738. package/skills/skill-creator/scripts/init_skill.py +322 -0
  739. package/skills/skill-creator/scripts/package_skill.py +110 -0
  740. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  741. package/skills/skill-creator/templates/router-skill.md +73 -0
  742. package/skills/skill-creator/templates/simple-skill.md +34 -0
  743. package/skills/skill-creator/workflows/add-reference.md +96 -0
  744. package/skills/skill-creator/workflows/add-script.md +104 -0
  745. package/skills/skill-creator/workflows/add-template.md +83 -0
  746. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  747. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  748. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  749. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  750. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  751. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  752. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  753. package/skills/skill-security-scan/SKILL.md +145 -0
  754. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  755. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  756. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  757. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  758. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  759. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  760. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  761. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  762. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  763. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  764. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  765. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  766. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  767. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  768. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  769. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  770. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  771. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  772. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  773. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  774. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  775. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  776. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  777. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  778. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  779. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  780. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  781. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  782. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  783. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  784. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  785. package/skills/social-distribute/SKILL.md +485 -0
  786. package/skills/spec-templates/SKILL.md +274 -0
  787. package/skills/sync/SKILL.md +49 -0
  788. package/skills/test-browser/SKILL.md +464 -0
  789. package/skills/test-browser/references/feature-map.md +161 -0
  790. package/skills/test-fix-loop/SKILL.md +159 -0
  791. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  792. package/skills/triage/SKILL.md +402 -0
  793. package/skills/trigger-cron/SKILL.md +136 -0
  794. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  795. package/skills/user-set-role/SKILL.md +147 -0
  796. package/skills/user-set-role/scripts/set-role.sh +218 -0
  797. package/skills/user-story-writer/SKILL.md +77 -0
  798. package/skills/ux-audit/SKILL.md +251 -0
  799. package/skills/ux-audit/references/finding.schema.json +62 -0
  800. package/skills/ux-audit/references/route-list.yaml +95 -0
  801. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  802. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  803. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  804. package/skills/verification-scaffold/SKILL.md +73 -0
  805. package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
  806. package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
  807. package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
  808. package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
  809. package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
  810. package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
  811. package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
  812. package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
  813. package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
  814. package/skills/verification-scaffold/references/guards.tsv +21 -0
  815. package/skills/verification-scaffold/references/verification-readme.template +55 -0
  816. package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
  817. package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
  818. package/skills/verification-scaffold/test/generator.test.sh +319 -0
  819. package/skills/verification-scaffold/test/manifest.test.sh +144 -0
  820. package/skills/work/SKILL.md +1480 -0
  821. package/skills/work/references/end-of-work-resume.md +7 -0
  822. package/skills/work/references/hook-test-main-cwd.md +24 -0
  823. package/skills/work/references/key-principles.md +83 -0
  824. package/skills/work/references/property-testing.md +122 -0
  825. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  826. package/skills/work/references/work-agent-teams.md +97 -0
  827. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  828. package/skills/work/references/work-lockfile-bumps.md +97 -0
  829. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  830. package/skills/work/references/work-subagent-fanout.md +61 -0
  831. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  832. package/skills/xcode-test/SKILL.md +360 -0
@@ -0,0 +1,734 @@
1
+ #!/usr/bin/env bash
2
+ # Self-tests for the constraint-scaffold L1 import-boundary gate (ADR-071).
3
+ # Runs in the scripts shard (scripts/test-all.sh globs
4
+ # plugins/soleur/skills/*/test/*.test.sh). Proves the gate is NOT vacuous:
5
+ #
6
+ # AC3 value import of server/** via the @/server/... alias FAILS;
7
+ # an `import type` of the same PASSES; 0 couldNotResolve edges into
8
+ # the secret set (alias resolution is live).
9
+ # AC6 the secret (`to`) set is explicit and non-empty.
10
+ # AC6b a parenthesized/metacharacter route-group path is matched
11
+ # (regex-escaping works); an empty from-set while "use client" files
12
+ # exist is a HARD ERROR, not a silently-disabled rule.
13
+ # AC5 neither app/ nor components/ present (empty input) fails closed;
14
+ # a broken .cjs makes the shared runner fail closed.
15
+ #
16
+ # Hermetic: every fixture is synthesized under a mktemp dir; nothing is written
17
+ # into the real apps/web-platform tree.
18
+ set -uo pipefail
19
+
20
+ REPO_ROOT="$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse --show-toplevel)"
21
+ APP="$REPO_ROOT/apps/web-platform"
22
+ CFG="$APP/.dependency-cruiser.cjs"
23
+ RUNNER="$APP/scripts/constraint-gates.sh"
24
+
25
+ pass=0
26
+ fail=0
27
+ # The INDEPENDENT case counter (ADR-193 #2). Incremented at every CALL SITE, and NEVER
28
+ # inside ok()/bad() — the VERDICT helpers, which touch only the verdict counters. That
29
+ # separation is the whole point: a counter bumped inside the verdict helpers moves WITH the
30
+ # verdict, so stubbing bad() drops the row and its count together and `pass + fail == cases`
31
+ # still holds under the exact fault it exists to catch (ADR-193 Context, third failure mode —
32
+ # measured on this very ok()/bad() shape). Incremented at top level only, never inside a
33
+ # `$( … )` command substitution: a subshell discards the increment while reading as correct.
34
+ cases=0
35
+ # Anti-vacuity thresholds. Declared here (not adjacent to their `if`) so BOTH exit doors bind
36
+ # them and so guard-vacuity-floor's backward slice-widening finds them bound under `set -u`.
37
+ #
38
+ # TOOLCHAIN_FREE_MIN_ASSERTIONS guards the toolchain-SKIP exit. Derived as a genuine lower
39
+ # bound, not a snapshot: 12 fixed assertions (1 AC4 + 8 drift-trip + 1 drift-no-false-positive
40
+ # + 1 P2 anchoring + 1 AC5b direct-baseline) plus at least 1 VALUE_SAFE_PATH module — the
41
+ # module count is product content that #5850 plans to shrink by relocating modules out of
42
+ # server/**, so pinning it at today's 4 would set a landmine; the `vs_checked -lt 1` floor
43
+ # guards that loop separately.
44
+ # MIN_ASSERTIONS adds the 22 fixed assertions that run past the toolchain probe (3 AC3/AC6b +
45
+ # 3 directive-form + 7 transitive 4.x + AC3 couldNotResolve + AC6 + AC6b empty-from-set +
46
+ # AC5 empty-input + AC5 broken-cjs + AC10 + 4.8 + 4.10 + 4.11).
47
+ #
48
+ # These two are the CONSERVATIVE BASE (12 + 1 module, and + 22), used only when the
49
+ # VALUE_SAFE_PATH extraction fails. On the normal path they are RATCHETED below to
50
+ # `12 + <module count read from $CFG> (+ 22)` the moment that list is known. The bases alone
51
+ # left slack equal to `module_count - 1` — today 3 fungible slots on the very gate this suite
52
+ # exists to pin (the L1 client -> server-secret import boundary), so three assertions could be
53
+ # deleted with the floor still green. Deriving from the config keeps the shrink-safety the
54
+ # fixed `1` was chosen for (#5850 relocates modules out of server/**, and the floor now
55
+ # follows that down automatically) while removing the slack, and it stays non-tautological
56
+ # because the operand comes from $CFG, not from the loop the floor is watching.
57
+ TOOLCHAIN_FREE_MIN_ASSERTIONS=13
58
+ MIN_ASSERTIONS=35
59
+ ok() { printf 'ok - %s\n' "$1"; pass=$((pass + 1)); }
60
+ bad() { printf 'FAIL - %s\n' "$1"; fail=$((fail + 1)); }
61
+
62
+ [[ -f "$CFG" ]] || { echo "fatal: missing $CFG (run constraint-scaffold.sh)"; exit 2; }
63
+ [[ -f "$RUNNER" ]] || { echo "fatal: missing $RUNNER (run constraint-scaffold.sh)"; exit 2; }
64
+
65
+ BASELINE="$APP/.dependency-cruiser-known-violations.json"
66
+ [[ -f "$BASELINE" ]] || { echo "fatal: missing $BASELINE (run constraint-scaffold.sh)"; exit 2; }
67
+
68
+ # =============================================================================
69
+ # Toolchain-FREE assertions (#5777, ADR-071 amendment). These parse the committed
70
+ # baseline JSON + grep real source — NO dependency-cruiser needed — so they run in
71
+ # EVERY shard, before the toolchain SKIP guard below. They are the always-on half
72
+ # of the D2/D3/D4 invariants.
73
+ # =============================================================================
74
+
75
+ # --- AC4 (D3.1): committed baseline suppresses the transitive rule NOWHERE -------
76
+ # A baselined entry that names the transitive rule is never benign: dependency-cruiser
77
+ # softens it per-ORIGIN (from+rule.name, ignoring `to`/`via` AND `type`), so one such
78
+ # entry blinds that client to every future transitive secret. Key on the transitive
79
+ # rule NAME (not just type:"reachability") — a hand-authored type:"module" entry
80
+ # naming the rule suppresses it identically while a type-only count reads 0. A
81
+ # non-array baseline => -1 => fails closed.
82
+ TRANSITIVE_RULE="no-client-to-server-secret-transitive"
83
+ count_suppressors() { # $1 = baseline path; echoes count of transitive-suppressing entries, -1 on non-array/parse-err
84
+ node -e '
85
+ const fs = require("fs");
86
+ const RULE = process.argv[2];
87
+ try { const b = JSON.parse(fs.readFileSync(process.argv[1],"utf8"));
88
+ if (!Array.isArray(b)) { process.stdout.write("-1"); }
89
+ else process.stdout.write(String(b.filter(e => e && (e.type==="reachability" || (e.rule && e.rule.name===RULE))).length));
90
+ } catch(e){ process.stdout.write("-1"); }' "$1" "$TRANSITIVE_RULE" 2>/dev/null
91
+ }
92
+ REACH_CT="$(count_suppressors "$BASELINE")"
93
+ cases=$((cases + 1))
94
+ if [[ "$REACH_CT" == "0" ]]; then
95
+ ok "AC4(D3.1): committed baseline has zero transitive-rule-suppressing entries"
96
+ else
97
+ bad "AC4(D3.1): committed baseline has $REACH_CT transitive-suppressing entries (must be 0; non-array/parse err = -1)"
98
+ fi
99
+
100
+ # --- AC5b (D3.3): direct-rule non-regression floor ------------------------------
101
+ # tsPreCompilationDeps:false makes the direct rule's value-edge set a strict SUBSET
102
+ # of v1's (type-only edges are elided; value edges are never elided), so a flip
103
+ # regression can only SHRINK the direct baseline below the recorded floor of 10 — a
104
+ # legitimate NEW value-safe direct import GROWS it (still fine). Assert a lower bound,
105
+ # not equality, so this plugin self-test does not false-fail on unrelated product
106
+ # growth with a misleading "flip regression" message. REACH_CT==0 (above) is the
107
+ # load-bearing security invariant; this is the flip-correctness tripwire.
108
+ DEP_CT="$(node -e '
109
+ const fs = require("fs");
110
+ try { const b = JSON.parse(fs.readFileSync(process.argv[1],"utf8"));
111
+ process.stdout.write(String((Array.isArray(b)?b:[]).filter(e=>e&&e.type==="dependency").length));
112
+ } catch(e){ process.stdout.write("-1"); }' "$BASELINE" 2>/dev/null)"
113
+ # ADR-193 #1: this floor's failure arm reports with `printf >&2` + `exit 1` DIRECTLY rather
114
+ # than through bad(). It measures a SYSTEM UNDER TEST (the committed baseline) rather than the
115
+ # suite itself, but that makes no difference to the argument: routed through bad() it
116
+ # incremented the same `fail` counter the exit status reads, so neutering bad() silenced this
117
+ # floor together with every assertion row. Its operand ($DEP_CT) is independent of the verdict
118
+ # counters, so no ordering conflict with the conservation check arises (ADR-193 #4).
119
+ DIRECT_BASELINE_FLOOR=10
120
+ if ! [[ "$DEP_CT" =~ ^[0-9]+$ ]] || [[ "$DEP_CT" -lt "$DIRECT_BASELINE_FLOOR" ]]; then
121
+ printf '\n[FATAL] AC5b(D3.3) direct-rule non-regression floor: baseline count is %s, expected >= %d (-1 = non-array/parse error).\n' \
122
+ "$DEP_CT" "$DIRECT_BASELINE_FLOOR" >&2
123
+ printf ' A tsPreCompilationDeps flip regression would shrink the direct value-edge set. If you LEGITIMATELY removed a client->value-safe-module direct import, lower this floor; otherwise investigate a flip regression.\n' >&2
124
+ exit 1
125
+ fi
126
+ cases=$((cases + 1))
127
+ ok "AC5b(D3.3): direct-rule baseline count is $DEP_CT (>= floor $DIRECT_BASELINE_FLOOR; flip did not shrink the value-edge set)"
128
+
129
+ # --- AC5 (D4/D3c): VALUE_SAFE_PATH modules are drift-proof value-safe -----------
130
+ # Each module the transitive rule excludes via to.pathNot MUST NOT gain a secret,
131
+ # because it is exempt from BOTH the direct baseline and the transitive pathNot (the
132
+ # deepest fail-open). This is a best-effort content tripwire, NOT a full secret
133
+ # scanner — #5850 (relocation out of server/**) is the structural fix. It flags:
134
+ # (a) a process.env read (dot OR bracket access) — dependency-cruiser cannot see
135
+ # this, so it is the guard's UNIQUE contribution;
136
+ # (b) a value import/re-export edge (single- OR multi-line; import type / export
137
+ # type are erased at build -> safe) — backstopped by the transitive rule for
138
+ # edges to NON-value-safe modules, checked here for defense in depth;
139
+ # (c) a hardcoded secret LITERAL (known token prefixes / PEM header) with no import
140
+ # and no env read — otherwise uncaught by anything.
141
+ # Derive the module list FROM the .cjs VALUE_SAFE_PATH alternation so the two never drift.
142
+ check_value_safe_drift() { # returns 0 = value-safe, 1 = drift detected
143
+ local f="$1"
144
+ # (a) process.env value read — dot (`process.env.X`) OR bracket (`process["env"]`, `process['env']`).
145
+ grep -qE 'process\.env|process[[:space:]]*\[[[:space:]]*["'\''`]env' "$f" && return 1
146
+ # (c) hardcoded secret literal (canonical token prefixes + PEM header). Same shape
147
+ # the repo-wide secret scanners use; a value-safe registry must hold no secret.
148
+ grep -qE 'BEGIN [A-Z ]*PRIVATE KEY|ghp_[A-Za-z0-9._~+/=-]{20,}|gho_[A-Za-z0-9._~+/=-]{20,}|ghu_[A-Za-z0-9._~+/=-]{20,}|ghs_[A-Za-z0-9._~+/=-]{20,}|ghr_[A-Za-z0-9._~+/=-]{20,}|github_pat_[A-Za-z0-9._~+/=-]{20,}|sk-ant-[A-Za-z0-9_-]{20,}|sk_(test|live)_[A-Za-z0-9]{20,}|sbp_[A-Za-z0-9]{20,}|xoxb-[A-Za-z0-9-]{20,}|AKIA[0-9A-Z]{16}|dp\.(pt|st|sa|ct)\.[A-Za-z0-9_-]{40,}' "$f" && return 1
149
+ # (b1) a value IMPORT statement: a line beginning with `import ` (the single-line
150
+ # form OR the opener of a multi-line import) that is NOT a whole-clause `import type`.
151
+ # A mixed `import { type A, realX }` opener begins with `import ` (not `import type`),
152
+ # so its value half is still flagged.
153
+ if grep -E '^[[:space:]]*import[[:space:]]' "$f" \
154
+ | grep -vE '^[[:space:]]*import[[:space:]]+type[[:space:]]' | grep -c >/dev/null .; then
155
+ return 1
156
+ fi
157
+ # (b2) a value RE-EXPORT edge: `export ... from "..."` that is NOT `export type ... from`.
158
+ # (Plain `export const/function/type X = …` declarations carry no `from` and are safe.)
159
+ if grep -E '^[[:space:]]*export[[:space:]].*[[:space:]]from[[:space:]]*["'\''`]' "$f" \
160
+ | grep -vE '^[[:space:]]*export[[:space:]]+type[[:space:]]' | grep -c >/dev/null .; then
161
+ return 1
162
+ fi
163
+ # (b3) dynamic `import(...)` / `require(...)` edge.
164
+ grep -qE '\b(import|require)[[:space:]]*\(' "$f" && return 1
165
+ return 0
166
+ }
167
+ # Non-vacuity: each drift class MUST trip the guard; a clean import-type-only module
168
+ # MUST pass. Build the secret literal by concatenation so no contiguous token is
169
+ # committed to this test file (GitHub push protection) while the runtime fixture holds
170
+ # the real shape.
171
+ DRIFT_TMP="$(mktemp -d)"
172
+ # Own the cleanup with a trap, not just the `rm -rf` at the end of this block. The
173
+ # trailing rm only runs on the happy path — any early exit between here and there (a
174
+ # `set -e` abort in a future edit, an operator ^C, a SIGTERM) skips it and leaks the
175
+ # directory. /tmp here is a 4 GiB RAM-backed tmpfs, so leaked scratch is not free.
176
+ trap 'rm -rf -- "${DRIFT_TMP:-}"' EXIT INT TERM
177
+ printf 'export const X = process.env.SECRET_KEY;\n' > "$DRIFT_TMP/bad-env-dot.ts"
178
+ printf 'export const X = process["env"]["SECRET_KEY"];\n' > "$DRIFT_TMP/bad-env-bracket.ts"
179
+ SK="sk_""live_"; printf 'export const K = "%s%s";\n' "$SK" "0123456789abcdefABCDEF0123456789" > "$DRIFT_TMP/bad-literal.ts"
180
+ # New-shape GitHub installation token (ghs_<APPID>_<JWT>, ~390-520 chars over the
181
+ # canonical credential alphabet). Prefix split-assembled for the same reason as SK
182
+ # above; the 64-char tail (x6 = 384 + 4 = 388 total) carries every newly-admitted
183
+ # byte, with `.` at tail offset 13 so the legacy [A-Za-z0-9_]{20,} run dies below
184
+ # its floor — a reverted class CANNOT trip on this fixture, so the widened arm is
185
+ # what the drift row below actually proves.
186
+ GHS="ghs""_"
187
+ GHS_SEG='kJ8xQ2mW9pL4.vR7tN3bS_5y~cH0gF+uA6wE9zX2M7/K4dP8qT1jG6vB0nC=hZ-i'
188
+ printf 'export const K = "%s%s";\n' "$GHS" "$GHS_SEG$GHS_SEG$GHS_SEG$GHS_SEG$GHS_SEG$GHS_SEG" > "$DRIFT_TMP/bad-ghs-literal.ts"
189
+ printf 'import {\n SECRET_TOKEN,\n} from "@/server/secret";\nexport const g = () => SECRET_TOKEN;\n' > "$DRIFT_TMP/bad-multiline.ts"
190
+ printf 'import { X } from "@/server/secret";\nexport const g = () => X;\n' > "$DRIFT_TMP/bad-import.ts"
191
+ printf 'export { SECRET_TOKEN } from "@/server/secret";\n' > "$DRIFT_TMP/bad-reexport.ts"
192
+ printf 'export const load = () => import("@/server/secret");\n' > "$DRIFT_TMP/bad-dynamic.ts"
193
+ printf 'import type { T } from "@/lib/types";\nexport const LEADERS = ["a"] as const;\nexport function isX(s: string): s is T { return true; }\n' > "$DRIFT_TMP/good.ts"
194
+ for bad in bad-env-dot bad-env-bracket bad-literal bad-ghs-literal bad-multiline bad-import bad-reexport bad-dynamic; do
195
+ cases=$((cases + 1))
196
+ if ! check_value_safe_drift "$DRIFT_TMP/$bad.ts"; then
197
+ ok "AC5(D4): drift guard TRIPS on $bad (non-vacuous)"
198
+ else
199
+ bad "AC5(D4): drift guard did NOT trip on $bad (vacuous fail-open!)"
200
+ fi
201
+ done
202
+ # good.ts mirrors the real modules' shape: an `import type`, an `export const` array,
203
+ # and an `export function` declaration — none are value edges.
204
+ cases=$((cases + 1))
205
+ if check_value_safe_drift "$DRIFT_TMP/good.ts"; then
206
+ ok "AC5(D4): drift guard PASSES a registry with import-type + export-const/function only (no false positive)"
207
+ else
208
+ bad "AC5(D4): drift guard false-positived on a clean value-safe registry"
209
+ fi
210
+ rm -rf "$DRIFT_TMP"
211
+
212
+ # --- P2 (VALUE_SAFE_PATH anchoring): dot-suffixed siblings are NOT excluded ------
213
+ # The pathNot regex is end-anchored to the file extension; a bare trailing `\.` would
214
+ # prefix-match `server/providers.server.ts` and silently exempt it from the transitive
215
+ # rule. Read the RUNTIME pathNot value off the required config (avoids source-escaping
216
+ # ambiguity) and assert sibling non-match + real-module match.
217
+ cases=$((cases + 1))
218
+ if node -e '
219
+ const cfg = require(process.argv[1]);
220
+ const rule = (cfg.forbidden||[]).find(r=>r.name==="no-client-to-server-secret-transitive");
221
+ if (!rule || !rule.to || !rule.to.pathNot) process.exit(2);
222
+ const re = new RegExp(rule.to.pathNot);
223
+ const must = ["server/providers.ts","server/scope-grants/action-class-map.ts"];
224
+ const mustNot = ["server/providers.server.ts","server/providers.keys.ts","server/domain-leaders.data.ts","server/providers-internal.ts"];
225
+ process.exit(must.every(p=>re.test(p)) && mustNot.every(p=>!re.test(p)) ? 0 : 1);
226
+ ' "$CFG" 2>/dev/null; then
227
+ ok "AC5(D4/P2): VALUE_SAFE_PATH matches real modules but NOT dot-suffixed siblings (end-anchored)"
228
+ else
229
+ bad "AC5(D4/P2): VALUE_SAFE_PATH anchoring wrong — a dot-suffixed sibling (providers.server.ts) is excluded, or a real module is not matched"
230
+ fi
231
+ # Extract the module basenames from the .cjs VALUE_SAFE_PATH alternation and assert
232
+ # each real server module is still value-safe.
233
+ VS_MODULES="$(grep -E 'VALUE_SAFE_PATH[[:space:]]*=' -A1 "$CFG" | grep -oE '\([^)]*\)' | head -1 | tr -d '()' | tr '|' ' ')"
234
+ if [[ -z "$VS_MODULES" ]]; then
235
+ cases=$((cases + 1))
236
+ bad "AC5(D4): could not extract VALUE_SAFE_PATH module list from $CFG"
237
+ else
238
+ # Ratchet both floors onto the module count the config actually declares (see the derivation
239
+ # note beside their declaration). Read from $CFG, never from the loop below, so deleting the
240
+ # loop still trips the floor rather than shrinking it in lockstep.
241
+ read -ra _vs_declared <<< "$VS_MODULES"
242
+ vs_expected=${#_vs_declared[@]}
243
+ if [[ "$vs_expected" -gt 1 ]]; then
244
+ TOOLCHAIN_FREE_MIN_ASSERTIONS=$((12 + vs_expected))
245
+ MIN_ASSERTIONS=$((TOOLCHAIN_FREE_MIN_ASSERTIONS + 22))
246
+ printf 'note - anti-vacuity floors derived from %d declared VALUE_SAFE_PATH module(s): toolchain-free >= %d, full >= %d\n' \
247
+ "$vs_expected" "$TOOLCHAIN_FREE_MIN_ASSERTIONS" "$MIN_ASSERTIONS"
248
+ fi
249
+ vs_checked=0
250
+ for m in $VS_MODULES; do
251
+ mf="$APP/server/${m}.ts"
252
+ cases=$((cases + 1))
253
+ if [[ ! -f "$mf" ]]; then
254
+ bad "AC5(D4): VALUE_SAFE_PATH lists server/${m} but $mf does not exist"
255
+ continue
256
+ fi
257
+ vs_checked=$((vs_checked + 1))
258
+ if check_value_safe_drift "$mf"; then
259
+ ok "AC5(D4): server/${m}.ts is value-safe (no process.env value read / no value import)"
260
+ else
261
+ bad "AC5(D4): server/${m}.ts DRIFTED out of value-safe (reads process.env or value-imports) — it is pathNot-excluded, so a secret there ships green; fix it or remove from VALUE_SAFE_PATH (see #5850)"
262
+ fi
263
+ done
264
+ # ADR-193 #1: reports directly, never through bad(). This is the floor that notices the
265
+ # VALUE_SAFE_PATH loop asserted NOTHING; routed through bad() it was silenced by the same
266
+ # neutered-helper fault it exists to witness. Its operand ($vs_checked) is independent of
267
+ # the verdict counters.
268
+ if [[ "$vs_checked" -lt 1 ]]; then
269
+ printf '\n[FATAL] AC5(D4) VALUE_SAFE_PATH floor: zero modules checked, expected >= 1.\n' >&2
270
+ printf ' The .cjs VALUE_SAFE_PATH extraction or the module glob broke — every drift assertion in this block was skipped, so a green run here is vacuous.\n' >&2
271
+ exit 1
272
+ fi
273
+ fi
274
+
275
+ # --- locate (or install) the dependency-cruiser binary -----------------------
276
+ # Fast path: the installed web-platform binary (present locally + in the
277
+ # test-webplat CI shard). Fallback: the test-scripts shard has node+npm but no
278
+ # web-platform deps, so install dependency-cruiser on demand into a temp dir.
279
+ TMPROOT="$(mktemp -d)" || { echo "FATAL: cannot create scratch root" >&2; exit 1; }
280
+ : "${TMPROOT:?scratch root must be non-empty}"
281
+ [[ "$TMPROOT" == /* && -d "$TMPROOT" && ! -L "$TMPROOT" ]] || {
282
+ echo "FATAL: scratch root is not a plain absolute directory: '$TMPROOT'" >&2; exit 1; }
283
+ # EXIT **INT TERM**, not EXIT alone. bash traps REPLACE rather than stack, so an
284
+ # EXIT-only registration here left the earlier `… INT TERM` handler live and still
285
+ # pointing at DRIFT_TMP — which is already deleted by this point. A ^C during the
286
+ # `npm install` below (the longest step in this file) would then run that stale handler,
287
+ # never touch TMPROOT, and orphan a full node_modules tree onto the 4 GiB tmpfs: the
288
+ # exact leak class this PR exists to close, reintroduced in the second half of the file.
289
+ trap 'rm -rf -- "${TMPROOT:-}"' EXIT INT TERM
290
+
291
+ DEPCRUISE="$APP/node_modules/.bin/depcruise"
292
+ if [[ ! -x "$DEPCRUISE" ]]; then
293
+ echo "# dependency-cruiser not installed in apps/web-platform — installing on demand..." >&2
294
+ # Seed an empty package.json so npm installs INTO this temp dir. Without it,
295
+ # `npm install` in a bare dir walks UP the tree, finds a parent project, reports
296
+ # "up to date", and installs nothing → binary missing (env-dependent fragility).
297
+ printf '{"name":"constraint-scaffold-test","private":true}\n' > "$TMPROOT/package.json"
298
+ # typescript is REQUIRED alongside dependency-cruiser: depcruise cannot parse
299
+ # .ts/.tsx (nor honor tsConfig alias resolution + tsPreCompilationDeps) without
300
+ # the TS compiler. Omitting it makes depcruise emit ZERO edges from the .tsx
301
+ # fixtures → every positive-detection assertion silently fails (the scripts-shard
302
+ # CI failure on PR #5770). The non-vacuity guard below fails loud if this regresses.
303
+ ( cd "$TMPROOT" && npm install --no-audit --no-fund dependency-cruiser@^16 typescript >/dev/null 2>&1 ) \
304
+ || { echo "fatal: could not install dependency-cruiser + typescript"; exit 2; }
305
+ DEPCRUISE="$TMPROOT/node_modules/.bin/depcruise"
306
+ [[ -x "$DEPCRUISE" ]] || { echo "fatal: dependency-cruiser binary still missing after install"; exit 2; }
307
+ fi
308
+ NODE_MODULES="$(cd "$(dirname "$DEPCRUISE")/.." && pwd)"
309
+
310
+ # --- build a hermetic fixture Next.js-shaped app -----------------------------
311
+ # Returns the fixture path on stdout.
312
+ make_fixture() {
313
+ local fx="$TMPROOT/fixture-$1"
314
+ mkdir -p "$fx/server" "$fx/components/leakdir" "$fx/components/(a|b)"
315
+ ln -s "$NODE_MODULES" "$fx/node_modules"
316
+ cat > "$fx/tsconfig.json" <<'JSON'
317
+ {
318
+ "compilerOptions": {
319
+ "baseUrl": ".",
320
+ "module": "esnext",
321
+ "moduleResolution": "bundler",
322
+ "jsx": "preserve",
323
+ "paths": { "@/*": ["./*"] }
324
+ },
325
+ "include": ["**/*.ts", "**/*.tsx"]
326
+ }
327
+ JSON
328
+ printf 'export const SECRET_TOKEN = "sk-do-not-ship";\nexport type SecretShape = { id: string };\n' > "$fx/server/secret.ts"
329
+ # client module taking a VALUE import on a server secret -> must be flagged
330
+ printf '"use client";\nimport { SECRET_TOKEN } from "@/server/secret";\nexport const Leak = () => SECRET_TOKEN;\n' > "$fx/components/leakdir/leak.tsx"
331
+ # client module taking a TYPE-ONLY import of the same -> must NOT be flagged
332
+ printf '"use client";\nimport type { SecretShape } from "@/server/secret";\nexport const T = (_: SecretShape) => null;\n' > "$fx/components/leakdir/typeonly.tsx"
333
+ # client module under a regex-metacharacter route-group dir "(a|b)" -> must be
334
+ # flagged. If the from-path were NOT regex-escaped, ^components/(a|b)/...$
335
+ # would match literal "a"/"b" (never the literal "(a|b)" source) and the leak
336
+ # would be silently missed.
337
+ printf '"use client";\nimport { SECRET_TOKEN } from "@/server/secret";\nexport const P = () => SECRET_TOKEN;\n' > "$fx/components/(a|b)/parenleak.tsx"
338
+ # client module with a leading license/eslint LINE-comment before the
339
+ # directive (valid Next.js). If the directive test required the directive to
340
+ # be the exact first non-empty line, this is misclassified as non-client and
341
+ # its value import goes UNFLAGGED (silent leak). -> must be flagged.
342
+ printf '// SPDX-License-Identifier: MIT\n"use client";\nimport { SECRET_TOKEN } from "@/server/secret";\nexport const B = () => SECRET_TOKEN;\n' > "$fx/components/leakdir/bannerleak.tsx"
343
+ # client module with a leading BLOCK-comment banner before the directive.
344
+ printf '/* banner\n spanning lines */\n"use client";\nimport { SECRET_TOKEN } from "@/server/secret";\nexport const K = () => SECRET_TOKEN;\n' > "$fx/components/leakdir/blockbannerleak.tsx"
345
+ # client module with a trailing comment on the directive line: `"use client"; // x`.
346
+ printf '"use client"; // hydration boundary\nimport { SECRET_TOKEN } from "@/server/secret";\nexport const H = () => SECRET_TOKEN;\n' > "$fx/components/leakdir/trailingleak.tsx"
347
+
348
+ # ---- #5777 TRANSITIVE-rule fixtures: helper in lib/ (outside app/components/ --
349
+ # dependency-cruiser still FOLLOWS the edge into lib/ for reachability even though
350
+ # lib/ is not a cruise root). `server/secret.ts` is NOT in VALUE_SAFE_PATH, so the
351
+ # transitive rule genuinely fires; `server/domain-leaders.ts` IS (pathNot target).
352
+ mkdir -p "$fx/lib" "$fx/components/trans"
353
+ printf 'export const LEADERS = ["a"] as const;\n' > "$fx/server/domain-leaders.ts"
354
+ # 4.1 NEGATIVE transitive (client -> lib helper(value) -> server/secret(value)) -> MUST FLAG
355
+ printf 'import { SECRET_TOKEN } from "@/server/secret";\nexport const fmtT = () => SECRET_TOKEN;\n' > "$fx/lib/leak-helper.ts"
356
+ printf '"use client";\nimport { fmtT } from "@/lib/leak-helper";\nexport const Trans = () => fmtT();\n' > "$fx/components/trans/transitive.tsx"
357
+ # 4.2 POSITIVE first-hop type-only (client -> import type helper -> server value) -> MUST NOT FLAG
358
+ printf 'import { SECRET_TOKEN } from "@/server/secret";\nexport const g = () => SECRET_TOKEN;\nexport type GT = string;\n' > "$fx/lib/typed-helper.ts"
359
+ printf '"use client";\nimport type { GT } from "@/lib/typed-helper";\nexport const TFirst = (_: GT) => null;\n' > "$fx/components/trans/typeonly-firsthop.tsx"
360
+ # 4.3 NEGATIVE mixed import { type A, realValue } on BOTH hops -> value edge MUST survive -> MUST FLAG
361
+ printf 'import { type SecretShape, SECRET_TOKEN } from "@/server/secret";\nexport type MHT = SecretShape;\nexport const mfmt = (_: SecretShape) => SECRET_TOKEN;\n' > "$fx/lib/mixed-helper.ts"
362
+ printf '"use client";\nimport { type MHT, mfmt } from "@/lib/mixed-helper";\nexport const Mx = (_: MHT) => mfmt(_);\n' > "$fx/components/trans/mixed.tsx"
363
+ # 4.4 NEGATIVE barrel/re-export (export * AND named export-from) -> MUST FLAG
364
+ printf 'export * from "@/server/secret";\n' > "$fx/lib/barrel.ts"
365
+ printf '"use client";\nimport { SECRET_TOKEN } from "@/lib/barrel";\nexport const Bx = () => SECRET_TOKEN;\n' > "$fx/components/trans/barrel.tsx"
366
+ printf 'export { SECRET_TOKEN } from "@/server/secret";\n' > "$fx/lib/named-barrel.ts"
367
+ printf '"use client";\nimport { SECRET_TOKEN } from "@/lib/named-barrel";\nexport const NBx = () => SECRET_TOKEN;\n' > "$fx/components/trans/named-barrel.tsx"
368
+ # 4.5 NEGATIVE dynamic import (statically resolvable) -> MUST FLAG
369
+ printf 'export async function load(){ const m = await import("@/server/secret"); return m.SECRET_TOKEN; }\n' > "$fx/lib/dyn-helper.ts"
370
+ printf '"use client";\nimport { load } from "@/lib/dyn-helper";\nexport const Dx = () => load();\n' > "$fx/components/trans/dynamic.tsx"
371
+ # 4.6 POSITIVE pathNot target (client -> lib helper(value) -> server/domain-leaders(value)) -> MUST NOT FLAG
372
+ printf 'import { LEADERS } from "@/server/domain-leaders";\nexport const safe = () => LEADERS;\n' > "$fx/lib/safe-helper.ts"
373
+ printf '"use client";\nimport { safe } from "@/lib/safe-helper";\nexport const SafeTarget = () => safe();\n' > "$fx/components/trans/safe-target.tsx"
374
+
375
+ cp "$CFG" "$fx/.dependency-cruiser.cjs"
376
+ printf '%s' "$fx"
377
+ }
378
+
379
+ FX="$(make_fixture main)"
380
+
381
+ # --- Toolchain probe: can this depcruise actually PARSE the .tsx fixtures? -----
382
+ # The lightweight `test-scripts` CI shard has no apps/web-platform/node_modules,
383
+ # so depcruise is provisioned on-demand; that install can lack the exact TS
384
+ # toolchain depcruise needs to traverse .tsx (observed: "0 modules cruised" even
385
+ # with typescript present). When depcruise parses ZERO modules from a fixture
386
+ # that demonstrably contains .tsx client files, the TOOLCHAIN is the problem, not
387
+ # the gate — SKIP cleanly (exit 0) rather than emit false failures. The gate's
388
+ # real end-to-end coverage is the `constraint-gates` dogfood workflow (cruises
389
+ # the live apps/web-platform tree) plus local/webplat runs that use the committed
390
+ # depcruise. A gate REGRESSION (parses modules but misses a violation) still
391
+ # FAILS below — only a non-parsing toolchain skips. Non-vacuous by construction:
392
+ # the skip is loud and names where the real validation lives.
393
+ PARSED_COMPONENTS="$( cd "$FX" && "$DEPCRUISE" --config .dependency-cruiser.cjs --output-type json components server 2>/dev/null | node -e '
394
+ let s=""; process.stdin.on("data",d=>s+=d); process.stdin.on("end",()=>{
395
+ let n=0; try { const j=JSON.parse(s);
396
+ for (const m of j.modules||[]) if (/^components\//.test(m.source||"")) n++;
397
+ } catch(e){ n=0; } process.stdout.write(String(n)); });' 2>/dev/null )"
398
+ if ! [[ "$PARSED_COMPONENTS" =~ ^[0-9]+$ ]] || [[ "$PARSED_COMPONENTS" -lt 1 ]]; then
399
+ echo "SKIP: depcruise parsed 0 component modules from the .tsx fixtures — toolchain"
400
+ echo " unavailable in this shard. The L1 gate is validated end-to-end by the"
401
+ echo " constraint-gates dogfood workflow (live apps/web-platform) + local runs."
402
+ # This `exit 0` is a SECOND clean-exit door, so the trailer's conservation check and floor
403
+ # are repeated here rather than referenced: a guarantee that only guards one of two exits is
404
+ # not a guarantee. Everything above this point is toolchain-FREE and runs in EVERY shard, so
405
+ # it carries its own floor. Conservation FIRST (ADR-193 #4), both reported directly.
406
+ if [[ $((pass + fail)) -ne "$cases" ]]; then
407
+ printf '\n[FATAL] accounting: pass+fail (%d) != cases (%d).\n' "$((pass + fail))" "$cases" >&2
408
+ if [[ $((pass + fail)) -lt "$cases" ]]; then
409
+ printf ' An assertion was counted but its verdict was not recorded — that is what a neutered ok()/bad() looks like.\n' >&2
410
+ else
411
+ printf ' A verdict was recorded at a call site with no `cases=$((cases + 1))` before it. This is a harness bug, not a product failure: add the increment at that call site.\n' >&2
412
+ fi
413
+ echo "boundary.test.sh: $pass passed, $fail failed ($cases assertions, SKIPPED at the toolchain probe)"
414
+ exit 1
415
+ fi
416
+ if [[ "$cases" -lt "$TOOLCHAIN_FREE_MIN_ASSERTIONS" ]]; then
417
+ printf '\n[FATAL] anti-vacuity floor (toolchain-free half): only %d assertion(s) ran, expected >= %d.\n' \
418
+ "$cases" "$TOOLCHAIN_FREE_MIN_ASSERTIONS" >&2
419
+ printf ' Arms were deleted or skipped before the toolchain probe; skipping the depcruise half is sanctioned, asserting nothing at all is not.\n' >&2
420
+ echo "boundary.test.sh: $pass passed, $fail failed ($cases assertions, SKIPPED at the toolchain probe)"
421
+ exit 1
422
+ fi
423
+ echo "boundary.test.sh: $pass passed, $fail failed ($cases assertions, SKIPPED at the toolchain probe)"
424
+ [[ "$fail" -eq 0 ]]
425
+ exit
426
+ fi
427
+
428
+ # --- AC3 + AC6b: positive/negative + regex-escaping --------------------------
429
+ ERR_OUT="$( cd "$FX" && "$DEPCRUISE" --config .dependency-cruiser.cjs --output-type err components server 2>&1 )"
430
+
431
+ cases=$((cases + 1))
432
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/leakdir/leak.tsx'; then
433
+ ok "AC3: value import of server/** via @/server alias is flagged"
434
+ else
435
+ bad "AC3: value import of server/** via @/server alias was NOT flagged"
436
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
437
+ fi
438
+
439
+ cases=$((cases + 1))
440
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/leakdir/typeonly.tsx'; then
441
+ bad "AC3: import type of server/** was flagged (type-only must be allowed)"
442
+ else
443
+ ok "AC3: import type of server/** is allowed (not flagged)"
444
+ fi
445
+
446
+ cases=$((cases + 1))
447
+ if printf '%s' "$ERR_OUT" | grep -cF >/dev/null 'components/(a|b)/parenleak.tsx'; then
448
+ ok "AC6b: regex-metacharacter route-group path matched (regex-escaping works)"
449
+ else
450
+ bad "AC6b: parenthesized-path client file NOT matched — regex-escaping is broken"
451
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
452
+ fi
453
+
454
+ # --- #2: directive preceded by a leading comment banner is still client -------
455
+ cases=$((cases + 1))
456
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/leakdir/bannerleak.tsx'; then
457
+ ok "#2: leading line-comment before \"use client\" still classified client (flagged)"
458
+ else
459
+ bad "#2: leading line-comment banner client file NOT flagged (fail-open misclassification)"
460
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
461
+ fi
462
+ cases=$((cases + 1))
463
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/leakdir/blockbannerleak.tsx'; then
464
+ ok "#2: leading block-comment before \"use client\" still classified client (flagged)"
465
+ else
466
+ bad "#2: leading block-comment banner client file NOT flagged (fail-open misclassification)"
467
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
468
+ fi
469
+ cases=$((cases + 1))
470
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/leakdir/trailingleak.tsx'; then
471
+ ok "#2: \"use client\"; // trailing-comment form still classified client (flagged)"
472
+ else
473
+ bad "#2: trailing-comment directive form client file NOT flagged (fail-open misclassification)"
474
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
475
+ fi
476
+
477
+ # --- #5777 TRANSITIVE rule assertions (AC3, D1/D2). ERR_OUT is the same
478
+ # `components server` cruise; dependency-cruiser follows edges into lib/ for
479
+ # reachability. Anti-vacuity (4.9): we are PAST the toolchain SKIP guard, so these
480
+ # MUST execute and MUST fail (not skip) if a negative fixture is not flagged.
481
+ # 4.1 NEGATIVE transitive via lib/ helper -> MUST FLAG
482
+ cases=$((cases + 1))
483
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/transitive.tsx'; then
484
+ ok "4.1: transitive value chain (client -> lib helper -> server/secret) is flagged"
485
+ else
486
+ bad "4.1: transitive value chain NOT flagged (the #5777 gap is still open)"
487
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
488
+ fi
489
+ # 4.2 POSITIVE first-hop type-only -> MUST NOT FLAG (type-only edge elided globally)
490
+ cases=$((cases + 1))
491
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/typeonly-firsthop.tsx'; then
492
+ bad "4.2: first-hop import-type chain was FLAGGED (type-only must be elided -> false positive)"
493
+ else
494
+ ok "4.2: first-hop import-type chain is not flagged (type-only elided, position-independent)"
495
+ fi
496
+ # 4.3 NEGATIVE mixed import { type A, realValue } -> value edge survives -> MUST FLAG
497
+ cases=$((cases + 1))
498
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/mixed.tsx'; then
499
+ ok "4.3: mixed { type A, realValue } chain is flagged (value edge survives the flip)"
500
+ else
501
+ bad "4.3: mixed-import chain NOT flagged — a value edge was wrongly elided as type-only (silent fail-open)"
502
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
503
+ fi
504
+ # 4.4 NEGATIVE barrel (export *) + named export-from -> MUST FLAG
505
+ cases=$((cases + 1))
506
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/barrel.tsx'; then
507
+ ok "4.4a: barrel re-export (export * from) chain is flagged"
508
+ else
509
+ bad "4.4a: barrel (export *) chain NOT flagged"
510
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
511
+ fi
512
+ cases=$((cases + 1))
513
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/named-barrel.tsx'; then
514
+ ok "4.4b: named export-from re-export chain is flagged"
515
+ else
516
+ bad "4.4b: named export-from chain NOT flagged"
517
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
518
+ fi
519
+ # 4.5 NEGATIVE dynamic import() -> MUST FLAG
520
+ cases=$((cases + 1))
521
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/dynamic.tsx'; then
522
+ ok "4.5: dynamic import() chain is flagged (reachability traverses dynamic edges)"
523
+ else
524
+ bad "4.5: dynamic import() chain NOT flagged"
525
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
526
+ fi
527
+ # 4.6 POSITIVE pathNot target (server/domain-leaders) -> MUST NOT FLAG by transitive rule
528
+ cases=$((cases + 1))
529
+ if printf '%s' "$ERR_OUT" | grep -c >/dev/null 'components/trans/safe-target.tsx'; then
530
+ bad "4.6: pathNot-target chain (client -> helper -> server/domain-leaders) was FLAGGED (pathNot broken)"
531
+ printf '%s\n' "$ERR_OUT" | sed 's/^/ /'
532
+ else
533
+ ok "4.6: pathNot-target chain is not flagged (value-safe target excluded, no baseline double-count)"
534
+ fi
535
+
536
+ # --- AC3: 0 couldNotResolve edges into the secret set ------------------------
537
+ JSON_OUT="$( cd "$FX" && "$DEPCRUISE" --config .dependency-cruiser.cjs --output-type json components server 2>/dev/null )"
538
+ UNRESOLVED_INTO_SERVER="$(
539
+ printf '%s' "$JSON_OUT" | node -e '
540
+ let s = ""; process.stdin.on("data", d => s += d); process.stdin.on("end", () => {
541
+ let n = 0;
542
+ try {
543
+ const j = JSON.parse(s);
544
+ for (const m of j.modules || [])
545
+ for (const dep of m.dependencies || [])
546
+ if (/^server\//.test(dep.resolved || "") && dep.couldNotResolve) n++;
547
+ } catch (e) { n = -1; }
548
+ process.stdout.write(String(n));
549
+ });
550
+ ' 2>/dev/null
551
+ )"
552
+ cases=$((cases + 1))
553
+ if [[ "$UNRESOLVED_INTO_SERVER" == "0" ]]; then
554
+ ok "AC3: 0 couldNotResolve edges into server/ (tsConfig alias resolution live)"
555
+ else
556
+ bad "AC3: couldNotResolve edges into server/ = $UNRESOLVED_INTO_SERVER (expected 0)"
557
+ fi
558
+
559
+ # --- AC6: the secret (`to`) set is explicit and non-empty --------------------
560
+ cases=$((cases + 1))
561
+ if grep -q 'SECRET_PATH = "\^server/"' "$CFG"; then
562
+ ok "AC6: secret (to) set is explicit and non-empty (^server/)"
563
+ else
564
+ bad "AC6: secret (to) set not found / not the expected ^server/ in .cjs"
565
+ fi
566
+
567
+ # --- AC6b: empty from-set while "use client" files exist -> HARD ERROR --------
568
+ EMPTY_OUT="$( cd "$FX" && CONSTRAINT_SCAFFOLD_TEST_FORCE_EMPTY=1 node -e 'require("./.dependency-cruiser.cjs")' 2>&1 )"
569
+ EMPTY_RC=$?
570
+ cases=$((cases + 1))
571
+ if [[ "$EMPTY_RC" -ne 0 ]] && printf '%s' "$EMPTY_OUT" | grep -c >/dev/null 'from-set is empty'; then
572
+ ok "AC6b: empty from-set while client files exist throws (not silently disabled)"
573
+ else
574
+ bad "AC6b: empty from-set did NOT hard-fail (rc=$EMPTY_RC): $EMPTY_OUT"
575
+ fi
576
+
577
+ # --- AC5: empty input (no app/ and no components/) fails closed ---------------
578
+ EMPTYDIR="$TMPROOT/no-client-dirs"
579
+ mkdir -p "$EMPTYDIR/server"
580
+ ln -s "$NODE_MODULES" "$EMPTYDIR/node_modules"
581
+ cp "$CFG" "$EMPTYDIR/.dependency-cruiser.cjs"
582
+ NOINPUT_OUT="$( cd "$EMPTYDIR" && node -e 'require("./.dependency-cruiser.cjs")' 2>&1 )"
583
+ NOINPUT_RC=$?
584
+ cases=$((cases + 1))
585
+ if [[ "$NOINPUT_RC" -ne 0 ]] && printf '%s' "$NOINPUT_OUT" | grep -cE >/dev/null 'neither app/ nor components/'; then
586
+ ok "AC5: empty input (no client dirs) fails closed (distinct from 'no client modules')"
587
+ else
588
+ bad "AC5: empty input did NOT fail closed (rc=$NOINPUT_RC): $NOINPUT_OUT"
589
+ fi
590
+
591
+ # --- AC5: broken .cjs -> shared runner fails closed --------------------------
592
+ BROKEN="$TMPROOT/broken-app"
593
+ mkdir -p "$BROKEN/app" "$BROKEN/components" "$BROKEN/server" "$BROKEN/scripts"
594
+ ln -s "$NODE_MODULES" "$BROKEN/node_modules"
595
+ printf 'module.exports = { this is not valid javascript\n' > "$BROKEN/.dependency-cruiser.cjs"
596
+ printf '[]\n' > "$BROKEN/.dependency-cruiser-known-violations.json"
597
+ BROKEN_OUT="$( CONSTRAINT_GATES_DIR="$BROKEN" bash "$RUNNER" 2>&1 )"
598
+ BROKEN_RC=$?
599
+ cases=$((cases + 1))
600
+ if [[ "$BROKEN_RC" -ne 0 ]] && printf '%s' "$BROKEN_OUT" | grep -c >/dev/null 'config/binary error'; then
601
+ ok "AC5: broken .cjs makes the shared runner fail closed (rc=$BROKEN_RC)"
602
+ else
603
+ bad "AC5: broken .cjs did NOT fail the runner closed (rc=$BROKEN_RC): $BROKEN_OUT"
604
+ fi
605
+
606
+ # --- AC10: shared runner is GREEN on a clean baselined fixture ----------------
607
+ # In v2 the reachable rule is a SUPERSET of the direct rule (a direct edge is a
608
+ # length-1 path), so a direct leak to a NON-value-safe module ALSO produces a
609
+ # type:"reachability" violation that must NOT be baselined (the D3 runner guard
610
+ # rejects it). The real app is green because its baselined direct edges all target
611
+ # VALUE_SAFE modules (pathNot-excluded from the reachable rule). Mirror that exactly:
612
+ # a client that directly value-imports a value-safe server module -> the direct rule
613
+ # flags it (a baselineable dependency), the reachable rule excludes it (no
614
+ # reachability entry) -> baseline all -> runner green.
615
+ CLEAN="$BROKEN-clean"
616
+ mkdir -p "$CLEAN/app" "$CLEAN/components/c" "$CLEAN/server" "$CLEAN/scripts"
617
+ ln -s "$NODE_MODULES" "$CLEAN/node_modules"
618
+ cp "$FX/tsconfig.json" "$CLEAN/tsconfig.json"
619
+ cp "$CFG" "$CLEAN/.dependency-cruiser.cjs"
620
+ printf 'export const LEADERS = ["a"] as const;\n' > "$CLEAN/server/domain-leaders.ts"
621
+ printf '"use client";\nimport { LEADERS } from "@/server/domain-leaders";\nexport const V = () => LEADERS;\n' > "$CLEAN/components/c/valuesafe.tsx"
622
+ ( cd "$CLEAN" && "$DEPCRUISE" --config .dependency-cruiser.cjs --output-type baseline app components server > .dependency-cruiser-known-violations.json 2>/dev/null )
623
+ CLEAN_OUT="$( CONSTRAINT_GATES_DIR="$CLEAN" bash "$RUNNER" 2>&1 )"
624
+ CLEAN_RC=$?
625
+ cases=$((cases + 1))
626
+ if [[ "$CLEAN_RC" -eq 0 ]]; then
627
+ ok "AC10: shared runner is green (rc=0) when all (value-safe direct) violations are baselined"
628
+ else
629
+ bad "AC10: shared runner not green on baselined fixture (rc=$CLEAN_RC): $CLEAN_OUT"
630
+ fi
631
+
632
+ # --- 4.8: real-runner rc != 0 on an un-baselined TRANSITIVE leak ---------------
633
+ # The full FX fixture contains transitive leaks. With an EMPTY baseline (0
634
+ # reachability entries -> the D3 runner guard passes), the cruise itself must fail
635
+ # on the transitive reachability violation and reach the runner's 'dependency
636
+ # violations' fail branch — proving a reachability violation is enforced end-to-end
637
+ # through the real runner (not only via --output-type json).
638
+ LEAKY="$BROKEN-transitive-leak"
639
+ cp -r "$FX" "$LEAKY"
640
+ rm -f "$LEAKY/node_modules"; ln -s "$NODE_MODULES" "$LEAKY/node_modules"
641
+ mkdir -p "$LEAKY/app" "$LEAKY/scripts"
642
+ # Remove DIRECT-leak fixtures so the ONLY violation the runner sees is transitive —
643
+ # proves the reachable rule (not the direct rule) drives the non-zero exit.
644
+ rm -rf "$LEAKY/components/leakdir" "$LEAKY/components/(a|b)"
645
+ rm -f "$LEAKY/components/trans/typeonly-firsthop.tsx" "$LEAKY/components/trans/safe-target.tsx" \
646
+ "$LEAKY/lib/typed-helper.ts" "$LEAKY/lib/safe-helper.ts"
647
+ printf '[]\n' > "$LEAKY/.dependency-cruiser-known-violations.json"
648
+ LEAKY_OUT="$( CONSTRAINT_GATES_DIR="$LEAKY" bash "$RUNNER" 2>&1 )"
649
+ LEAKY_RC=$?
650
+ cases=$((cases + 1))
651
+ if [[ "$LEAKY_RC" -ne 0 ]] && printf '%s' "$LEAKY_OUT" | grep -c >/dev/null 'import-boundary violation'; then
652
+ ok "4.8: real runner fails closed (rc=$LEAKY_RC) on an un-baselined transitive leak"
653
+ else
654
+ bad "4.8: real runner did NOT fail on a transitive leak (rc=$LEAKY_RC): $LEAKY_OUT"
655
+ fi
656
+
657
+ # --- 4.10: runner rejects a type:"module" baseline entry naming the transitive rule
658
+ # (P1 regression). dependency-cruiser softens the transitive rule per-origin on
659
+ # from+rule.name IGNORING type, so a hand-authored type:"module" entry would suppress
660
+ # a real transitive leak while a type:"reachability"-only guard reads 0. The runner
661
+ # guard must key on the rule name and fail closed. This is the exact bypass a
662
+ # careless/hostile baseline edit would use.
663
+ MODENTRY="$BROKEN-modentry"
664
+ mkdir -p "$MODENTRY/app" "$MODENTRY/components" "$MODENTRY/server" "$MODENTRY/scripts"
665
+ ln -s "$NODE_MODULES" "$MODENTRY/node_modules"
666
+ cp "$CFG" "$MODENTRY/.dependency-cruiser.cjs"
667
+ cat > "$MODENTRY/.dependency-cruiser-known-violations.json" <<'JSON'
668
+ [{"type":"module","from":"components/c/leak.tsx","to":"server/secret.ts","rule":{"severity":"error","name":"no-client-to-server-secret-transitive"}}]
669
+ JSON
670
+ MODENTRY_OUT="$( CONSTRAINT_GATES_DIR="$MODENTRY" bash "$RUNNER" 2>&1 )"
671
+ MODENTRY_RC=$?
672
+ cases=$((cases + 1))
673
+ if [[ "$MODENTRY_RC" -ne 0 ]] && printf '%s' "$MODENTRY_OUT" | grep -c >/dev/null 'suppress the transitive rule'; then
674
+ ok "4.10: runner rejects a type:\"module\" baseline entry naming the transitive rule (rc=$MODENTRY_RC)"
675
+ else
676
+ bad "4.10: runner did NOT reject a type:\"module\" transitive-suppressing baseline entry (rc=$MODENTRY_RC) — P1 bypass open: $MODENTRY_OUT"
677
+ fi
678
+
679
+ # --- 4.11: runner fails closed on a non-array (but valid-JSON) baseline ----------
680
+ # `{}` / `null` / `42` parse fine but are not an entry array; the guard must treat
681
+ # them as -1 (fail closed), not as an empty array (0 -> pass).
682
+ NONARRAY="$BROKEN-nonarray"
683
+ mkdir -p "$NONARRAY/app" "$NONARRAY/components" "$NONARRAY/server" "$NONARRAY/scripts"
684
+ ln -s "$NODE_MODULES" "$NONARRAY/node_modules"
685
+ cp "$CFG" "$NONARRAY/.dependency-cruiser.cjs"
686
+ printf '{}\n' > "$NONARRAY/.dependency-cruiser-known-violations.json"
687
+ NONARRAY_OUT="$( CONSTRAINT_GATES_DIR="$NONARRAY" bash "$RUNNER" 2>&1 )"
688
+ NONARRAY_RC=$?
689
+ cases=$((cases + 1))
690
+ if [[ "$NONARRAY_RC" -ne 0 ]]; then
691
+ ok "4.11: runner fails closed on a non-array baseline (rc=$NONARRAY_RC)"
692
+ else
693
+ bad "4.11: runner passed a non-array baseline (rc=$NONARRAY_RC) — fail-open: $NONARRAY_OUT"
694
+ fi
695
+
696
+ echo "---"
697
+
698
+ # --- Accounting conservation (ADR-193 #3) --------------------------------------------------
699
+ # Ordered BEFORE the floor (ADR-193 #4): a neutered bad()/ok() deflates the verdict counters, so
700
+ # the floor below would ALSO trip and would report the misleading "arms were deleted". This says
701
+ # "a verdict was discarded" instead. Reported with `printf >&2` + `exit 1` DIRECTLY, never
702
+ # through bad(): a check that reports by calling the verdict helper increments the very counter
703
+ # the exit status reads, so neutering bad() silences the rows AND the check meant to notice the
704
+ # silence. Every assertion records exactly one verdict, so pass+fail MUST equal cases; because
705
+ # `cases` moves at the CALL SITE and not inside the verdict helpers, the identity is a real
706
+ # constraint rather than a tautology. The literal `[FATAL] accounting` is load-bearing —
707
+ # guard-vacuity-floor's ARM 10 builds its conservation population by grepping that exact string.
708
+ if [[ $((pass + fail)) -ne "$cases" ]]; then
709
+ printf '\n[FATAL] accounting: pass+fail (%d) != cases (%d).\n' "$((pass + fail))" "$cases" >&2
710
+ if [[ $((pass + fail)) -lt "$cases" ]]; then
711
+ printf ' An assertion was counted but its verdict was not recorded — that is what a neutered ok()/bad() looks like.\n' >&2
712
+ else
713
+ printf ' A verdict was recorded at a call site with no `cases=$((cases + 1))` before it. This is a harness bug, not a product failure: add the increment at that call site.\n' >&2
714
+ fi
715
+ echo "boundary.test.sh: $pass passed, $fail failed ($cases assertions)"
716
+ exit 1
717
+ fi
718
+
719
+ # --- Anti-vacuity floor (ADR-193 #1) -------------------------------------------------------
720
+ # Reads the INDEPENDENT `cases` counter, and reports with `printf >&2` + `exit 1` DIRECTLY.
721
+ # This suite previously carried NO suite-level floor at all: a harness that silently asserted
722
+ # nothing (a fixture generator that no-ops, an editing slip that drops a block) printed a clean
723
+ # smaller total and exited 0. See MIN_ASSERTIONS above for how the number is derived and when
724
+ # to ratchet it.
725
+ if [[ "$cases" -lt "$MIN_ASSERTIONS" ]]; then
726
+ printf '\n[FATAL] anti-vacuity floor: only %d assertion(s) ran, expected >= %d.\n' \
727
+ "$cases" "$MIN_ASSERTIONS" >&2
728
+ printf ' Arms were deleted or skipped; a green run here would be a coverage loss.\n' >&2
729
+ echo "boundary.test.sh: $pass passed, $fail failed ($cases assertions)"
730
+ exit 1
731
+ fi
732
+
733
+ echo "boundary.test.sh: $pass passed, $fail failed ($cases assertions)"
734
+ [[ "$fail" -eq 0 ]]