@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,444 @@
1
+ #!/usr/bin/env bash
2
+ # The /ship Phase 5.5 Technical-Ruling Gate (hard rule hr-technical-fork-is-not-an-operator-question).
3
+ #
4
+ # Property: no PR reaches ready with a decision-challenges.md or PR-body line that asks the operator a
5
+ # TECHNICAL question. Every row of the artifact's `| Item | Class | Ruling |` tables has a valid class;
6
+ # every `technical` row carries a `Ruled by CTO|CLO agent, <date>:` cell; no `pending - assumed`
7
+ # placeholder survives; and the "Owner decision needed" / "Owner ruling needed" label appears only with
8
+ # `(operator: <category>)`. The gate checks FORM, never truth: a model that mislabels a technical
9
+ # question as `operator (scope)` still passes (a stated residual, technical-ruling-delegation.md
10
+ # section 6); the check on that is review and the operator-visible rendering of operator rows.
11
+ #
12
+ # Usage:
13
+ # technical-ruling-gate.sh <path> check one decision-challenges.md
14
+ # technical-ruling-gate.sh --branch check this branch's artifact under
15
+ # knowledge-base/project/specs/<branch>/, or under
16
+ # specs/archive/<date>-<slug>/ when archived early;
17
+ # an absent artifact is `[PASS] no decision-challenges artifact`
18
+ # technical-ruling-gate.sh --pr-body <file> check a PR body for an unscoped owner-decision label
19
+ # or a surviving `pending - assumed` placeholder
20
+ #
21
+ # Exit codes:
22
+ # 0 every examined row passes (`[PASS]` on stdout). An artifact with NO table is `[WARN]` + exit 0
23
+ # (legacy artifacts and in-flight branches are not blocked); the label and `pending` lints still run.
24
+ # 1 at least one failure (`[FAIL] <path>:<line>: <reason> - <remedy>` on stderr, one per finding;
25
+ # <line> is always a line of the checked file)
26
+ # 2 could not measure: usage error, an unreadable or EMPTY artifact or PR body (whitespace only counts as
27
+ # empty), a table header with 0 data rows, a header that looks like the Decision Classes header (a
28
+ # separator line follows it) but is not exactly `| Item | Class | Ruling |`, a row whose Class is
29
+ # `technical` that sits OUTSIDE any recognised table (a row after a blank line, a header-less table),
30
+ # an unclosed code fence in the artifact or the PR body (everything after it would be hidden), or an
31
+ # ambiguous archive match. Never a silent pass on something that exists but was not examined.
32
+ #
33
+ # Table rules (GFM): a table ends at the first line that does not start with `|` (a blank line included);
34
+ # a row appended after a blank line is outside the table (a `technical` one is exit 2, never skipped). A
35
+ # later writer adds its own header+separator. Inline `code spans` are ignored by the label and pending
36
+ # lints (a PR that documents this machinery may quote the strings). A UTF-8 BOM is tolerated. Tables without
37
+ # a leading pipe, inside a blockquote or inside a list item are not recognised (residual: the stray-row
38
+ # check above catches a `technical` row there).
39
+ #
40
+ # Reasons (the suite asserts each): bad-class, bad-category, unruled-technical, bad-ruling-shape,
41
+ # owner-label-unscoped, delegation-invalid, delegation-unverifiable, receipt-missing, receipt-mismatch,
42
+ # receipt-unreadable.
43
+ #
44
+ # Delegation arm (ADR-289, hr-menu-option-ack-not-prod-write-auth): a row whose Class is exactly
45
+ # `operator (production-mutating)` and whose Ruling is
46
+ # Authorized by delegation <comment-url>, envelope <path>[, ran <ISO 8601 UTC time>]
47
+ # is validated through plugins/soleur/scripts/delegation-verify.sh. A row WITHOUT `ran` is an authorization for an
48
+ # act that has not happened: plain `verify` (expiry and an open epic are enforced now). A row WITH `ran` records an
49
+ # act that did: `verify --audit --at <time>` (the delegation must have been in force at that time; only a closed
50
+ # epic is forgiven), and the row must also be backed by an execution receipt on the epic: a comment whose FIRST line
51
+ # is `<!-- soleur-delegated-act v1 delegation=<url> envelope=<path> sha256=<verified-envelope-sha256> result=ok|rolled-back
52
+ # run=<url|none> -->`, written by an OWNER, MEMBER or COLLABORATOR, naming this row's delegation URL and envelope
53
+ # path, the sha256 the verifier just reported for that envelope, and a result of ok or rolled-back. Every field is
54
+ # compared EXACTLY, a missing author_association never defaults, and the receipt must lie inside the delegation's life
55
+ # (created at or after the delegation, not after the end of its expiry day, not in the future), must never have been
56
+ # edited (updated_at == created_at), must come from a User (not a bot), must be created at or after the `ran` instant it
57
+ # vouches for (a receipt posted in advance is no receipt), and satisfies at most ONE row (three rows
58
+ # cannot share one receipt). A `ran` time later than now is `delegation-invalid`. A delegation row needs a time-limit tool
59
+ # (timeout or gtimeout); without one it is `delegation-unverifiable`, never an unbounded call. That is all the check proves:
60
+ # a receipt exists, is attributable and matches the row. It is NOT proof of what ran (a receipt-checking
61
+ # hook on the executed command is the stronger follow-up, #10361). Missing, mismatching or unreadable receipts are
62
+ # `receipt-missing`, `receipt-mismatch`, `receipt-unreadable` (exit 2, never a pass).
63
+ # Verdicts: valid passes; invalid is `delegation-invalid` (exit 1); unverifiable, including a missing verifier or a
64
+ # verifier whose rc and first line disagree, is `delegation-unverifiable` (exit 2, never a pass). The same ruling
65
+ # shape on any other Class is `bad-ruling-shape`: a delegation authorizes only production-mutating acts. The row
66
+ # stays required (no row, no pass), every delegation row is examined (the first valid one does not end the scan),
67
+ # one verifier call per (delegation, envelope, time) and one receipt read per epic, and a delegation row outside a
68
+ # recognised table is exit 2. An ARCHIVED artifact (`--branch` found it under specs/archive/) is checked for row
69
+ # shape ONLY, with no network, and says so in its [NOTE] and [PASS] lines. A plain `operator (production-mutating)`
70
+ # row with no delegation text passes on form, as before. Format source:
71
+ # skills/brainstorm-techniques/references/standing-delegation.md.
72
+ #
73
+ # Test seams: TRG_VERIFY_TIMEOUT (seconds, 1-59: it can only SHORTEN the 60 s verifier limit), TRG_EXEC_LOG (append one line per examined row), TRG_SPECS_ROOT and TRG_BRANCH (the
74
+ # `--branch` lookup, so a suite needs no git repository); any of them being set is announced on stderr.
75
+ # Lines carrying `# mut:<name>` are the mutation points the suite edits to prove each check can fail.
76
+ #
77
+ # `set -uo pipefail`, deliberately NOT `-e`: the scanners are pipelines whose `grep` exits 1 on no match.
78
+ # Portable to bash 3.2 and to mawk (no `${var,,}`, no `sed -i`, no awk `{m,n}` intervals).
79
+
80
+ set -uo pipefail
81
+ export LC_ALL=C
82
+ shopt -s nocasematch
83
+
84
+ CATEGORIES="money scope priority schedule irreversible production-mutating legal-risk brand"
85
+ CATS_RE="${CATEGORIES// /|}"
86
+ LABEL_RE='owner[ \t-]+(decision|ruling)s?[ \t]+((is|are)[ \t]+)?(needed|required)|decision[ \t]+needed[ \t]+from[ \t]+the[ \t]+owner|needs?[ \t]+(the[ \t]+)?owner[ \t]+(decision|ruling)'
87
+ RULING_RE='^Ruled by (CTO|CLO) agent, [0-9]{4}-[0-9]{2}-[0-9]{2}: .+'
88
+ PENDING_RE='pending[ \t]*[^a-z0-9 \t]+[ \t]*assumed'
89
+ VERIFIER="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)/../../../scripts/delegation-verify.sh"
90
+
91
+ # Shared context-sanitize lib (#10395), three levels up at scripts/lib/. When it
92
+ # is unreadable the same-name fallback carries this site's pre-change strip set
93
+ # (tr's [[:cntrl:]] class, under the ambient locale exactly as before — no
94
+ # LC_ALL=C pin, so the fallback never strips less than the site did) — never
95
+ # weaker than today.
96
+ _ctx_lib="$(cd -P "${BASH_SOURCE[0]%/*}/../../../scripts/lib" 2>/dev/null && pwd -P)/context-sanitize.sh"
97
+ _ctx_lib="${_ctx_lib:-/nonexistent/context-sanitize.sh}"
98
+ # shellcheck source=/dev/null
99
+ [[ -r "$_ctx_lib" ]] && . "$_ctx_lib" || true
100
+ declare -F soleur_ctx_sanitize >/dev/null 2>&1 \
101
+ || soleur_ctx_sanitize() { tr -d '[:cntrl:]'; }
102
+ DELEG_RE='^Authorized by delegation (https://github\.com/([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+)/(issues|pull)/([0-9]+)#issuecomment-[0-9]+), envelope ([A-Za-z0-9_./#@ -]+)(, ran ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z))?$'
103
+ SHAPE_ONLY=0
104
+ SHAPE_ROWS=0
105
+ DR=0
106
+ TOG=(); TOV=(); HAVE_TO=0; TOBIN=""
107
+ CONSUMED=""
108
+ if command -v timeout >/dev/null 2>&1; then TOBIN=timeout
109
+ elif command -v gtimeout >/dev/null 2>&1; then TOBIN=gtimeout; fi # mut:gtimeout
110
+ if [[ -n "$TOBIN" ]]; then
111
+ HAVE_TO=1
112
+ VT=60
113
+ case "${TRG_VERIFY_TIMEOUT:-}" in ''|*[!0-9]*) ;; *) [[ "$TRG_VERIFY_TIMEOUT" -ge 1 && "$TRG_VERIFY_TIMEOUT" -lt 60 ]] && VT="$TRG_VERIFY_TIMEOUT" ;; esac
114
+ TOG=("$TOBIN" 60); TOV=("$TOBIN" "$VT")
115
+ fi
116
+ CTO_REMEDY='spawn soleur:engineering:cto now (at most two attempts, see technical-ruling-delegation.md), write the Ruled by cell, re-run; after two failed attempts leave the PR draft and file one domain/engineering issue, never an operator question'
117
+
118
+ work_dir=""
119
+ UNCLOSED_SEEN=0
120
+ cleanup() { [[ -n "$work_dir" ]] && rm -rf "${work_dir:?}"; return 0; }
121
+ trap cleanup EXIT
122
+
123
+ cat_ok() { case " $CATEGORIES " in *" $1 "*) return 0 ;; esac; return 1; } # mut:cat
124
+ is_unruled() { [[ -z "$1" ]]; } # mut:unruled
125
+ shape_ok() { [[ "$1" =~ $RULING_RE ]]; } # mut:shape
126
+
127
+ die2() { printf '[ERROR] %s\n' "$*" >&2; cleanup; exit 2; }
128
+
129
+ # unfenced_match <file> <regex>: `<line>\t<text>` for every unfenced line whose lowercase form matches, with
130
+ # inline `code spans` removed first. A fence closes only on the same character, at least as long, with no info
131
+ # string (CommonMark); a backtick fence whose info string contains a backtick is inline code, not a fence.
132
+ # `@UNCLOSED` is printed when a fence is still open at end of file.
133
+ unfenced_match() {
134
+ awk -v re="$2" '
135
+ function fence_toggle( tok, c, n) {
136
+ tok = $0; sub(/^ +/, "", tok)
137
+ match(tok, /^(`+|~+)/); c = substr(tok, 1, 1); n = RLENGTH
138
+ if (!f) { if (c == "`" && substr(tok, n + 1) ~ /`/) return; f = 1; fc = c; fn = n; return }
139
+ if (c == fc && n >= fn && tok ~ /^(`+|~+)[ \t]*$/) f = 0
140
+ }
141
+ { sub(/\r$/, ""); if (NR == 1) sub(/^\357\273\277/, "") }
142
+ /^ ? ? ?(```+|~~~+)/ { fence_toggle(); next } # mut:fence
143
+ f { next }
144
+ { line = $0; gsub(/`[^`]*`/, "", line); if (tolower(line) ~ re) printf "%d\t%s\n", NR, $0 }
145
+ END { if (f) print "@UNCLOSED" }
146
+ ' "$1"
147
+ }
148
+
149
+ # table_rows <file>: per unfenced `| Item | Class | Ruling |` header `@TABLE`, then `<line>\t<row>` per data
150
+ # row; `@EMPTY` for a table with no data row, `@BADHEADER` for a header-like row followed by a separator
151
+ # that is not exactly ours, `@STRAY` for a `technical` row outside any recognised table, `@UNCLOSED` when a
152
+ # code fence is still open at end of file.
153
+ table_rows() {
154
+ awk '
155
+ function fence_toggle( tok, c, n) {
156
+ tok = $0; sub(/^ +/, "", tok)
157
+ match(tok, /^(`+|~+)/); c = substr(tok, 1, 1); n = RLENGTH
158
+ if (!f) { if (c == "`" && substr(tok, n + 1) ~ /`/) return; f = 1; fc = c; fn = n; return }
159
+ if (c == fc && n >= fn && tok ~ /^(`+|~+)[ \t]*$/) f = 0
160
+ }
161
+ function end_table() { if ((state == 3 && rows_in == 0) || state == 2) print "@EMPTY"; state = 0 }
162
+ { sub(/\r$/, ""); if (NR == 1) sub(/^\357\273\277/, "") }
163
+ /^ ? ? ?(```+|~~~+)/ { fence_toggle(); next } # mut:fence-table
164
+ f { next }
165
+ { if (hdr_pending) { if ($0 ~ /^ ? ? ?\|[ :|-]+$/) print "@BADHEADER"; hdr_pending = 0 } }
166
+ { if ((state != 3 || $0 !~ /^ ? ? ?\|/) && tolower($0) ~ /\|[ \t]*technical[ \t]*\|/) print "@STRAY" }
167
+ { if ((state != 3 || $0 !~ /^ ? ? ?\|/) && $0 ~ /^ ? ? ?\|/ && tolower($0) ~ /authorized by delegation/) print "@STRAY" } # mut:stray-deleg
168
+ /^ ? ? ?\|/ {
169
+ line = $0; sub(/^ +/, "", line); sub(/[ \t]+$/, "", line); low = tolower(line)
170
+ if (line ~ /^\|[ \t]*Item[ \t]*\|[ \t]*Class[ \t]*\|[ \t]*Ruling[ \t]*\|$/) { end_table(); print "@TABLE"; state = 2; rows_in = 0; next }
171
+ if (low ~ /item/ && low ~ /class/ && low ~ /ruling/ && state != 3) { hdr_pending = 1; next }
172
+ if (state == 2 && line ~ /^\|[ :|-]+$/) { state = 3; next }
173
+ if (state == 3) { printf "%d\t%s\n", NR, line; rows_in++; next }
174
+ end_table(); next
175
+ }
176
+ { end_table() }
177
+ END { end_table(); if (f) print "@UNCLOSED" }
178
+ ' "$1"
179
+ }
180
+
181
+ check_labels() { # <file> <display-path>; prints [FAIL] lines, returns the count (capped: a status wraps at 256)
182
+ local file="$1" shown="$2" n=0 ln text
183
+ while IFS=$'\t' read -r ln text; do
184
+ [[ -n "$ln" ]] || continue
185
+ if [[ "$ln" == "@UNCLOSED" ]]; then UNCLOSED_SEEN=1; continue; fi
186
+ if [[ ! "$text" =~ \(operator:\ ($CATS_RE)\) ]]; then
187
+ printf '[FAIL] %s:%s: owner-label-unscoped - the owner-decision label may only carry an operator-class item; append (operator: <category>) with a category from the closed list (%s), or route the question to the CTO (technical-ruling-delegation.md)\n' "$shown" "$ln" "$CATEGORIES" >&2
188
+ n=$((n + 1))
189
+ fi
190
+ done < <(unfenced_match "$file" "$LABEL_RE")
191
+ (( n > 255 )) && n=255
192
+ return "$n"
193
+ }
194
+
195
+ check_pending() { # <file> <display-path>; an unresolved placeholder anywhere in the file, returns the count (capped)
196
+ local file="$1" shown="$2" n=0 ln text
197
+ while IFS=$'\t' read -r ln text; do
198
+ [[ -n "$ln" ]] || continue
199
+ if [[ "$ln" == "@UNCLOSED" ]]; then UNCLOSED_SEEN=1; continue; fi
200
+ printf '[FAIL] %s:%s: unruled-technical - a "pending - assumed" placeholder survives: %s\n' "$shown" "$ln" "$CTO_REMEDY" >&2
201
+ n=$((n + 1))
202
+ done < <(unfenced_match "$file" "$PENDING_RE") # mut:pending
203
+ (( n > 255 )) && n=255
204
+ return "$n"
205
+ }
206
+
207
+ # memo_find <keyfile> <key>: prints the 1-based entry number of <key>, or nothing. One key per line.
208
+ memo_find() { [[ -f "$1" ]] || return 0; grep -nxF -- "$2" "$1" 2>/dev/null </dev/null | head -1 | cut -d: -f1; } # mut:memo
209
+
210
+ # receipt_check <delegation-url> <repo> <epic> <envelope-path> <sha> <verified-created-at> <verified-expiry>: sets
211
+ # RC_REASON to ok, receipt-missing, receipt-mismatch or receipt-unreadable. One read of the epic's comments per epic;
212
+ # every call has stdin closed. A receipt counts only if: its delegation and envelope equal the row's EXACTLY, its sha256
213
+ # is the verifier's, its result is ok or rolled-back, its author_association is OWNER, MEMBER or COLLABORATOR (a missing
214
+ # one never defaults), it was created inside the delegation's life (not before the delegation, not after the end of its
215
+ # expiry day) and not in the future, it was never edited (updated_at == created_at), its author is a User (not a bot),
216
+ # and it has not already satisfied another row (a receipt is consumed by the row that uses it).
217
+ receipt_check() {
218
+ local durl="$1" repo="$2" epic="$3" env="$4" sha="$5" vcre="$6" vexp="$7" ran="$8" key="$2#$3" n rd re rs rr ra rk rcre rupd rtyp nrec=0 okrec=0 now
219
+ RC_REASON=unreadable
220
+ now="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
221
+ n="$(memo_find "$work_dir/rcpt.keys" "$key")"
222
+ if [[ -z "$n" ]]; then
223
+ echo "$key" >> "$work_dir/rcpt.keys"; n="$(wc -l < "$work_dir/rcpt.keys" | tr -d ' ')"
224
+ if ${TOG[@]+"${TOG[@]}"} gh api "repos/$repo/issues/$epic/comments" --paginate >"$work_dir/rcpt.$n.json" 2>/dev/null </dev/null \
225
+ && jq -r -s '[.[][]] | to_entries | .[] | .key as $k | .value
226
+ | (.body // "" | split("\n") | (.[0] // "") | sub("\r$"; "")) as $l
227
+ | ([$l | capture("^<!-- soleur-delegated-act v1 delegation=(?<d>[^ ]+) envelope=(?<e>.+?) sha256=(?<s>[0-9a-f]{64}) result=(?<r>[A-Za-z-]+) run=(?<u>[^ ]+) -->$")] | .[0]) as $m
228
+ | select($m != null) | [$m.d, $m.e, $m.s, $m.r, (.author_association // "ABSENT"), ($k | tostring), (.created_at // "none"), (.updated_at // "none2"), (.user.type // "NONE")] | @tsv' "$work_dir/rcpt.$n.json" >"$work_dir/rcpt.$n.tsv" 2>/dev/null </dev/null; then
229
+ echo ok > "$work_dir/rcpt.$n.st"
230
+ else
231
+ echo bad > "$work_dir/rcpt.$n.st"
232
+ fi
233
+ fi
234
+ [[ "$(cat "$work_dir/rcpt.$n.st")" == ok ]] || return 0
235
+ while IFS=$'\t' read -r rd re rs rr ra rk rcre rupd rtyp; do
236
+ [[ "$rd" == "$durl" ]] || continue # mut:receipt-deleg
237
+ case " $CONSUMED " in *" $n:$rk "*) continue ;; esac # mut:receipt-consume
238
+ nrec=$((nrec + 1))
239
+ [[ "$re" == "$env" ]] || continue # mut:receipt-env
240
+ [[ "$rs" == "$sha" ]] || continue # mut:receipt-sha
241
+ case "$rr" in ok|rolled-back) ;; *) continue ;; esac # mut:receipt-result
242
+ case "$ra" in OWNER|MEMBER|COLLABORATOR) ;; *) continue ;; esac # mut:receipt-author
243
+ [[ "$rcre" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$ ]] || continue
244
+ # created >= ran also bounds the receipt below by the delegation itself: the verifier enforces delegation created <= ran
245
+ [[ "$rcre" < "$ran" ]] && continue # mut:receipt-before-ran
246
+ [[ "$rcre" > "$now" ]] && continue # mut:receipt-future
247
+ [[ "$rcre" > "${vexp}T23:59:59Z" ]] && continue # mut:receipt-expiry
248
+ [[ "$rupd" == "$rcre" ]] || continue # mut:receipt-edited
249
+ [[ "$rtyp" == User ]] || continue # mut:receipt-bot
250
+ okrec=1; CONSUMED="$CONSUMED $n:$rk"; break
251
+ done < "$work_dir/rcpt.$n.tsv"
252
+ if (( okrec )); then RC_REASON=ok; elif (( nrec > 0 )); then RC_REASON=receipt-mismatch; else RC_REASON=receipt-missing; fi
253
+ }
254
+
255
+ # check_delegation_row <line> <class> <ruling>: DR=0 pass, 1 a finding was printed, 2 could not verify (printed).
256
+ # Runs with nocasematch OFF: the phrase, the class and the link are matched exactly.
257
+ check_delegation_row() {
258
+ local had=0
259
+ shopt -q nocasematch && had=1
260
+ shopt -u nocasematch # mut:case-off
261
+ check_delegation_row_inner "$@"
262
+ (( had )) && shopt -s nocasematch
263
+ return 0
264
+ }
265
+ check_delegation_row_inner() {
266
+ local ln="$1" cls="$2" ruling="$3" durl repo epic dpath dran reason why dv_rc dv_line key n sha vcre vexp now
267
+ DR=0
268
+ [[ "$cls" == "operator (production-mutating)" ]] || { printf '[FAIL] %s:%s: bad-ruling-shape - a delegation can authorize only an operator (production-mutating) act, not "%s"\n' "$shown" "$ln" "$cls" >&2; DR=1; return; } # mut:deleg-class
269
+ [[ "$ruling" =~ $DELEG_RE ]] || { printf '[FAIL] %s:%s: bad-ruling-shape - a delegation ruling must read: Authorized by delegation <comment-url>, envelope <path>[, ran <time as 2026-01-31T09:30:00Z>] (standing-delegation.md)\n' "$shown" "$ln" >&2; DR=1; return; }
270
+ durl="${BASH_REMATCH[1]}"; repo="${BASH_REMATCH[2]}"; epic="${BASH_REMATCH[4]}"; dpath="${BASH_REMATCH[5]}"; dran="${BASH_REMATCH[7]:-}"
271
+ [[ -n "${TRG_EXEC_LOG:-}" ]] && echo "delegation $shown:$ln" >> "${TRG_EXEC_LOG:?}" # mut:deleg-log
272
+ if (( SHAPE_ONLY )); then SHAPE_ROWS=$((SHAPE_ROWS + 1)); DR=0; return; fi
273
+ (( HAVE_TO )) || { printf '[FAIL] %s:%s: delegation-unverifiable - no time limit tool (timeout or gtimeout) is installed, so the delegation was not checked, which is never a pass\n' "$shown" "$ln" >&2; DR=2; return; } # mut:need-timeout
274
+ now="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
275
+ [[ -n "$dran" && "$dran" > "$now" ]] && { printf '[FAIL] %s:%s: delegation-invalid - the row says the act ran at %s, which is in the future, so it cannot have run yet (reason: ran-in-future)\n' "$shown" "$ln" "$dran" >&2; DR=1; return; } # mut:ran-future
276
+ [[ -f "$VERIFIER" ]] || { printf '[FAIL] %s:%s: delegation-unverifiable - the delegation checker was not found next to this gate, so the row was not examined\n' "$shown" "$ln" >&2; DR=2; return; }
277
+ key="$durl|$dpath|$dran"
278
+ n="$(memo_find "$work_dir/dv.keys" "$key")"
279
+ if [[ -z "$n" ]]; then
280
+ echo "$key" >> "$work_dir/dv.keys"; n="$(wc -l < "$work_dir/dv.keys" | tr -d ' ')"
281
+ if [[ -z "$dran" ]]; then
282
+ ${TOV[@]+"${TOV[@]}"} bash "$VERIFIER" verify --delegation "$durl" --envelope "$dpath" </dev/null >"$work_dir/dv.$n.out" 2>"$work_dir/dv.$n.err"; dv_rc=$? # mut:deleg-call
283
+ else
284
+ ${TOV[@]+"${TOV[@]}"} bash "$VERIFIER" verify --delegation "$durl" --envelope "$dpath" --audit --at "$dran" </dev/null >"$work_dir/dv.$n.out" 2>"$work_dir/dv.$n.err"; dv_rc=$? # mut:deleg-audit
285
+ fi
286
+ echo "$dv_rc" > "$work_dir/dv.$n.rc"
287
+ fi
288
+ dv_rc="$(cat "$work_dir/dv.$n.rc")"
289
+ dv_line="$(head -1 "$work_dir/dv.$n.out")"
290
+ reason="$(printf '%s\n' "$dv_line" | sed -n 's/^delegation: [a-z]* reason=\(.*\)$/\1/p' | soleur_ctx_sanitize | cut -c1-60)"
291
+ why="$(head -1 "$work_dir/dv.$n.err" | soleur_ctx_sanitize | cut -c1-200)"
292
+ if (( dv_rc == 0 )) && [[ "$dv_line" != "delegation: valid reason="* ]]; then dv_rc=2; reason="verifier-error"; why="the delegation checker exited cleanly without saying valid"; fi # mut:deleg-line
293
+ (( dv_rc == 1 )) && { printf '[FAIL] %s:%s: delegation-invalid - %s (reason: %s)\n' "$shown" "$ln" "$why" "$reason" >&2; DR=1; return; }
294
+ (( dv_rc == 0 )) || { printf '[FAIL] %s:%s: delegation-unverifiable - %s (reason: %s); the row was not examined, which is never a pass\n' "$shown" "$ln" "$why" "${reason:-none}" >&2; DR=2; return; } # mut:deleg-unv
295
+ if [[ -n "$dran" ]]; then
296
+ sha="$(sed -n 's/^verified-envelope-sha256: \([0-9a-f]\{64\}\)$/\1/p' "$work_dir/dv.$n.out" | head -1)"
297
+ if [[ -z "$sha" ]]; then
298
+ printf '[FAIL] %s:%s: receipt-unreadable - the delegation checker did not report the runbook fingerprint, so the execution receipt cannot be matched; the row was not examined, which is never a pass\n' "$shown" "$ln" >&2; DR=2; return
299
+ fi
300
+ vcre="$(sed -n 's/^verified-created-at: \([0-9T:Z-]*\)$/\1/p' "$work_dir/dv.$n.out" | head -1)"
301
+ vexp="$(sed -n 's/^verified-expiry: \([0-9-]*\)$/\1/p' "$work_dir/dv.$n.out" | head -1)"
302
+ if [[ ! "$vcre" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$ || ! "$vexp" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
303
+ printf '[FAIL] %s:%s: receipt-unreadable - the delegation checker did not report when the delegation was recorded and when it ends, so the receipt window cannot be checked; the row was not examined, which is never a pass\n' "$shown" "$ln" >&2; DR=2; return
304
+ fi
305
+ receipt_check "$durl" "$repo" "$epic" "$dpath" "$sha" "$vcre" "$vexp" "$dran"
306
+ case "$RC_REASON" in
307
+ ok) ;;
308
+ receipt-missing) printf '[FAIL] %s:%s: receipt-missing - no execution receipt for this delegation is on epic #%s; the CTO writes one comment per delegated act (standing-delegation.md section 8) before this row may say the act ran\n' "$shown" "$ln" "$epic" >&2; DR=2; return ;;
309
+ receipt-mismatch) printf '[FAIL] %s:%s: receipt-mismatch - epic #%s has a receipt for this delegation but none names this envelope path and its verified fingerprint with result ok or rolled-back, written by an owner, member or collaborator\n' "$shown" "$ln" "$epic" >&2; DR=2; return ;;
310
+ *) printf '[FAIL] %s:%s: receipt-unreadable - the comments on epic #%s could not be read, so the execution receipt was not checked, which is never a pass\n' "$shown" "$ln" "$epic" >&2; DR=2; return ;;
311
+ esac
312
+ fi
313
+ echo 'SOLEUR_RULE_APPLIED rule=hr-menu-option-ack-not-prod-write-auth note=delegation-verified'
314
+ }
315
+
316
+ check_artifact() { # <file> <display-path>
317
+ local file="$1" shown="$2" idx=0 fails=0 unv=0 tables=0 ln row inner pipes c2 c3
318
+ [[ -e "$file" ]] || die2 "$shown: no such file"
319
+ [[ -f "$file" && -r "$file" ]] || die2 "$shown: not a readable regular file"
320
+ grep -q '[^[:space:]]' "$file" || die2 "$shown: the artifact is EMPTY; nothing was examined"
321
+ work_dir="$(mktemp -d -t trg.XXXXXXXX)" || die2 "mktemp failed"
322
+ table_rows "$file" > "$work_dir/raw"
323
+ grep -qxF '@UNCLOSED' "$work_dir/raw" && die2 "$shown: a code fence is never closed, so the rest of the file was not examined (close it)"
324
+ grep -qxF '@BADHEADER' "$work_dir/raw" && die2 "$shown: a table header names Item, Class and Ruling but is not exactly '| Item | Class | Ruling |' (fix the header; the rows were not examined)"
325
+ grep -qxF '@STRAY' "$work_dir/raw" && die2 "$shown: a row with Class technical sits outside any '| Item | Class | Ruling |' table (a row after a blank line, or a table without the header); put it in the table or add the header and separator"
326
+ grep -qxF '@EMPTY' "$work_dir/raw" && die2 "$shown: Decision Classes table has 0 rows examined (a header without data rows, or without its separator line)"
327
+ tables="$(grep -cxF '@TABLE' "$work_dir/raw" || true)"
328
+ grep -v '^@' "$work_dir/raw" > "$work_dir/rows" || true
329
+ while IFS=$'\t' read -r ln row; do
330
+ idx=$((idx + 1)) # mut:count
331
+ [[ -n "${TRG_EXEC_LOG:-}" ]] && echo "row $shown:$idx" >> "${TRG_EXEC_LOG:?}"
332
+ inner="${row#|}"; inner="${inner%|}"
333
+ inner="${inner//\\|/$'\001'}"
334
+ pipes="${inner//[^|]/}"
335
+ if [[ ${#pipes} -ne 2 ]]; then
336
+ printf '[FAIL] %s:%s: bad-class - the row must have exactly three cells: Item | Class | Ruling (write a literal pipe as \\|)\n' "$shown" "$ln" >&2
337
+ fails=$((fails + 1)); continue
338
+ fi
339
+ IFS='|' read -r _ c2 c3 _ <<<"$inner"
340
+ c2="${c2#"${c2%%[![:space:]]*}"}"; c2="${c2%"${c2##*[![:space:]]}"}"
341
+ c3="${c3#"${c3%%[![:space:]]*}"}"; c3="${c3%"${c3##*[![:space:]]}"}"
342
+ c2="${c2//$'\001'/|}"; c3="${c3//$'\001'/|}"
343
+ if [[ "$c3" == "Authorized by delegation"* ]]; then check_delegation_row "$ln" "$c2" "$c3"; case "$DR" in 0) ;; 1) fails=$((fails + 1)) ;; *) unv=$((unv + 1)) ;; esac; continue; fi # mut:deleg-all
344
+ if [[ "$c2" == technical ]]; then
345
+ if [[ "$c3" == "pending - assumed"* ]]; then
346
+ : # reported once, with its line, by the file-wide pending lint below
347
+ elif is_unruled "$c3"; then
348
+ printf '[FAIL] %s:%s: unruled-technical - the row is technical with no ruling: %s\n' "$shown" "$ln" "$CTO_REMEDY" >&2
349
+ fails=$((fails + 1))
350
+ elif ! shape_ok "$c3"; then
351
+ printf '[FAIL] %s:%s: bad-ruling-shape - a technical ruling must start: Ruled by CTO agent, <date>: <decision> - <rationale> (anything else, a bare "pending" included, is not a ruling)\n' "$shown" "$ln" >&2
352
+ fails=$((fails + 1))
353
+ fi
354
+ elif [[ "$c2" == taste ]]; then
355
+ : # user-legible Taste: auto-decided with a recommendation, rendered under Model Dissents, no ruling cell
356
+ elif [[ "$c2" =~ ^operator\ \(([a-z-]+)\)$ ]]; then
357
+ if ! cat_ok "${BASH_REMATCH[1]}"; then
358
+ printf '[FAIL] %s:%s: bad-category - category "%s" is not in the closed list (%s)\n' "$shown" "$ln" "${BASH_REMATCH[1]}" "$CATEGORIES" >&2
359
+ fails=$((fails + 1))
360
+ elif [[ -z "$c3" ]]; then
361
+ printf '[FAIL] %s:%s: bad-ruling-shape - an operator row must name the ACTION being authorised in its Ruling cell\n' "$shown" "$ln" >&2
362
+ fails=$((fails + 1))
363
+ fi
364
+ elif [[ "$c2" == operator ]]; then
365
+ printf '[FAIL] %s:%s: bad-category - a bare "operator" is invalid; write operator (<category>) with a category from the closed list (%s)\n' "$shown" "$ln" "$CATEGORIES" >&2
366
+ fails=$((fails + 1))
367
+ else
368
+ printf '[FAIL] %s:%s: bad-class - Class must be "technical", "taste" or "operator (<category>)", got "%s"\n' "$shown" "$ln" "$c2" >&2
369
+ fails=$((fails + 1))
370
+ fi
371
+ done < "$work_dir/rows"
372
+ check_pending "$file" "$shown"; fails=$((fails + $?))
373
+ check_labels "$file" "$shown"; fails=$((fails + $?))
374
+ if (( fails > 0 )); then return 1; fi
375
+ if (( unv > 0 )); then return 2; fi
376
+ if (( tables == 0 )); then
377
+ printf '[WARN] %s: no "| Item | Class | Ruling |" table outside a fenced block; label and pending lints ran, rows were not examined (add the table: technical-ruling-delegation.md section 6)\n' "$shown"
378
+ return 0
379
+ fi
380
+ if (( SHAPE_ROWS > 0 )); then
381
+ printf '[PASS] %s: %s rows examined (archived: %s delegation rows were checked for shape only and were NOT verified)\n' "$shown" "$idx" "$SHAPE_ROWS"
382
+ else
383
+ printf '[PASS] %s: %s rows examined\n' "$shown" "$idx"
384
+ fi
385
+ return 0
386
+ }
387
+
388
+ if [[ -n "${TRG_SPECS_ROOT:-}${TRG_BRANCH:-}${TRG_EXEC_LOG:-}${TRG_VERIFY_TIMEOUT:-}" ]]; then
389
+ printf '[NOTE] test seam active (TRG_SPECS_ROOT=%s TRG_BRANCH=%s): this is not the live repository lookup\n' "${TRG_SPECS_ROOT:-}" "${TRG_BRANCH:-}" >&2
390
+ fi
391
+
392
+ mode="${1:-}"
393
+ case "$mode" in
394
+ --pr-body)
395
+ f="${2:-}"; [[ -n "$f" ]] || die2 "usage: --pr-body <file>"
396
+ [[ -f "$f" && -r "$f" ]] || die2 "$f: not a readable regular file"
397
+ if ! { [[ -s "$f" ]] && grep -q '[^[:space:]]' "$f"; }; then
398
+ die2 "$f: the PR body is EMPTY (the fetch that wrote it most likely failed); nothing was examined"
399
+ fi
400
+ fails=0
401
+ check_pending "$f" "$f"; fails=$((fails + $?))
402
+ check_labels "$f" "$f"; fails=$((fails + $?))
403
+ (( UNCLOSED_SEEN )) && die2 "$f: a code fence in the PR body is never closed, so the rest of it was not examined (close it)"
404
+ if (( fails > 0 )); then exit 1; fi
405
+ printf '[PASS] %s: no unscoped owner-decision label and no pending placeholder\n' "$f"
406
+ exit 0 ;;
407
+ --branch)
408
+ branch="${TRG_BRANCH:-$(git rev-parse --abbrev-ref HEAD 2>/dev/null)}"
409
+ [ -n "$branch" ] && [ "$branch" != HEAD ] || die2 "cannot resolve the branch (detached HEAD or no git)"
410
+ if [[ -n "${TRG_SPECS_ROOT:-}" ]]; then
411
+ root="$TRG_SPECS_ROOT"
412
+ else
413
+ top="$(git rev-parse --show-toplevel 2>/dev/null)" || top=""
414
+ [[ -n "$top" ]] || die2 "not inside a git repository, so the specs directory cannot be located"
415
+ root="$top/knowledge-base/project/specs"
416
+ fi
417
+ safe="${branch//\//-}"; slug="$safe"
418
+ slug="${slug#feature-}"; slug="${slug#feat-}"; slug="${slug#fix-}"
419
+ matches=()
420
+ add_match() { local m; for m in ${matches[@]+"${matches[@]}"}; do [[ "$m" == "$1" ]] && return 0; done; matches+=("$1"); }
421
+ [[ -f "$root/$safe/decision-challenges.md" ]] && add_match "$root/$safe/decision-challenges.md"
422
+ [[ -f "$root/archive/$safe/decision-challenges.md" ]] && add_match "$root/archive/$safe/decision-challenges.md"
423
+ # archive directories are `<date>-<name>`, `<date>-<time>-<name>` or `<date>-<name>`: anchor the whole prefix
424
+ # so a short slug never suffix-matches another feature's longer name.
425
+ for pre in '????-??-??' '????????-??????' '????????'; do
426
+ for nm in "$slug" "$safe"; do
427
+ for cand in "$root"/archive/$pre-"$nm"/decision-challenges.md; do
428
+ [[ -f "$cand" ]] && add_match "$cand"
429
+ done
430
+ done
431
+ done
432
+ if (( ${#matches[@]} == 0 )); then
433
+ printf '[PASS] no decision-challenges artifact for %s\n' "$branch"
434
+ exit 0
435
+ fi
436
+ (( ${#matches[@]} == 1 )) || die2 "ambiguous: ${#matches[@]} decision-challenges.md files match branch $branch (${matches[*]}); examine the right one by path"
437
+ case "${matches[0]}" in */archive/*) SHAPE_ONLY=1; printf '[NOTE] archived artifact: delegation rows are checked for shape only and are NOT verified (no network)\n' >&2 ;; esac
438
+ check_artifact "${matches[0]}" "${matches[0]}"; exit $? ;;
439
+ ""|-h|--help)
440
+ die2 "usage: $(basename "$0") <path> | --branch | --pr-body <file>" ;;
441
+ -*) die2 "unknown option: $mode" ;;
442
+ *)
443
+ check_artifact "$mode" "$mode"; exit $? ;;
444
+ esac