@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,383 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Stop hook: refuse a turn that ENDS on a promise it did not keep.
4
+ #
5
+ # THE DEFECT
6
+ # ----------
7
+ # A turn ends with a sentence naming the next action -- "implementing now",
8
+ # "I'll run those next" -- and the action never runs. The operator has to ask
9
+ # "why did you stop". Measured 2026-09-07: five times in one session, three of
10
+ # them inside the turns building this hook.
11
+ #
12
+ # Prose already covers it and already failed: `review/SKILL.md` section 6 names
13
+ # the shape exactly, and was read and violated repeatedly in the session it
14
+ # governs. This repo's record is that every hook exists BECAUSE a rule failed.
15
+ #
16
+ # Why a Stop hook: every other enforcement here fires on a tool call. This
17
+ # failure is the ABSENCE of one, and nothing observed the moment a turn ends.
18
+ #
19
+ # It matters more for users than for the author. The operator caught it because
20
+ # they can read pipeline state; a non-technical user gets a confident summary,
21
+ # nothing red, and a half-finished task.
22
+ #
23
+ # LOOP SAFETY -- `stop_hook_active`, not a counter
24
+ # ------------------------------------------------
25
+ # The runtime sets `stop_hook_active: true` on a stop that a hook already
26
+ # blocked. Honouring it means this hook blocks at most ONCE per stop-chain, so
27
+ # it can never wedge a session and needs no persistence.
28
+ #
29
+ # An earlier revision kept a per-session counter on disk instead, and justified
30
+ # it with a comment claiming the runtime "force-stops after 3 successive Stop
31
+ # blocks". Corrected twice, so both errors are recorded: the number was wrong
32
+ # (the shipped runtime uses CLAUDE_CODE_STOP_HOOK_BLOCK_CAP ?? 8), and the
33
+ # follow-up claim that the mechanism was UNSOURCED was also wrong -- it exists,
34
+ # and `stop-hook.sh`'s HARD_CAP=50 counts ralph-loop ITERATIONS, so it never
35
+ # contradicted it. The accurate statement: the runtime caps consecutive Stop
36
+ # blocks at 8, and `stop_hook_active` is the tighter per-chain bound, which is
37
+ # what makes a local counter redundant. The counter is still deleted, but on the
38
+ # real reason rather than an invented one -- it produced every defect this hook
39
+ # has had (correlated fixtures, cross-run state leakage, a symlink-followable
40
+ # state directory, and a hardlink-truncation primitive that survived its own
41
+ # ownership check).
42
+
43
+ # SCOPING -- the sentence, not a byte window
44
+ # ------------------------------------------
45
+ # The allow arms are tested against THE SAME SENTENCE as the promise. An earlier
46
+ # revision scanned a 700-byte tail for both, so a courtesy closer anywhere in
47
+ # the window vetoed a promise anywhere else in it: appending "Let me know if you
48
+ # want it different." to any of the three real instances made the hook ALLOW
49
+ # them. A guard that stops working when the turn is polite is inert in practice.
50
+ #
51
+ # VOCABULARY -- a sentence-initial `Paused:` / `Blocked:` label
52
+ # -------------------------------------------------------------
53
+ # Paused: <what you are waiting on>.
54
+ # Blocked: <what is blocking>.
55
+ # Plain prose, readable wherever it is shown, so nothing needs stripping. It
56
+ # replaced a literal `<stop>OPERATOR-GATE: ...</stop>` tag that users read as raw
57
+ # markup; the legacy tag is not honoured (a model still emitting it is blocked
58
+ # once, then released by `stop_hook_active`).
59
+ #
60
+ # Matching is anchored to the start of the FINAL sentence and needs the colon, so
61
+ # "the deploy was blocked by CI" or "Blocked PRs are listed below" buy nothing.
62
+ # A label with no content ("Blocked: none.") is a status line, not a declaration,
63
+ # and does not count (STOP_NOOP_RE). The reason must be ONE sentence: a pause
64
+ # sentence followed by a promise sentence is a promise.
65
+ #
66
+ # Deliberately NOT the marker one-shot owns:
67
+ # ONE_SHOT_DONE_MARKER (lib/workflow-fidelity.ts) is bound to "PR merged,
68
+ # release green, postmerge verified", and stop-hook.sh treats a match as a
69
+ # ralph-loop completion and DELETES the loop state. An earlier revision offered
70
+ # that marker as this hook's escape hatch, which would have taught the model to
71
+ # forge the pipeline's completion token on a turn that had just been blocked,
72
+ # and could kill a live loop. This hook owns `Paused:`/`Blocked:` and nothing else.
73
+ #
74
+ # KNOWN RESIDUALS -- this guard is NARROWER than the property it names
75
+ # -------------------------------------------------------------------
76
+ # Stated here rather than implied away, because a guard that reads complete is
77
+ # more dangerous than one whose limits are written down. A structural
78
+ # enumeration (2026-09-07) established residuals 0-6; residual 7 is a 2026-09-30
79
+ # scope decision, not part of that enumeration:
80
+ #
81
+ # 0. THE PARKED ARM IS NARROWER THAN ITS NAME, in ways measured by a structural
82
+ # enumeration (2026-09-17) rather than guessed. It catches only a turn that
83
+ # VOLUNTEERS the sentinel and phrases the parking inside a closed vocabulary:
84
+ # * omitting the label is a complete defence, and a parked turn has
85
+ # no other reason to emit one (it makes no promise);
86
+ # * off-vocabulary parking escapes -- `the merge is yours`, `awaiting
87
+ # approval`, `merge when you have a moment`, `the ball is in your court`;
88
+ # * `PARKED_AUTH_RE` is polarity-blind, so "Nothing destructive here" in the
89
+ # label's own sentence buys an exit;
90
+ # * five or more sentences after the label evict it from CLOSING, as does a
91
+ # fenced block, an unterminated fence, and a >8 kB message whose tail
92
+ # starts inside a fence (the awk toggle then reads the CLOSING fence as an
93
+ # opening one);
94
+ # * `stop_hook_active` means restating the parked sentence once clears it;
95
+ # * `SubagentStop` is unregistered, so a sub-agent parking its deliverable
96
+ # on the parent is unobserved.
97
+ # None is closable by widening the regex -- the assembly reads ONE STRING and
98
+ # never consults gh, git or pipeline state, so it cannot see that a PR is open.
99
+ # Written down because a guard that reads complete is worse than one whose
100
+ # limits are stated.
101
+ #
102
+ # 1. VOCABULARY. The predicate is a regex over a closed set of phrasings.
103
+ # "We'll ...", "Going to ...", "Next: ...", "The plan is to ...",
104
+ # "On to the ...", and any gerund outside GERUND_RE evade it. Broadened
105
+ # below to the highest-frequency forms; NOT complete, and cannot be.
106
+ # 2. EVENT COVERAGE. `Stop` does not fire on user interrupt or on an API
107
+ # error (that is `StopFailure`, unregistered here), and subagent turns end
108
+ # on `SubagentStop` (also unregistered). A promise made in a subagent's
109
+ # final message is unobserved.
110
+ # 3. INSTALLATION. .claude/settings.json registers no Stop hook, so this
111
+ # repo's own sessions are covered only via the plugin.
112
+ # 4. ONE BLOCK PER CHAIN. `stop_hook_active` means a determined turn can
113
+ # restate the promise on the next stop and proceed. That is deliberate --
114
+ # the alternative is a hook that can wedge a session.
115
+ # 5. TAG QUESTION. A message ending in '?' is treated as waiting on an
116
+ # answer, so "Implementing now. Reasonable?" buys an exit. The inverse --
117
+ # blocking a genuine question -- pushes the model past information it
118
+ # needs, which is the worse failure.
119
+ # 6. SELF-DISARM. A turn whose FINAL sentence starts `Paused:` or `Blocked:`
120
+ # satisfies the escape hatch whether or not it is a real declaration, because
121
+ # a label a person writes unprompted is the price of not showing them markup.
122
+ # Empty labels (`Blocked: none.`) are excluded; a populated one still counts.
123
+ # 7. WEB SESSIONS OPT OUT. This hook is operator-CLI vocabulary: its block reason
124
+ # instructs the model in words a chat user must never see, and the web runtime
125
+ # loads it anyway (see WEB RUNTIME OPT-OUT below). Accepted trade-off: the
126
+ # header above says the guard matters more for non-technical users, but in the
127
+ # web Concierge the old tag vocabulary leaked `<stop>OPERATOR-GATE` over the
128
+ # user's question list (a block turn still replaces the reply there).
129
+ # The unkept-promise duty is therefore currently UNOWNED in web: no Concierge
130
+ # prompt carries an end-of-turn follow-through rule. That gap is tracked in
131
+ # #9289 (which also covers the non-Stop plugin hooks); it is not closed here.
132
+ #
133
+ # What it DOES buy: the common case, which is a plain closing sentence naming
134
+ # the next action. Measured against the five real 2026-09-07 instances, it
135
+ # catches the three that were plain prose.
136
+
137
+ set -uo pipefail
138
+
139
+ # SUT-WRITTEN EXECUTION MARKER (test-only, opt-in via an env var production never
140
+ # sets). The suite's coverage floor counted lines its OWN harness appended before
141
+ # spawning anything, so it measured the harness and not the subject: one line --
142
+ # `expect() { EXPECT_ROWS=$((EXPECT_ROWS+1)); echo x >> "$LOG"; pass "$2"; }` --
143
+ # satisfied all three floors at once and printed their exact green-run values with
144
+ # the hook never spawned for any parked row.
145
+ #
146
+ # EMITTED TO STDERR, NOT WRITTEN TO A PATH. A path operand here is flagged by the
147
+ # P1b guard (fixture-relative-assert) as "not provably absolute": the value comes
148
+ # from the environment, and a `case /*)` at the use site is invisible to a scanner
149
+ # that reasons about BINDING. Recording it in that guard's baseline would have
150
+ # banked a real hazard -- a hook runs from whatever CWD the session is in, so a
151
+ # relative value would append into an arbitrary working tree. fd 2 is not a path,
152
+ # so the hazard does not exist rather than being accepted. stdout stays reserved
153
+ # for the block protocol; the harness counts this marker from captured stderr, so
154
+ # a harness that never spawns the hook still counts zero.
155
+ [ -n "${SOLEUR_HOOK_TRACE:-}" ] && printf 'SOLEUR_HOOK_RAN\n' >&2
156
+
157
+ # WEB RUNTIME OPT-OUT. The web Concierge loads this plugin's hooks.json through the
158
+ # SDK plugin binding, so this operator-CLI guard ran against end users: its block
159
+ # reason told the model to write `<stop>OPERATOR-GATE: ...</stop>`, which replaced
160
+ # a CRM question list in the chat bubble. The platform sets this variable in
161
+ # `buildAgentEnv` (apps/web-platform/server/agent-env.ts); it also works as an
162
+ # operator kill switch, mirroring SOLEUR_DISABLE_COMPACTION_HOOKS. Its position is
163
+ # load-bearing in ONE direction: it must sit AFTER the trace marker above (the suite
164
+ # counts executions through that stderr line, so an opted-out spawn is still counted
165
+ # as a run — moving it above the marker trips the floor). Its position relative to the
166
+ # jq fail-open below is behaviourally equivalent (both exit 0 silently), so it sits
167
+ # first only to keep an opted-out session independent of jq.
168
+ [[ "${SOLEUR_DISABLE_UNKEPT_PROMISE_HOOK:-0}" == "1" ]] && exit 0
169
+
170
+
171
+ # Fail OPEN on every infrastructure problem: this must never be the reason a
172
+ # session cannot end.
173
+ command -v jq >/dev/null 2>&1 || exit 0
174
+ HOOK_INPUT=$(cat 2>/dev/null) || exit 0
175
+ [[ -n "$HOOK_INPUT" ]] || exit 0
176
+
177
+ # Already blocked once in this stop-chain -- do not block again.
178
+ ACTIVE=$(printf '%s' "$HOOK_INPUT" | jq -r '.stop_hook_active // false' 2>/dev/null) || exit 0
179
+ [[ "$ACTIVE" == "true" ]] && exit 0
180
+
181
+ LAST_MSG=$(printf '%s' "$HOOK_INPUT" | jq -r '.last_assistant_message // ""' 2>/dev/null) || exit 0
182
+ [[ -n "$LAST_MSG" ]] || exit 0
183
+
184
+ # Split into sentences, newest last. Markdown bullets and headings end a line
185
+ # without punctuation, so line breaks are sentence boundaries too.
186
+ # Drop fenced blocks first: wg-end-of-work-emit-resume-prompt REQUIRES a fenced
187
+ # resume prompt as the final block of every /work and /one-shot turn -- the very
188
+ # class this defect lives in. Left in, it becomes the "closing sentences" and
189
+ # hides the promise above it. Also drop leading markdown bullet/emphasis markers
190
+ # so a "Next steps:" list is not invisible to the sentence-initial anchors.
191
+ # Bound the input before any pipeline touches it. Only the closing sentences are
192
+ # ever used, and an unbounded message costs real time on every turn end
193
+ # (measured on the prior revision: 20 MB -> 6.5 s, 186 MB RSS). It also removes
194
+ # the SIGPIPE hazard below at the source.
195
+ BOUNDED=$(printf '%s' "$LAST_MSG" | tail -c 8000)
196
+ PROSE=$(printf '%s' "$BOUNDED" | awk '/^[[:space:]]*```/{f=!f; next} !f')
197
+ # Newlines are folded to RS so a sentence-ending period followed by a line break
198
+ # still splits, then folded BACK with `tr` -- not `sed`. `tr` interprets \036 as
199
+ # an octal escape and `sed` does not, so `sed 's/\036/\n/g'` silently matched
200
+ # nothing: the separators survived, the whole message stayed ONE "sentence", and
201
+ # per-sentence scoping was inert for any newline-separated text. Every fixture
202
+ # used ". " separators, so the suite could not see it.
203
+ SENTENCES=$(printf '%s' "$PROSE" | tr '\n' '\036' \
204
+ | sed 's/\([.!?]\)[[:space:]]/\1\n/g' \
205
+ | tr '\036' '\n' \
206
+ | sed 's/^[[:space:]]*//; s/^[-*+][[:space:]]*//; s/^\*\*//; s/[[:space:]]*$//' \
207
+ | grep -v '^$' || true)
208
+ [[ -n "$SENTENCES" ]] || exit 0
209
+
210
+ # Only the closing few sentences are evidence about where the turn STOPPED.
211
+ CLOSING=$(printf '%s' "$SENTENCES" | tail -n 4)
212
+
213
+ # THE PARKED-DELIVERABLE ARM (2026-09-17).
214
+ # ----------------------------------------
215
+ # Denies a stop that hands FINISHED WORK back for a merge/review/ship. That end
216
+ # state is the one `rf-never-skip-qa-review-before-merging` names: "Carry every PR
217
+ # to MERGED in-session; 'awaiting review'/'needs a human' as an end state defers to
218
+ # an operator who cannot clear it."
219
+ #
220
+ # WHY THE LABEL ALONE WAS NOT ENOUGH. The stop-label arm below exits 0 on the PRESENCE
221
+ # of a label, with nothing constraining what is being waited ON, so the one end state
222
+ # the corpus forbids bought an exit. Parking READS as diligence, which is why prose
223
+ # could not close it: the class was recorded 2026-08-04 and recurred 2026-09-17 with
224
+ # the rule in force.
225
+ #
226
+ # THE OBJECT SET IS DELIBERATELY NARROW: merge, review, ship. An earlier revision
227
+ # also matched `decision|approv|go-?ahead|sign-off`, and review measured it blocking
228
+ # 13 of 15 rule-MANDATED operator gates -- `wg-zero-agents-until-user-confirms`
229
+ # ("pending your go-ahead before I spawn the agents"), the API-budget disclosure,
230
+ # an invoice awaiting sign-off before reaching a customer, a social post awaiting
231
+ # approval -- while answering each with "Do it now, in THIS turn". A guard that
232
+ # fires on `wg-zero-agents-until-user-confirms` and replies "do it now" is worse
233
+ # than no guard. `hr-technical-fork-is-not-an-operator-question` is explicit that
234
+ # authorization, COST and SCOPE are the operator's to answer; only the delivery of
235
+ # reviewed work is not.
236
+ #
237
+ # PLACEMENT, both measured against the real turn rather than reasoned:
238
+ # * scoped to the whole closing, not `tail -n 1` -- the declaration began in one sentence
239
+ # and its reason ran into the next, so a last-sentence test saw only the trailing clause;
240
+ # * runs INDEPENDENTLY of promise detection -- a parked turn makes no promise, so
241
+ # an arm nested in the promise path could never fire.
242
+ # The declaration marker: a sentence that STARTS with `Paused:` or `Blocked:`. The
243
+ # sentence prep's bullet strip eats one `*` of a leading `**`, hence `[*]*`; both
244
+ # `**Paused**:` and `**Paused:**` match. See VOCABULARY above.
245
+ STOP_MARK_RE='^[*]*(paused|blocked)[*[:space:]]*:'
246
+ # A label whose content is empty or a negative status ("Blocked: none.").
247
+ STOP_NOOP_RE='^[^:]*:[*[:space:]]*((no|none|nothing|n/?a)[[:punct:][:space:]]*)?$'
248
+ is_stop_mark() { grep -qiE "$STOP_MARK_RE" <<<"$1" && ! grep -qiE "$STOP_NOOP_RE" <<<"$1"; }
249
+
250
+ PARKED_RE='(awaiting|waiting[[:space:]]+(on|for)|pending|needs?|requires?)[^.]{0,60}(your|operator|the[[:space:]]+operator|human|a[[:space:]]+human)[^.]{0,60}(merge|review|ship)|awaiting[[:space:]]+(review|merge)([[:space:]]|[.,;:]|$)|needs?[[:space:]]+a[[:space:]]+human([[:space:]]|[.,;:]|$)|ready[[:space:]]+(for[[:space:]]+(you|your)|to[[:space:]]+merge[[:space:]]+when[[:space:]]+you)|(yours|over[[:space:]]+to[[:space:]]+you|handing[[:space:]]+(it[[:space:]]+)?off[[:space:]]+to[[:space:]]+you)[^.]{0,40}(merge|review|ship)'
251
+
252
+ # The sanctioned pause survives: `hr-menu-option-ack-not-prod-write-auth` requires
253
+ # per-command confirmation before a destructive production write.
254
+ #
255
+ # SCOPED TO THE MATCHING SENTENCE, NOT THE WINDOW -- and that is this file's own
256
+ # documented lesson, reintroduced by the first revision of this arm and caught in
257
+ # review. The header's SCOPING section records that a window-scoped allow arm is
258
+ # what made the promise arm inert ("a courtesy closer anywhere in the window vetoed
259
+ # a promise anywhere else in it"). Measured on the first revision: "I revoked the
260
+ # old token as part of cleanup. Paused: PR #8244 is green and awaiting
261
+ # your merge." ALLOWED, because `revoke` appeared in an unrelated sentence.
262
+ PARKED_AUTH_RE='(irreversible|destroy|destructive|wipe|revoke|cutover|host[[:space:]]+replace|replace[[:space:]]+the[[:space:]]+(production[[:space:]]+)?host|per-command|prod(uction)?[[:space:]]+(write|mutation|apply))'
263
+
264
+ # ALL THREE TERMS ARE TESTED ON THE MARKER'S OWN SENTENCE, not on the window.
265
+ #
266
+ # The first revision tested them independently over $CLOSING, so they could be
267
+ # satisfied by THREE DIFFERENT sentences -- which is co-occurrence, not the
268
+ # waiting-on relationship this arm's header claims to key on. Measured in review:
269
+ # "The sibling PR is still awaiting review by the other team.
270
+ # Paused: waiting on CI run 123 for this one." -> BLOCK
271
+ # A legitimate in-flight CI gate, vetoed because a neighbouring sentence mentioned
272
+ # somebody else's review. Same shape in the other direction, and same shape the
273
+ # header's own SCOPING section records as what made the promise arm inert.
274
+ #
275
+ # A turn ending in a genuine QUESTION is excused here, mirroring the message-level
276
+ # arm further down. Residual #5 records the deliberate judgement that "forcing a
277
+ # real question through is the worse failure"; because this arm runs above that
278
+ # escape, it would otherwise reverse that judgement for labelled turns without
279
+ # amending the residual.
280
+ PARKED_SENTENCE=$(printf '%s\n' "$CLOSING" | grep -iE "$STOP_MARK_RE" | tail -n 1)
281
+ if [ -n "$PARKED_SENTENCE" ] &&
282
+ ! grep -q '?' < <(printf '%s' "$PROSE" | sed 's/[[:space:]]*$//' | tail -c 2) &&
283
+ grep -qiE "$PARKED_RE" <<<"$PARKED_SENTENCE" &&
284
+ ! grep -qiE "$PARKED_AUTH_RE" <<<"$PARKED_SENTENCE"; then
285
+ PARKED_REASON="Your Paused/Blocked line hands finished work back for a merge, review or ship. That is not a
286
+ legitimate gate -- it defers to someone who cannot clear it.
287
+
288
+ rf-never-skip-qa-review-before-merging: \"Carry every PR to MERGED in-session;
289
+ 'awaiting review'/'needs a human' as an end state defers to an operator who
290
+ cannot clear it.\" \"Review-gated\" means /soleur:review RAN and its findings were
291
+ fixed -- never that a person approves.
292
+
293
+ If the review has not run, run it now and fix its findings inline. If it has, and
294
+ the checks are green, merge. Do it in THIS turn.
295
+
296
+ This arm is about DELIVERY only. It does not block -- and you should still stop
297
+ for -- any of these:
298
+ - an in-flight CI run, workflow or agent
299
+ - authorization for an irreversible production action (hr-menu-option-ack-not-prod-write-auth)
300
+ - COST or SCOPE, or spawning agents (hr-technical-fork-is-not-an-operator-question,
301
+ wg-zero-agents-until-user-confirms)
302
+ - an outward-facing effect that leaves the repo -- an invoice, a post, an email
303
+ - a genuine fork in requirements that changes what gets built"
304
+ jq -n --arg r "$PARKED_REASON" \
305
+ '{"decision":"block","reason":$r,"systemMessage":"unkept-promise-hook: finished work parked on the operator"}' 2>/dev/null \
306
+ || exit 0
307
+ exit 0
308
+ fi
309
+
310
+ # Escape hatch, scanned over the CLOSING sentences only -- deliberately the same
311
+ # scope as the predicate.
312
+ #
313
+ # An earlier revision scanned the whole message, which was wrong twice over.
314
+ # (a) ASYMMETRY: a turn that merely DISCUSSED the sentinel -- documenting it,
315
+ # reviewing this hook, quoting a user's paste -- disarmed the guard while
316
+ # still closing on a promise. That silently exempted exactly the sessions
317
+ # that edit this file, including this PR's own turns.
318
+ # (b) SIGPIPE: `printf "$BIG" | grep -q` under `set -o pipefail` returns 141
319
+ # when grep exits on first match, so the `if` read a MATCH as a NON-match.
320
+ # Measured on the prior revision: a valid sentinel was ignored at >=64 KB,
321
+ # non-deterministically at the pipe-buffer boundary -- i.e. the only way to
322
+ # declare a legitimate stop failed precisely on long closing messages.
323
+ # Both are closed by scoping to CLOSING, which is a handful of short lines.
324
+ # Narrower still: the FINAL sentence. Declaring a stop is a closing act, so a
325
+ # sentinel merely mentioned earlier -- documenting it, reviewing this hook,
326
+ # quoting a paste -- no longer disarms the guard. CLOSING alone was not enough:
327
+ # in a two-sentence message both the mention and the promise sit inside it.
328
+ if is_stop_mark "$(printf '%s' "$CLOSING" | tail -n 1)"; then
329
+ exit 0
330
+ fi
331
+
332
+ # A turn ENDING in a question is waiting on an answer, whatever else it said.
333
+ # This one arm is message-level, not per-sentence: blocking it would push the
334
+ # model past a question it needs answered, and produce work built on a guess.
335
+ # The cost is a named residual -- a tag question ("Implementing now. Reasonable?")
336
+ # buys an exit. Accepted: forcing a real question through is the worse failure.
337
+ if grep -q '?' < <(printf '%s' "$PROSE" | sed 's/[[:space:]]*$//' | tail -c 2); then
338
+ exit 0
339
+ fi
340
+
341
+ PROMISE_RE="(i'll |i will |i am going to |i'm going to |im going to |we'll |we will |let me [a-z]+|going to [a-z]+|about to [a-z]+|next:|next step|the plan is to |on to the |time to [a-z]+)"
342
+ GERUND_RE='^(implementing|running|building|writing|committing|pushing|shipping|fixing|creating|adding|executing|starting|continuing|proceeding|applying|updating|wiring|merging|deploying|verifying|refactoring|drafting|opening|rebasing|patching|migrating|landing|testing|checking|investigating|finishing|queuing|spawning|handing)\b'
343
+
344
+ # Allow arms, evaluated PER SENTENCE against the sentence that carries the
345
+ # promise -- never against the window, which is what let a closer veto a promise
346
+ # it had nothing to do with.
347
+ # conditional : the promise is contingent on the operator
348
+ # pending : the promise is contingent on work already in flight
349
+ # `let me know` is matched by PROMISE_RE, so CONDITIONAL must be tested first.
350
+ CONDITIONAL_RE='(say the word|if you|once you|when you|whenever you|let me know|tell me|your call|up to you|on your (go|signal|say))'
351
+ PENDING_RE='(report (what|back)|(when|once|as soon as|after) (it|they|those|the (run|tests|ci|build|merge))|(they|it|those) (find|finds|land|lands|complete|completes|merge|merges|return|returns)|still running|in flight|notification arrives)'
352
+
353
+ FIRED=""
354
+ while IFS= read -r s; do
355
+ [[ -n "$s" ]] || continue
356
+ grep -qiE "$CONDITIONAL_RE" <<<"$s" && continue
357
+ grep -qiE "$PENDING_RE" <<<"$s" && continue
358
+ if grep -qiE "$PROMISE_RE" <<<"$s"; then
359
+ FIRED="a first-person commitment to act"; break
360
+ fi
361
+ if grep -qiE "$GERUND_RE" <<<"$s"; then
362
+ FIRED="a bare gerund announcement"; break
363
+ fi
364
+ done <<< "$CLOSING"
365
+
366
+ [[ -n "$FIRED" ]] || exit 0
367
+
368
+ REASON="Your closing text names an action you have not taken -- ${FIRED} -- and the turn is ending.
369
+
370
+ Do it now, in THIS turn. Writing the next action down is not doing it.
371
+
372
+ If the stop is legitimate, end the message with ONE plain sentence that starts with
373
+ the label and says why (no markup, no sentence break inside it):
374
+ Paused: the one thing you are waiting on.
375
+ Blocked: the one thing that is blocking you.
376
+
377
+ Stopping is allowed. Stopping silently is not -- an operator who cannot see the
378
+ pipeline has no way to tell a finished task from an abandoned one."
379
+
380
+ jq -n --arg r "$REASON" \
381
+ '{"decision":"block","reason":$r,"systemMessage":"unkept-promise-hook: turn ended on an unexecuted commitment"}' 2>/dev/null \
382
+ || exit 0
383
+ exit 0
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env bash
2
+ # version-banner.sh — SessionStart (matcher: startup) one-line Soleur version banner.
3
+ #
4
+ # Prints ONE JSON object on stdout: {"systemMessage": "Soleur <vX.Y.Z | commit <sha12>[ (local checkout)]>[ — newer release vA.B.C available]"}
5
+ # `commit <sha12> (local checkout)` is an in-place install (a local-Folder marketplace or --plugin-dir):
6
+ # the resolver read the HEAD commit of the git checkout the plugin is loaded from.
7
+ # `systemMessage` is shown to the user and costs zero model tokens (no additionalContext).
8
+ #
9
+ # The banner itself is ON by default and makes NO network call. Only the "newer release"
10
+ # check is opt-in: with SOLEUR_UPDATE_CHECK=1 (exactly `1`; `0`, empty and any other value
11
+ # are off) the hook reads the per-install release cache and, when that cache is stale,
12
+ # missing or corrupt, spawns ONE detached background refresh. The hook itself never touches
13
+ # the network and never waits on it: it prints the cached answer now.
14
+ #
15
+ # Skips silently (exit 0, no output) when CLAUDE_PLUGIN_ROOT is unset, on the non-Claude
16
+ # harness markers hooks/welcome-hook.sh uses (CODEX_THREAD_ID, PLUGIN_ROOT), when
17
+ # SOLEUR_DISABLE_VERSION_BANNER=1, and when the installed version cannot be determined.
18
+ #
19
+ # Fails open: every path exits 0 and any error prints nothing. Plugin hooks are GLOBAL
20
+ # (they fire in every project), so a banner that errors or blocks would hit every session.
21
+ set -uo pipefail
22
+ case "$-" in
23
+ *x*) printf '[FATAL] refusing to run under xtrace: this script handles a live credential and -x would print it (see #7797)\n' >&2; exit 78 ;;
24
+ esac
25
+ # `set -u` aborts with status 1 and no ERR trap on an unbound variable; force a clean exit.
26
+ trap 'exit 0' EXIT
27
+
28
+ # Refresh dedupe: an atomic mkdir lock under the cache dir. It is deliberately never
29
+ # removed by the refresh; it simply ages out, which also rate-limits repeated attempts
30
+ # while offline (one attempt per LOCK_TTL_S instead of one per session).
31
+ LOCK_TTL_S=600
32
+
33
+ json_escape() { # escape a string for use inside a JSON string literal
34
+ local s="$1"
35
+ s="${s//\\/\\\\}"
36
+ s="${s//\"/\\\"}"
37
+ s="${s//$'\n'/ }"
38
+ s="${s//$'\r'/ }"
39
+ s="${s//$'\t'/ }"
40
+ printf '%s' "$s"
41
+ }
42
+
43
+ # Spawn at most one detached background refresh. Never blocks, never prints.
44
+ spawn_refresh() { # <resolver> <cache_dir>
45
+ local resolver="$1" cache_dir="$2" lock now mtime v
46
+ # The resolver reports an absolute cache dir or none (HOME unset, relative XDG).
47
+ [[ "$cache_dir" == /* ]] || return 0
48
+ lock="$cache_dir/refresh.lock"
49
+ ( umask 077; mkdir -p "$cache_dir" ) 2>/dev/null || return 0
50
+ # Same trust rule as the resolver: only lock inside a directory we own that is not a symlink.
51
+ [[ -d "$cache_dir" && -O "$cache_dir" && ! -L "$cache_dir" ]] || return 0
52
+ if [[ -d "$lock" ]]; then
53
+ now="$(date +%s)"
54
+ mtime="$(stat -c %Y "$lock" 2>/dev/null || stat -f %m "$lock" 2>/dev/null || echo "$now")"
55
+ [[ "$mtime" =~ ^[0-9]+$ ]] || mtime="$now"
56
+ # A future-dated lock (clock change) counts as expired, like a future-dated cache.
57
+ if (( now - mtime >= LOCK_TTL_S || mtime > now + 60 )); then rmdir "$lock" 2>/dev/null || true; fi
58
+ fi
59
+ # mkdir is the atomic claim: of two concurrent starts exactly one succeeds.
60
+ ( umask 077; mkdir "$lock" ) 2>/dev/null || return 0
61
+ # The child gets an allowlisted environment (no inherited secrets) and stdin, stdout and
62
+ # stderr all on /dev/null, or the hook's pipes stay open through the child and the
63
+ # session waits on it.
64
+ local -a childenv=(env -i "PATH=${PATH:-/usr/bin:/bin}" "HOME=${HOME:-}")
65
+ for v in XDG_CACHE_HOME CLAUDE_PLUGIN_ROOT TMPDIR SOLEUR_FETCH_TIMEOUT \
66
+ SSL_CERT_FILE SSL_CERT_DIR CURL_CA_BUNDLE GIT_SSL_CAINFO \
67
+ http_proxy https_proxy all_proxy no_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY; do
68
+ [[ -n "${!v:-}" ]] && childenv+=("$v=${!v}")
69
+ done
70
+ if command -v setsid >/dev/null 2>&1; then
71
+ setsid nohup "${childenv[@]}" bash "$resolver" --latest --refresh </dev/null >/dev/null 2>&1 &
72
+ else
73
+ nohup "${childenv[@]}" bash "$resolver" --latest --refresh </dev/null >/dev/null 2>&1 &
74
+ fi
75
+ disown 2>/dev/null || true
76
+ return 0
77
+ }
78
+
79
+ main() {
80
+ [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]] || return 0
81
+ [[ -n "${CODEX_THREAD_ID:-}" || -n "${PLUGIN_ROOT:-}" ]] && return 0
82
+ [[ "${SOLEUR_DISABLE_VERSION_BANNER:-}" == "1" ]] && return 0
83
+
84
+ local here resolver mode="--installed"
85
+ here="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" || return 0
86
+ resolver="$here/../scripts/plugin-version.sh"
87
+ [[ -f "$resolver" ]] || return 0
88
+ # One resolver call per start: --cached-latest also prints the installed keys, reads the
89
+ # cache only and makes no network call.
90
+ [[ "${SOLEUR_UPDATE_CHECK:-}" == "1" ]] && mode="--cached-latest"
91
+
92
+ local k v source="" version="" commit="" cache="" cache_dir="" latest="" relation="" label=""
93
+ while IFS='=' read -r k v; do
94
+ case "$k" in
95
+ source) source="$v" ;; version) version="$v" ;; commit) commit="$v" ;;
96
+ cache) cache="$v" ;; cache_dir) cache_dir="$v" ;; latest) latest="$v" ;; relation) relation="$v" ;;
97
+ esac
98
+ done < <(bash "$resolver" "$mode" 2>/dev/null)
99
+ case "$source" in
100
+ manifest) [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || return 0; label="v$version" ;;
101
+ commit) [[ "$commit" =~ ^[0-9a-f]{12}$ ]] || return 0; label="commit $commit" ;;
102
+ checkout) [[ "$commit" =~ ^[0-9a-f]{12}$ ]] || return 0; label="commit $commit (local checkout)" ;;
103
+ *) return 0 ;;
104
+ esac
105
+
106
+ local msg="Soleur $label"
107
+
108
+ if [[ "$mode" == "--cached-latest" ]]; then
109
+ # A stale value is still shown below; the refresh only helps the NEXT session.
110
+ case "$cache" in stale|missing|corrupt) spawn_refresh "$resolver" "$cache_dir" ;; esac
111
+
112
+ if [[ "$relation" == "older" && "$latest" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
113
+ local warn=1
114
+ if [[ "$source" == "manifest" ]]; then
115
+ # Never warn a downgrade: re-check the order here rather than trust the cached relation alone.
116
+ [[ "$(bash "$resolver" --cmp "$version" "${latest#v}" 2>/dev/null)" == "older" ]] || warn=0
117
+ fi
118
+ (( warn )) && msg="$msg — newer release $latest available"
119
+ fi
120
+ fi
121
+
122
+ printf '{"systemMessage": "%s"}\n' "$(json_escape "$msg")"
123
+ return 0
124
+ }
125
+
126
+ main "$@" 2>/dev/null
127
+ exit 0
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ [[ -n "${CODEX_THREAD_ID:-}" || -n "${PLUGIN_ROOT:-}" ]] && exit 0
5
+
6
+ # --- Sentinel Check ---
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+ source "$SCRIPT_DIR/../scripts/resolve-git-root.sh" || {
9
+ # Not in a git repo -- skip welcome silently
10
+ exit 0
11
+ }
12
+ PROJECT_ROOT="$GIT_ROOT"
13
+
14
+ # The plugin's own SessionStart registration implies the plugin is installed for
15
+ # the user — but plugin hooks are GLOBAL, firing in every project the user opens,
16
+ # so registration is not a per-project scope predicate (the old
17
+ # `plugins/soleur`-dir guard was the #1383 fix AND the #5119 root cause: it
18
+ # silenced real installs while failing to scope). The dedupe lives OUTSIDE the
19
+ # project tree — a plugin-owned state dir keyed by the repo-hash trick
20
+ # emit-decision.sh uses — so no artifact lands in the user's repo at all and
21
+ # welcome still fires once per project on real (marketplace) installs.
22
+
23
+ if command -v sha256sum >/dev/null 2>&1; then
24
+ repo_key="$(printf '%s' "$PROJECT_ROOT" | sha256sum | cut -c1-16)"
25
+ elif command -v shasum >/dev/null 2>&1; then
26
+ repo_key="$(printf '%s' "$PROJECT_ROOT" | shasum -a 256 | cut -c1-16)"
27
+ else
28
+ # No sha tool: fall back to a path-derived key (slashes flattened, bounded).
29
+ repo_key="$(printf '%s' "$PROJECT_ROOT" | tr -c '[:alnum:]' '_' | cut -c1-120)"
30
+ fi
31
+
32
+ SENTINEL_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/soleur/welcomed"
33
+ SENTINEL_FILE="$SENTINEL_DIR/$repo_key"
34
+
35
+ [[ -f "$SENTINEL_FILE" ]] && exit 0
36
+
37
+ # --- First-Time Welcome ---
38
+ # Only emit when the dedupe marker lands — a welcome that cannot be remembered
39
+ # fires every session, which is worse than none.
40
+ mkdir -p "$SENTINEL_DIR" 2>/dev/null || exit 0
41
+ touch "$SENTINEL_FILE" 2>/dev/null || exit 0
42
+
43
+ cat <<'WELCOME_JSON'
44
+ {
45
+ "hookSpecificOutput": {
46
+ "hookEventName": "SessionStart",
47
+ "additionalContext": "Welcome to Soleur! This appears to be the first session with Soleur installed. Suggest the user run /soleur:sync to analyze their project, or /soleur:help to see all available commands."
48
+ }
49
+ }
50
+ WELCOME_JSON