@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,706 @@
1
+ #!/usr/bin/env bash
2
+ # github-community.sh -- GitHub community data wrapper
3
+ #
4
+ # Usage: github-community.sh <command> [args]
5
+ # Commands:
6
+ # activity [days] - Recent issues, PRs, and comments
7
+ # contributors [days] - Active contributors in period
8
+ # discussions [days] - Recent discussions (if enabled)
9
+ # repo-stats [days] - Stars, forks, watchers, new stargazers
10
+ # (new_stargazers_count is null when the token cannot list
11
+ # stargazers: a read-only token gets 403; see stargazers_unavailable)
12
+ # fetch-interactions [days] - External user comments on issues/PRs
13
+ #
14
+ # Prerequisites: gh CLI authenticated
15
+ # Environment:
16
+ # SOLEUR_COLLECTOR_COMPACT=1 - print ONE line of compact JSON per command holding only
17
+ # the fields the community-monitor prompt reads (#9678).
18
+ # Unset, or any other value, leaves the output unchanged.
19
+ # Output: JSON to stdout
20
+ # Errors: Messages to stderr, exit 1
21
+
22
+ set -euo pipefail
23
+
24
+ # Page size for every list endpoint below. check_cap compares against it, so
25
+ # binding both sides to one constant keeps the truncation detector from
26
+ # silently retiring if a URL changes.
27
+ readonly PER_PAGE=100
28
+
29
+ # Compact mode (#9678): the spawned agent has no file tools, so output past the Bash
30
+ # tool's inline limit (30,000 characters) is unreadable. Caps are deterministic;
31
+ # `count` fields stay exact, titles are the newest COMPACT_MAX_ITEMS per list.
32
+ readonly COMPACT_MAX_ITEMS=40
33
+ readonly COMPACT_TITLE_MAX=60
34
+ readonly COMPACT_BUDGET_BYTES=6000
35
+
36
+ # --- Validation ---
37
+
38
+ validate_gh() {
39
+ if ! command -v gh >/dev/null 2>&1; then
40
+ echo "Error: gh CLI is not installed." >&2
41
+ echo "Install: https://cli.github.com/" >&2
42
+ exit 1
43
+ fi
44
+
45
+ if ! gh auth status >/dev/null 2>&1; then
46
+ echo "Error: gh CLI is not authenticated." >&2
47
+ echo "Run: gh auth login" >&2
48
+ exit 1
49
+ fi
50
+ }
51
+
52
+ detect_repo() {
53
+ # Fast path: GITHUB_REPOSITORY is always set in GitHub Actions
54
+ if [[ -n "${GITHUB_REPOSITORY:-}" ]]; then
55
+ echo "$GITHUB_REPOSITORY"
56
+ return 0
57
+ fi
58
+
59
+ local remote_url
60
+ remote_url=$(git remote get-url origin 2>/dev/null) || {
61
+ echo "Error: No git remote 'origin' found." >&2
62
+ exit 1
63
+ }
64
+
65
+ # Extract owner/repo from SSH or HTTPS URL
66
+ # Handles: https://github.com/owner/repo.git
67
+ # git@github.com:owner/repo.git
68
+ # https://x-access-token:TOKEN@github.com/owner/repo.git
69
+ local repo
70
+ repo=$(echo "$remote_url" | sed -E 's#https?://([^@]+@)?github\.com/##' | sed -E 's#git@github\.com:##' | sed 's/\.git$//')
71
+
72
+ if [[ -z "$repo" || "$repo" == "$remote_url" ]]; then
73
+ echo "Error: Could not parse GitHub repo from remote URL: ${remote_url}" >&2
74
+ exit 1
75
+ fi
76
+
77
+ echo "$repo"
78
+ }
79
+
80
+ date_n_days_ago() {
81
+ local days="${1:-7}"
82
+ if ! [[ "$days" =~ ^[0-9]+$ ]]; then
83
+ echo "Error: days must be a positive integer." >&2
84
+ exit 1
85
+ fi
86
+ date -u -d "${days} days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || \
87
+ date -u -v-"${days}"d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null
88
+ }
89
+
90
+ check_rate_limit() {
91
+ local response="$1"
92
+ if grep -qi "rate limit" < <(jq -e '.message // empty' 2>/dev/null <<<"$response"); then
93
+ _CAUSE="rate-limit"
94
+ echo "Error: GitHub API rate limit exceeded." >&2
95
+ echo "" >&2
96
+ echo "Options:" >&2
97
+ echo " 1. Wait and retry (resets hourly)" >&2
98
+ echo " 2. Check limit: gh api rate_limit" >&2
99
+ exit 1
100
+ fi
101
+ }
102
+
103
+ # --- Run state, cleanup, and the collector-status sidecar ---
104
+ #
105
+ # One trap, registered once in main(), owns BOTH tempfile cleanup and the status
106
+ # record. Bash EXIT traps are global and singular -- a second `trap ... EXIT`
107
+ # REPLACES the first -- so registering one per tempfile would silently leak all
108
+ # but the last on every run. Files are appended to _TMPFILES in the parent
109
+ # scope; a helper that appended inside a command substitution would lose every
110
+ # entry to the subshell.
111
+
112
+ _TMPFILES=()
113
+ _COMMAND=""
114
+ _CAUSE=""
115
+ _CAP_WARN=""
116
+ _COMPACT_CAUSE=""
117
+ _COMPACT_OFF=0
118
+
119
+ # Appends one JSONL record per dispatch -- success AND failure -- to a path the
120
+ # caller supplies. This is the only failure channel that does not terminate in
121
+ # the spawned agent's context window: the handler reads it directly from the
122
+ # run's working directory, with no LLM in the path. No-op when unset, so
123
+ # interactive use is unchanged.
124
+ _record_status() { # $1=command $2=exit $3=cause
125
+ [[ -n "${SOLEUR_COLLECTOR_STATUS_DIR:-}" ]] || return 0
126
+ mkdir -p "$SOLEUR_COLLECTOR_STATUS_DIR" 2>/dev/null || return 0
127
+ jq -nc \
128
+ --arg c "$1" \
129
+ --argjson e "$2" \
130
+ --arg r "${3:-}" \
131
+ --arg w "${_CAP_WARN:-}" \
132
+ '{collector: "github", command: $c, exit: $e, cause: $r}
133
+ + (if $w == "" then {} else {warn: $w} end)' \
134
+ >>"$SOLEUR_COLLECTOR_STATUS_DIR/collector-status.jsonl" 2>/dev/null || true
135
+ }
136
+
137
+ _on_exit() {
138
+ local rc=$?
139
+ if ((${#_TMPFILES[@]} > 0)); then
140
+ rm -f "${_TMPFILES[@]}"
141
+ fi
142
+ # A failure after the compact projection was armed, with no earlier cause, is the projection.
143
+ if ((rc != 0)) && [[ -z "$_CAUSE" ]]; then _CAUSE="$_COMPACT_CAUSE"; fi
144
+ # Inside the cron (status dir set) but the handler flag did not reach us: say so in-surface.
145
+ if [[ "$_COMPACT_OFF" -eq 1 && ( -z "$_CAP_WARN" || "$_CAP_WARN" == truncated_at_per_page ) ]]; then _CAP_WARN="compact_off"; fi
146
+ _record_status "${_COMMAND:-unknown}" "$rc" "$_CAUSE"
147
+ }
148
+
149
+ # Rejects any payload that is not a JSON array. A 404/403/410 body arrives at
150
+ # exit 0 and reaches jq as an object; without this the failure surfaces as an
151
+ # opaque "Cannot index string" from deep inside a jq program. This turns it into
152
+ # a named, greppable cause.
153
+ check_array_response() { # $1=file $2=what
154
+ # An empty body is NOT an empty result. The API renders "no results" as `[]`,
155
+ # so zero bytes means the response was lost, not that the period was quiet --
156
+ # and slurping an empty file yields [], which would render a plausible 0. This
157
+ # is the last path by which a missing fetch could still look like a quiet day.
158
+ if [[ ! -s "$1" ]] || [[ "$(jq -s 'length' <"$1" 2>/dev/null || echo 0)" -eq 0 ]]; then
159
+ _CAUSE="${2}-empty-response"
160
+ echo "GITHUB_COLLECTOR_CAUSE=${2} returned an empty body (expected a JSON array)" >&2
161
+ echo "Error: Failed to fetch ${2} (empty response)" >&2
162
+ exit 1
163
+ fi
164
+ if ! jq -se 'all(type == "array")' <"$1" >/dev/null 2>&1; then
165
+ local detail
166
+ detail=$(jq -rs '.[0].message? // empty' <"$1" 2>/dev/null | head -c 200)
167
+ _CAUSE="${2}-non-array"
168
+ echo "GITHUB_COLLECTOR_CAUSE=${2} returned a non-array payload: ${detail:-unparseable}" >&2
169
+ echo "Error: Failed to fetch ${2} (non-array response)" >&2
170
+ exit 1
171
+ fi
172
+ }
173
+
174
+ # True when the handler asked for compact output. A non-empty value other than 1 prints
175
+ # one fixed line (never the raw value) and leaves output unchanged.
176
+ compact_on() {
177
+ [[ "${SOLEUR_COLLECTOR_COMPACT:-}" == "1" ]] && return 0
178
+ if [[ -n "${SOLEUR_COLLECTOR_COMPACT:-}" ]]; then
179
+ echo "compact mode ignored: SOLEUR_COLLECTOR_COMPACT must be 1" >&2
180
+ fi
181
+ return 1
182
+ }
183
+
184
+ # Prints a compact result. Called in the parent scope (never through a pipe), so the
185
+ # warn it may set reaches the EXIT trap's sidecar record.
186
+ emit_compact() { # $1=compact JSON
187
+ local bytes
188
+ bytes=$(printf '%s' "$1" | wc -c)
189
+ # Lowest priority: a truncation warn means counts may be undercounted, and
190
+ # stargazers_unavailable is acted on by the handler; both outrank a size note.
191
+ if ((bytes > COMPACT_BUDGET_BYTES)) && [[ -z "$_CAP_WARN" ]]; then
192
+ _CAP_WARN="compact_over_budget"
193
+ fi
194
+ # The projection succeeded: a later failure is not a projection failure.
195
+ _COMPACT_CAUSE=""
196
+ printf '%s\n' "$1"
197
+ }
198
+
199
+ _json_len() { # $1=file
200
+ jq -s 'add // [] | length' <"$1" 2>/dev/null || echo 0
201
+ }
202
+
203
+ # A response holding exactly per_page items is indistinguishable from a
204
+ # truncated one. Record it so a future growth-driven undercount is loud instead
205
+ # of silent. This is detection, not pagination.
206
+ #
207
+ # NOT applied to stargazers: that fetch paginates to exhaustion, so a total of
208
+ # exactly PER_PAGE means the set is COMPLETE, not truncated -- warning there
209
+ # would cry wolf on any repo sitting at exactly 100 stars.
210
+ #
211
+ # Takes a COUNT, not a file, because "a full page" only means truncation for
212
+ # endpoints that filter server-side. The pulls endpoint deliberately over-fetches
213
+ # a fixed page and filters by date afterwards, so a full raw page is its normal
214
+ # state -- warning on it would fire every run and train the reader to ignore the
215
+ # signal. For that endpoint the caller passes the post-filter count instead,
216
+ # where a full page really does mean the window is saturated.
217
+ check_cap() { # $1=count $2=what
218
+ if [[ "${1:-0}" -eq "$PER_PAGE" ]]; then
219
+ _CAP_WARN="truncated_at_per_page"
220
+ echo "WARN: ${2} returned exactly ${PER_PAGE} items (per_page cap) -- results may be truncated" >&2
221
+ fi
222
+ }
223
+
224
+ # --- Commands ---
225
+
226
+ cmd_activity() {
227
+ local days="${1:-7}"
228
+ local repo
229
+ repo=$(detect_repo)
230
+ local since
231
+ since=$(date_n_days_ago "$days")
232
+
233
+ # Payloads are spooled to files and read by jq through a file descriptor.
234
+ # Passing them as command-line bindings placed the whole body in a single
235
+ # execve argument, which breaches MAX_ARG_STRLEN (131,072 B PER ARGUMENT --
236
+ # not the 2 MB ARG_MAX total). That is why this failed on as few as 10 items:
237
+ # the ceiling is per-argument byte size, not item count. `printf` is a shell
238
+ # builtin, so spooling itself invokes no execve and has no size limit.
239
+ local issues_f prs_f
240
+ issues_f=$(mktemp)
241
+ _TMPFILES+=("$issues_f")
242
+ prs_f=$(mktemp)
243
+ _TMPFILES+=("$prs_f")
244
+
245
+ local issues prs
246
+ issues=$(gh api "repos/${repo}/issues?state=all&since=${since}&per_page=${PER_PAGE}" 2>&1) || {
247
+ _CAUSE="issues-fetch-failed"
248
+ echo "GITHUB_COLLECTOR_CAUSE=issues: $(echo "$issues" | head -c 200 | tr '\n' ' ')" >&2
249
+ echo "Error: Failed to fetch issues ($(echo "$issues" | head -c 200))" >&2
250
+ exit 1
251
+ }
252
+ check_rate_limit "$issues"
253
+ printf '%s' "$issues" >"$issues_f"
254
+ check_array_response "$issues_f" issues
255
+ check_cap "$(_json_len "$issues_f")" issues
256
+
257
+ prs=$(gh api "repos/${repo}/pulls?state=all&sort=updated&direction=desc&per_page=${PER_PAGE}" 2>&1) || {
258
+ _CAUSE="pulls-fetch-failed"
259
+ echo "GITHUB_COLLECTOR_CAUSE=pulls: $(echo "$prs" | head -c 200 | tr '\n' ' ')" >&2
260
+ echo "Error: Failed to fetch PRs ($(echo "$prs" | head -c 200))" >&2
261
+ exit 1
262
+ }
263
+ check_rate_limit "$prs"
264
+ printf '%s' "$prs" >"$prs_f"
265
+ check_array_response "$prs_f" pulls
266
+ # Post-filter count: see check_cap on why pulls is measured after the date filter.
267
+ check_cap "$(jq -s --arg since "$since" 'add // [] | map(select(.updated_at >= $since)) | length' <"$prs_f" 2>/dev/null || echo 0)" pulls
268
+
269
+ # The slurped binding wraps the file's contents in an array, so a single-array
270
+ # body reads as [[...]] and a paginated body as [[...],[...]]. `add // []`
271
+ # flattens both to one array, giving every binding in this file the same
272
+ # dereference shape. Leaving `length` applied to the wrapper while fixing only
273
+ # the projection is the silent failure: it emits count 1 alongside a full
274
+ # items array, at exit 0.
275
+ if compact_on; then
276
+ _COMPACT_CAUSE="compact-projection-failed"
277
+ local out
278
+ out=$(jq -nc \
279
+ --slurpfile issues "$issues_f" \
280
+ --slurpfile prs "$prs_f" \
281
+ --arg since "$since" \
282
+ --argjson max "$COMPACT_MAX_ITEMS" \
283
+ --argjson tmax "$COMPACT_TITLE_MAX" \
284
+ 'def titles: sort_by(.updated_at) | reverse | .[:$max] | map((.title // "" | tostring | gsub("[[:cntrl:]\\p{Cf}\u2028\u2029]"; " "))[:$tmax]);
285
+ ($issues | add // [] | map(select(.pull_request == null))) as $iss
286
+ | ($prs | add // [] | map(select(.updated_at >= $since))) as $pr
287
+ | {issues: {count: ($iss | length), titles: ($iss | titles)},
288
+ pull_requests: {count: ($pr | length), titles: ($pr | titles)}}')
289
+ emit_compact "$out"
290
+ return 0
291
+ fi
292
+
293
+ jq -n \
294
+ --slurpfile issues "$issues_f" \
295
+ --slurpfile prs "$prs_f" \
296
+ --arg since "$since" \
297
+ --arg repo "$repo" \
298
+ '($issues | add // [] | map(select(.pull_request == null))) as $iss
299
+ | ($prs | add // [] | map(select(.updated_at >= $since))) as $pr
300
+ | {
301
+ repo: $repo,
302
+ since: $since,
303
+ issues: {
304
+ count: ($iss | length),
305
+ items: [$iss[] | {number, title, state, user: .user.login, created_at, updated_at}]
306
+ },
307
+ pull_requests: {
308
+ count: ($pr | length),
309
+ items: [$pr[] | {number, title, state, user: .user.login, created_at, updated_at, merged_at}]
310
+ }
311
+ }'
312
+ }
313
+
314
+ cmd_contributors() {
315
+ local days="${1:-7}"
316
+ local repo
317
+ repo=$(detect_repo)
318
+ local since
319
+ since=$(date_n_days_ago "$days")
320
+
321
+ # Same per-argument ceiling as cmd_activity -- spool, then read via jq's file
322
+ # descriptor. Both files are registered with the single EXIT trap.
323
+ local commits_f issues_f
324
+ commits_f=$(mktemp)
325
+ _TMPFILES+=("$commits_f")
326
+ issues_f=$(mktemp)
327
+ _TMPFILES+=("$issues_f")
328
+
329
+ # Get contributors from recent commits
330
+ local commits
331
+ commits=$(gh api "repos/${repo}/commits?since=${since}&per_page=${PER_PAGE}" 2>&1) || {
332
+ _CAUSE="commits-fetch-failed"
333
+ echo "GITHUB_COLLECTOR_CAUSE=commits: $(echo "$commits" | head -c 200 | tr '\n' ' ')" >&2
334
+ echo "Error: Failed to fetch commits ($(echo "$commits" | head -c 200))" >&2
335
+ exit 1
336
+ }
337
+ check_rate_limit "$commits"
338
+ printf '%s' "$commits" >"$commits_f"
339
+ check_array_response "$commits_f" commits
340
+ check_cap "$(_json_len "$commits_f")" commits
341
+
342
+ # Compact mode reads only the commit total: the issues fetch below would add a call (and a
343
+ # failure surface) for a field the compact line never carries.
344
+ if compact_on; then
345
+ _COMPACT_CAUSE="compact-projection-failed"
346
+ local out
347
+ out=$(jq -nc --slurpfile commits "$commits_f" \
348
+ '{commit_total: ([($commits | add // [])[] | .author.login // .commit.author.name | select(. != null)] | length)}')
349
+ emit_compact "$out"
350
+ return 0
351
+ fi
352
+
353
+ # Get contributors from recent issues/PRs
354
+ local issues
355
+ issues=$(gh api "repos/${repo}/issues?state=all&since=${since}&per_page=${PER_PAGE}" 2>&1) || {
356
+ _CAUSE="issues-fetch-failed"
357
+ echo "GITHUB_COLLECTOR_CAUSE=issues: $(echo "$issues" | head -c 200 | tr '\n' ' ')" >&2
358
+ echo "Error: Failed to fetch issues ($(echo "$issues" | head -c 200))" >&2
359
+ exit 1
360
+ }
361
+ check_rate_limit "$issues"
362
+ printf '%s' "$issues" >"$issues_f"
363
+ check_array_response "$issues_f" issues
364
+ check_cap "$(_json_len "$issues_f")" issues
365
+
366
+ jq -n \
367
+ --slurpfile commits "$commits_f" \
368
+ --slurpfile issues "$issues_f" \
369
+ --arg since "$since" \
370
+ --arg repo "$repo" \
371
+ '($commits | add // []) as $cm
372
+ | ($issues | add // []) as $iss
373
+ | {
374
+ repo: $repo,
375
+ since: $since,
376
+ commit_authors: [
377
+ $cm[]
378
+ | .author.login // .commit.author.name
379
+ | select(. != null)
380
+ ] | group_by(.) | map({login: .[0], commits: length}) | sort_by(-.commits),
381
+ issue_authors: [
382
+ $iss[]
383
+ | .user.login
384
+ | select(. != null)
385
+ ] | group_by(.) | map({login: .[0], activity: length}) | sort_by(-.activity)
386
+ }'
387
+ }
388
+
389
+ cmd_discussions() {
390
+ local days="${1:-7}"
391
+ local repo
392
+ repo=$(detect_repo)
393
+ local owner repo_name
394
+ owner=$(echo "$repo" | cut -d/ -f1)
395
+ repo_name=$(echo "$repo" | cut -d/ -f2)
396
+ local since
397
+ since=$(date_n_days_ago "$days")
398
+
399
+ # Discussions require GraphQL
400
+ local query='query($owner: String!, $repo: String!) {
401
+ repository(owner: $owner, name: $repo) {
402
+ discussions(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) {
403
+ nodes {
404
+ number
405
+ title
406
+ author { login }
407
+ createdAt
408
+ updatedAt
409
+ answerChosenAt
410
+ comments { totalCount }
411
+ category { name }
412
+ }
413
+ }
414
+ }
415
+ }'
416
+
417
+ local result
418
+ result=$(gh api graphql -f query="$query" -f owner="$owner" -f repo="$repo_name" 2>&1) || {
419
+ # Discussions not enabled -- return empty
420
+ if grep -qi "not found\|not accessible\|discussions are not enabled" <<<"$result"; then
421
+ if compact_on; then
422
+ emit_compact '{"titles":[]}'
423
+ return 0
424
+ fi
425
+ echo '{"discussions": [], "note": "Discussions not enabled for this repository"}'
426
+ return 0
427
+ fi
428
+ echo "Error: Failed to fetch discussions ($(echo "$result" | head -c 200))" >&2
429
+ exit 1
430
+ }
431
+ check_rate_limit "$result"
432
+
433
+ if compact_on; then
434
+ _COMPACT_CAUSE="compact-projection-failed"
435
+ local out
436
+ out=$(jq -c --arg since "$since" \
437
+ --argjson max "$COMPACT_MAX_ITEMS" \
438
+ --argjson tmax "$COMPACT_TITLE_MAX" \
439
+ '{titles: [.data.repository.discussions.nodes
440
+ | map(select(.updatedAt >= $since))
441
+ | sort_by(.updatedAt) | reverse | .[:$max][]
442
+ | (.title // "" | tostring | gsub("[[:cntrl:]\\p{Cf}\u2028\u2029]"; " "))[:$tmax]]}' <<<"$result")
443
+ emit_compact "$out"
444
+ return 0
445
+ fi
446
+
447
+ # Filter to recent discussions and format
448
+ echo "$result" | jq --arg since "$since" '{
449
+ discussions: [
450
+ .data.repository.discussions.nodes[]
451
+ | select(.updatedAt >= $since)
452
+ | {
453
+ number,
454
+ title,
455
+ author: .author.login,
456
+ created_at: .createdAt,
457
+ updated_at: .updatedAt,
458
+ answered: (.answerChosenAt != null),
459
+ comment_count: .comments.totalCount,
460
+ category: .category.name
461
+ }
462
+ ]
463
+ }'
464
+ }
465
+
466
+ cmd_repo_stats() {
467
+ local days="${1:-7}"
468
+ local repo
469
+ repo=$(detect_repo)
470
+ local since
471
+ since=$(date_n_days_ago "$days")
472
+
473
+ # Fetch repo metadata. This body is a single repo object (~7 KB), well under
474
+ # the per-argument ceiling, so it stays an inline binding.
475
+ local repo_data
476
+ repo_data=$(gh api "repos/${repo}" 2>&1) || {
477
+ _CAUSE="repo-metadata-fetch-failed"
478
+ echo "GITHUB_COLLECTOR_CAUSE=repo metadata: $(echo "$repo_data" | head -c 200 | tr '\n' ' ')" >&2
479
+ echo "Error: Failed to fetch repo metadata ($(echo "$repo_data" | head -c 200))" >&2
480
+ exit 1
481
+ }
482
+ check_rate_limit "$repo_data"
483
+
484
+ # Object-shaped counterpart to check_array_response: an error body would
485
+ # otherwise reach the jq program and surface as an opaque indexing error.
486
+ if ! echo "$repo_data" | jq -e '(.stargazers_count | type) == "number"' >/dev/null 2>&1; then
487
+ _CAUSE="repo-metadata-non-numeric"
488
+ echo "GITHUB_COLLECTOR_CAUSE=repo metadata lacked a numeric stargazers_count: $(echo "$repo_data" | jq -r '.message // "unknown"' 2>/dev/null | head -c 200)" >&2
489
+ echo "Error: Failed to fetch repo metadata (unexpected shape)" >&2
490
+ exit 1
491
+ fi
492
+
493
+ # Fetch stargazers with timestamps (custom Accept header).
494
+ # stdout and stderr go to SEPARATE files. Folding the error stream into the
495
+ # JSON stream is what broke this parse: a single warning byte from the API
496
+ # client made the whole payload unparseable. Keeping them apart preserves the
497
+ # diagnostic without corrupting the data.
498
+ # --paginate emits one array per page; the slurped binding is flattened below.
499
+ local star_f star_err
500
+ star_f=$(mktemp)
501
+ _TMPFILES+=("$star_f")
502
+ star_err=$(mktemp)
503
+ _TMPFILES+=("$star_err")
504
+
505
+ # A READ-scoped installation token cannot list stargazers: GitHub answers 403
506
+ # "Resource not accessible by integration" unless the token carries contents:write
507
+ # (measured 2026-10-06 against REST and GraphQL; no read-level permission unlocks
508
+ # it). The cron spawns this script with a read-only token on purpose, so that
509
+ # response is the token's known limit and not a collector fault: the count is
510
+ # reported as null (unavailable) while everything else in repo-stats stays valid.
511
+ # Any other failure is still a hard failure.
512
+ local star_unavailable=0
513
+ if ! gh api "repos/${repo}/stargazers?per_page=${PER_PAGE}" \
514
+ -H "Accept: application/vnd.github.star+json" \
515
+ --paginate >"$star_f" 2>"$star_err"; then
516
+ # Both conjuncts: the message alone also appears behind other statuses, and a bare 403
517
+ # is also what a rate limit or SSO block prints. gh prints
518
+ # `gh: Resource not accessible by integration (HTTP 403)` on stderr (measured).
519
+ if grep -qi 'Resource not accessible by integration' "$star_err" && grep -q 'HTTP 403' "$star_err"; then
520
+ star_unavailable=1
521
+ # Recorded in the sidecar so the HANDLER knows without trusting the model: it forces
522
+ # the github row to partial/auth while this warn is present (cron-community-monitor.ts).
523
+ _CAP_WARN="stargazers_unavailable"
524
+ echo '[]' >"$star_f"
525
+ echo "WARN: stargazers are not readable with this token; new_stargazers_count is null" >&2
526
+ else
527
+ _CAUSE="stargazers-fetch-failed"
528
+ echo "GITHUB_COLLECTOR_CAUSE=stargazers: $(head -c 200 "$star_err" | tr '\n' ' ')" >&2
529
+ echo "Error: Failed to fetch stargazers" >&2
530
+ exit 1
531
+ fi
532
+ fi
533
+ check_array_response "$star_f" stargazers
534
+
535
+ if compact_on; then
536
+ _COMPACT_CAUSE="compact-projection-failed"
537
+ local out
538
+ out=$(jq -nc \
539
+ --argjson repo_data "$repo_data" \
540
+ --slurpfile stargazers "$star_f" \
541
+ --arg since "$since" \
542
+ --argjson unavailable "$star_unavailable" \
543
+ 'def num: if type == "number" then . else error("compact: numeric field missing") end;
544
+ (($stargazers | add // []) | map(select(.starred_at >= $since)) | length) as $new
545
+ | {
546
+ stargazers_count: ($repo_data.stargazers_count | num),
547
+ forks_count: ($repo_data.forks_count | num),
548
+ subscribers_count: ($repo_data.subscribers_count | num),
549
+ new_stargazers_count: (if $unavailable == 1 then null else $new end),
550
+ stargazers_unavailable: ($unavailable == 1)
551
+ }')
552
+ emit_compact "$out"
553
+ return 0
554
+ fi
555
+
556
+ # Combine and filter
557
+ jq -n \
558
+ --argjson repo_data "$repo_data" \
559
+ --slurpfile stargazers "$star_f" \
560
+ --arg since "$since" \
561
+ --arg repo "$repo" \
562
+ --argjson days "$days" \
563
+ --argjson unavailable "$star_unavailable" \
564
+ '($stargazers | add // []) as $sg
565
+ | ([$sg[] | select(.starred_at >= $since) | {login: .user.login, starred_at}]) as $new
566
+ | {
567
+ repo: $repo,
568
+ since: $since,
569
+ stargazers_count: $repo_data.stargazers_count,
570
+ forks_count: $repo_data.forks_count,
571
+ watchers_count: $repo_data.watchers_count,
572
+ subscribers_count: $repo_data.subscribers_count,
573
+ new_stargazers: (if $unavailable == 1 then null else $new end),
574
+ new_stargazers_count: (if $unavailable == 1 then null else ($new | length) end),
575
+ stargazers_unavailable: ($unavailable == 1),
576
+ period_days: $days
577
+ }'
578
+ }
579
+
580
+ cmd_fetch_interactions() {
581
+ local days="${1:-1}"
582
+ local repo
583
+ repo=$(detect_repo)
584
+ local since
585
+ since=$(date_n_days_ago "$days")
586
+
587
+ # Fetch all issue/PR comments since cutoff (paginated).
588
+ # Use temp file -- paginated results can exceed shell argument limits.
589
+ # Registered with the single EXIT trap rather than removed by hand: the old
590
+ # form cleaned up only on the paths it remembered, leaking the spool on every
591
+ # other early exit.
592
+ #
593
+ # stdout and stderr go to separate files for the same reason as the stargazer
594
+ # fetch. The old form discarded stderr and collapsed the body through
595
+ # `add // []` BEFORE any validation, so a lost or error response became an
596
+ # empty interaction list at exit 0 -- a quiet day, indistinguishable from a
597
+ # real one.
598
+ local tmpfile err_f
599
+ tmpfile=$(mktemp)
600
+ _TMPFILES+=("$tmpfile")
601
+ err_f=$(mktemp)
602
+ _TMPFILES+=("$err_f")
603
+
604
+ if ! gh api "repos/${repo}/issues/comments?since=${since}&per_page=${PER_PAGE}" \
605
+ --paginate >"$tmpfile" 2>"$err_f"; then
606
+ _CAUSE="issue-comments-fetch-failed"
607
+ echo "GITHUB_COLLECTOR_CAUSE=issue comments: $(head -c 200 "$err_f" | tr '\n' ' ')" >&2
608
+ echo "Error: Failed to fetch issue comments" >&2
609
+ exit 1
610
+ fi
611
+ check_array_response "$tmpfile" issue-comments
612
+
613
+ if compact_on; then
614
+ _COMPACT_CAUSE="compact-projection-failed"
615
+ local out
616
+ # Counts computed here so no login or comment text reaches the model.
617
+ out=$(jq -nc --slurpfile comments "$tmpfile" \
618
+ '[($comments | add // [])[]
619
+ | select(
620
+ (.author_association == "NONE" or
621
+ .author_association == "CONTRIBUTOR" or
622
+ .author_association == "FIRST_TIMER" or
623
+ .author_association == "FIRST_TIME_CONTRIBUTOR") and
624
+ (.user.type != "Bot") and
625
+ (.user.login | test("\\[bot\\]$") | not)
626
+ )] as $i
627
+ | {external_contributors: ([$i[] | .user.login] | unique | length),
628
+ interactions_count: ($i | length)}')
629
+ emit_compact "$out"
630
+ return 0
631
+ fi
632
+
633
+ # Filter to external users only, exclude bots
634
+ jq -n --slurpfile comments "$tmpfile" --arg since "$since" --arg repo "$repo" \
635
+ '($comments | add // []) as $c
636
+ | {
637
+ repo: $repo,
638
+ since: $since,
639
+ interactions: [
640
+ $c[]
641
+ | select(
642
+ (.author_association == "NONE" or
643
+ .author_association == "CONTRIBUTOR" or
644
+ .author_association == "FIRST_TIMER" or
645
+ .author_association == "FIRST_TIME_CONTRIBUTOR") and
646
+ (.user.type != "Bot") and
647
+ (.user.login | test("\\[bot\\]$") | not)
648
+ )
649
+ | {
650
+ user: .user.login,
651
+ issue_number: (.issue_url | split("/") | last | tonumber),
652
+ body_snippet: (.body | gsub("\n"; " ") | .[:120]),
653
+ url: .html_url,
654
+ created_at: .created_at
655
+ }
656
+ ]
657
+ }'
658
+ }
659
+
660
+ # --- Main ---
661
+
662
+ main() {
663
+ local command="${1:-}"
664
+ shift || true
665
+
666
+ if [[ -z "$command" ]]; then
667
+ echo "Usage: github-community.sh <command> [args]" >&2
668
+ echo "" >&2
669
+ echo "Commands:" >&2
670
+ echo " activity [days] - Recent issues, PRs, and comments" >&2
671
+ echo " contributors [days] - Active contributors in period" >&2
672
+ echo " discussions [days] - Recent discussions (if enabled)" >&2
673
+ echo " repo-stats [days] - Stars, forks, watchers, new stargazers" >&2
674
+ echo " fetch-interactions [days] - External user comments on issues/PRs" >&2
675
+ exit 1
676
+ fi
677
+
678
+ # One trap for the whole run, registered before the first thing that can
679
+ # fail, so cleanup and the status record cover validation failures too.
680
+ # EXIT, never RETURN: a RETURN trap does not fire on `exit`, which is exactly
681
+ # how every failure branch below terminates.
682
+ _COMMAND="$command"
683
+ trap _on_exit EXIT
684
+
685
+ # Inside the cron (status dir set) the handler is expected to have set the flag.
686
+ if [[ -n "${SOLEUR_COLLECTOR_STATUS_DIR:-}" && "${SOLEUR_COLLECTOR_COMPACT:-}" != "1" ]]; then
687
+ _COMPACT_OFF=1
688
+ fi
689
+
690
+ validate_gh
691
+
692
+ case "$command" in
693
+ activity) cmd_activity "$@" ;;
694
+ contributors) cmd_contributors "$@" ;;
695
+ discussions) cmd_discussions "$@" ;;
696
+ repo-stats) cmd_repo_stats "$@" ;;
697
+ fetch-interactions) cmd_fetch_interactions "$@" ;;
698
+ *)
699
+ echo "Error: Unknown command '${command}'" >&2
700
+ echo "Run 'github-community.sh' without arguments for usage." >&2
701
+ exit 1
702
+ ;;
703
+ esac
704
+ }
705
+
706
+ main "$@"