@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,92 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Harness-parity census over the plugin doc population (ADR-226, #8299).
4
+ *
5
+ * Usage:
6
+ * bun plugins/soleur/scripts/harness-parity-census.ts --report # print every non-canonical site; exit 1 if any
7
+ * bun plugins/soleur/scripts/harness-parity-census.ts --fix # rewrite the mechanical shapes in place (idempotent)
8
+ *
9
+ * The gate is `plugins/soleur/test/harness-parity-tree.test.ts`; this CLI is the author's
10
+ * inner loop and the remediation tool. `--fix` inverts only `/soleur:x`, `$soleur:x`,
11
+ * `@agent-soleur:x` and grok `/x` for a known skill; bare agent leaves, `@agent-<leaf>`
12
+ * mentions and grok stems in prose are hand edits (the sentence around them changes).
13
+ *
14
+ * `--fix` REWRITES TRACKED FILES IN PLACE and is the remedy the gate's own failure message
15
+ * prescribes, so it refuses to run against a dirty working tree unless `--force` is passed.
16
+ * That is not ceremony: a grok slash and a root-relative path are lexically identical after a
17
+ * boundary character (`run /plan` vs `POST /invoice`), so a rewrite CAN consume a real byte,
18
+ * and the result then classifies CANONICAL — meaning the census reports clean and the loss is
19
+ * invisible to the gate. Requiring a clean tree makes every rewrite reviewable with `git diff`
20
+ * and revertible with `git checkout`, which is the only guard that covers the whole class
21
+ * rather than one spelling of it.
22
+ */
23
+
24
+ import { execFileSync } from "child_process";
25
+ import { writeFileSync } from "fs";
26
+ import { resolve } from "path";
27
+ import { REPO_ROOT, census, classifyDoc, fixDoc, formatReport, readIndex, readPopulation } from "../lib/harness-parity";
28
+
29
+ const args = new Set(process.argv.slice(2));
30
+ const mode = args.has("--fix") ? "fix" : args.has("--report") ? "report" : undefined;
31
+ if (mode === undefined) {
32
+ console.error("usage: harness-parity-census.ts --report | --fix [--force]");
33
+ process.exit(2);
34
+ }
35
+
36
+ if (mode === "fix" && !args.has("--force")) {
37
+ const dirty = execFileSync("git", ["status", "--porcelain", "--", "plugins/soleur"], {
38
+ cwd: REPO_ROOT,
39
+ encoding: "utf-8",
40
+ }).trim();
41
+ if (dirty.length > 0) {
42
+ console.error(
43
+ [
44
+ "harness-parity --fix: refusing to rewrite a dirty tree — it edits tracked files in place,",
45
+ "and an uncommitted change would be indistinguishable from its own rewrites in `git diff`.",
46
+ "Commit or discard the changes below, then re-run; pass --force to override.",
47
+ "",
48
+ dirty,
49
+ ].join("\n"),
50
+ );
51
+ process.exit(2);
52
+ }
53
+ }
54
+
55
+ const index = readIndex();
56
+ const docs = readPopulation();
57
+
58
+ if (mode === "fix") {
59
+ let changed = 0;
60
+ let skipped = 0;
61
+ for (const doc of docs) {
62
+ // A malformed marker leaves the region state unreliable, and `fixDoc` mirrors that state to
63
+ // decide what is exempt — so rewriting such a doc can edit inside a region the author meant
64
+ // to protect. Report it and leave it; the marker is RED in the gate either way.
65
+ const pre = classifyDoc(doc.text, index, doc.regionPolicy, doc.path);
66
+ if (pre.errors.length > 0) {
67
+ console.log(`skipped ${doc.path} — malformed marker, fix the marker first:`);
68
+ for (const e of pre.errors) console.log(` ${e}`);
69
+ skipped += 1;
70
+ continue;
71
+ }
72
+ const fixed = fixDoc(doc.text, index, doc.regionPolicy);
73
+ if (fixed !== doc.text) {
74
+ writeFileSync(resolve(REPO_ROOT, doc.path), fixed);
75
+ changed += 1;
76
+ console.log(`fixed ${doc.path}`);
77
+ }
78
+ }
79
+ const after = census(readPopulation(), index);
80
+ console.log(`harness-parity --fix: ${changed} docs rewritten, ${skipped} skipped for malformed markers; ${after.noncanonical.length} non-canonical sites remain (hand edits)`);
81
+ process.exit(0);
82
+ }
83
+
84
+ const result = census(docs, index);
85
+ console.log(formatReport(result));
86
+ if (result.noncanonical.length > 0 || result.errors.length > 0) {
87
+ console.log(
88
+ `\nRED: ${result.noncanonical.length} non-canonical sites, ${result.errors.length} marker errors. ` +
89
+ "Run `bun plugins/soleur/scripts/harness-parity-census.ts --fix` for the mechanical shapes (it requires a clean tree, so its rewrites stay reviewable with `git diff`); the rest are hand edits.",
90
+ );
91
+ process.exit(1);
92
+ }
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bun
2
+ // Discoverability probe for #8296 PR-1: does the SOURCE declare the Inngest wrong-volume
3
+ // Better Stack alert ARMED? Resolves `paused = !var.inngest_luks_cutover_complete` against the
4
+ // variable's declared default through the same code path the drift reconciler uses
5
+ // (../lib/heartbeat-live-reconcile.ts via discoverLogsAlertsFromInfra), so a regression in either
6
+ // the declaration or the resolver prints EXEMPT here before it silences the twice-daily report.
7
+ //
8
+ // Credential-free and sub-second: it reads apps/web-platform/infra/*.tf only. It says nothing
9
+ // about the LIVE alert (a Doppler TF_VAR override, or a vendor-side pause) — that half is the
10
+ // reconciler's job on scheduled-terraform-drift.yml, and PR-2's followthrough probe covers the
11
+ // device the store is actually on.
12
+ //
13
+ // This is a standalone file, not a `bun -e` one-liner, because preflight Check 10 (ADR-175)
14
+ // runs the plan's discoverability command inside a sandbox behind a shell-active-token reject:
15
+ // an arrow function's `=>` and a statement `;` both trip it, by design.
16
+ //
17
+ // Exit 0 + "ARMED" when the declaration resolves to paused=false; exit 1 + "EXEMPT" otherwise
18
+ // (unresolvable variable, non-boolean default, or the alert missing from the root entirely).
19
+ import { discoverLogsAlertsFromInfra } from "./reconcile-live-heartbeats.ts";
20
+
21
+ // argv[2] is a TEST seam only (a synthesized root with the default flipped); the plan's
22
+ // discoverability command passes nothing and reads the real root.
23
+ const INFRA_DIR = process.argv[2] ?? "apps/web-platform/infra";
24
+ const RESOURCE = "inngest_luks_wrong_volume";
25
+
26
+ const alert = discoverLogsAlertsFromInfra(INFRA_DIR).find((a) => a.resourceName === RESOURCE);
27
+ const armed = alert?.pausedResolvesFalse === true;
28
+ console.log(armed ? "ARMED" : "EXEMPT");
29
+ process.exit(armed ? 0 : 1);
@@ -0,0 +1,520 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Install the generated OpenCode front door into an OpenCode config directory.
4
+ *
5
+ * bun plugins/soleur/scripts/install-opencode-adapter.ts # ~/.config/opencode
6
+ * bun plugins/soleur/scripts/install-opencode-adapter.ts --target DIR # e.g. a project .opencode
7
+ * bun plugins/soleur/scripts/install-opencode-adapter.ts --check --target DIR
8
+ *
9
+ * Why this exists: the generated tree commits its paths as `__SOLEUR_PLUGIN_ROOT__` rather
10
+ * than absolute ones, because the tree is shared across machines and an absolute path would
11
+ * make `sync-opencode-adapter.ts --check` machine-dependent. OpenCode's `skills` and
12
+ * `instructions` keys take plain paths with no env expansion, and the config schema has no
13
+ * `import` key (measurement §7.1), so something must resolve the token once, on the
14
+ * operator's machine. That is this script.
15
+ *
16
+ * Shapes here are each forced by a measurement:
17
+ *
18
+ * - `agents/` and `commands/` are copied straight into the config dir, because those are
19
+ * the roots OpenCode discovers (§3.0, §4.0). Skills are **not** copied — they register
20
+ * from the canonical tree through the `skills` key (§2.0), so the config points at the
21
+ * checkout and a second skill tree that could drift is never created.
22
+ * - The config fragment is merged rather than written, so an operator's existing
23
+ * `skills` / `instructions` entries and every other key survive — for a config this script
24
+ * can READ. A config it cannot parse (JSONC comments, a syntax error, a torn write) is
25
+ * **refused**, not replaced: silently substituting `{}` would discard every key the operator
26
+ * ever set, and report success. `--force` replaces it after writing a `.bak-<ts>` beside it.
27
+ * - Writes are temp-file + rename, so an interrupted install cannot leave a half-written
28
+ * `opencode.json` whose next read takes the unparseable path.
29
+ * - The hook module (`opencode/plugin.ts`, source rather than a generated stub) is copied
30
+ * into `<configdir>/plugins/`, OpenCode's plugin discovery directory (measurement §6.6),
31
+ * with the plugin-root token resolved so the installed copy still reaches the checkout's
32
+ * guard scripts.
33
+ *
34
+ * `--check` writes nothing: it compares the target against `expectedInstalled` and exits 1
35
+ * on a difference.
36
+ */
37
+
38
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "fs";
39
+ import { dirname, join, relative, resolve } from "path";
40
+ import {
41
+ ADAPTER_DIR,
42
+ ADAPTER_SOURCE_FILES,
43
+ PLUGIN_ROOT_TOKEN,
44
+ configFragmentValues,
45
+ expectedOpenCodeAdapter,
46
+ } from "./sync-opencode-adapter";
47
+
48
+ const PLUGIN_ROOT = resolve(dirname(import.meta.filename), "..");
49
+
50
+ /**
51
+ * Where a vendored payload lives, target-relative.
52
+ *
53
+ * `<configdir>/soleur/` is already Soleur's exclusive namespace in a config dir (the installed
54
+ * `INSTRUCTIONS.md` lives there and `installedExtras` treats everything under it as ours by
55
+ * name), so the payload joins it rather than opening a second namespace. One directory is also
56
+ * one thing to remove on uninstall.
57
+ */
58
+ export const VENDOR_DIR = "soleur";
59
+
60
+ /**
61
+ * The plugin-root subtrees a vendored payload carries.
62
+ *
63
+ * A vendored payload is the canonical plugin root copied into the config dir. It exists because
64
+ * the npm distribution has **no checkout to point at**: `npx` runs the installer out of an
65
+ * ephemeral cache directory, so a config that named the package path rots the moment that cache
66
+ * is pruned — and the failure is silent, because the `skills` key and the guard scripts simply
67
+ * stop resolving. The copy is the durable root.
68
+ *
69
+ * Each entry is load-bearing: `skills` is what the `skills` key registers, `agents`/`commands`
70
+ * are what the generated stubs name, `hooks` is what the installed hook module spawns its guards
71
+ * from, `scripts` is what the canonical prose calls as `<root>/scripts/<name>.sh` (404 call
72
+ * sites), `lib` is what those scripts import, `opencode` is the generated tree the installer
73
+ * itself reads, and `.claude-plugin` is the identity marker `plugin-version.sh` and
74
+ * `resolve-regenerable-conflicts.sh` resolve the root by.
75
+ */
76
+ export const PAYLOAD_DIRS = [
77
+ "skills",
78
+ "agents",
79
+ "commands",
80
+ "hooks",
81
+ "scripts",
82
+ "lib",
83
+ ADAPTER_DIR,
84
+ ".claude-plugin",
85
+ ] as const;
86
+
87
+ /**
88
+ * Marker that tells a plugin root apart as a **vendored payload** rather than a checkout.
89
+ *
90
+ * It is what lets the copy's own `scripts/install-opencode-adapter.ts --check` pass: run from
91
+ * `<configdir>/soleur/`, the payload is inside the target, so the extras sweep would otherwise
92
+ * report every one of the ~800 payload files as EXTRA and exit 1 — a correct install graded as
93
+ * broken.
94
+ */
95
+ export const VENDOR_MARKER = ".soleur-vendored.json";
96
+
97
+ /** True when `root` is a payload the installer vendored, not a checkout. */
98
+ export function isVendoredRoot(root: string): boolean {
99
+ return existsSync(join(root, VENDOR_MARKER));
100
+ }
101
+
102
+ /**
103
+ * Deterministic marker bytes. No version and no timestamp: the payload's own files carry the
104
+ * version (an upgrade changes them and `--check` reports STALE), and a version here would make
105
+ * the marker flap between the two install modes.
106
+ */
107
+ function vendorMarkerContent(): string {
108
+ return `${JSON.stringify({ format: 1, kind: "soleur-opencode-payload", owns: [...PAYLOAD_DIRS] }, null, 2)}\n`;
109
+ }
110
+
111
+ /** Every file under `<root>/<dir>`, keyed `<dir>/<relative path>`, in sorted order. */
112
+ function walkPayloadFiles(root: string, dir: string): Array<[string, string]> {
113
+ const found: Array<[string, string]> = [];
114
+ const visit = (relativeDir: string): void => {
115
+ let entries;
116
+ try {
117
+ entries = readdirSync(join(root, relativeDir), { withFileTypes: true });
118
+ } catch {
119
+ return;
120
+ }
121
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
122
+ const path = `${relativeDir}/${entry.name}`;
123
+ if (entry.isDirectory()) {
124
+ visit(path);
125
+ continue;
126
+ }
127
+ found.push([path, readFileSync(join(root, path), "utf-8")]);
128
+ }
129
+ };
130
+ visit(dir);
131
+ return found;
132
+ }
133
+
134
+ export interface InstallOptions {
135
+ force?: boolean;
136
+ /**
137
+ * Mirror the canonical payload into `<target>/soleur/` and point every installed file at that
138
+ * copy instead of at `pluginRoot`. Used by the npm distribution, which has no checkout.
139
+ *
140
+ * A vendored payload is also recognised without this flag: a root carrying `VENDOR_MARKER`
141
+ * owns its payload wherever it sits inside the target, so the copy's own `--check` agrees
142
+ * with the install that produced it.
143
+ */
144
+ vendorPayload?: boolean;
145
+ }
146
+
147
+ /** `__SOLEUR_PLUGIN_ROOT__` → the real checkout. The only substitution in the whole install. */
148
+ function resolveToken(content: string, pluginRoot: string): string {
149
+ return content.split(PLUGIN_ROOT_TOKEN).join(pluginRoot);
150
+ }
151
+
152
+ /** Union a fragment's path arrays into an existing config, preserving every other key. */
153
+ export function mergeFragment(
154
+ existing: Record<string, unknown>,
155
+ fragment: { skills: string[]; instructions: string[] },
156
+ ): Record<string, unknown> {
157
+ const merged: Record<string, unknown> = { ...existing };
158
+ for (const key of ["skills", "instructions"] as const) {
159
+ const present = Array.isArray(existing[key]) ? (existing[key] as unknown[]) : [];
160
+ merged[key] = [...present, ...fragment[key]].filter((value, index, all) => all.indexOf(value) === index);
161
+ }
162
+ return merged;
163
+ }
164
+
165
+ /**
166
+ * A config file that exists but cannot be read as a JSON object.
167
+ *
168
+ * This is not a generic parse error: it is the branch that decides between merging into an
169
+ * operator's config and destroying it. It names the path and the remedy because the caller's
170
+ * only sane action is to look at that file.
171
+ */
172
+ export class UnparseableConfigError extends Error {
173
+ constructor(
174
+ readonly path: string,
175
+ readonly detail: string,
176
+ ) {
177
+ super(
178
+ `${path} exists but is not a JSON object (${detail}). Refusing to overwrite it — that would replace every key you set with the Soleur fragment alone. Fix the file, move it aside, or re-run with --force (which writes a timestamped backup first).`,
179
+ );
180
+ this.name = "UnparseableConfigError";
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Where each generated file lands in a config dir, with tokens resolved.
186
+ *
187
+ * The plugin module is the one file here that is **source, not a generated stub**: it is
188
+ * hand-written in the generator's namespace (`ADAPTER_SOURCE_FILES`) and installed into
189
+ * OpenCode's plugin discovery directory, `<configdir>/plugins/`, with the plugin-root token
190
+ * resolved so the checkout's guard scripts stay reachable from the installed copy.
191
+ */
192
+ export function expectedInstalled(
193
+ targetDir: string,
194
+ pluginRoot = PLUGIN_ROOT,
195
+ config?: Record<string, unknown>,
196
+ options: InstallOptions = {},
197
+ ): Map<string, string> {
198
+ const expected = new Map<string, string>();
199
+ // Where the installed files POINT, as opposed to where their bytes come from. The two are the
200
+ // same for a checkout install. They differ for a vendored payload, where the bytes come from
201
+ // the package and the pointer must name the copy — the only path that outlives the npm cache.
202
+ const effectiveRoot = options.vendorPayload === true ? join(targetDir, VENDOR_DIR) : pluginRoot;
203
+ for (const [path, content] of expectedOpenCodeAdapter(pluginRoot)) {
204
+ if (path === `${ADAPTER_DIR}/opencode.json`) continue; // merged below, never copied verbatim
205
+ // `opencode/` is the generator's namespace, not a discovery root. INSTRUCTIONS.md keeps a
206
+ // `soleur/` prefix so it cannot collide with anything the operator already has.
207
+ const installed =
208
+ path === `${ADAPTER_DIR}/INSTRUCTIONS.md` ? `soleur/${relative(ADAPTER_DIR, path)}` : relative(ADAPTER_DIR, path);
209
+ expected.set(installed, resolveToken(content, effectiveRoot));
210
+ }
211
+ for (const source of ADAPTER_SOURCE_FILES) {
212
+ if (!source.startsWith(`${ADAPTER_DIR}/`)) continue;
213
+ // Every `*.ts` in `<configdir>/plugins/` loads (measurement §6.6), so the installed name
214
+ // carries the plugin's namespace: a bare `plugin.ts` would collide with an operator's own.
215
+ const installed = `plugins/soleur-${source.slice(ADAPTER_DIR.length + 1)}`;
216
+ expected.set(installed, resolveToken(readFileSync(join(pluginRoot, source), "utf-8"), effectiveRoot));
217
+ }
218
+ for (const [path, content] of payloadExpected(targetDir, pluginRoot, effectiveRoot, options)) {
219
+ expected.set(path, content);
220
+ }
221
+ // One definition of the fragment's shape, shared with the generator: the generator emits it
222
+ // with the token, this resolves the token and unions it into the operator's config.
223
+ const fragment = configFragmentValues(effectiveRoot);
224
+ const merged = mergeFragment(config ?? readConfig(join(targetDir, "opencode.json")), {
225
+ skills: fragment.skills,
226
+ // The installed path (`soleur/`), not the generator's `opencode/` namespace.
227
+ instructions: [join(targetDir, "soleur", "INSTRUCTIONS.md")],
228
+ });
229
+ expected.set("opencode.json", `${JSON.stringify(merged, null, 2)}\n`);
230
+ return expected;
231
+ }
232
+
233
+ /**
234
+ * The payload files this install owns, keyed target-relative.
235
+ *
236
+ * Content always comes from `sourceRoot` and is written under `effectiveRoot`, which is what
237
+ * makes the two install modes one code path: a checkout install has no payload inside the target
238
+ * (the checkout is the root, so `effectiveRoot` is outside it and this returns nothing), while a
239
+ * vendored install has `effectiveRoot` inside the target and mirrors the bytes there.
240
+ *
241
+ * Ownership is the point, not the copy: these paths join `expected`, so the extras sweep — which
242
+ * deletes anything under `soleur/` the installer did not write — keeps them instead of deleting
243
+ * the payload one pass after writing it.
244
+ */
245
+ function payloadExpected(
246
+ targetDir: string,
247
+ sourceRoot: string,
248
+ effectiveRoot: string,
249
+ options: InstallOptions,
250
+ ): Map<string, string> {
251
+ const owned = options.vendorPayload === true || isVendoredRoot(sourceRoot);
252
+ const result = new Map<string, string>();
253
+ if (!owned) return result;
254
+ const prefix = relative(targetDir, effectiveRoot).split("\\").join("/");
255
+ // A root outside the target owns nothing inside it: that is the checkout install.
256
+ if (prefix === "" || prefix.startsWith("..")) return result;
257
+ for (const dir of PAYLOAD_DIRS) {
258
+ for (const [path, content] of walkPayloadFiles(sourceRoot, dir)) {
259
+ result.set(`${prefix}/${path}`, content);
260
+ }
261
+ }
262
+ result.set(`${prefix}/${VENDOR_MARKER}`, vendorMarkerContent());
263
+ return result;
264
+ }
265
+
266
+ /**
267
+ * Read an operator config. A **missing** config is an empty one (a first install); anything
268
+ * else that is not a JSON object throws `UnparseableConfigError`. The two cases were one branch
269
+ * (`catch → {}`), which made "first install" and "operator config with JSONC comments"
270
+ * indistinguishable — and the write path then replaced the second with the fragment alone.
271
+ */
272
+ function readConfig(path: string): Record<string, unknown> {
273
+ let raw: string;
274
+ try {
275
+ raw = readFileSync(path, "utf-8");
276
+ } catch (error) {
277
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return {};
278
+ throw new UnparseableConfigError(path, `could not be read: ${String(error)}`);
279
+ }
280
+ let parsed: unknown;
281
+ try {
282
+ parsed = JSON.parse(raw);
283
+ } catch (error) {
284
+ throw new UnparseableConfigError(path, String(error));
285
+ }
286
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
287
+ throw new UnparseableConfigError(path, `top level is ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`);
288
+ }
289
+ return parsed as Record<string, unknown>;
290
+ }
291
+
292
+ /** Target-relative paths of every file under `dir` (empty when the directory is absent). */
293
+ function walkFiles(targetDir: string, dir: string): string[] {
294
+ const found: string[] = [];
295
+ const visit = (relativeDir: string): void => {
296
+ let entries;
297
+ try {
298
+ entries = readdirSync(join(targetDir, relativeDir), { withFileTypes: true });
299
+ } catch {
300
+ return;
301
+ }
302
+ for (const entry of entries) {
303
+ const path = `${relativeDir}/${entry.name}`;
304
+ if (entry.isDirectory()) visit(path);
305
+ else found.push(path);
306
+ }
307
+ };
308
+ visit(dir);
309
+ return found.sort();
310
+ }
311
+
312
+ /**
313
+ * The generated stubs' own signature. `agents/` and `commands/` are SHARED with the operator, so
314
+ * a file there is only removable when it says, in its own text, that this generator wrote it and
315
+ * that it points at the resolved checkout. Anything else in those roots is not ours.
316
+ */
317
+ const STUB_SIGNATURES = ["Stub for the canonical agent `", "Run the canonical `"] as const;
318
+
319
+ function isGeneratedStub(content: string, pluginRoot: string): boolean {
320
+ return content.includes(pluginRoot) && STUB_SIGNATURES.some((signature) => content.includes(signature));
321
+ }
322
+
323
+ /**
324
+ * Files an install owns but no longer generates. Without this, deleting an agent or renaming a
325
+ * command in the canonical tree leaves its installed stub loading forever — a half-updated
326
+ * install that `--check` would call ok.
327
+ */
328
+ export function installedExtras(
329
+ targetDir: string,
330
+ expected: Map<string, string>,
331
+ root = PLUGIN_ROOT,
332
+ ): string[] {
333
+ const extras: string[] = [];
334
+ // Exclusive namespaces: everything under `soleur/` and `plugins/soleur-*` is ours by name.
335
+ // A vendored payload's own files are in `expected`, so they are not "extras".
336
+ for (const path of walkFiles(targetDir, "soleur")) if (!expected.has(path)) extras.push(path);
337
+ for (const path of walkFiles(targetDir, "plugins")) {
338
+ if (path.startsWith("plugins/soleur-") && !expected.has(path)) extras.push(path);
339
+ }
340
+ // Shared roots: attributed by content, never by location. A stub names the RESOLVED root, so
341
+ // `root` here is the effective root the install wrote into those stubs, not the source.
342
+ for (const root_ of ["agents", "commands"]) {
343
+ for (const path of walkFiles(targetDir, root_)) {
344
+ if (expected.has(path)) continue;
345
+ let content: string;
346
+ try {
347
+ content = readFileSync(join(targetDir, path), "utf-8");
348
+ } catch {
349
+ continue;
350
+ }
351
+ if (isGeneratedStub(content, root)) extras.push(path);
352
+ }
353
+ }
354
+ return extras.sort();
355
+ }
356
+
357
+ /** Write through a sibling temp file and rename, so a reader never sees a partial file. */
358
+ function writeAtomic(full: string, content: string): void {
359
+ mkdirSync(dirname(full), { recursive: true });
360
+ const temp = `${full}.soleur-tmp-${process.pid}`;
361
+ writeFileSync(temp, content);
362
+ renameSync(temp, full);
363
+ }
364
+
365
+ export interface InstallResult {
366
+ /** Config-dir-relative files written or updated, sorted. */
367
+ written: string[];
368
+ /** Config-dir-relative files that were already correct, sorted. */
369
+ unchanged: string[];
370
+ /** Config-dir-relative stale files removed, sorted. */
371
+ removed: string[];
372
+ }
373
+
374
+ export function installOpenCodeAdapter(
375
+ targetDir: string,
376
+ pluginRoot = PLUGIN_ROOT,
377
+ options: InstallOptions = {},
378
+ ): InstallResult {
379
+ const result: InstallResult = { written: [], unchanged: [], removed: [] };
380
+ const configPath = join(targetDir, "opencode.json");
381
+ let config: Record<string, unknown> | undefined;
382
+ try {
383
+ config = readConfig(configPath);
384
+ } catch (error) {
385
+ if (!(error instanceof UnparseableConfigError)) throw error;
386
+ if (options.force !== true) throw error;
387
+ const backup = `${configPath}.bak-${Date.now()}`;
388
+ copyFileSync(configPath, backup);
389
+ console.error(`[soleur] --force: replaced ${configPath}; the previous bytes are at ${backup}`);
390
+ config = {};
391
+ }
392
+ const expected = expectedInstalled(targetDir, pluginRoot, config, options);
393
+ const effectiveRoot = options.vendorPayload === true ? join(targetDir, VENDOR_DIR) : pluginRoot;
394
+ for (const [path, content] of expected) {
395
+ const full = join(targetDir, path);
396
+ let current: string | undefined;
397
+ try {
398
+ current = readFileSync(full, "utf-8");
399
+ } catch {
400
+ current = undefined;
401
+ }
402
+ if (current === content) {
403
+ result.unchanged.push(path);
404
+ continue;
405
+ }
406
+ writeAtomic(full, content);
407
+ result.written.push(path);
408
+ }
409
+ for (const path of installedExtras(targetDir, expected, effectiveRoot)) {
410
+ rmSync(join(targetDir, path), { force: true });
411
+ result.removed.push(path);
412
+ }
413
+ result.written.sort();
414
+ result.unchanged.sort();
415
+ result.removed.sort();
416
+ return result;
417
+ }
418
+
419
+ /** Read-only: paths the target does not already match. Empty means installed and current. */
420
+ export function installProblems(targetDir: string, pluginRoot = PLUGIN_ROOT, options: InstallOptions = {}): string[] {
421
+ const problems: string[] = [];
422
+ const expected = expectedInstalled(targetDir, pluginRoot, undefined, options);
423
+ const effectiveRoot = options.vendorPayload === true ? join(targetDir, VENDOR_DIR) : pluginRoot;
424
+ for (const [path, content] of expected) {
425
+ let current: string | undefined;
426
+ try {
427
+ current = readFileSync(join(targetDir, path), "utf-8");
428
+ } catch {
429
+ current = undefined;
430
+ }
431
+ if (current !== content) problems.push(current === undefined ? `MISSING: ${path}` : `STALE: ${path}`);
432
+ }
433
+ for (const path of installedExtras(targetDir, expected, effectiveRoot)) {
434
+ problems.push(`EXTRA: ${path}`);
435
+ }
436
+ return problems.sort();
437
+ }
438
+
439
+ function parseArg(argv: readonly string[], flag: string): string | undefined {
440
+ const index = argv.indexOf(flag);
441
+ if (index === -1) return undefined;
442
+ const value = argv[index + 1];
443
+ if (value === undefined) throw new Error(`${flag} requires a directory`);
444
+ return value;
445
+ }
446
+
447
+ const USAGE = [
448
+ "Usage: bun plugins/soleur/scripts/install-opencode-adapter.ts [--target DIR] [--plugin-root DIR] [--vendor-payload] [--check] [--force] [--help]",
449
+ "",
450
+ " --target DIR config dir to install into (default: $HOME/.config/opencode)",
451
+ " --plugin-root DIR checkout (or package) the installed files should point at (default: this checkout)",
452
+ " --vendor-payload copy the payload into <target>/soleur/ and point the installed files at that",
453
+ " copy; required when there is no checkout to point at (the npm distribution)",
454
+ " --check write nothing; report MISSING / STALE / EXTRA",
455
+ " --force replace an existing opencode.json that cannot be parsed (backup first)",
456
+ " --help, -h print this text and exit 0 without writing",
457
+ ].join("\n");
458
+
459
+ /**
460
+ * Unknown arguments are rejected: a typo (`--chek`) otherwise falls through to the WRITE path,
461
+ * which is the direction that changes an operator's machine.
462
+ */
463
+ function validateArgs(argv: readonly string[]): void {
464
+ const withValue = new Set(["--target", "--plugin-root"]);
465
+ const known = new Set([...withValue, "--vendor-payload", "--check", "--force", "--help", "-h"]);
466
+ for (let i = 0; i < argv.length; i += 1) {
467
+ const arg = argv[i];
468
+ if (arg === "--help" || arg === "-h") {
469
+ console.log(USAGE);
470
+ process.exit(0);
471
+ }
472
+ if (!known.has(arg)) {
473
+ console.error(`unknown argument: ${arg}\n${USAGE}`);
474
+ process.exit(2);
475
+ }
476
+ if (withValue.has(arg)) i += 1;
477
+ }
478
+ }
479
+
480
+ function main(): void {
481
+ const argv = process.argv.slice(2);
482
+ validateArgs(argv);
483
+ const explicitTarget = parseArg(argv, "--target");
484
+ const home = process.env["HOME"];
485
+ if (explicitTarget === undefined && (home === undefined || home === "")) {
486
+ console.error(
487
+ "HOME is not set and --target was not given: refusing to install into a cwd-relative `.config/opencode`. Pass --target DIR.",
488
+ );
489
+ process.exit(2);
490
+ }
491
+ const targetDir = resolve(explicitTarget ?? join(home as string, ".config", "opencode"));
492
+ const pluginRoot = resolve(parseArg(argv, "--plugin-root") ?? PLUGIN_ROOT);
493
+ const options: InstallOptions = {
494
+ force: argv.includes("--force"),
495
+ vendorPayload: argv.includes("--vendor-payload"),
496
+ };
497
+ try {
498
+ if (argv.includes("--check")) {
499
+ const problems = installProblems(targetDir, pluginRoot, options);
500
+ if (problems.length > 0) {
501
+ for (const problem of problems) console.error(problem);
502
+ process.exit(1);
503
+ }
504
+ console.log("opencode-install ok");
505
+ return;
506
+ }
507
+ const result = installOpenCodeAdapter(targetDir, pluginRoot, options);
508
+ console.log(
509
+ `opencode-adapter installed into ${targetDir} (${result.written.length} written, ${result.unchanged.length} unchanged, ${result.removed.length} removed)`,
510
+ );
511
+ } catch (error) {
512
+ if (error instanceof UnparseableConfigError) {
513
+ console.error(error.message);
514
+ process.exit(1);
515
+ }
516
+ throw error;
517
+ }
518
+ }
519
+
520
+ if (import.meta.main) main();