@soleur/opencode 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (812) hide show
  1. package/.claude-plugin/agents.manifest.json +476 -0
  2. package/.claude-plugin/plugin.json +42 -0
  3. package/README.md +44 -2
  4. package/agents/community/.gitkeep +0 -0
  5. package/agents/engineering/cto.md +87 -0
  6. package/agents/engineering/design/ddd-architect.md +95 -0
  7. package/agents/engineering/discovery/agent-finder.md +214 -0
  8. package/agents/engineering/discovery/functional-discovery.md +182 -0
  9. package/agents/engineering/infra/infra-security.md +151 -0
  10. package/agents/engineering/infra/platform-strategist.md +109 -0
  11. package/agents/engineering/infra/terraform-architect.md +171 -0
  12. package/agents/engineering/prompt-engineer.md +37 -0
  13. package/agents/engineering/research/best-practices-researcher.md +115 -0
  14. package/agents/engineering/research/framework-docs-researcher.md +93 -0
  15. package/agents/engineering/research/git-history-analyzer.md +53 -0
  16. package/agents/engineering/research/learnings-researcher.md +285 -0
  17. package/agents/engineering/research/repo-research-analyst.md +118 -0
  18. package/agents/engineering/review/agent-native-reviewer.md +279 -0
  19. package/agents/engineering/review/architecture-strategist.md +61 -0
  20. package/agents/engineering/review/code-quality-analyst.md +92 -0
  21. package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
  22. package/agents/engineering/review/data-integrity-guardian.md +82 -0
  23. package/agents/engineering/review/data-migration-expert.md +98 -0
  24. package/agents/engineering/review/deployment-verification-agent.md +183 -0
  25. package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
  26. package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
  27. package/agents/engineering/review/legacy-code-expert.md +55 -0
  28. package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
  29. package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
  30. package/agents/engineering/review/performance-oracle.md +130 -0
  31. package/agents/engineering/review/security-sentinel.md +167 -0
  32. package/agents/engineering/review/semgrep-sast.md +36 -0
  33. package/agents/engineering/review/test-design-reviewer.md +150 -0
  34. package/agents/engineering/review/user-impact-reviewer.md +70 -0
  35. package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
  36. package/agents/finance/budget-analyst.md +29 -0
  37. package/agents/finance/cfo.md +44 -0
  38. package/agents/finance/financial-reporter.md +30 -0
  39. package/agents/finance/revenue-analyst.md +30 -0
  40. package/agents/legal/clo.md +115 -0
  41. package/agents/legal/legal-compliance-auditor.md +110 -0
  42. package/agents/legal/legal-document-generator.md +134 -0
  43. package/agents/marketing/analytics-analyst.md +25 -0
  44. package/agents/marketing/brand-architect.md +181 -0
  45. package/agents/marketing/cmo.md +76 -0
  46. package/agents/marketing/conversion-optimizer.md +19 -0
  47. package/agents/marketing/copywriter.md +20 -0
  48. package/agents/marketing/fact-checker.md +70 -0
  49. package/agents/marketing/growth-strategist.md +145 -0
  50. package/agents/marketing/paid-media-strategist.md +28 -0
  51. package/agents/marketing/pricing-strategist.md +17 -0
  52. package/agents/marketing/programmatic-seo-specialist.md +25 -0
  53. package/agents/marketing/retention-strategist.md +23 -0
  54. package/agents/marketing/seo-aeo-analyst.md +164 -0
  55. package/agents/operations/coo.md +50 -0
  56. package/agents/operations/ops-advisor.md +78 -0
  57. package/agents/operations/ops-provisioner.md +101 -0
  58. package/agents/operations/ops-research.md +52 -0
  59. package/agents/operations/service-automator.md +278 -0
  60. package/agents/product/business-validator.md +206 -0
  61. package/agents/product/competitive-intelligence.md +89 -0
  62. package/agents/product/cpo.md +63 -0
  63. package/agents/product/design/ux-design-lead.md +209 -0
  64. package/agents/product/spec-flow-analyzer.md +122 -0
  65. package/agents/sales/cro.md +44 -0
  66. package/agents/sales/deal-architect.md +29 -0
  67. package/agents/sales/outbound-strategist.md +29 -0
  68. package/agents/sales/pipeline-analyst.md +29 -0
  69. package/agents/support/cco.md +48 -0
  70. package/agents/support/community-manager.md +570 -0
  71. package/agents/support/ticket-triage.md +70 -0
  72. package/bin/soleur-opencode.js +29 -0
  73. package/commands/go.md +659 -0
  74. package/commands/help.md +273 -0
  75. package/commands/sync.md +977 -0
  76. package/commands/version.md +103 -0
  77. package/hooks/antigravity-hooks.json +84 -0
  78. package/hooks/antigravity-session-start.sh +15 -0
  79. package/hooks/bare-root-cwd-guard.sh +131 -0
  80. package/hooks/browser-snapshot-credential-guard.sh +200 -0
  81. package/hooks/codex-session-start.sh +9 -0
  82. package/hooks/compaction-state.sh +525 -0
  83. package/hooks/destructive-command-guard.sh +1387 -0
  84. package/hooks/devin-session-start.sh +90 -0
  85. package/hooks/ext-filter-detect.sh +171 -0
  86. package/hooks/hooks.json +133 -0
  87. package/hooks/lib/hook-tool-kind.sh +24 -0
  88. package/hooks/lib/log-rotation.sh +176 -0
  89. package/hooks/lib/shell-argv.pl +576 -0
  90. package/hooks/memory-backstop.sh +1114 -0
  91. package/hooks/operator-stage-approval.sh +391 -0
  92. package/hooks/stop-hook.sh +367 -0
  93. package/hooks/unkept-promise-hook.sh +383 -0
  94. package/hooks/version-banner.sh +127 -0
  95. package/hooks/welcome-hook.sh +50 -0
  96. package/install.js +108 -0
  97. package/lib/agent-registry.ts +154 -0
  98. package/lib/c4-canonical-cli.mjs +34 -0
  99. package/lib/c4-canonical.mjs +46 -0
  100. package/lib/c4-from-components.ts +554 -0
  101. package/lib/go-routing.ts +81 -0
  102. package/lib/grok-inspect-contract.ts +311 -0
  103. package/lib/harness-model-map.ts +101 -0
  104. package/lib/harness-parity.ts +726 -0
  105. package/lib/harness-tool-map.ts +180 -0
  106. package/lib/harness.ts +716 -0
  107. package/lib/heartbeat-live-reconcile.ts +1153 -0
  108. package/lib/heartbeat-manifest.ts +342 -0
  109. package/lib/kb-coverage.ts +252 -0
  110. package/lib/pr-merge-poll.ts +103 -0
  111. package/lib/workflow-fidelity.ts +388 -0
  112. package/opencode/INSTRUCTIONS.md +152 -0
  113. package/opencode/agents/engineering/cto.md +10 -0
  114. package/opencode/agents/engineering/design/ddd-architect.md +10 -0
  115. package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
  116. package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
  117. package/opencode/agents/engineering/infra/infra-security.md +10 -0
  118. package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
  119. package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
  120. package/opencode/agents/engineering/prompt-engineer.md +10 -0
  121. package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
  122. package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
  123. package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
  124. package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
  125. package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
  126. package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
  127. package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
  128. package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
  129. package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
  130. package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
  131. package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
  132. package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
  133. package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
  134. package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
  135. package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
  136. package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
  137. package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
  138. package/opencode/agents/engineering/review/performance-oracle.md +10 -0
  139. package/opencode/agents/engineering/review/security-sentinel.md +10 -0
  140. package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
  141. package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
  142. package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
  143. package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
  144. package/opencode/agents/finance/budget-analyst.md +10 -0
  145. package/opencode/agents/finance/cfo.md +10 -0
  146. package/opencode/agents/finance/financial-reporter.md +10 -0
  147. package/opencode/agents/finance/revenue-analyst.md +10 -0
  148. package/opencode/agents/legal/clo.md +10 -0
  149. package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
  150. package/opencode/agents/legal/legal-document-generator.md +10 -0
  151. package/opencode/agents/marketing/analytics-analyst.md +10 -0
  152. package/opencode/agents/marketing/brand-architect.md +10 -0
  153. package/opencode/agents/marketing/cmo.md +10 -0
  154. package/opencode/agents/marketing/conversion-optimizer.md +10 -0
  155. package/opencode/agents/marketing/copywriter.md +10 -0
  156. package/opencode/agents/marketing/fact-checker.md +10 -0
  157. package/opencode/agents/marketing/growth-strategist.md +10 -0
  158. package/opencode/agents/marketing/paid-media-strategist.md +10 -0
  159. package/opencode/agents/marketing/pricing-strategist.md +10 -0
  160. package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
  161. package/opencode/agents/marketing/retention-strategist.md +10 -0
  162. package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
  163. package/opencode/agents/operations/coo.md +10 -0
  164. package/opencode/agents/operations/ops-advisor.md +10 -0
  165. package/opencode/agents/operations/ops-provisioner.md +10 -0
  166. package/opencode/agents/operations/ops-research.md +10 -0
  167. package/opencode/agents/operations/service-automator.md +10 -0
  168. package/opencode/agents/product/business-validator.md +10 -0
  169. package/opencode/agents/product/competitive-intelligence.md +10 -0
  170. package/opencode/agents/product/cpo.md +10 -0
  171. package/opencode/agents/product/design/ux-design-lead.md +10 -0
  172. package/opencode/agents/product/spec-flow-analyzer.md +10 -0
  173. package/opencode/agents/sales/cro.md +10 -0
  174. package/opencode/agents/sales/deal-architect.md +10 -0
  175. package/opencode/agents/sales/outbound-strategist.md +10 -0
  176. package/opencode/agents/sales/pipeline-analyst.md +10 -0
  177. package/opencode/agents/support/cco.md +10 -0
  178. package/opencode/agents/support/community-manager.md +10 -0
  179. package/opencode/agents/support/ticket-triage.md +10 -0
  180. package/opencode/commands/go.md +10 -0
  181. package/opencode/commands/help.md +10 -0
  182. package/opencode/commands/sync.md +10 -0
  183. package/opencode/commands/version.md +11 -0
  184. package/opencode/opencode.json +8 -0
  185. package/opencode/plugin.ts +493 -0
  186. package/package.json +36 -4
  187. package/scripts/admin-merge-ready.sh +545 -0
  188. package/scripts/admin-merge-ready.test.sh +753 -0
  189. package/scripts/affected-tests.sh +908 -0
  190. package/scripts/affected-tests.test.sh +1797 -0
  191. package/scripts/alpha-metrics.sh +78 -0
  192. package/scripts/alpha-metrics.test.sh +115 -0
  193. package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
  194. package/scripts/audit-flag-flip.sh +107 -0
  195. package/scripts/check-red-on-main.sh +316 -0
  196. package/scripts/ci-head-verdict.sh +363 -0
  197. package/scripts/cloud-detect.sh +193 -0
  198. package/scripts/delegation-verify.sh +657 -0
  199. package/scripts/delegation-verify.test.sh +1424 -0
  200. package/scripts/deploy-arm.sh +475 -0
  201. package/scripts/domain-model-drift.sh +419 -0
  202. package/scripts/emit-decision.sh +144 -0
  203. package/scripts/emit-decision.test.sh +144 -0
  204. package/scripts/ext-filter-divergence-corpus.txt +15 -0
  205. package/scripts/ext-filter-divergence.sh +189 -0
  206. package/scripts/generate-c4-from-components.ts +442 -0
  207. package/scripts/grok-fidelity-gate.sh +68 -0
  208. package/scripts/grok-pre-push-gate.sh +232 -0
  209. package/scripts/harness-discovery-smoke.ts +906 -0
  210. package/scripts/harness-parity-census.ts +92 -0
  211. package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
  212. package/scripts/install-opencode-adapter.ts +520 -0
  213. package/scripts/lib/affected-tests/common.sh +365 -0
  214. package/scripts/lib/affected-tests/go.sh +157 -0
  215. package/scripts/lib/affected-tests/js.sh +188 -0
  216. package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
  217. package/scripts/lib/affected-tests/python.sh +185 -0
  218. package/scripts/lib/context-sanitize.sh +49 -0
  219. package/scripts/lib/domain-model-lib.sh +180 -0
  220. package/scripts/lib/ext-filter-grammar.tsv +34 -0
  221. package/scripts/lib/operator-script.sh +1236 -0
  222. package/scripts/lib/proc.sh +580 -0
  223. package/scripts/lib/session-state.sh +748 -0
  224. package/scripts/lib/tmp-classify.sh +843 -0
  225. package/scripts/lib/wrapper-boundary.sh +47 -0
  226. package/scripts/lint-ratchet.py +1547 -0
  227. package/scripts/monitor-pr-checks.sh +441 -0
  228. package/scripts/pipeline-tally.sh +756 -0
  229. package/scripts/pipeline-tally.test.sh +740 -0
  230. package/scripts/plugin-version.sh +528 -0
  231. package/scripts/precommit-guard.sh +113 -0
  232. package/scripts/precommit-guard.test.sh +254 -0
  233. package/scripts/reconcile-live-heartbeats.ts +705 -0
  234. package/scripts/render-c4-model.sh +217 -0
  235. package/scripts/resolve-git-root.sh +55 -0
  236. package/scripts/resolve-regenerable-conflicts.sh +363 -0
  237. package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
  238. package/scripts/ruff-requirements.txt +22 -0
  239. package/scripts/run-in-pid-namespace.sh +98 -0
  240. package/scripts/run-in-pid-namespace.test.sh +290 -0
  241. package/scripts/scan-ancestor-signal-helpers.py +556 -0
  242. package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
  243. package/scripts/setup-ralph-loop.sh +238 -0
  244. package/scripts/sync-cursor-name-map.ts +316 -0
  245. package/scripts/sync-grok-agent-compat.ts +188 -0
  246. package/scripts/sync-npm-package.ts +178 -0
  247. package/scripts/sync-opencode-adapter.ts +479 -0
  248. package/scripts/sync-pr-behind.sh +534 -0
  249. package/scripts/sync-pr-behind.test.sh +252 -0
  250. package/scripts/taste-profile-update.sh +180 -0
  251. package/scripts/taste-profile-update.test.sh +167 -0
  252. package/scripts/write-budget-marker.sh +23 -0
  253. package/scripts/write-kb-coverage.ts +113 -0
  254. package/skills/admin-ip-refresh/SKILL.md +81 -0
  255. package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
  256. package/skills/agent-browser/SKILL.md +698 -0
  257. package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
  258. package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
  259. package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
  260. package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
  261. package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
  262. package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
  263. package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
  264. package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
  265. package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
  266. package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
  267. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
  268. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
  269. package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
  270. package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
  271. package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
  272. package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
  273. package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
  274. package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
  275. package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
  276. package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
  277. package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
  278. package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
  279. package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
  280. package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
  281. package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
  282. package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
  283. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
  284. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
  285. package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
  286. package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
  287. package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
  288. package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
  289. package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
  290. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
  291. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
  292. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
  293. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
  294. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
  295. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
  296. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
  297. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
  298. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
  299. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
  300. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
  301. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
  302. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
  303. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
  304. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
  305. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
  306. package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
  307. package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
  308. package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
  309. package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
  310. package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
  311. package/skills/agent-native-architecture/SKILL.md +479 -0
  312. package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
  313. package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
  314. package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
  315. package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
  316. package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
  317. package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
  318. package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
  319. package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
  320. package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
  321. package/skills/agent-native-architecture/references/product-implications.md +478 -0
  322. package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
  323. package/skills/agent-native-architecture/references/self-modification.md +294 -0
  324. package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
  325. package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
  326. package/skills/agent-native-audit/SKILL.md +300 -0
  327. package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
  328. package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
  329. package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  330. package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  331. package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  332. package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
  333. package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  334. package/skills/architecture/SKILL.md +436 -0
  335. package/skills/architecture/references/adr-template.md +154 -0
  336. package/skills/architecture/references/likec4-reference.md +136 -0
  337. package/skills/architecture/references/nfr-reference.md +126 -0
  338. package/skills/archive-kb/SKILL.md +86 -0
  339. package/skills/archive-kb/scripts/archive-kb.sh +300 -0
  340. package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
  341. package/skills/atdd-developer/SKILL.md +65 -0
  342. package/skills/brainstorm/SKILL.md +701 -0
  343. package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
  344. package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
  345. package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
  346. package/skills/brainstorm/references/ui-surface-terms.md +42 -0
  347. package/skills/brainstorm-techniques/SKILL.md +231 -0
  348. package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
  349. package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
  350. package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
  351. package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
  352. package/skills/campaign-calendar/SKILL.md +145 -0
  353. package/skills/cf-token-scope/SKILL.md +164 -0
  354. package/skills/cf-token-scope/references/widen-playbook.md +114 -0
  355. package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
  356. package/skills/changelog/SKILL.md +142 -0
  357. package/skills/code-to-prd/SKILL.md +66 -0
  358. package/skills/code-to-prd/references/banner-template.md +12 -0
  359. package/skills/code-to-prd/references/prd-template.md +41 -0
  360. package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
  361. package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
  362. package/skills/code-to-prd/test/fixture/.env.example +7 -0
  363. package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
  364. package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
  365. package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
  366. package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
  367. package/skills/code-to-prd/test/fixture/package.json +6 -0
  368. package/skills/cohort-status/SKILL.md +62 -0
  369. package/skills/community/SKILL.md +210 -0
  370. package/skills/community/scripts/bsky-community.sh +644 -0
  371. package/skills/community/scripts/bsky-setup.sh +631 -0
  372. package/skills/community/scripts/community-router.sh +93 -0
  373. package/skills/community/scripts/discord-community.sh +487 -0
  374. package/skills/community/scripts/discord-setup.sh +784 -0
  375. package/skills/community/scripts/github-community.sh +706 -0
  376. package/skills/community/scripts/hn-community.sh +233 -0
  377. package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
  378. package/skills/community/scripts/linkedin-community.sh +750 -0
  379. package/skills/community/scripts/linkedin-setup.sh +758 -0
  380. package/skills/community/scripts/x-community.sh +890 -0
  381. package/skills/community/scripts/x-setup.sh +713 -0
  382. package/skills/community/test/community-argv.test.sh +2922 -0
  383. package/skills/community/test/github-community.test.sh +981 -0
  384. package/skills/competitive-analysis/SKILL.md +69 -0
  385. package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
  386. package/skills/compound/SKILL.md +673 -0
  387. package/skills/compound/scripts/token-efficiency-report.sh +334 -0
  388. package/skills/compound/test/phase-16.test.sh +379 -0
  389. package/skills/compound-capture/SKILL.md +791 -0
  390. package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
  391. package/skills/compound-capture/assets/resolution-template.md +116 -0
  392. package/skills/compound-capture/references/yaml-schema.md +67 -0
  393. package/skills/compound-capture/schema.yaml +181 -0
  394. package/skills/constraint-scaffold/SKILL.md +175 -0
  395. package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
  396. package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
  397. package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
  398. package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
  399. package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
  400. package/skills/constraint-scaffold/references/shared-runner.template +135 -0
  401. package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
  402. package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
  403. package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
  404. package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
  405. package/skills/constraint-scaffold/test/generator.test.sh +93 -0
  406. package/skills/constraint-scaffold/test/parity.test.sh +285 -0
  407. package/skills/content-writer/SKILL.md +242 -0
  408. package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
  409. package/skills/cron-delete/SKILL.md +56 -0
  410. package/skills/cron-list/SKILL.md +54 -0
  411. package/skills/deepen-plan/SKILL.md +937 -0
  412. package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
  413. package/skills/deploy/SKILL.md +115 -0
  414. package/skills/deploy/references/hetzner-setup.md +65 -0
  415. package/skills/deploy/scripts/deploy.sh +37 -0
  416. package/skills/deploy-docs/SKILL.md +95 -0
  417. package/skills/dhh-rails-style/SKILL.md +203 -0
  418. package/skills/dhh-rails-style/references/architecture.md +717 -0
  419. package/skills/dhh-rails-style/references/controllers.md +323 -0
  420. package/skills/dhh-rails-style/references/frontend.md +556 -0
  421. package/skills/dhh-rails-style/references/gems.md +316 -0
  422. package/skills/dhh-rails-style/references/models.md +388 -0
  423. package/skills/dhh-rails-style/references/testing.md +354 -0
  424. package/skills/discord-content/SKILL.md +126 -0
  425. package/skills/docs-site/SKILL.md +214 -0
  426. package/skills/drain-labeled-backlog/SKILL.md +203 -0
  427. package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
  428. package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
  429. package/skills/drain-prs/SKILL.md +142 -0
  430. package/skills/drain-prs/scripts/triage-prs.sh +192 -0
  431. package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
  432. package/skills/dspy-ruby/SKILL.md +634 -0
  433. package/skills/dspy-ruby/assets/config-template.rb +359 -0
  434. package/skills/dspy-ruby/assets/module-template.rb +326 -0
  435. package/skills/dspy-ruby/assets/signature-template.rb +143 -0
  436. package/skills/dspy-ruby/references/core-concepts.md +268 -0
  437. package/skills/dspy-ruby/references/optimization.md +623 -0
  438. package/skills/dspy-ruby/references/providers.md +335 -0
  439. package/skills/eval-harness/README.md +194 -0
  440. package/skills/eval-harness/SKILL.md +157 -0
  441. package/skills/eval-harness/enums/go-routes.json +13 -0
  442. package/skills/eval-harness/enums/incident-threshold.json +5 -0
  443. package/skills/eval-harness/enums/lane.json +5 -0
  444. package/skills/eval-harness/enums/tool-selection.json +20 -0
  445. package/skills/eval-harness/enums/triage-levels.json +5 -0
  446. package/skills/eval-harness/gated-skills.json +34 -0
  447. package/skills/eval-harness/models.generated.json +5 -0
  448. package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
  449. package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
  450. package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
  451. package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
  452. package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
  453. package/skills/eval-harness/prompts/go-baseline.txt +6 -0
  454. package/skills/eval-harness/prompts/go-skill.txt +21 -0
  455. package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
  456. package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
  457. package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
  458. package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
  459. package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
  460. package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
  461. package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
  462. package/skills/eval-harness/prompts/triage-skill.txt +10 -0
  463. package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
  464. package/skills/eval-harness/scripts/extract-block.cjs +87 -0
  465. package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
  466. package/skills/eval-harness/scripts/gen-models.sh +41 -0
  467. package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
  468. package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
  469. package/skills/eval-harness/scripts/parse-label.cjs +93 -0
  470. package/skills/eval-harness/scripts/verdict.cjs +132 -0
  471. package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
  472. package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
  473. package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
  474. package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
  475. package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
  476. package/skills/eval-harness/test/eval-gate.test.sh +132 -0
  477. package/skills/eval-harness/test/extract-block.test.sh +87 -0
  478. package/skills/eval-harness/test/gate-classification.test.sh +77 -0
  479. package/skills/eval-harness/test/gen-models.test.sh +75 -0
  480. package/skills/eval-harness/test/measure-classification.test.sh +74 -0
  481. package/skills/eval-harness/test/parse-label.test.sh +129 -0
  482. package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
  483. package/skills/eval-harness/test/verdict.test.sh +123 -0
  484. package/skills/every-style-editor/SKILL.md +142 -0
  485. package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  486. package/skills/feature-tweet/SKILL.md +199 -0
  487. package/skills/feature-video/SKILL.md +412 -0
  488. package/skills/feature-video/scripts/check_deps.sh +281 -0
  489. package/skills/file-todos/SKILL.md +267 -0
  490. package/skills/file-todos/assets/todo-template.md +166 -0
  491. package/skills/fix-issue/SKILL.md +278 -0
  492. package/skills/fix-issue/references/agent-authored-exclusion.md +118 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -0
  494. package/skills/flag-bootstrap/SETUP.md +142 -0
  495. package/skills/flag-create/SKILL.md +145 -0
  496. package/skills/flag-create/scripts/create.sh +273 -0
  497. package/skills/flag-delete/SKILL.md +167 -0
  498. package/skills/flag-delete/scripts/delete.sh +288 -0
  499. package/skills/flag-list/SKILL.md +99 -0
  500. package/skills/flag-list/scripts/list.sh +275 -0
  501. package/skills/flag-set-role/SKILL.md +229 -0
  502. package/skills/flag-set-role/scripts/flip.sh +774 -0
  503. package/skills/frontend-anti-slop/SKILL.md +106 -0
  504. package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
  505. package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
  506. package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
  507. package/skills/frontend-design/SKILL.md +77 -0
  508. package/skills/gdpr-gate/NOTICE +136 -0
  509. package/skills/gdpr-gate/SKILL.md +341 -0
  510. package/skills/gdpr-gate/references/fields.md +160 -0
  511. package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
  512. package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
  513. package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
  514. package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
  515. package/skills/gdpr-gate/references/layers/frontend.md +249 -0
  516. package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
  517. package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
  518. package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
  519. package/skills/gdpr-gate/references/legal-consent.md +140 -0
  520. package/skills/gdpr-gate/references/non-negotiables.md +60 -0
  521. package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
  522. package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
  523. package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
  524. package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
  525. package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
  526. package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
  527. package/skills/gemini-imagegen/SKILL.md +283 -0
  528. package/skills/gemini-imagegen/requirements.txt +5 -0
  529. package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
  530. package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
  531. package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
  532. package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
  533. package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  534. package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
  535. package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
  536. package/skills/git-worktree/SKILL.md +534 -0
  537. package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
  538. package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
  539. package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
  540. package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
  541. package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
  542. package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
  543. package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
  544. package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
  545. package/skills/go/SKILL.md +54 -0
  546. package/skills/growth/SKILL.md +164 -0
  547. package/skills/harvest-debt/SKILL.md +78 -0
  548. package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
  549. package/skills/heal-skill/SKILL.md +173 -0
  550. package/skills/help/SKILL.md +46 -0
  551. package/skills/incident/NOTICE +39 -0
  552. package/skills/incident/SKILL.md +395 -0
  553. package/skills/incident/scripts/dry-run.sh +448 -0
  554. package/skills/incident/scripts/redact-engine.py +412 -0
  555. package/skills/incident/scripts/redact-sentinel.sh +44 -0
  556. package/skills/incident/templates/pir.md +139 -0
  557. package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
  558. package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
  559. package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
  560. package/skills/incident/test/fixtures/positive-corpus.md +87 -0
  561. package/skills/incident/test/redact-sentinel.test.sh +1420 -0
  562. package/skills/invoice/SKILL.md +206 -0
  563. package/skills/kb-glossary/SKILL.md +71 -0
  564. package/skills/kb-glossary/references/glossary-format.md +111 -0
  565. package/skills/kb-glossary/references/rejected-request-register.md +115 -0
  566. package/skills/kb-search/SKILL.md +276 -0
  567. package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
  568. package/skills/legal-audit/SKILL.md +161 -0
  569. package/skills/legal-generate/NOTICE +242 -0
  570. package/skills/legal-generate/SKILL.md +244 -0
  571. package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
  572. package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
  573. package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
  574. package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
  575. package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
  576. package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
  577. package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
  578. package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
  579. package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
  580. package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
  581. package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
  582. package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
  583. package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
  584. package/skills/linear-fetch/SKILL.md +247 -0
  585. package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
  586. package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
  587. package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
  588. package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
  589. package/skills/linear-fetch/test/parity.test.sh +112 -0
  590. package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
  591. package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
  592. package/skills/merge-pr/SKILL.md +668 -0
  593. package/skills/model-launch-review/SKILL.md +255 -0
  594. package/skills/model-launch-review/scripts/audit-models.sh +501 -0
  595. package/skills/one-shot/SKILL.md +316 -0
  596. package/skills/one-shot/references/token-discipline.md +74 -0
  597. package/skills/operator-bootstrap/SKILL.md +412 -0
  598. package/skills/operator-bootstrap/template.sh +439 -0
  599. package/skills/operator-digest/SKILL.md +287 -0
  600. package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
  601. package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
  602. package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
  603. package/skills/operator-rephrase/SKILL.md +98 -0
  604. package/skills/pencil-setup/SKILL.md +201 -0
  605. package/skills/pencil-setup/scripts/check_deps.sh +556 -0
  606. package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
  607. package/skills/pencil-setup/scripts/package-lock.json +1172 -0
  608. package/skills/pencil-setup/scripts/package.json +14 -0
  609. package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
  610. package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
  611. package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
  612. package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
  613. package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
  614. package/skills/plan/SKILL.md +1140 -0
  615. package/skills/plan/references/differential-migration-testing.md +185 -0
  616. package/skills/plan/references/plan-community-discovery.md +42 -0
  617. package/skills/plan/references/plan-founder-check.md +137 -0
  618. package/skills/plan/references/plan-functional-overlap.md +25 -0
  619. package/skills/plan/references/plan-host-fanout.md +51 -0
  620. package/skills/plan/references/plan-issue-templates.md +779 -0
  621. package/skills/plan/references/plan-network-outage-checklist.md +131 -0
  622. package/skills/plan/references/plan-scope-check.md +126 -0
  623. package/skills/plan/references/plan-sharp-edges.md +325 -0
  624. package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
  625. package/skills/plan/references/webapp-cwv-observability.md +143 -0
  626. package/skills/plan-review/SKILL.md +91 -0
  627. package/skills/plan-review/lib/named-panel.mjs +58 -0
  628. package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
  629. package/skills/postmerge/SKILL.md +642 -0
  630. package/skills/postmerge/references/deploy-status-debugging.md +138 -0
  631. package/skills/postmerge/references/graceful-degradation.md +20 -0
  632. package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
  633. package/skills/preflight/SKILL.md +1553 -0
  634. package/skills/preflight/references/check-13-founder-check.md +286 -0
  635. package/skills/preflight/scripts/founder-check.py +1640 -0
  636. package/skills/preflight/scripts/parse-form-a.awk +107 -0
  637. package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
  638. package/skills/product-roadmap/SKILL.md +357 -0
  639. package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
  640. package/skills/provision-cloudflare/SKILL.md +67 -0
  641. package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
  642. package/skills/provision-doppler/SKILL.md +58 -0
  643. package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
  644. package/skills/provision-github/SKILL.md +59 -0
  645. package/skills/provision-github/scripts/provision-github.sh +300 -0
  646. package/skills/provision-hetzner/SKILL.md +76 -0
  647. package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
  648. package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
  649. package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
  650. package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
  651. package/skills/qa/SKILL.md +263 -0
  652. package/skills/qa/references/browser-preflight.md +22 -0
  653. package/skills/questionnaire-generate/SKILL.md +328 -0
  654. package/skills/questionnaire-generate/references/questionnaire.template +60 -0
  655. package/skills/rclone/SKILL.md +162 -0
  656. package/skills/rclone/scripts/check_setup.sh +63 -0
  657. package/skills/release-announce/SKILL.md +65 -0
  658. package/skills/release-docs/SKILL.md +92 -0
  659. package/skills/reproduce-bug/SKILL.md +358 -0
  660. package/skills/resolve-debt/SKILL.md +85 -0
  661. package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
  662. package/skills/resolve-parallel/SKILL.md +45 -0
  663. package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
  664. package/skills/resolve-pr-parallel/SKILL.md +68 -0
  665. package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
  666. package/skills/resolve-todo-parallel/SKILL.md +57 -0
  667. package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
  668. package/skills/review/SKILL.md +1621 -0
  669. package/skills/review/references/anti-slop-scanner-hook.md +40 -0
  670. package/skills/review/references/defect-classes-migrations.md +9 -0
  671. package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
  672. package/skills/review/references/review-e2e-testing.md +116 -0
  673. package/skills/review/references/review-todo-structure.md +165 -0
  674. package/skills/review/references/risk-tier-and-fix-rounds.md +95 -0
  675. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  676. package/skills/review/references/ultrathink-phases.md +98 -0
  677. package/skills/review/references/wfs.md +6 -0
  678. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  679. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  680. package/skills/review/scripts/fix-round-seats.sh +197 -0
  681. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  682. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  683. package/skills/review/test/fix-round-seats.test.sh +237 -0
  684. package/skills/review/workflows/README.md +147 -0
  685. package/skills/review/workflows/review.workflow.js +667 -0
  686. package/skills/schedule/SKILL.md +796 -0
  687. package/skills/seo-aeo/SKILL.md +139 -0
  688. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  689. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  690. package/skills/ship/SKILL.md +3022 -0
  691. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  692. package/skills/ship/references/affected-gate-contract.md +115 -0
  693. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  694. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  695. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  696. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  697. package/skills/ship/references/decision-challenges-render.md +71 -0
  698. package/skills/ship/references/detached-battery-verdict.md +13 -0
  699. package/skills/ship/references/feature-tweet-draft.md +42 -0
  700. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  701. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  702. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  703. package/skills/ship/references/operator-holds.md +149 -0
  704. package/skills/ship/references/pipeline-tally-render.md +43 -0
  705. package/skills/ship/references/pr-overlap.md +153 -0
  706. package/skills/ship/references/queue-mode.md +7 -0
  707. package/skills/ship/references/ready-run-wait.md +36 -0
  708. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  709. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  710. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  711. package/skills/ship/references/supabase-column-probe.md +13 -0
  712. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  713. package/skills/ship/scripts/battery-owed.sh +403 -0
  714. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  715. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  716. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  717. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  718. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  719. package/skills/skill-creator/SKILL.md +299 -0
  720. package/skills/skill-creator/references/api-security.md +248 -0
  721. package/skills/skill-creator/references/authoring-levers.md +110 -0
  722. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  723. package/skills/skill-creator/references/best-practices.md +431 -0
  724. package/skills/skill-creator/references/common-patterns.md +639 -0
  725. package/skills/skill-creator/references/core-principles.md +193 -0
  726. package/skills/skill-creator/references/executable-code.md +188 -0
  727. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  728. package/skills/skill-creator/references/official-spec.md +193 -0
  729. package/skills/skill-creator/references/recommended-structure.md +180 -0
  730. package/skills/skill-creator/references/skill-structure.md +396 -0
  731. package/skills/skill-creator/references/using-scripts.md +122 -0
  732. package/skills/skill-creator/references/using-templates.md +120 -0
  733. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  734. package/skills/skill-creator/scripts/init_skill.py +322 -0
  735. package/skills/skill-creator/scripts/package_skill.py +110 -0
  736. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  737. package/skills/skill-creator/templates/router-skill.md +73 -0
  738. package/skills/skill-creator/templates/simple-skill.md +34 -0
  739. package/skills/skill-creator/workflows/add-reference.md +96 -0
  740. package/skills/skill-creator/workflows/add-script.md +104 -0
  741. package/skills/skill-creator/workflows/add-template.md +83 -0
  742. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  743. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  744. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  745. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  746. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  747. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  748. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  749. package/skills/skill-security-scan/SKILL.md +145 -0
  750. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  751. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  752. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  753. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  754. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  755. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  756. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  757. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  758. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  759. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  760. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  761. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  762. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  763. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  764. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  765. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  766. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  767. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  768. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  769. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  770. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  771. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  772. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  773. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  774. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  775. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  776. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  777. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  778. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  779. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  780. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  781. package/skills/social-distribute/SKILL.md +485 -0
  782. package/skills/spec-templates/SKILL.md +274 -0
  783. package/skills/sync/SKILL.md +49 -0
  784. package/skills/test-browser/SKILL.md +464 -0
  785. package/skills/test-browser/references/feature-map.md +161 -0
  786. package/skills/test-fix-loop/SKILL.md +159 -0
  787. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  788. package/skills/triage/SKILL.md +402 -0
  789. package/skills/trigger-cron/SKILL.md +136 -0
  790. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  791. package/skills/user-set-role/SKILL.md +147 -0
  792. package/skills/user-set-role/scripts/set-role.sh +218 -0
  793. package/skills/user-story-writer/SKILL.md +77 -0
  794. package/skills/ux-audit/SKILL.md +251 -0
  795. package/skills/ux-audit/references/finding.schema.json +62 -0
  796. package/skills/ux-audit/references/route-list.yaml +95 -0
  797. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  798. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  799. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  800. package/skills/work/SKILL.md +1479 -0
  801. package/skills/work/references/end-of-work-resume.md +7 -0
  802. package/skills/work/references/hook-test-main-cwd.md +24 -0
  803. package/skills/work/references/key-principles.md +83 -0
  804. package/skills/work/references/property-testing.md +122 -0
  805. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  806. package/skills/work/references/work-agent-teams.md +97 -0
  807. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  808. package/skills/work/references/work-lockfile-bumps.md +97 -0
  809. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  810. package/skills/work/references/work-subagent-fanout.md +61 -0
  811. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  812. package/skills/xcode-test/SKILL.md +360 -0
