@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,363 @@
1
+ #!/usr/bin/env bash
2
+ # ci-head-verdict.sh -- the ONE resolver every reader of a PR head's CI state goes through (ADR-276 S3, #9728).
3
+ #
4
+ # ci-head-verdict.sh verdict <pr> [--repo OWNER/REPO]
5
+ # ci-head-verdict.sh wait-ready-run <pr> --before-count K [--timeout SEC] [--repo OWNER/REPO]
6
+ # ci-head-verdict.sh ready-count <pr> [--repo OWNER/REPO]
7
+ #
8
+ # WHY. With CI_DRAFT_LIGHT on, a draft PR's `test` context is RED BY DESIGN ("draft: full battery owed at ready",
9
+ # Option R). A reader that sees that red row on a PR that has since been marked ready misreads it as a failure
10
+ # (monitor, the Phase 7 poll, drain-prs triage, admin-merge --wait), and one that sees it with no ready run ever
11
+ # created misreads the silence as "still running" forever. The decision is TIME-BASED, so no reader needs a
12
+ # light-run detector: only a `ci.yml` pull_request run created at or after the PR's latest ready event speaks for a
13
+ # non-draft head. A run created at or after T was triggered by the ready event or a later push; the ci.yml
14
+ # `draft-light` step reads the PR LIVE and runs full for ACTION == ready_for_review and for a non-draft PR.
15
+ #
16
+ # APPLICABILITY. The mechanism exists only in a repo whose default-branch `.github/workflows/ci.yml` carries the
17
+ # `draft-light` job (the key may carry a trailing comment or quotes; a 200 body without a top-level `jobs:` key is an API
18
+ # error, never "not applicable"). Any other repo (a customer repo the plugin is installed in) never produces a ready run, so
19
+ # `verdict` answers n/a (reason no-draft-light) and `wait-ready-run` answers ok (reason not-applicable): its ship and
20
+ # merge flow is the one it had without this script, plus one timeline read and one contents read. A 404 on that file is "not applicable"; any other
21
+ # read failure is an API error (exit 3), never a guess.
22
+ #
23
+ # `verdict` prints exactly one marker as the last stdout line and exits 0 (a decision was made) or 3 (it could not be):
24
+ # SOLEUR_CI_HEAD_VERDICT state=<n/a|full-decided|pending-full|no-run|stalled|awaiting-approval> pr=<N> sha=<H> run=<id|none> reason=<token>
25
+ # The state set is CLOSED. On exit 3 the marker is `state=error` (reason names the cause): a state OUTSIDE the closed
26
+ # set, so a reader that whitelists the six states ignores it and keeps its own reading (a real red `test` stays red).
27
+ # Never answer a read failure with a member of the closed set: that would let an API hiccup read as a decision.
28
+ # Order of evaluation:
29
+ # 0. the repo does not carry the mechanism (see APPLICABILITY) -> n/a
30
+ # 1. no ready event ever (never a draft: bot-opened PRs with synthetic rows and no pull_request run), or the PR is a
31
+ # draft NOW -> n/a
32
+ # 2. the newest `test` check run (github-actions app) at H is completed + success -> full-decided (reason
33
+ # green-test, regardless of T: under Option R a green `test` is never a light result)
34
+ # 3. list `workflows/ci.yml/runs?event=pull_request&head_sha=H` (NEVER a run's pull_requests[], empty for ~92% of
35
+ # runs) and keep runs created at or after T; T is the latest ReadyForReviewEvent's server time. No skew
36
+ # allowance: the ready run was measured 2 to 3 s AFTER T (S3 gate 4), and an allowance would adopt a DRAFT push's
37
+ # light run created just before the ready call as "the ready run"
38
+ # 4. the newest kept run decides: not completed -> pending-full; completed success|failure|timed_out ->
39
+ # full-decided (its own rows are authoritative, a failure is never hidden as PENDING); action_required ->
40
+ # awaiting-approval; cancelled|skipped|stale|neutral|startup_failure|anything else -> no-run (fail closed);
41
+ # no kept run -> no-run
42
+ # 5. (a conflicting PR, mergeable_state dirty, with no run stays no-run reason=conflicting: GitHub builds no merge ref
43
+ # for it, so no run can ever appear and an undo/ready would not help)
44
+ # pending-full and no-run become `stalled` once more than N=120 minutes have passed since T (above the declared
45
+ # 73-minute path plus a ~14-minute p90 queue wait; a run still in flight at N is not a healthy slow run)
46
+ # `run=` is the DECIDING run: a reader judging `test` must use that run's rows. A newer `test` row that belongs to a
47
+ # different run (a manual re-run of a pre-T run) is stale; the row's run id is the `/actions/runs/<id>/` segment of
48
+ # its details_url. Every time comes from the SERVER (the PR read's Date header, the timeline, the runs API), never
49
+ # the local clock.
50
+ #
51
+ # `wait-ready-run` is the arm-after-ready gate. The caller reads K with `ready-count` BEFORE `gh pr ready`; the wait
52
+ # polls (every 10 s plus the calls themselves, budget --timeout, default 300: the real elapsed time is up to ~365 s, so
53
+ # give the calling tool a timeout of 420 s)
54
+ # until the PR's ReadyForReviewEvent count exceeds K AND a live read says it is not a draft (read-after-write lag
55
+ # guard: the previous event is never taken as T), takes the newest event's server time as T, then polls for a
56
+ # pull_request run at H created at or after T. Last stdout line:
57
+ # SOLEUR_CI_WAIT_READY_RUN result=<ok|fail> pr=<N> sha=<H|unknown> run=<id|none> reason=<run-created|not-applicable|no-ready-event|no-run|awaiting-approval|api-error>
58
+ # Exit 0 on ok, 1 on fail (FAIL CLOSED: the caller must NOT run `gh pr merge --auto`), 2 usage, 3 when the LAST poll
59
+ # could not read (api-error: the ready state is unknown, so re-run `verdict`; do NOT `gh pr ready --undo`).
60
+ #
61
+ # `ready-count` prints the number of ReadyForReviewEvents on the PR (the filtered nodes, NOT the timeline totalCount,
62
+ # which counts every event type) and exits 3 without a number when it cannot be counted.
63
+ #
64
+ # EXIT CODES: 0 decided/ok | 1 wait failed | 2 usage | 3 gh/jq/API error (verdict prints state=error reason=<cause>).
65
+ # PORTABILITY: bash, gh and jq only (jq does the time arithmetic; no GNU `date -d`), so it runs on a stock macOS host.
66
+ # TEST SEAMS: CI_HEAD_VERDICT_NOW (ISO-8601 UTC, replaces the server clock), CI_HEAD_VERDICT_POLL_SECONDS (default 10,
67
+ # the sleep between wait polls; the poll BUDGET is always counted in 10-second units).
68
+ #
69
+ # Every `gh pr ready` caller must use a non-GITHUB_TOKEN identity: measured on the S3 probe, GITHUB_TOKEN cannot
70
+ # ready a PR at all (markPullRequestReadyForReview: Resource not accessible by integration), so it can never produce
71
+ # the ready event or the ready run this script waits for.
72
+ set -uo pipefail
73
+
74
+ readonly MARKER="SOLEUR_CI_HEAD_VERDICT"
75
+ readonly WAIT_MARKER="SOLEUR_CI_WAIT_READY_RUN"
76
+ STALL_MINUTES=120
77
+ # shellcheck disable=SC2016 # GraphQL variables ($owner...) are not shell expansions
78
+ readonly READY_QUERY='query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){pullRequest(number:$number){timelineItems(last: 100, itemTypes: [READY_FOR_REVIEW_EVENT]){pageInfo{hasPreviousPage} nodes{... on ReadyForReviewEvent{createdAt}}}}}}'
79
+
80
+ usage() {
81
+ cat <<'EOF'
82
+ usage: ci-head-verdict.sh verdict <pr> [--repo OWNER/REPO]
83
+ ci-head-verdict.sh wait-ready-run <pr> --before-count K [--timeout SEC] [--repo OWNER/REPO]
84
+ ci-head-verdict.sh ready-count <pr> [--repo OWNER/REPO]
85
+
86
+ verdict: last stdout line
87
+ SOLEUR_CI_HEAD_VERDICT state=<n/a|full-decided|pending-full|no-run|stalled|awaiting-approval> pr=<N> sha=<H> run=<id|none> reason=<token>
88
+ (exit 3: state=error, outside that set)
89
+ wait-ready-run: last stdout line
90
+ SOLEUR_CI_WAIT_READY_RUN result=<ok|fail> pr=<N> sha=<H|unknown> run=<id|none> reason=<run-created|not-applicable|no-ready-event|no-run|awaiting-approval|api-error>
91
+ exit 0 ok | 1 wait failed (do NOT arm auto-merge) | 2 usage | 3 gh/jq/API error (ready state unknown: re-run verdict)
92
+ arm order: K=$(ready-count PR) && gh pr ready PR && wait-ready-run PR --before-count "$K"; arm only on exit 0
93
+ EOF
94
+ }
95
+
96
+ usage_error() { echo "ci-head-verdict: $1" >&2; usage >&2; exit 2; }
97
+
98
+ # ── args ──────────────────────────────────────────────────────────────────────────────────────
99
+ if [[ "${1-}" == "--help" || "${1-}" == "-h" ]]; then usage; exit 0; fi
100
+ CMD="${1-}"
101
+ case "$CMD" in verdict|wait-ready-run|ready-count) shift ;; *) usage_error "unknown or missing subcommand '${CMD}'" ;; esac
102
+ PR="${1-}"
103
+ [[ "$PR" =~ ^[0-9]+$ ]] || usage_error "<pr> must be a number"
104
+ shift
105
+ BEFORE=""; TIMEOUT=300
106
+ while (( $# > 0 )); do
107
+ case "$1" in
108
+ --repo)
109
+ [[ "${2-}" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*/[A-Za-z0-9._-]+$ ]] || usage_error "--repo must be OWNER/REPO (not a URL)"
110
+ export GH_REPO="$2"; shift 2 ;;
111
+ --before-count)
112
+ [[ "$CMD" == wait-ready-run && "${2-}" =~ ^[0-9]+$ ]] || usage_error "--before-count K (an integer) is for wait-ready-run only"
113
+ BEFORE=$((10#$2)); shift 2 ;;
114
+ --timeout)
115
+ # shellcheck disable=SC2015 # A && B || usage_error is the guard idiom here
116
+ [[ "$CMD" == wait-ready-run && "${2-}" =~ ^[0-9]+$ ]] && (( 10#$2 > 0 )) || usage_error "--timeout takes a positive integer and is for wait-ready-run only"
117
+ TIMEOUT=$((10#$2)); shift 2 ;;
118
+ *) usage_error "unknown argument '$1'" ;;
119
+ esac
120
+ done
121
+ [[ "$CMD" != wait-ready-run || -n "$BEFORE" ]] || usage_error "wait-ready-run needs --before-count K (read it with ready-count BEFORE gh pr ready)"
122
+ POLL_SECONDS="${CI_HEAD_VERDICT_POLL_SECONDS:-10}"
123
+ [[ "$POLL_SECONDS" =~ ^[0-9]+$ ]] || usage_error "CI_HEAD_VERDICT_POLL_SECONDS must be ^[0-9]+\$"
124
+
125
+ SHA_OUT="unknown"
126
+ # fail_api <message> [reason]: a read the resolver could not make. `verdict` prints a marker whose state is `error` (NOT a
127
+ # member of the closed set: a reader that whitelists the six states then keeps its own reading, so a real red `test`
128
+ # is never softened by an API hiccup) and exits 3; ready-count prints no number.
129
+ fail_api() {
130
+ local reason="${2:-api-error}"
131
+ echo "ci-head-verdict: $1" >&2
132
+ if [[ "$CMD" == verdict ]]; then
133
+ printf '%s state=error pr=%s sha=%s run=none reason=%s\n' "$MARKER" "$PR" "$SHA_OUT" "$reason"
134
+ elif [[ "$CMD" == wait-ready-run ]]; then
135
+ printf '%s result=fail pr=%s sha=unknown run=none reason=api-error\n' "$WAIT_MARKER" "$PR"
136
+ fi
137
+ exit 3
138
+ }
139
+
140
+ for bin in gh jq; do
141
+ command -v "$bin" >/dev/null 2>&1 || fail_api "$bin not found on PATH" missing-tool
142
+ done
143
+ WORK="$(mktemp -d)" || fail_api "mktemp failed" mktemp
144
+ trap 'rm -rf "$WORK"' EXIT
145
+
146
+ ERRMSG=""
147
+ # ── reads. Each returns 0 on a parsed answer, 1 with ERRMSG set otherwise. ─────────────────────
148
+ PR_DRAFT=""; PR_SHA=""; PR_MSTATE=""; SERVER_DATE=""
149
+ read_pr() {
150
+ gh api -i "repos/{owner}/{repo}/pulls/$PR" > "$WORK/pr.http" 2> "$WORK/err" \
151
+ || { ERRMSG="reading PR $PR failed: $(head -c 200 "$WORK/err" | tr '\n' ' ')"; return 1; }
152
+ awk 'b { print; next } /^\r?$/ { b = 1 }' "$WORK/pr.http" > "$WORK/pr.json"
153
+ SERVER_DATE="$(awk 'b { exit } /^\r?$/ { b = 1; next } tolower($0) ~ /^date:/ { sub(/^[Dd][Aa][Tt][Ee]:[ \t]*/, ""); sub(/\r$/, ""); print; exit }' "$WORK/pr.http")"
154
+ jq -e 'type == "object" and (.draft | type) == "boolean" and (.head.sha | type) == "string" and (.head.sha | test("^[0-9a-f]{40}$"))' \
155
+ "$WORK/pr.json" >/dev/null 2>&1 || { ERRMSG="unparseable PR $PR body"; return 1; }
156
+ PR_DRAFT="$(jq -r '.draft' "$WORK/pr.json")"
157
+ PR_SHA="$(jq -r '.head.sha' "$WORK/pr.json")"
158
+ PR_MSTATE="$(jq -r '(.mergeable_state // "") | if type == "string" then . else "" end' "$WORK/pr.json")"
159
+ }
160
+
161
+ READY_COUNT=0; READY_T=""; READY_TRUNC="false"
162
+ read_ready() {
163
+ gh api graphql -F owner='{owner}' -F name='{repo}' -F number="$PR" -f query="$READY_QUERY" > "$WORK/ready.json" 2> "$WORK/err" \
164
+ || { ERRMSG="reading the ready-event timeline of PR $PR failed: $(head -c 200 "$WORK/err" | tr '\n' ' ')"; return 1; }
165
+ jq -e '.data.repository.pullRequest.timelineItems
166
+ | (.nodes | type) == "array" and all(.nodes[]; (.createdAt | type) == "string") and (.pageInfo.hasPreviousPage | type) == "boolean"' \
167
+ "$WORK/ready.json" >/dev/null 2>&1 || { ERRMSG="unparseable ready-event timeline for PR $PR"; return 1; }
168
+ READY_COUNT="$(jq -r '.data.repository.pullRequest.timelineItems.nodes | length' "$WORK/ready.json")"
169
+ READY_T="$(jq -r '.data.repository.pullRequest.timelineItems.nodes | last | .createdAt // ""' "$WORK/ready.json")"
170
+ READY_TRUNC="$(jq -r '.data.repository.pullRequest.timelineItems.pageInfo.hasPreviousPage' "$WORK/ready.json")"
171
+ }
172
+
173
+ # The newest `test` check run (github-actions app) at <sha>: TEST_STATUS / TEST_CONCLUSION / TEST_RUN (id or "").
174
+ TEST_STATUS=""; TEST_CONCLUSION=""; TEST_RUN=""
175
+ read_test_row() {
176
+ gh api --paginate --slurp "repos/{owner}/{repo}/commits/$1/check-runs?check_name=test&per_page=100&filter=all" > "$WORK/checks.json" 2> "$WORK/err" \
177
+ || { ERRMSG="reading check runs at $1 failed: $(head -c 200 "$WORK/err" | tr '\n' ' ')"; return 1; }
178
+ jq -e 'type == "array" and all(.[]; type == "object" and (.check_runs | type) == "array")' "$WORK/checks.json" >/dev/null 2>&1 \
179
+ || { ERRMSG="unparseable check-runs response at $1"; return 1; }
180
+ jq -c --arg h "$1" '[.[].check_runs[] | select(.name == "test" and .app.id == 15368 and .head_sha == $h)]
181
+ | if length == 0 then null else max_by(.id | tonumber) end' "$WORK/checks.json" > "$WORK/testrow.json" \
182
+ || { ERRMSG="unparseable check-runs response at $1"; return 1; }
183
+ TEST_STATUS="$(jq -r '.status // ""' "$WORK/testrow.json")"
184
+ TEST_CONCLUSION="$(jq -r '.conclusion // ""' "$WORK/testrow.json")"
185
+ TEST_RUN="$(jq -r '(.details_url // "") | capture("/actions/runs/(?<id>[0-9]+)(/|$)") | .id' "$WORK/testrow.json" 2>/dev/null || true)"
186
+ }
187
+
188
+ # The newest ci.yml pull_request run at <sha> created at or after <floor-epoch>: RUN_ID / RUN_STATUS / RUN_CONCLUSION
189
+ # (RUN_ID empty when none). Looked up by head_sha, never through a run's pull_requests[].
190
+ RUN_ID=""; RUN_STATUS=""; RUN_CONCLUSION=""
191
+ read_newest_run() { # <sha> <floor-epoch>
192
+ gh api --paginate --slurp "repos/{owner}/{repo}/actions/workflows/ci.yml/runs?event=pull_request&head_sha=$1&per_page=100" > "$WORK/runs.json" 2> "$WORK/err" \
193
+ || { ERRMSG="listing ci.yml runs at $1 failed: $(head -c 200 "$WORK/err" | tr '\n' ' ')"; return 1; }
194
+ jq -e 'type == "array" and all(.[]; type == "object" and (.workflow_runs | type) == "array")' "$WORK/runs.json" >/dev/null 2>&1 \
195
+ || { ERRMSG="unparseable ci.yml run list at $1"; return 1; }
196
+ jq -c --arg h "$1" --argjson floor "$2" '
197
+ [ .[] | .workflow_runs[]? | select(.head_sha == $h and .event == "pull_request")
198
+ | . + {ts: (.created_at | fromdateiso8601)} | select(.ts >= $floor) ]
199
+ | sort_by([.ts, .id]) | last // null' "$WORK/runs.json" > "$WORK/newest.json" \
200
+ || { ERRMSG="unparseable ci.yml run list at $1"; return 1; }
201
+ RUN_ID="$(jq -r '(.id // "") | tostring' "$WORK/newest.json")"
202
+ [[ -z "$RUN_ID" || "$RUN_ID" =~ ^[0-9]+$ ]] || { ERRMSG="non-numeric run id in the ci.yml run list at $1"; return 1; }
203
+ RUN_STATUS="$(jq -r '.status // ""' "$WORK/newest.json")"
204
+ RUN_CONCLUSION="$(jq -r '.conclusion // ""' "$WORK/newest.json")"
205
+ }
206
+
207
+ # Does this repo carry the mechanism? True when the DEFAULT branch's ci.yml has a `draft-light` job. APPLICABLE is
208
+ # 1/0; a 404 (no ci.yml) is 0, any other failure is an error (ERRMSG set, return 1).
209
+ APPLICABLE=""
210
+ read_applicable() {
211
+ gh api -H 'Accept: application/vnd.github.raw+json' "repos/{owner}/{repo}/contents/.github/workflows/ci.yml" > "$WORK/ci.yml" 2> "$WORK/err" || {
212
+ if grep -qE 'HTTP 404' "$WORK/err"; then APPLICABLE=0; return 0; fi
213
+ ERRMSG="reading the default branch's ci.yml failed: $(head -c 200 "$WORK/err" | tr '\n' ' ')"; return 1
214
+ }
215
+ [[ -s "$WORK/ci.yml" ]] || { ERRMSG="empty ci.yml body"; return 1; }
216
+ # A 200 that is not a workflow file (an HTML error page, a truncated body) is an error, never "not applicable": that
217
+ # answer would switch the wait gate off. The job key may carry a trailing comment or quotes.
218
+ grep -qE '^jobs:' "$WORK/ci.yml" || { ERRMSG="the default branch's ci.yml body has no top-level jobs: key"; return 1; }
219
+ if grep -qE "^ ['\"]?draft-light['\"]?:[[:space:]]*(#.*)?$" "$WORK/ci.yml"; then APPLICABLE=1; else APPLICABLE=0; fi
220
+ }
221
+
222
+ # <status> <conclusion> -> "<state> <reason>" (the closed mapping of rule 4)
223
+ classify_run() {
224
+ case "$1" in
225
+ completed) : ;;
226
+ queued|in_progress|waiting|requested|pending) echo "pending-full run-in-progress"; return 0 ;;
227
+ *) echo "no-run run-unknown-status"; return 0 ;;
228
+ esac
229
+ case "$2" in
230
+ success) echo "full-decided run-success" ;;
231
+ failure) echo "full-decided run-failure" ;;
232
+ timed_out) echo "full-decided run-timed-out" ;;
233
+ action_required) echo "awaiting-approval run-action-required" ;;
234
+ cancelled|skipped|stale|neutral|startup_failure) echo "no-run run-${2//_/-}" ;;
235
+ *) echo "no-run run-unknown-conclusion" ;;
236
+ esac
237
+ }
238
+
239
+ # Epoch seconds from an ISO-8601 UTC time (2031-03-04T05:06:07Z) or an HTTP Date header (RFC 1123), via jq so the
240
+ # script runs without GNU `date -d`. Prints digits and returns 0, or returns 1.
241
+ epoch_of() {
242
+ local out
243
+ out="$(LC_ALL=C jq -rn --arg s "$1" 'if ($s | test("^[A-Za-z]{3}, ")) then ($s | strptime("%a, %d %b %Y %H:%M:%S GMT") | mktime) else ($s | fromdateiso8601) end' 2>/dev/null)" || return 1
244
+ [[ "$out" =~ ^[0-9]+$ ]] || return 1
245
+ printf '%s\n' "$out"
246
+ }
247
+
248
+ NOW_EPOCH=0
249
+ server_now() {
250
+ local raw="${CI_HEAD_VERDICT_NOW:-$SERVER_DATE}"
251
+ [[ -n "$raw" ]] || return 1
252
+ epoch_of "$raw"
253
+ }
254
+
255
+ emit() { # <state> <run|""> <reason>
256
+ printf '%s state=%s pr=%s sha=%s run=%s reason=%s\n' "$MARKER" "$1" "$PR" "$SHA_OUT" "${2:-none}" "$3"
257
+ exit 0
258
+ }
259
+
260
+ # ── verdict ───────────────────────────────────────────────────────────────────────────────────
261
+ cmd_verdict() {
262
+ local t_epoch st rs
263
+ read_pr || fail_api "$ERRMSG"
264
+ SHA_OUT="$PR_SHA"
265
+ NOW_EPOCH=$(server_now) || fail_api "no usable server time (Date header absent or unparseable)" no-server-time
266
+ read_ready || fail_api "$ERRMSG"
267
+ (( READY_COUNT > 0 )) || emit n/a "" never-ready
268
+ [[ "$PR_DRAFT" == true ]] && emit n/a "" draft
269
+ read_applicable || fail_api "$ERRMSG"
270
+ [[ "$APPLICABLE" == 1 ]] || emit n/a "" no-draft-light
271
+ t_epoch=$(epoch_of "$READY_T") || fail_api "unparseable ready-event time '$READY_T'"
272
+
273
+ read_test_row "$PR_SHA" || fail_api "$ERRMSG"
274
+ if [[ "$TEST_STATUS" == completed && "$TEST_CONCLUSION" == success ]]; then
275
+ emit full-decided "$TEST_RUN" green-test
276
+ fi
277
+
278
+ read_newest_run "$PR_SHA" "$t_epoch" || fail_api "$ERRMSG"
279
+ if [[ -z "$RUN_ID" ]]; then
280
+ st="no-run"; rs="no-run-after-ready"
281
+ else
282
+ read -r st rs <<<"$(classify_run "$RUN_STATUS" "$RUN_CONCLUSION")" || fail_api "run classification failed"
283
+ [[ -n "$st" ]] || fail_api "run classification failed"
284
+ fi
285
+ # A conflicting PR (mergeable_state dirty) gets NO pull_request run at all: GitHub cannot build the merge ref. That is
286
+ # the conflict's doing, not a lost ready run, and `stalled` would advise an undo/ready that cannot help: it stays no-run.
287
+ if [[ "$st" == no-run && "$rs" == no-run-after-ready && "$PR_MSTATE" == dirty ]]; then rs="conflicting"
288
+ elif [[ "$st" == pending-full || "$st" == no-run ]] && (( NOW_EPOCH - t_epoch > STALL_MINUTES * 60 )); then
289
+ st=stalled; rs="undecided-after-${STALL_MINUTES}m"
290
+ fi
291
+ emit "$st" "$RUN_ID" "$rs"
292
+ }
293
+
294
+ # ── ready-count ───────────────────────────────────────────────────────────────────────────────
295
+ cmd_ready_count() {
296
+ read_ready || fail_api "$ERRMSG"
297
+ [[ "$READY_TRUNC" != true ]] || fail_api "more ReadyForReviewEvents than one timeline page holds; cannot count" too-many-events
298
+ printf '%s\n' "$READY_COUNT"
299
+ }
300
+
301
+ # ── wait-ready-run ────────────────────────────────────────────────────────────────────────────
302
+ WAIT_REASON="no-ready-event"; WAIT_RUN=""; WAIT_SHA="unknown"; WAIT_API_ERR=0
303
+ # One poll. 0 = a ready run exists; 1 = keep waiting (WAIT_REASON says what is missing; WAIT_API_ERR=1 when a READ
304
+ # failed, which is not the same as "not there yet"); 2 = terminal failure.
305
+ wait_once() {
306
+ local t_epoch st rs
307
+ WAIT_REASON="no-ready-event"; WAIT_RUN=""; WAIT_API_ERR=1
308
+ read_pr || { echo "ci-head-verdict: $ERRMSG" >&2; return 1; }
309
+ WAIT_SHA="$PR_SHA"
310
+ read_ready || { echo "ci-head-verdict: $ERRMSG" >&2; return 1; }
311
+ [[ "$READY_TRUNC" != true ]] || { echo "ci-head-verdict: too many ready events to count" >&2; return 1; }
312
+ WAIT_API_ERR=0
313
+ if [[ "$READY_COUNT" -gt "$BEFORE" && "$PR_DRAFT" == false ]]; then
314
+ :
315
+ else
316
+ return 1
317
+ fi
318
+ t_epoch=$(epoch_of "$READY_T") || { echo "ci-head-verdict: unparseable ready-event time '$READY_T'" >&2; WAIT_API_ERR=1; return 1; }
319
+ WAIT_REASON="no-run"
320
+ read_newest_run "$PR_SHA" "$t_epoch" || { echo "ci-head-verdict: $ERRMSG" >&2; WAIT_API_ERR=1; return 1; }
321
+ [[ -n "$RUN_ID" ]] || return 1
322
+ WAIT_RUN="$RUN_ID"
323
+ read -r st rs <<<"$(classify_run "$RUN_STATUS" "$RUN_CONCLUSION")"
324
+ case "$st" in
325
+ pending-full|full-decided) WAIT_REASON="run-created"; return 0 ;;
326
+ awaiting-approval) WAIT_REASON="awaiting-approval"; return 2 ;;
327
+ *) return 1 ;;
328
+ esac
329
+ }
330
+
331
+ wait_marker() { # <ok|fail>
332
+ printf '%s result=%s pr=%s sha=%s run=%s reason=%s\n' "$WAIT_MARKER" "$1" "$PR" "$WAIT_SHA" "${WAIT_RUN:-none}" "$WAIT_REASON"
333
+ }
334
+
335
+ cmd_wait() {
336
+ local max=$(( (TIMEOUT + 9) / 10 )) poll rc prev=""
337
+ (( max >= 1 )) || max=1
338
+ # A repo without the mechanism has no ready run to wait for: arming is today's behaviour there.
339
+ if ! read_applicable; then echo "ci-head-verdict: $ERRMSG" >&2; WAIT_REASON="api-error"; wait_marker fail; exit 3; fi
340
+ if [[ "$APPLICABLE" != 1 ]]; then WAIT_REASON="not-applicable"; wait_marker ok; exit 0; fi
341
+ for (( poll = 1; poll <= max; poll++ )); do
342
+ wait_once; rc=$?
343
+ case "$rc" in
344
+ 0) wait_marker ok; exit 0 ;;
345
+ 2) wait_marker fail; exit 1 ;;
346
+ esac
347
+ if [[ "$WAIT_REASON" != "$prev" ]]; then
348
+ printf 'WAIT poll=%d/%d waiting-for=%s\n' "$poll" "$max" "$WAIT_REASON"
349
+ prev="$WAIT_REASON"
350
+ fi
351
+ (( poll < max )) && sleep "$POLL_SECONDS"
352
+ done
353
+ # The last poll could not READ: the ready state is unknown, which is not "no ready event / no run".
354
+ if (( WAIT_API_ERR == 1 )); then WAIT_REASON="api-error"; wait_marker fail; exit 3; fi
355
+ wait_marker fail
356
+ exit 1
357
+ }
358
+
359
+ case "$CMD" in
360
+ verdict) cmd_verdict ;;
361
+ ready-count) cmd_ready_count ;;
362
+ wait-ready-run) cmd_wait ;;
363
+ esac
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env bash
2
+ # cloud-detect.sh -- the ONE local-vs-cloud classifier for Devin sessions (TR1).
3
+ #
4
+ # Emits exactly one token on stdout:
5
+ # local -- positive this-host, plugin-sourced local-session evidence
6
+ # not-local:<reason> -- everything else; consumers MUST fail closed on it
7
+ #
8
+ # Reasons, in priority order (first match wins):
9
+ # sentinel-absent -- no .devin/soleur-local-session under the git root (or no git
10
+ # repo/git) on a box that IS Devin-marked (some DEVIN* var set)
11
+ # no-devin-env -- no sentinel AND no DEVIN / DEVIN_HOME / DEVIN_PROJECT_DIR /
12
+ # DEVIN_PLUGIN_ROOT / DEVIN_DIR set. This means "not a Devin
13
+ # session at all" — local Devin exec shells expose ZERO DEVIN*
14
+ # vars (probe 2026-09-15, both arms), so env cannot gate the
15
+ # `local` verdict; the sentinel carries it. Callers treat
16
+ # no-devin-env like `local` (a Claude Code session must not
17
+ # activate the cloud contract).
18
+ # malformed -- sentinel exists but is not a JSON object or lacks host/hook_source
19
+ # foreign-host -- sentinel host != `hostname` (committed sentinel; measured 2026-09-17:
20
+ # /handoff transfers committed content only, so a gitignored sentinel
21
+ # cannot travel via it — the arm remains forward-defense for any
22
+ # transport that does carry the file, and for user repos that commit it)
23
+ # non-plugin-source -- sentinel hook_source != "plugin" (repo-level SessionStart firing in
24
+ # cloud must never read as a local session)
25
+ # conflicting-evidence -- valid plugin-sourced, this-host sentinel on a box whose env
26
+ # marks it as a cloud VM (DEVIN_DIR / DEVIN_DISABLE_HISTEXPAND are
27
+ # measured cloud-only in exec shells). The upstream-convergence arm:
28
+ # if Cognition ships plugin-hook dispatch in cloud (#8160) before
29
+ # plugin subagents, the hook fires and writes a sentinel while the
30
+ # capability gap persists — that must NOT read as local.
31
+ #
32
+ # Exit status is ALWAYS 0 for a classification outcome: a classifier that errors
33
+ # fails OPEN at consumers, and fail-open is exactly the defect this script exists
34
+ # to kill. (Usage errors — unknown flags — exit 2; that is not a classification.)
35
+ #
36
+ # --banner: when classification is not-local, also emit a reason-aware capability
37
+ # banner to STDERR naming the absent surfaces (plugin subagents, SessionStart /
38
+ # SessionEnd hooks) and what still works (skills, AGENTS.md rules, MCP). Emits
39
+ # nothing extra when local. Callers are expected to gate on positive Devin
40
+ # identity before invoking --banner (the contract in devin/INSTRUCTIONS.md), so a
41
+ # Claude Code session never sees cloud banners.
42
+ #
43
+ # Sentinel shape (written by hooks/devin-session-start.sh):
44
+ # {"host":"<hostname>","ts":"<ISO8601 utc>","hook_source":"plugin"|"repo"}
45
+ #
46
+ # Deliberately jq- and python3-free: both may be absent on a minimal cloud VM, so
47
+ # the flat JSON is parsed with grep/sed, whitespace-tolerant and fail-closed.
48
+
49
+ set -euo pipefail
50
+
51
+ BANNER=0
52
+ for arg in "$@"; do
53
+ case "$arg" in
54
+ --banner) BANNER=1 ;;
55
+ *)
56
+ echo "cloud-detect.sh: unknown argument: $arg" >&2
57
+ echo "usage: cloud-detect.sh [--banner]" >&2
58
+ exit 2
59
+ ;;
60
+ esac
61
+ done
62
+
63
+ # Extract a top-level string field from the flat sentinel JSON — whitespace
64
+ # tolerant, no jq/python3 dependency. Prints the value (possibly empty); never
65
+ # fails, because an unreadable/unparseable file must classify malformed, not die.
66
+ sentinel_field() {
67
+ local field="$1" file="$2"
68
+ grep -oE "\"${field}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$file" 2>/dev/null \
69
+ | head -n 1 \
70
+ | sed -E 's/^[^:]*:[[:space:]]*"//; s/"[[:space:]]*$//' \
71
+ || true
72
+ }
73
+
74
+ # Any DEVIN* marker present — used only to pick the reason when the sentinel is
75
+ # missing; it never gates `local` (local exec shells expose no DEVIN* vars).
76
+ devin_env_present() {
77
+ [[ -n "${DEVIN:-}" || -n "${DEVIN_HOME:-}" || -n "${DEVIN_PROJECT_DIR:-}" || -n "${DEVIN_PLUGIN_ROOT:-}" || -n "${DEVIN_DIR:-}" ]]
78
+ }
79
+
80
+ classify() {
81
+ # 1. Sentinel under the git root; outside a repo (or without git) there is
82
+ # nowhere for it to live. Absent sentinel: Devin-marked box → sentinel-absent;
83
+ # no Devin env at all → no-devin-env (likely not a Devin session — callers
84
+ # proceed normally).
85
+ local root sentinel
86
+ root="$(git rev-parse --show-toplevel 2>/dev/null)" || root=""
87
+ sentinel="${root:+$root/.devin/soleur-local-session}"
88
+ if [[ -z "$root" || ! -f "$sentinel" ]]; then
89
+ if devin_env_present; then
90
+ echo "not-local:sentinel-absent"
91
+ else
92
+ echo "not-local:no-devin-env"
93
+ fi
94
+ return
95
+ fi
96
+
97
+ # 2. Content-bearing sentinel: must look like a JSON object and carry both
98
+ # required fields, else malformed.
99
+ local content host hook_source
100
+ content="$(cat "$sentinel" 2>/dev/null || true)"
101
+ if [[ ! "$content" =~ ^[[:space:]]*\{ ]] || [[ ! "$content" =~ \}[[:space:]]*$ ]]; then
102
+ echo "not-local:malformed"
103
+ return
104
+ fi
105
+ host="$(sentinel_field host "$sentinel")"
106
+ hook_source="$(sentinel_field hook_source "$sentinel")"
107
+ if [[ -z "$host" || -z "$hook_source" ]]; then
108
+ echo "not-local:malformed"
109
+ return
110
+ fi
111
+
112
+ # 3. Host must match — a sentinel that travelled is not evidence of THIS
113
+ # host's session (measured 2026-09-17: /handoff carries committed content
114
+ # only, so gitignored files do not move via it; the live cause is a
115
+ # commit in a user repo that doesn't gitignore .devin/, plus any future
116
+ # transport that does carry the file). Same `hostname` invocation as the
117
+ # write side.
118
+ local this_host
119
+ this_host="$(hostname 2>/dev/null || true)"
120
+ if [[ -z "$this_host" || "$host" != "$this_host" ]]; then
121
+ echo "not-local:foreign-host"
122
+ return
123
+ fi
124
+
125
+ # 4. Source must be the plugin registration — a repo-level SessionStart hook
126
+ # firing on a cloud VM (the undocumented arm the probe checks) writes a
127
+ # matching-host sentinel, which must NOT read as local.
128
+ if [[ "$hook_source" != "plugin" ]]; then
129
+ echo "not-local:non-plugin-source"
130
+ return
131
+ fi
132
+
133
+ # 5. Conflicting evidence: everything above attests "plugin SessionStart fired
134
+ # on this host" — but a cloud-only env marker is present. If Cognition ships
135
+ # plugin-hook dispatch in cloud (#8160) before plugin subagents, this arm is
136
+ # what keeps the gap fail-closed instead of silently reading as local.
137
+ if [[ -n "${DEVIN_DIR:-}" || -n "${DEVIN_DISABLE_HISTEXPAND:-}" ]]; then
138
+ echo "not-local:conflicting-evidence"
139
+ return
140
+ fi
141
+
142
+ echo "local"
143
+ }
144
+
145
+ # Reason-aware capability banner — stderr only, never stdout. Silence about
146
+ # absent surfaces is the failure class this feature exists to kill.
147
+ emit_banner() {
148
+ local reason="$1" detail
149
+ case "$reason" in
150
+ no-devin-env)
151
+ detail="no Devin session environment (DEVIN, DEVIN_HOME, DEVIN_PROJECT_DIR, DEVIN_PLUGIN_ROOT, DEVIN_DIR all unset)"
152
+ ;;
153
+ sentinel-absent)
154
+ detail="no local-session sentinel at .devin/soleur-local-session (plugin SessionStart never ran here)"
155
+ ;;
156
+ malformed)
157
+ detail="local-session sentinel is unreadable, not a JSON object, or missing host/hook_source"
158
+ ;;
159
+ foreign-host)
160
+ detail="local-session sentinel was written by a different host (committed file — /handoff does not carry gitignored content, measured 2026-09-17)"
161
+ ;;
162
+ non-plugin-source)
163
+ detail="local-session sentinel was written by a repo-level hook, not the plugin registration"
164
+ ;;
165
+ conflicting-evidence)
166
+ detail="plugin-sourced sentinel on a cloud-marked VM (DEVIN_DIR set) — plugin hooks may partially dispatch here; the capability gap persists"
167
+ ;;
168
+ *)
169
+ detail="unrecognized classification"
170
+ ;;
171
+ esac
172
+ {
173
+ printf '=== Soleur Cloud Mode — reduced-capability session ===\n'
174
+ printf 'This Devin session is NOT running the local Soleur surface (reason: %s — %s).\n' "$reason" "$detail"
175
+ printf 'Absent surfaces: plugin subagents (run_subagent / Task agent fan-out), ALL hooks\n'
176
+ printf ' (SessionStart / SessionEnd / PreToolUse / PostToolUse / Stop — incl.\n'
177
+ printf ' the credential guard, guardrails, and DONE-marker stop-gate)\n'
178
+ printf 'Still available: /soleur:* skills, AGENTS.md rules, MCP servers\n'
179
+ printf 'Degrade path: spawn-site skills run agent roles sequentially inline and disclose with\n'
180
+ printf ' "Reviewed-Coverage: sequential-fallback" in the deliverable\n'
181
+ printf 'Secrets/prod: reads and mutations require an explicit cloud acknowledgement first\n'
182
+ } >&2
183
+ }
184
+
185
+ RESULT="$(classify)"
186
+ echo "$RESULT"
187
+ # --banner is suppressed for no-devin-env as well as local: that reason means
188
+ # "no Devin markers at all" (e.g. a Claude Code session), and the banner asserts
189
+ # "This Devin session…" — emitting it there would be a false claim.
190
+ if [[ "$RESULT" != "local" && "$RESULT" != "not-local:no-devin-env" && "$BANNER" -eq 1 ]]; then
191
+ emit_banner "${RESULT#not-local:}"
192
+ fi
193
+ exit 0