@@ -0,0 +1,534 @@
1
+ #!/usr/bin/env bash
2
+ # BEHIND resync — merge origin/main into the current PR branch and push.
3
+ #
4
+ # THE ONE IMPLEMENTATION of the Phase 7 BEHIND auto-sync (#8383). Three callers:
5
+ # 1. ship/SKILL.md Phase 7 poll fence — runs `sync-pr-behind.sh <n> --step`
6
+ # 2. merge-pr/SKILL.md §5.2 mirror fence — runs `sync-pr-behind.sh <n> --step`
7
+ # 3. standalone (Grok AwaitShell, review/SKILL.md's CONFLICTING-but-clean
8
+ # recovery) — runs `sync-pr-behind.sh <n> [--max-attempts N]`
9
+ # A fix to the merge/push path is made in sync_step() below and reaches all three.
10
+ # The fences keep their own `BEHIND detected` / `auto-sync N pushed` lines and their
11
+ # counters; this script owns the attempt and reports it.
12
+ #
13
+ # What one attempt does (sync_step), and why:
14
+ # 1. Refuses to touch an operation it did not start: MERGE_HEAD, or a rebase /
15
+ # cherry-pick / revert in progress -> kind=merge_in_progress (an unconditional
16
+ # `--abort` there discards the operator's staged resolution — measured, #8339).
17
+ # Detached HEAD -> kind=detached_head (git push would have no branch to update).
18
+ # 2. Fetches main with an explicit refspec (a worktree whose remote.origin.fetch does
19
+ # not map main would otherwise merge a STALE origin/main). Failure is exit 5: the
20
+ # poll skips and counts the attempt, and the next tick retries.
21
+ # 3. Merges origin/main with --no-edit, reading git's OWN exit status — captured
22
+ # before any display `tail`, since `cmd | tail` returns tail's 0 (#8339). rc 1
23
+ # with MERGE_HEAD is a conflict (or a rejecting pre-merge-commit hook) this
24
+ # attempt started: abort, exit 6. Any other rc with MERGE_HEAD arrived during the
25
+ # fetch window — left alone, exit 9. Non-zero without MERGE_HEAD is a refusal
26
+ # (dirty tree, untracked overwrite): nothing to abort, exit 10. A merge that
27
+ # moved nothing is exit 11 (GitHub's mergeStateStatus lags) — no push.
28
+ # 4. Pushes the merge commit so GitHub re-evaluates the queued auto-merge. A failure
29
+ # is exit 7 and retains the local merge commit.
30
+ # Before 1. Merge queue (#9454): a PR that is IN the merge queue is skipped before any
31
+ # git work — nothing merged or pushed: `--step` prints `kind=queued rc=11` and exits 11
32
+ # (the fences' uncounted sync_noop arm), the standalone loop `kind=queued rc=0`, exit 0. A push to a
33
+ # queued PR dequeues it, and the queue itself keeps the entry current. The read is
34
+ # queue_state_read() below, retried once on a transient failure, and is also the one
35
+ # shared read: `sync-pr-behind.sh <pr> --queue-state` prints it (the pre-merge hook and
36
+ # monitor-pr-checks.sh call that). It lives in THIS file, not a sibling, because the Phase 7
37
+ # fences run a frozen snapshot of this script that has no sibling files. A read that still
38
+ # fails is `kind=gh` (exit 4), NEVER "not queued" — that would push to a queued PR.
39
+ # Dequeue: a read that finds the PR OPEN, out of the queue, and either seen queued before (a
40
+ # marker in the per-worktree git dir, left by a queued sighting) or carrying a CURRENT
41
+ # RemovedFromMergeQueueEvent (newer than the auto-merge re-arm and than the head commit) is a
42
+ # dequeue — a failed merge_group run, or a removal: `kind=dequeued rc=13`, exit 13, nothing merged or
43
+ # pushed; the line has the reason and the recovery. Auto-merge state is NOT consulted (measured 2026-10-05,
44
+ # #9482: it stays armed after a failed_checks removal and GitHub re-queues the PR; a removed PR is
45
+ # reported whether or not it is still armed). One re-read after a short nap precedes the report, so the
46
+ # queue's own merge landing (not queued, OPEN, about to read MERGED) is never one. A PR with neither
47
+ # marker nor event keeps the old reading (not queued yet / re-enqueues itself after a push). A dequeue
48
+ # reached through the marker alone is reported ONCE: --step (exit 13) and --queue-state (the `dequeued` print) each
49
+ # consume the marker, so a PR the agent fixed and re-armed is not reported again. The
50
+ # fences reach this on a BEHIND tick via --step and on every 5th OPEN tick via --queue-state.
51
+ # Before 1, standalone only. Armed BEHIND on a merge-queue repo (2026-10-09, PR 9839): a PR that GitHub reports BEHIND
52
+ # (not DIRTY), with auto-merge armed and a merge_queue rule on main, is skipped before any git work — `kind=queue_wait`
53
+ # rc=0, exit 0, nothing fetched, merged or pushed (queue_wait_gate() below). The window it closes is between the arm
54
+ # and the enqueue, where queue_gate sees no entry and a push restarts every required check for nothing. `--step` is
55
+ # NOT guarded: it is the Phase 7 fence's call, and the fence owns the queue-mode decision and its expiry fallback.
56
+ # Every tagged line is `[pr-behind-sync] kind=<k> rc=<n> — …` on STDOUT (a Monitor
57
+ # streams stdout only). rc is git's own exit status where a git command failed, else
58
+ # this script's exit code. Exit codes: see usage() / --help — the one table.
59
+ #
60
+ # Any unrecognised argument exits 2. The strictness is load-bearing: an older copy
61
+ # silently ignored unknown flags, so `--step` ran a full standalone sync and exited 0
62
+ # on "no sync needed" — which a fence would print as `pushed`. The fences refuse a
63
+ # copy whose --help does not name --step.
64
+ #
65
+ # Portability: runs on customer hosts including macOS's bash 3.2 — no mapfile, no
66
+ # ${x,,}, no associative arrays, no date; `timeout` only when present and `sleep` only between
67
+ # queue-read and rules-read retries (the Phase 7 fixture shadows date and sleep in the PARENT only and sets
68
+ # PR_QUEUE_RETRY_SLEEP=0 for the child).
69
+ # Preconditions: run from inside the PR feature worktree (not bare repo root).
70
+ set -euo pipefail
71
+
72
+ # git treats GIT_CURL_VERBOSE as on when merely PRESENT (even =0), and every trace knob
73
+ # can print token-bearing URLs and push result lines out of the `tail` windows below.
74
+ # Stripped once for every git call this process makes; the caller's shell is untouched.
75
+ unset GIT_CURL_VERBOSE GIT_TRACE GIT_TRACE_CURL GIT_TRACE_PACKET GIT_TRACE2 \
76
+ GIT_TRACE2_EVENT GIT_TRACE2_PERF GIT_TRACE_PERFORMANCE GIT_TRACE_SETUP
77
+ export GIT_TRACE_REDACT=1
78
+
79
+ usage() {
80
+ cat <<'USAGE'
81
+ usage: sync-pr-behind.sh <pr-number> [--max-attempts N]
82
+ sync-pr-behind.sh <pr-number> --step
83
+ sync-pr-behind.sh <pr-number> --queue-state
84
+ sync-pr-behind.sh --help
85
+
86
+ Run from the PR's feature worktree, on its branch: the script syncs $PWD's branch.
87
+
88
+ --step one sync attempt on the current branch (merge origin/main, push);
89
+ its only gh call is the merge-queue read — the caller already read
90
+ mergeStateStatus. A PR in the merge queue is skipped (a push would
91
+ dequeue it). The Phase 7 fence's call: the fence owns the queue-mode
92
+ decision (rule, armed, expiry); do not call it from your own loop
93
+ --queue-state print `<queued|not_queued|dequeued> <OPEN|CLOSED|MERGED> <armed|disarmed> removal=<reason|none>`
94
+ (the merge queue state; `dequeued` = out of the queue, OPEN, and seen queued or a current removal
95
+ event; no push, no worktree needed) and exit 0, or `kind=gh` exit 4 after one retry. Writes
96
+ nothing except to CONSUME the seen-queued marker when it prints `dequeued`: that verdict is
97
+ reported once, so a re-armed PR is not reported again (a current removal event needs no marker)
98
+ Env: PR_QUEUE_TIMEOUT (s, default 10), PR_QUEUE_ATTEMPTS (default 2 = one retry),
99
+ PR_QUEUE_RETRY_SLEEP (s, default 2), PR_QUEUE_REPO=OWNER/REPO (else the cwd repo);
100
+ the same four also govern the standalone loop's merge-queue rule read
101
+ --max-attempts N standalone loop (N = 1..999): check the PR's head branch is the
102
+ current branch, read state, sync while BEHIND, up to N times
103
+
104
+ exit codes (each non-zero exit prints one tagged `kind=<k> rc=<n>` line on stdout):
105
+ 0 synced and pushed (--step), or nothing to do / BEHIND resolved (standalone), or
106
+ the PR is in the merge queue — standalone only: skipped, nothing merged or pushed
107
+ (kind=queued; --step exits 11 for it, see below), or BEHIND + armed on a merge-queue
108
+ repo — standalone only: skipped, nothing fetched, merged or pushed (kind=queue_wait)
109
+ 2 usage error or unknown argument (kind=usage)
110
+ 3 not inside a work tree (kind=not_worktree)
111
+ 4 a gh call failed (kind=gh): gh pr view (standalone), the merge-queue read after one retry,
112
+ or (standalone, armed BEHIND PR) the main merge-queue rule read
113
+ 5 fetching main failed (kind=fetch)
114
+ 6 merge conflict, or merge not committed (hook) — the merge was aborted (kind=merge)
115
+ 7 git push failed — the local merge commit is retained (kind=push)
116
+ 8 still BEHIND after N attempts (standalone, kind=exhausted); after a kind=pushed
117
+ line the push landed and GitHub has not recomputed yet — re-arm the poll
118
+ 9 a merge/rebase/cherry-pick/revert this script did not start, or detached HEAD
119
+ (kind=merge_in_progress or detached_head)
120
+ 10 git merge refused to start (nothing to abort, kind=merge_refused)
121
+ 11 origin/main already merged and pushed — nothing to push (kind=noop); GitHub's
122
+ mergeStateStatus lags the ref. Also --step on a PR in the merge queue: skipped,
123
+ nothing merged or pushed (kind=queued). Fences keep polling; standalone exits so the
124
+ caller re-runs once GitHub recomputes the state
125
+ 12 the current branch is not the PR's head branch (standalone, kind=wrong_branch)
126
+ 13 the PR is out of the merge queue, OPEN, and was seen queued or has a current removal event (a failed
127
+ merge_group run or a removal; kind=dequeued; auto-merge state is not consulted) — nothing merged or
128
+ pushed; the line has the removal reason and the recovery
129
+ USAGE
130
+ }
131
+
132
+ tag() { local k="$1" r="$2"; shift 2; echo "[pr-behind-sync] kind=$k rc=$r — $*"; }
133
+ usage_err() { tag usage 2 "$1"; usage; exit 2; }
134
+
135
+ PR=""; MODE=loop; MAX_ATTEMPTS=1
136
+ while [[ $# -gt 0 ]]; do
137
+ case "$1" in
138
+ --help|-h) usage; exit 0 ;;
139
+ --step) MODE=step ;;
140
+ --queue-state) MODE=queue_state ;;
141
+ --max-attempts)
142
+ [[ "${2:-}" =~ ^[1-9][0-9]{0,2}$ ]] || usage_err "--max-attempts takes 1..999, got '${2:-}'"
143
+ MAX_ATTEMPTS="$2"; shift ;;
144
+ *)
145
+ if [[ -z "$PR" && "$1" =~ ^[0-9]+$ ]]; then PR="$1"; else usage_err "unexpected argument '$1'"; fi ;;
146
+ esac
147
+ shift
148
+ done
149
+ [[ -n "$PR" ]] || usage_err "missing <pr-number>"
150
+ if [[ "$MODE" != loop && "$MAX_ATTEMPTS" != 1 ]]; then usage_err "--step and --queue-state take no --max-attempts"; fi
151
+
152
+ # queue_state_read — THE ONE copy of the merge-queue GraphQL read and its jq verdict program (the
153
+ # pre-merge hook and monitor-pr-checks.sh reach it through --queue-state). Sets QS_OUT to
154
+ # `<queued|not_queued> <state> <armed|disarmed> removal=<reason|none>` (`-` for a field the answer lacks;
155
+ # removal = the newest RemovedFromMergeQueueEvent, only while it is CURRENT: newer than the auto-merge re-arm
156
+ # and than the head commit, so a fixed-and-pushed or re-armed PR reads none) and returns 0, or
157
+ # sets QS_CAUSE (timeout | gh_error | unparseable) and QS_DETAIL and returns 1: a failed read is
158
+ # NEVER a verdict. `{owner}` / `{repo}` are filled by gh from the cwd repository (PR_QUEUE_REPO=o/r
159
+ # overrides). Both queue fields are read (an entry exists iff isInMergeQueue); the call runs under
160
+ # `bash -c` so a gh that is a shell function (an exported test mock) is still reached, and under
161
+ # timeout/gtimeout when present so a hung call cannot hang a poll tick or a hook.
162
+ queue_state_read() {
163
+ local to_s="${PR_QUEUE_TIMEOUT:-10}" attempts="${PR_QUEUE_ATTEMPTS:-2}" nap="${PR_QUEUE_RETRY_SLEEP:-2}"
164
+ local owner='{owner}' repo='{repo}' n=0 rc out errf query jqp
165
+ [[ "$to_s" =~ ^[1-9][0-9]{0,3}$ ]] || to_s=10
166
+ [[ "$attempts" =~ ^[1-9]$ ]] || attempts=2
167
+ [[ "$nap" =~ ^[0-9]{1,3}$ ]] || nap=2
168
+ if [[ "${PR_QUEUE_REPO:-}" =~ ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ ]]; then owner="${PR_QUEUE_REPO%%/*}"; repo="${PR_QUEUE_REPO#*/}"; fi
169
+ local to=()
170
+ if command -v timeout >/dev/null 2>&1; then to=(timeout -k 2 "$to_s")
171
+ elif command -v gtimeout >/dev/null 2>&1; then to=(gtimeout -k 2 "$to_s"); fi
172
+ # shellcheck disable=SC2016 # the GraphQL `$owner`/`$name`/`$number` are variables of the query, not shell
173
+ query='
174
+ query($owner: String!, $name: String!, $number: Int!) {
175
+ repository(owner: $owner, name: $name) {
176
+ pullRequest(number: $number) {
177
+ isInMergeQueue mergeQueueEntry { state } state autoMergeRequest { enabledAt }
178
+ commits(last: 1) { nodes { commit { committedDate } } }
179
+ timelineItems(last: 1, itemTypes: [REMOVED_FROM_MERGE_QUEUE_EVENT]) { nodes { ... on RemovedFromMergeQueueEvent { reason createdAt } } }
180
+ }
181
+ }
182
+ }'
183
+ # shellcheck disable=SC2016 # `$r` / `$en` / `$hd` are jq variables, not shell
184
+ jqp='.data.repository.pullRequest
185
+ | if . == null then "unreadable"
186
+ else (if .isInMergeQueue == true or .mergeQueueEntry != null then "queued"
187
+ elif .isInMergeQueue == false then "not_queued"
188
+ else "unreadable" end)
189
+ + " " + (.state // "-")
190
+ + " " + (if has("autoMergeRequest") then (if .autoMergeRequest == null then "disarmed" else "armed" end) else "-" end)
191
+ + " removal=" + (if has("timelineItems") then
192
+ (.timelineItems.nodes // [])[0] as $r
193
+ | (.autoMergeRequest.enabledAt // "") as $en
194
+ | ((.commits.nodes // [])[0].commit.committedDate // "") as $hd
195
+ | if $r == null or ($r.createdAt // "") <= $en or ($r.createdAt // "") <= $hd then "none"
196
+ else (($r.reason // "unknown") | tostring | gsub("[^A-Za-z0-9_-]"; "_")) end
197
+ else "-" end)
198
+ end'
199
+ errf="$(mktemp)" || { QS_CAUSE=gh_error; QS_DETAIL="mktemp failed"; return 1; } # lint-trap-ownership: ok — removed by rm -f on every return path of queue_state_read; a kill leaves one tiny file
200
+ while [[ "$n" -lt "$attempts" ]]; do
201
+ n=$((n + 1)); rc=0
202
+ # shellcheck disable=SC2016 # $1..$5 are bash -c's own positional parameters, not this shell's
203
+ out="$(${to[@]+"${to[@]}"} bash -c 'gh api graphql -F owner="$4" -F name="$5" -F number="$1" -f query="$2" --jq "$3"' \
204
+ _ "$PR" "$query" "$jqp" "$owner" "$repo" 2>"$errf")" || rc=$?
205
+ if [[ "$rc" -ne 0 ]]; then
206
+ case "$rc" in 124|137|143) QS_CAUSE=timeout ;; *) QS_CAUSE=gh_error ;; esac
207
+ QS_DETAIL="rc=$rc $(head -c 200 "$errf" | tr '\n' ' ')"
208
+ else
209
+ out="${out%%$'\n'*}"
210
+ case "${out%% *}" in
211
+ queued|not_queued) rm -f "$errf"; QS_OUT="$out"; return 0 ;;
212
+ *) QS_CAUSE=unparseable; QS_DETAIL="read returned '${out:0:80}' (want queued or not_queued)" ;;
213
+ esac
214
+ fi
215
+ if [[ "$n" -lt "$attempts" ]]; then sleep "$nap"; fi
216
+ done
217
+ rm -f "$errf"
218
+ return 1
219
+ }
220
+
221
+ # dq_candidate <marker> — 0 iff QS_OUT reads the PR out of the queue and OPEN AND it either was seen queued (the
222
+ # marker, per worktree git dir) or has a CURRENT removal event. Auto-merge state is NOT consulted: after a failed
223
+ # merge_group run it stays armed (measured 2026-10-05, #9482, two PRs) and GitHub may re-queue the PR, and a
224
+ # removed PR must be reported whether or not it is still armed. Only a PR with
225
+ # neither marker nor event keeps the old reading (not queued yet, or a push dequeued it and it re-enqueues itself).
226
+ dq_candidate() {
227
+ local v st am rm
228
+ read -r v st am rm <<<"$QS_OUT"
229
+ [[ "$v" == not_queued && "$st" == OPEN ]] || return 1
230
+ [[ ( -n "$1" && -f "$1" ) || ( -n "$rm" && "$rm" != removal=none && "$rm" != removal=- ) ]]
231
+ }
232
+
233
+ # queue_read_settled <marker> — queue_state_read, then ONE re-read after a short nap when the first answer is a
234
+ # dequeue candidate, so the instant the queue's own merge lands (not queued, OPEN, about to read MERGED) is never
235
+ # reported as a dequeue. Returns 1 (QS_CAUSE set) when either read fails: a failed read is never a verdict.
236
+ queue_read_settled() {
237
+ local nap="${PR_QUEUE_RETRY_SLEEP:-2}"
238
+ [[ "$nap" =~ ^[0-9]{1,3}$ ]] || nap=2
239
+ queue_state_read || return 1
240
+ if dq_candidate "$1"; then sleep "$nap"; queue_state_read || return 1; fi
241
+ return 0
242
+ }
243
+
244
+ # --queue-state: the shared read — no git work, no worktree needed, no push. It never WRITES the marker (only --step does,
245
+ # on a queued sighting); the one write it makes is the CONSUMPTION below: printing `dequeued` removes the marker, so the
246
+ # report is delivered once (a PR the agent fixed and re-armed — CI running, not queued yet — must not read dequeued on every
247
+ # later tick just because the marker outlived the first report). Handled before the worktree check so a caller outside a
248
+ # work tree (monitor-pr-checks.sh --repo) can use it.
249
+ if [[ "$MODE" == queue_state ]]; then
250
+ QS_OUT=""; QS_CAUSE=""; QS_DETAIL=""
251
+ qs_marker="$(git rev-parse --git-dir 2>/dev/null || true)"; [[ -z "$qs_marker" ]] || qs_marker="$qs_marker/pr-queue-seen-$PR"
252
+ if queue_read_settled "$qs_marker"; then
253
+ # The verdict a caller acts on: `dequeued` replaces `not_queued` for a candidate that survived the re-read. A
254
+ # dequeue reached through the MARKER alone (removal=none) is reported ONCE: the report consumes the marker, exactly
255
+ # as --step does on exit 13. A dequeue from a CURRENT removal event needs no marker (a re-arm after the fix makes
256
+ # the event older than enabledAt, so it stops matching); a stale marker beside one is consumed by the same report.
257
+ # A non-dequeued verdict (queued, MERGED, not_queued) never consumes it.
258
+ if dq_candidate "$qs_marker"; then
259
+ QS_OUT="dequeued ${QS_OUT#* }"
260
+ [[ -z "$qs_marker" ]] || rm -f "$qs_marker" # consume-on-report
261
+ fi
262
+ printf '%s\n' "$QS_OUT"; exit 0
263
+ fi
264
+ tag gh 4 "merge queue read failed (cause=$QS_CAUSE ${QS_DETAIL:0:200}) — queue state unknown"
265
+ exit 4
266
+ fi
267
+
268
+ # No `cd`: this script syncs the CALLER's worktree ($PWD). Resolving it from BASH_SOURCE
269
+ # synced the wrong repository (#8428) — pinned by the "SUT outside repo" test case.
270
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
271
+ tag not_worktree 3 "not inside a work tree — cd to the PR worktree (.worktrees/<branch>) and re-run"
272
+ exit 3
273
+ fi
274
+
275
+ BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo HEAD)"
276
+
277
+ # Merge-queue gate (#9454). Exits 11 in --step mode, 0 in the loop (kind=queued) when the PR is in the merge queue,
278
+ # 13 (kind=dequeued) when it is out of the queue, OPEN, and either was seen queued or has a CURRENT removal event
279
+ # (auto-merge state is not consulted), and 4 (kind=gh) when the read fails or answers anything but queued /
280
+ # not_queued; returns normally only on a positive "not queued" with no dequeue evidence. The read is
281
+ # queue_read_settled() above (queue_state_read owns the query and the verdict program; two attempts ride out a
282
+ # transient 5xx or rate limit, and a dequeue candidate is re-read once), so the fence needs no arm of its own.
283
+ queue_gate() {
284
+ local verdict st am rm marker git_dir reason
285
+ git_dir="$(git rev-parse --git-dir 2>/dev/null || true)"
286
+ marker=""; [[ -z "$git_dir" ]] || marker="$git_dir/pr-queue-seen-$PR"
287
+ QS_OUT=""; QS_CAUSE=""; QS_DETAIL=""
288
+ if ! queue_read_settled "$marker"; then
289
+ tag gh 4 "merge queue read failed (cause=$QS_CAUSE ${QS_DETAIL:0:200}) — not syncing; a push to a queued PR would dequeue it"
290
+ exit 4
291
+ fi
292
+ read -r verdict st am rm <<<"$QS_OUT"
293
+ case "$verdict" in
294
+ not_queued)
295
+ case "$st" in
296
+ MERGED|CLOSED) # the PR left the queue by merging (or was closed): a stale marker is cleared, nothing to sync
297
+ [[ -z "$marker" ]] || rm -f "$marker"
298
+ tag noop 11 "PR #$PR is $st — it left the queue; nothing to sync"
299
+ exit 11 ;;
300
+ esac
301
+ if dq_candidate "$marker"; then
302
+ [[ -z "$marker" ]] || rm -f "$marker"
303
+ reason="removal reason: ${rm#removal=}"
304
+ [[ "$rm" != removal=none && "$rm" != removal=- ]] || reason="seen in the queue earlier, no removal event read"
305
+ tag dequeued 13 "PR #$PR was in the merge queue and is no longer (OPEN, $am, $reason): a failed merge_group run or a removal — NOT syncing. Recover (ONE re-enqueue, procedure: plugins/soleur/skills/ship/references/merge-queue-dequeue.md): (1) read why: gh run list --event merge_group --limit 100 --json databaseId,headBranch,conclusion,url --jq '.[] | select(.headBranch | startswith(\"gh-readonly-queue/main/pr-$PR-\"))' then gh run view <databaseId> --log-failed; (2) fix on the branch, git merge origin/main, push; (3) re-arm once: gh pr merge $PR --squash --auto. A second dequeue: stop and report it."
306
+ exit 13
307
+ fi
308
+ return 0 ;;
309
+ queued)
310
+ [[ -z "$marker" ]] || { touch "$marker" 2>/dev/null || true; }
311
+ # --step exits 11 (the fence's uncounted no-op arm: nothing was pushed, so the ship and
312
+ # merge-pr fences must not count a sync); the standalone loop exits 0.
313
+ if [[ "$MODE" == step ]]; then
314
+ tag queued 11 "PR #$PR is in the merge queue; sync skipped (a push would dequeue it) — keep polling for MERGED or removal from the queue"
315
+ exit 11
316
+ fi
317
+ tag queued 0 "PR #$PR is in the merge queue; sync skipped (a push would dequeue it) — keep polling for MERGED or removal from the queue"
318
+ exit 0 ;;
319
+ *)
320
+ tag gh 4 "merge queue read returned '${QS_OUT:0:80}' (want queued or not_queued) — not syncing; a push to a queued PR would dequeue it"
321
+ exit 4 ;;
322
+ esac
323
+ }
324
+
325
+ # Armed-and-BEHIND gate (2026-10-09, PR 9839). Between `gh pr merge --auto` and the enqueue a PR is OPEN, BEHIND, armed
326
+ # and NOT in the queue, so queue_gate (which only sees an entry) lets it through, and a sync there pushes a commit that
327
+ # restarts every required check for nothing: on a merge-queue repo the queue makes the PR current itself. Standalone loop
328
+ # only. Fires when GitHub says BEHIND (not DIRTY: a DIRTY that is only recompute lag still resolves) AND auto-merge is
329
+ # armed (the third field of QS_OUT, set by the queue_gate that just ran: no extra call) AND `main` has a merge_queue rule
330
+ # (one rules read, selected by `.type`, never by position: merge_queue is not the first rule on a live repo, and the read
331
+ # asks for 100 rules per page: a merge_queue beyond rule 100 would read as absent). Verdict: rule found -> `kind=queue_wait` exit 0 with nothing fetched, merged or pushed;
332
+ # none -> return, the sync proceeds as before; a read that still fails after PR_QUEUE_ATTEMPTS tries (default 2, like
333
+ # queue_state_read), or answers empty or non-numeric -> `kind=gh` exit 4. That is the one place this script fails CLOSED
334
+ # on an unreadable rules answer (ADR-270 addendum 2026-10-09): the fence falls toward sync, but here the caller is a
335
+ # standalone run with no poll behind it, and an unknown answer is not a yes. The cause is in the tag. `--step` is not
336
+ # guarded: it is the Phase 7 fence's call and the fence owns the queue-mode decision and its expiry. Base is `main`.
337
+ # The standalone answer has NO expiry of its own: re-arming the Phase 7 poll is the bound (its fallback sync).
338
+ queue_wait_gate() { # <state_line>
339
+ local v st am rm out="" rc=0 n=0 detail="" errf msg owner='{owner}' repo='{repo}'
340
+ local to_s="${PR_QUEUE_TIMEOUT:-10}" attempts="${PR_QUEUE_ATTEMPTS:-2}" nap="${PR_QUEUE_RETRY_SLEEP:-2}" to=()
341
+ [[ "$1" == *BEHIND* && "$1" != *DIRTY* ]] || return 0
342
+ read -r v st am rm <<<"$QS_OUT"
343
+ [[ "$am" == armed ]] || return 0
344
+ [[ "$to_s" =~ ^[1-9][0-9]{0,3}$ ]] || to_s=10
345
+ [[ "$attempts" =~ ^[1-9]$ ]] || attempts=2
346
+ [[ "$nap" =~ ^[0-9]{1,3}$ ]] || nap=2
347
+ if [[ "${PR_QUEUE_REPO:-}" =~ ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ ]]; then owner="${PR_QUEUE_REPO%%/*}"; repo="${PR_QUEUE_REPO#*/}"; fi
348
+ if command -v timeout >/dev/null 2>&1; then to=(timeout -k 2 "$to_s")
349
+ elif command -v gtimeout >/dev/null 2>&1; then to=(gtimeout -k 2 "$to_s"); fi
350
+ errf="$(mktemp)" || { tag gh 4 "merge-queue rule read not attempted (mktemp failed) — not syncing; retry the poll"; exit 4; } # lint-trap-ownership: ok — removed by rm -f on every exit path of queue_wait_gate; a kill leaves one tiny file
351
+ while [[ "$n" -lt "$attempts" ]]; do
352
+ n=$((n + 1)); rc=0
353
+ # shellcheck disable=SC2016 # $1..$3 are bash -c's own positional parameters, not this shell's
354
+ out="$(${to[@]+"${to[@]}"} bash -c 'gh api "repos/$1/$2/rules/branches/main?per_page=100" --jq "$3"' \
355
+ _ "$owner" "$repo" '[.[] | select(.type == "merge_queue")] | length' 2>"$errf")" || rc=$?
356
+ out="${out%%$'\n'*}"
357
+ if [[ "$rc" -eq 0 && "$out" =~ ^[0-9]{1,6}$ ]]; then break; fi
358
+ detail="rc=$rc answered=${out:0:40} $(head -c 160 "$errf" | tr '\n' ' ')"
359
+ if [[ "$n" -lt "$attempts" ]]; then sleep "$nap"; fi
360
+ done
361
+ rm -f "$errf"
362
+ if [[ "$rc" -eq 0 && "$out" =~ ^[0-9]{1,6}$ ]]; then
363
+ if (( 10#$out >= 1 )); then
364
+ msg="PR #$PR is BEHIND, auto-merge is armed (not in the queue yet) and main has a merge queue: not syncing — a resync alone restarts every required check and the queue makes the PR current. Wait for MERGED or a dequeue; with no poll running, re-arm the Phase 7 poll with CLAUDE_PLUGIN_ROOT exported — its expiry fallback after 6 idle ticks is the sanctioned sync. Red required check? Push the fix itself, not a resync. Green and never enqueued? Follow plugins/soleur/skills/ship/references/merge-queue-dequeue.md ('Armed and green but never enqueued')."
365
+ tag queue_wait 0 "$msg"
366
+ exit 0
367
+ fi
368
+ return 0
369
+ fi
370
+ detail="$(printf '%s' "$detail" | tr -c '[:alnum:] ._:/=-' '?')"
371
+ tag gh 4 "merge-queue rule read failed after $n attempt(s) ($detail) — not syncing: that read decides whether this armed BEHIND PR may be resynced and an unknown answer is not a yes. Retry the poll; a persistent failure means the token cannot read repository rules (raise PR_QUEUE_ATTEMPTS, or resync by hand only after confirming main has no merge queue)."
372
+ exit 4
373
+ }
374
+
375
+ # One sync attempt. Returns the exit code documented in usage() and prints the tagged
376
+ # line for every non-zero outcome. Every git rc is captured with `|| rc=$?` before any
377
+ # display. Callers run it as `sync_step || rc=$?` (errexit is suspended inside); the
378
+ # `|| true` on display pipes keeps a future bare call from dying before the --abort.
379
+ sync_step() {
380
+ local git_dir rc out before conflicted
381
+ git_dir="$(git rev-parse --git-dir 2>/dev/null || true)"
382
+ if git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1 \
383
+ || [[ -n "$git_dir" && ( -d "$git_dir/rebase-merge" || -d "$git_dir/rebase-apply" \
384
+ || -f "$git_dir/CHERRY_PICK_HEAD" || -f "$git_dir/REVERT_HEAD" ) ]]; then
385
+ tag merge_in_progress 9 "a merge/rebase/cherry-pick/revert is in progress on $BRANCH; not touching it. If you did not start it (a previous poll may have died mid-sync), run git status, abort it, then re-arm the poll."
386
+ return 9
387
+ fi
388
+ if ! git symbolic-ref -q HEAD >/dev/null 2>&1; then
389
+ tag detached_head 9 "HEAD is detached; git push would have no branch to update. Check out the PR branch first — run the poll from the PR worktree."
390
+ return 9
391
+ fi
392
+
393
+ rc=0; out="$(git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main 2>&1)" || rc=$?
394
+ if [[ -n "$out" ]]; then printf '%s\n' "$out" | tail -2 || true; fi
395
+ if [[ "$rc" -ne 0 ]]; then
396
+ tag fetch "$rc" "fetch origin main failed"
397
+ return 5
398
+ fi
399
+
400
+ before="$(git rev-parse HEAD 2>/dev/null || true)"
401
+ rc=0; out="$(git merge origin/main --no-edit 2>&1)" || rc=$?
402
+ if [[ -n "$out" ]]; then printf '%s\n' "$out" | tail -5 || true; fi
403
+ if [[ "$rc" -ne 0 ]]; then
404
+ if [[ "$rc" -eq 1 ]] && git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1; then
405
+ # rerere.autoupdate can empty --diff-filter=U; the merge output cannot.
406
+ conflicted="$( { git diff --name-only --diff-filter=U 2>/dev/null || true; printf '%s\n' "$out" | grep '^CONFLICT ' || true; } )"
407
+ if [[ -n "$conflicted" ]]; then
408
+ tag merge "$rc" "git merge origin/main failed — merge conflict, aborting sync. Conflicted paths:"
409
+ printf '%s\n' "$conflicted"
410
+ else
411
+ tag merge "$rc" "git merge origin/main failed — merge not committed (hook rejected?), no conflicted paths; aborting sync."
412
+ fi
413
+ git merge --abort 2>&1 || echo "git merge --abort failed (rc=$?)"
414
+ if [[ -n "$conflicted" ]]; then
415
+ echo "Manual conflict resolution required on $BRANCH. Next: git merge origin/main, resolve, commit, push, then re-arm the poll."
416
+ else
417
+ echo "No conflict on $BRANCH. Next: run git merge origin/main and read the pre-merge-commit hook's output; fix what it reports, commit, push, then re-arm the poll."
418
+ fi
419
+ return 6
420
+ elif git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1; then
421
+ tag merge_in_progress "$rc" "MERGE_HEAD appeared during the sync (not started by this script); not touching it. Run git status, finish or abort it, then re-arm the poll."
422
+ return 9
423
+ fi
424
+ tag merge_refused "$rc" "git merge origin/main failed — refused to start (nothing to abort; run git status to see which operation is in progress). Worktree state:"
425
+ git status --short 2>&1 | head -20 || true
426
+ echo "Clear the worktree state on $BRANCH shown above, then re-run the Phase 7 poll (or this script)."
427
+ return 10
428
+ fi
429
+
430
+ # Nothing merged AND nothing unpushed: GitHub's BEHIND is stale. A retained merge
431
+ # commit from an earlier failed push (HEAD != upstream) still gets pushed below.
432
+ if [[ -n "$before" && "$(git rev-parse HEAD 2>/dev/null || true)" == "$before" \
433
+ && "$(git rev-parse '@{u}' 2>/dev/null || true)" == "$before" ]]; then
434
+ tag noop 11 "origin/main is already merged into $BRANCH and pushed; nothing to push. GitHub's mergeStateStatus lags — keep polling."
435
+ return 11
436
+ fi
437
+
438
+ rc=0; out="$(git push 2>&1)" || rc=$?
439
+ if [[ -n "$out" ]]; then printf '%s\n' "$out" | tail -2 || true; fi
440
+ if [[ "$rc" -ne 0 ]]; then
441
+ tag push "$rc" "git push failed after merge — auto-sync incomplete; the local merge commit is retained, nothing was aborted. Usually a concurrent push to $BRANCH: run git fetch origin $BRANCH, inspect git log --oneline HEAD...origin/$BRANCH, then git merge origin/$BRANCH (do not rebase — it would flatten the retained merge commit), push, then re-arm the poll."
442
+ return 7
443
+ fi
444
+ return 0
445
+ }
446
+
447
+ if [[ "$MODE" == step ]]; then
448
+ queue_gate
449
+ rc=0; sync_step || rc=$?
450
+ exit "$rc"
451
+ fi
452
+
453
+ # Standalone: the PR number must name THIS branch, or the sync lands on the wrong PR.
454
+ rc=0; head_ref="$(gh pr view "$PR" --json headRefName --jq .headRefName 2>&1)" || rc=$?
455
+ if [[ "$rc" -ne 0 ]]; then tag gh "$rc" "gh pr view failed: $head_ref"; exit 4; fi
456
+ if [[ "$head_ref" != "$BRANCH" ]]; then
457
+ tag wrong_branch 12 "PR #$PR's head branch is '$head_ref' but this worktree is on '$BRANCH' — cd to that PR's worktree (or pass the right PR number); not syncing."
458
+ exit 12
459
+ fi
460
+
461
+ attempt=0
462
+ while [[ "$attempt" -lt "$MAX_ATTEMPTS" ]]; do
463
+ attempt=$((attempt + 1))
464
+ rc=0; state_line="$(gh pr view "$PR" --json state,mergeStateStatus \
465
+ --jq '"\(.state) \(.mergeStateStatus)"' 2>&1)" || rc=$?
466
+ if [[ "$rc" -ne 0 ]]; then tag gh "$rc" "gh pr view failed: $state_line"; exit 4; fi
467
+
468
+ tag state 0 "PR #$PR state: $state_line (branch: $BRANCH)"
469
+
470
+ if [[ "$state_line" == MERGED* || "$state_line" == CLOSED* ]]; then
471
+ tag closed 0 "PR is ${state_line%% *} — no sync needed"
472
+ exit 0
473
+ fi
474
+
475
+ if [[ "$state_line" != *BEHIND* && "$state_line" != *DIRTY* ]]; then
476
+ tag not_behind 0 "BEHIND unchanged: mergeStateStatus is not BEHIND — no sync needed"
477
+ exit 0
478
+ fi
479
+
480
+ # A queued PR is never synced (queue_gate exits kind=queued, or 4 on a failed read).
481
+ queue_gate
482
+ # An armed BEHIND PR on a merge-queue repo is not synced either (queue_wait_gate exits kind=queue_wait, or 4).
483
+ queue_wait_gate "$state_line"
484
+
485
+ tag behind 0 "BEHIND detected — auto-sync attempt ${attempt}/${MAX_ATTEMPTS}"
486
+
487
+ # GitHub DIRTY with a clean local merge-tree is the kb-index class: the server-side
488
+ # merge lacks the local driver. Key on merge-tree's exit code; on failure its stdout
489
+ # carries the real conflicted paths (no merge is in progress, so --diff-filter=U is
490
+ # empty). BEHIND needs no classification — sync_step's merge is the test.
491
+ if [[ "$state_line" == *DIRTY* ]]; then
492
+ rc=0; out="$(git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main 2>&1)" || rc=$?
493
+ if [[ "$rc" -ne 0 ]]; then
494
+ tag fetch "$rc" "fetch origin main failed while classifying DIRTY"
495
+ exit 5
496
+ fi
497
+ rc=0; mt_out="$(git merge-tree --write-tree origin/main HEAD 2>&1)" || rc=$?
498
+ if [[ "$rc" -ne 0 ]]; then
499
+ # REGENERABLE-ARTIFACT CONFLICT (ADR-235): model.likec4.json is still committed, so
500
+ # it conflicts whenever two branches touch the .c4 sources. The resolver merges and
501
+ # regenerates it from the MERGED sources; it fails closed (touches nothing unless it
502
+ # committed) and never pushes. It ships beside this script; the target stays $PWD.
503
+ # After it commits, sync_step's merge is a no-op and HEAD != @{u}, so it pushes.
504
+ resolver="$(dirname "${BASH_SOURCE[0]}")/resolve-regenerable-conflicts.sh"
505
+ if [[ -f "$resolver" ]] && bash "$resolver" origin/main; then
506
+ tag regen_resolved 0 "regenerable conflict resolved — merge committed locally"
507
+ else
508
+ tag merge "$rc" "merge conflict — manual resolution required (merge-tree). Next: git merge origin/main, resolve, commit, push, then re-run. Conflicted paths:"
509
+ printf '%s\n' "$mt_out" | grep '^CONFLICT ' || true
510
+ exit 6
511
+ fi
512
+ fi
513
+ fi
514
+
515
+ rc=0; sync_step || rc=$?
516
+ # 11 (noop) exits too: re-reading state here would see the same lagging BEHIND and
517
+ # burn the remaining attempts on no-ops. The caller re-runs once GitHub catches up.
518
+ if [[ "$rc" -ne 0 ]]; then exit "$rc"; fi
519
+
520
+ tag pushed 0 "auto-sync ${attempt} pushed — CI will re-run on new SHA"
521
+
522
+ rc=0; state_line="$(gh pr view "$PR" --json state,mergeStateStatus \
523
+ --jq '"\(.state) \(.mergeStateStatus)"' 2>&1)" || rc=$?
524
+ if [[ "$rc" -ne 0 ]]; then tag gh "$rc" "post-push gh pr view failed: $state_line"; exit 4; fi
525
+ tag state 0 "post-sync state: $state_line"
526
+
527
+ if [[ "$state_line" != *BEHIND* ]]; then
528
+ tag resolved 0 "BEHIND resolved: branch caught up to main"
529
+ exit 0
530
+ fi
531
+ done
532
+
533
+ tag exhausted 8 "BEHIND still present after ${MAX_ATTEMPTS} sync(s) — main may be moving faster than CI"
534
+ exit 8