@soleur/opencode 0.0.0-stage → 3.354.2

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 (832) 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 +660 -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 +29 -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 +361 -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 +171 -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 +818 -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 +411 -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 +509 -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 +115 -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 +165 -0
  247. package/scripts/sync-opencode-adapter.ts +498 -0
  248. package/scripts/sync-pr-behind.sh +647 -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 +67 -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 +143 -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 +120 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -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 +670 -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 +331 -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 +141 -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 +1620 -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-evidence-comment.md +36 -0
  674. package/skills/review/references/review-todo-structure.md +165 -0
  675. package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
  676. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  677. package/skills/review/references/ultrathink-phases.md +98 -0
  678. package/skills/review/references/wfs.md +6 -0
  679. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  680. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  681. package/skills/review/scripts/fix-round-seats.sh +197 -0
  682. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  683. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  684. package/skills/review/test/fix-round-seats.test.sh +237 -0
  685. package/skills/review/workflows/README.md +147 -0
  686. package/skills/review/workflows/review.workflow.js +667 -0
  687. package/skills/schedule/SKILL.md +796 -0
  688. package/skills/seo-aeo/SKILL.md +139 -0
  689. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  690. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  691. package/skills/ship/SKILL.md +3023 -0
  692. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  693. package/skills/ship/references/affected-gate-contract.md +115 -0
  694. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  695. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  696. package/skills/ship/references/cleanup-merged-archival.md +39 -0
  697. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  698. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  699. package/skills/ship/references/decision-challenges-render.md +71 -0
  700. package/skills/ship/references/delegated-act-authoring-form.md +7 -0
  701. package/skills/ship/references/detached-battery-verdict.md +13 -0
  702. package/skills/ship/references/epic-close-sweep.md +62 -0
  703. package/skills/ship/references/feature-tweet-draft.md +42 -0
  704. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  705. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  706. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  707. package/skills/ship/references/operator-holds.md +179 -0
  708. package/skills/ship/references/pipeline-tally-render.md +43 -0
  709. package/skills/ship/references/pr-overlap.md +153 -0
  710. package/skills/ship/references/queue-mode.md +7 -0
  711. package/skills/ship/references/ready-run-wait.md +36 -0
  712. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  713. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  714. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  715. package/skills/ship/references/supabase-column-probe.md +13 -0
  716. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  717. package/skills/ship/scripts/battery-owed.sh +403 -0
  718. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  719. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  720. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  721. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  722. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  723. package/skills/skill-creator/SKILL.md +299 -0
  724. package/skills/skill-creator/references/api-security.md +248 -0
  725. package/skills/skill-creator/references/authoring-levers.md +110 -0
  726. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  727. package/skills/skill-creator/references/best-practices.md +431 -0
  728. package/skills/skill-creator/references/common-patterns.md +639 -0
  729. package/skills/skill-creator/references/core-principles.md +193 -0
  730. package/skills/skill-creator/references/executable-code.md +188 -0
  731. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  732. package/skills/skill-creator/references/official-spec.md +193 -0
  733. package/skills/skill-creator/references/recommended-structure.md +180 -0
  734. package/skills/skill-creator/references/skill-structure.md +396 -0
  735. package/skills/skill-creator/references/using-scripts.md +122 -0
  736. package/skills/skill-creator/references/using-templates.md +120 -0
  737. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  738. package/skills/skill-creator/scripts/init_skill.py +322 -0
  739. package/skills/skill-creator/scripts/package_skill.py +110 -0
  740. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  741. package/skills/skill-creator/templates/router-skill.md +73 -0
  742. package/skills/skill-creator/templates/simple-skill.md +34 -0
  743. package/skills/skill-creator/workflows/add-reference.md +96 -0
  744. package/skills/skill-creator/workflows/add-script.md +104 -0
  745. package/skills/skill-creator/workflows/add-template.md +83 -0
  746. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  747. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  748. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  749. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  750. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  751. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  752. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  753. package/skills/skill-security-scan/SKILL.md +145 -0
  754. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  755. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  756. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  757. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  758. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  759. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  760. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  761. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  762. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  763. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  764. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  765. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  766. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  767. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  768. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  769. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  770. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  771. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  772. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  773. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  774. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  775. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  776. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  777. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  778. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  779. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  780. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  781. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  782. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  783. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  784. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  785. package/skills/social-distribute/SKILL.md +485 -0
  786. package/skills/spec-templates/SKILL.md +274 -0
  787. package/skills/sync/SKILL.md +49 -0
  788. package/skills/test-browser/SKILL.md +464 -0
  789. package/skills/test-browser/references/feature-map.md +161 -0
  790. package/skills/test-fix-loop/SKILL.md +159 -0
  791. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  792. package/skills/triage/SKILL.md +402 -0
  793. package/skills/trigger-cron/SKILL.md +136 -0
  794. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  795. package/skills/user-set-role/SKILL.md +147 -0
  796. package/skills/user-set-role/scripts/set-role.sh +218 -0
  797. package/skills/user-story-writer/SKILL.md +77 -0
  798. package/skills/ux-audit/SKILL.md +251 -0
  799. package/skills/ux-audit/references/finding.schema.json +62 -0
  800. package/skills/ux-audit/references/route-list.yaml +95 -0
  801. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  802. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  803. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  804. package/skills/verification-scaffold/SKILL.md +73 -0
  805. package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
  806. package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
  807. package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
  808. package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
  809. package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
  810. package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
  811. package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
  812. package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
  813. package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
  814. package/skills/verification-scaffold/references/guards.tsv +21 -0
  815. package/skills/verification-scaffold/references/verification-readme.template +55 -0
  816. package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
  817. package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
  818. package/skills/verification-scaffold/test/generator.test.sh +319 -0
  819. package/skills/verification-scaffold/test/manifest.test.sh +144 -0
  820. package/skills/work/SKILL.md +1480 -0
  821. package/skills/work/references/end-of-work-resume.md +7 -0
  822. package/skills/work/references/hook-test-main-cwd.md +24 -0
  823. package/skills/work/references/key-principles.md +83 -0
  824. package/skills/work/references/property-testing.md +122 -0
  825. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  826. package/skills/work/references/work-agent-teams.md +97 -0
  827. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  828. package/skills/work/references/work-lockfile-bumps.md +97 -0
  829. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  830. package/skills/work/references/work-subagent-fanout.md +61 -0
  831. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  832. package/skills/xcode-test/SKILL.md +360 -0
package/commands/go.md ADDED
@@ -0,0 +1,660 @@
1
+ ---
2
+ name: go
3
+ description: Unified entry point that classifies intent and routes to the right workflow skill
4
+ argument-hint: "[what you want to do]"
5
+ ---
6
+
7
+ # Soleur Go
8
+
9
+ Unified entry point for all Soleur workflows. Classify the user's intent and route to the correct skill.
10
+
11
+ ## User Input
12
+
13
+ <user_input> #$ARGUMENTS </user_input>
14
+
15
+ **If the user input above is empty**, ask: "What would you like to do? Describe what you need and I'll route you to the right workflow."
16
+
17
+ Do not proceed until there is input from the user.
18
+
19
+ ## Step 0.0: Workspace Readiness Gate
20
+
21
+ Before the session-start preamble and before any routing, confirm a usable git repository exists. Run the readiness probe (it decides readiness AND, on failure, emits a `SOLEUR_GIT_REPO_DIAG` forensic line that the server-side telemetry hook mirrors to Better Stack — so a not-ready workspace is self-diagnosable without a manual probe):
22
+
23
+ ```bash
24
+ GATE=readiness
25
+ # --- soleur plugin-root resolver (ADR-179 decision 1 + decision 11 as amended by A16;
26
+ # #8308, #8401). The three copies in this file are byte-identical between these anchors;
27
+ # go-session-gates.test.sh pins that. Arm 1 is the loader-substituted token — on a
28
+ # substituting harness a literal fixed before bash runs, so no environment value can direct
29
+ # it (A10); on a read-from-disk harness (the Codex/Devin go mirrors) an ordinary variable
30
+ # those harnesses' INSTRUCTIONS tell the agent to set. Never a CWD default (#7442). POSIX
31
+ # only: no `xargs -r`, no `readlink -f`, no `sed -i`. Never enable `set -e`, `set -u` or
32
+ # `set -o pipefail` in these fences — line 1 is deliberately unguarded so it stays the exact
33
+ # token, and `-u` would abort before any marker is printed, which is the silent-skip class
34
+ # being fixed. ---
35
+ ROOT="${CLAUDE_PLUGIN_ROOT}"; SRC=plugin-root-token
36
+ if [ -z "$ROOT" ] && [ -n "${GROK_PLUGIN_ROOT:-}" ]; then
37
+ ROOT="$GROK_PLUGIN_ROOT"; SRC=grok-env
38
+ fi
39
+ # Arm 3 — the two managed Devin plugin caches, in ALL THREE gates since #8401. They were
40
+ # confined to Step 0.5 because Step 0 dispatches `cleanup-merged`; ADR-179 A16 records why
41
+ # that confinement is lifted (the capability gate below replaces it) and why the confinement
42
+ # was never about RESOLUTION in the first place. Identity-selected, never by basename;
43
+ # `[ -d ]`-gated so a non-Devin box searches nothing. `-exec … +`, not `xargs -r`: BSD/macOS
44
+ # xargs has no -r. `SOLEUR_DEVIN_CACHE_OPT` exists so a test can contain the ABSOLUTE arm —
45
+ # `run_gate` already contains the `$HOME` arm by overriding HOME, and a MUST-PASS suite whose
46
+ # verdict is a property of the host is not a suite. It is env-directed like `GROK_PLUGIN_ROOT`
47
+ # and subject to the same identity preflight, so it adds no trust class.
48
+ # Verify what arms 1-2 produced BEFORE deciding whether arm 3 is needed. A root that arrives
49
+ # but carries no Soleur manifest is not a usable root, and it must fall through exactly as an
50
+ # absent one does.
51
+ VERIFIED=false
52
+ if [ -n "$ROOT" ] \
53
+ && [ -f "${ROOT}/.claude-plugin/plugin.json" ] \
54
+ && grep -q '"name"[[:space:]]*:[[:space:]]*"soleur"' "${ROOT}/.claude-plugin/plugin.json"; then
55
+ VERIFIED=true
56
+ fi
57
+ # Arm 3 fires on `VERIFIED != true`, NOT on `-z "$ROOT"`. An earlier revision of this change
58
+ # used the empty test and thereby NARROWED Step 0.5: on `main` a set-but-unverified root still
59
+ # fell through to the cache, and under the empty test it stopped doing so — so a Devin host
60
+ # with a torn `CLAUDE_PLUGIN_ROOT` silently stopped engaging Cloud Mode, which is the fail-open
61
+ # class this work exists to close. Measured on both fences before and after.
62
+ PRIOR_SRC="$SRC"
63
+ PRIOR_ROOT="$ROOT"
64
+ if [ "$VERIFIED" != true ]; then
65
+ ROOT=""; SRC=none
66
+ for d in "$HOME/.local/share/devin/cli/plugins/cache" "${SOLEUR_DEVIN_CACHE_OPT:-/opt/.devin/plugins}"; do
67
+ [ -d "$d" ] || continue
68
+ # A cache directory EXISTED and was searched. That is a different state from "no cache at
69
+ # all" and carries a different remedy, so it gets its own value instead of collapsing into
70
+ # `none` (AP-021: do not name a cause this gate did not measure).
71
+ [ "$SRC" = none ] && SRC=devin-cache-nomatch
72
+ MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' \
73
+ -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"
74
+ if [ -n "$MANIFEST" ]; then
75
+ ROOT="${MANIFEST%/.claude-plugin/plugin.json}"; SRC=devin-cache; VERIFIED=true
76
+ break
77
+ fi
78
+ done
79
+ # Nothing resolved anywhere. If arms 1-2 DID name a root, report that arm rather than the
80
+ # cache's miss: "your token points at something that is not Soleur" is the actionable fact,
81
+ # and reporting `none` there would name a cause this gate did not measure.
82
+ if [ "$VERIFIED" != true ] && [ -n "$PRIOR_ROOT" ]; then
83
+ SRC="$PRIOR_SRC"
84
+ fi
85
+ fi
86
+ # EXACTLY ONE RESOLVE line per gate, emitted after verification. The cache arm used to print
87
+ # its own, so a cache hit emitted two and nothing pinned the count — `grep -F` is a presence
88
+ # check and cannot see a duplicate.
89
+ echo "SOLEUR_PLUGIN_ROOT_RESOLVE gate=${GATE} source=${SRC} verified=${VERIFIED}"
90
+ # --- end resolver ---
91
+ if [ "$VERIFIED" = true ]; then
92
+ # Identity is not freshness (#7474): a root that IS ours can still not carry
93
+ # this probe, and the bare invocation would then die with an unattributed
94
+ # interpreter error. The fallback below is already the right behaviour for
95
+ # that case — only the reason differs, so it is reported separately.
96
+ if [ -f "${ROOT}/skills/git-worktree/scripts/git-repo-readiness-diag.sh" ]; then
97
+ bash "${ROOT}/skills/git-worktree/scripts/git-repo-readiness-diag.sh" 2>&1
98
+ else
99
+ echo "SOLEUR_GIT_REPO_DIAG source=probe-unreachable reason=absent-from-verified-root"
100
+ git rev-parse --is-bare-repository 2>/dev/null || true
101
+ git rev-parse --is-inside-work-tree 2>/dev/null || true
102
+ fi
103
+ else
104
+ # Distinct from a not-ready workspace: the PROBE could not run. Emitting the
105
+ # same marker family keeps this visible to the telemetry hook instead of
106
+ # silently degrading into two git calls that print `true` (#7442). The
107
+ # RESOLVE line above says WHICH arm produced nothing, so this branch is now
108
+ # attributable rather than merely honest.
109
+ echo "SOLEUR_GIT_REPO_DIAG source=probe-unreachable reason=plugin-root-unverified"
110
+ git rev-parse --is-bare-repository 2>/dev/null || true
111
+ git rev-parse --is-inside-work-tree 2>/dev/null || true
112
+ fi
113
+ ```
114
+
115
+ **Read the `SOLEUR_PLUGIN_ROOT_RESOLVE` line before anything else — it says which arm produced the root, and each state below needs a different action. One blanket "file a defect" would misattribute a customer's own configuration to Soleur.** (The list is deliberately not headed by a count: it grew from four states to eight across #7442, #8308 and #8401, and a hard-coded number is the part that goes stale without anything noticing.)
116
+
117
+ - `source=none` **on Claude Code or Concierge** — no arm produced a root on a harness where the loader was expected to substitute one. That is a **Soleur plugin defect**. Per `wg-every-session-error-must-produce-either`, file an issue on `jikig-ai/soleur` quoting the three `RESOLVE` lines, then continue on the fallback.
118
+ - `source=none` **on a read-from-disk harness (Codex, Devin CLI, Grok Build, OpenCode)** — nothing substituted, nothing set the variable, **and no Devin plugin cache directory existed to search**. Since #8401 all three gates also try the two managed Devin caches, so on a Devin CLI host this value now means the caches are genuinely absent rather than merely unsearched. On **OpenCode this value is the expected state until you export the variable**: no plugin loader sets it there, so a bare `${CLAUDE_PLUGIN_ROOT}` call collapses to a workdir-relative path. **Set `CLAUDE_PLUGIN_ROOT` — or, on Grok Build, `GROK_PLUGIN_ROOT`, the one variable arm 2 consults — per your harness's `INSTRUCTIONS.md` §"Paths and entry points"**, and re-run. Not a Soleur defect.
119
+ - `source=devin-cache verified=true` — **nothing to do; this is the healthy Devin path.** Arms 1–2 produced nothing and a managed Devin plugin cache supplied the root, so the bytes about to run are the ones in that cache, not in any checkout on screen. Worth knowing for exactly one reason: when a later line refuses with `reason=reaper-capability-unverified source=devin-cache`, the stale artifact is that cached copy and `git pull` in your repository will not move it.
120
+ - `source=devin-cache-nomatch` — a Devin plugin cache directory EXISTS and was searched, but holds no `.claude-plugin/plugin.json` naming `soleur`. Distinct from `none`, and with a different remedy: the cache is present but does not carry Soleur. **Reinstall or update the plugin in that cache** (`devin plugins install ./plugins/soleur`, or `devin plugins update soleur`), then re-run. A **local configuration fact**, not a Soleur defect.
121
+ - `SOLEUR_SESSION_START_SKIPPED reason=reaper-capability-unverified source=<arm>` — the plugin root resolved and verified, but its `worktree-manager.sh` predates the branch-keyed reap guards (#8400), so the session-start gate refused to dispatch `cleanup-merged` from it rather than run a reaper whose per-branch safety guards may not cover a worktree-less merged branch. **A stale install, not a defect.** On Claude Code it takes TWO commands and the second one alone is a no-op: `claude plugin marketplace update soleur-marketplace` advances the marketplace checkout, then `claude plugin update soleur@soleur-marketplace` updates the plugin you actually run — skipping the first leaves you on the old bytes while the update reports success (this repo's own getting-started page says the same). On Devin, `devin plugins update soleur`. Restart the session either way. The `source=` field is carried for symmetry with the other `SKIPPED` reasons, but this refusal only ever reads `source=devin-cache`: the capability gate is scoped to that arm on purpose (ADR-179 A16 — the arm-agnostic form was measured to stop reaping on every long-lived worktree and every marketplace install between releases). A stale `plugin-root-token` or `grok-env` install is therefore NOT refused here; it dispatches its own reaper. The Claude Code remedy above is for that case, which you will recognise by an old reaper's output rather than by this marker. For `source=devin-cache` the stale artifact is in the Devin plugin cache rather than in any checkout you can see. Session-start maintenance is skipped until then, deliberately; everything else in the gate (the worktree listing and the `.mcp.json` restore) still runs.
122
+ - `source=grok-env verified=false` — `GROK_PLUGIN_ROOT` is set but does not point at the Soleur plugin. A **local configuration fact**: check what it targets (`grok plugin list`). Not a Soleur defect.
123
+ - `SOLEUR_SESSION_START_SKIPPED reason=cloud-session verdict=<v>` **on a machine you know is local** — `cloud-detect.sh` classified the session as a Devin one. The usual cause is a stray `DEVIN_DIR` or `DEVIN_DISABLE_HISTEXPAND` exported by your shell profile, which makes the box Devin-marked; unset it and re-run. Session-start maintenance is skipped until then, deliberately — the classifier fails closed by contract.
124
+ - `verified=false` with any other `source` — a root arrived but carries no Soleur manifest: a **torn or stale install**. Reinstall or update the plugin; file an issue only if a fresh install reproduces it.
125
+
126
+ **One caveat that applies to every `devin-cache*` value above.** The `/opt` arm is read through `${SOLEUR_DEVIN_CACHE_OPT:-/opt/.devin/plugins}`, so if that variable is exported the three bullets above are reporting on whatever it points at, not on `/opt/.devin/plugins`. It exists because `/opt/.devin/plugins` is absolute, and a MUST-PASS suite whose verdict depends on whether the host happens to carry a populated one is not a suite — `go-session-gates.test.sh` pins it to a scratch path (ADR-179 A16). It is env-directed exactly as `GROK_PLUGIN_ROOT` is and runs through the same identity preflight, so it adds no trust class; but if a `devin-cache` verdict surprises you, `echo "${SOLEUR_DEVIN_CACHE_OPT:-unset}"` before reading further.
127
+
128
+ The `else` branch runs the bare inline probes when the plugin payload cannot be verified (e.g. a repo-less workspace whose plugin symlink was not scaffolded). Readiness = the output contains `SOLEUR_GIT_REPO_READY=true` (script path) OR a bare `true` (fallback path).
129
+
130
+ **The fallback is not silent.** Before #7442 this was a bare `||` after an unquoted, unverified path: if the probe could not resolve, the fallback printed `true` and the gate read PASS while `SOLEUR_GIT_REPO_DIAG` — the forensic line the server-side hook mirrors to Better Stack — was never emitted. "Probe said not-ready" and "probe never ran" produced identical output. The `source=probe-unreachable` marker keeps them distinguishable, which matters because `soleur:go` is the first command of every session.
131
+
132
+ If the output shows `SOLEUR_GIT_REPO_READY=false` (or, on the fallback, **neither** probe printed `true`), the workspace has no usable git checkout. In the Soleur web (Concierge) environment this happens when a connected repository is still cloning in the background, or its setup failed (the CWD is then a repo-less `/workspaces/<id>`), OR the `.git` is present but git rejects it (a corrupt/masked config — the emitted `SOLEUR_GIT_REPO_DIAG config_parse_rc`/`err=` fields distinguish these). **Every** route (`go`/`brainstorm`/`plan`/`one-shot`/`fix`/`drain`) will fail: worktree creation, knowledge-base artifact writes, and the session-start preamble all need a real repo. Do NOT run the preamble, do NOT route, do NOT improvise filesystem exploration. STOP and reply with this honest, no-wait message:
133
+
134
+ > Your workspace isn't ready yet — its repository is still being set up, or its setup didn't finish. Please try again in a moment.
135
+
136
+ **Claude / Concierge:** if this keeps happening and your project lives in a **team workspace**, switch to that workspace and try again; if this is your own workspace, check that a repository is connected in **Settings → Repository**.
137
+
138
+ **Grok Build:** that Concierge settings path does not apply. Confirm `GROK_PLUGIN_ROOT` or `CLAUDE_PLUGIN_ROOT` points at the Soleur plugin (plugin.json name `soleur`) and that `grok inspect` lists it. Do not invent a Settings → Repository screen.
139
+
140
+ This gate is deterministic and fires on the first action, so a not-ready workspace produces a clear message instead of a long flail. (The runtime's `worktree_enter_failed` detector only catches a narrow repeated-`cd … && pwd` loop — #5313 — not the general "no repo, agent tries many different commands" case the Concierge no-repo session hit.)
141
+
142
+ ## Step 0.5: Cloud Mode detection
143
+
144
+ Before the mutating preamble below (worktree cleanup, `.mcp.json` restore), classify the session — a routed skill's marker block cannot protect work that runs before it loads:
145
+
146
+ ```bash
147
+ GATE=cloud-detect
148
+ # --- soleur plugin-root resolver (ADR-179 decision 1 + decision 11 as amended by A16;
149
+ # #8308, #8401). The three copies in this file are byte-identical between these anchors;
150
+ # go-session-gates.test.sh pins that. Arm 1 is the loader-substituted token — on a
151
+ # substituting harness a literal fixed before bash runs, so no environment value can direct
152
+ # it (A10); on a read-from-disk harness (the Codex/Devin go mirrors) an ordinary variable
153
+ # those harnesses' INSTRUCTIONS tell the agent to set. Never a CWD default (#7442). POSIX
154
+ # only: no `xargs -r`, no `readlink -f`, no `sed -i`. Never enable `set -e`, `set -u` or
155
+ # `set -o pipefail` in these fences — line 1 is deliberately unguarded so it stays the exact
156
+ # token, and `-u` would abort before any marker is printed, which is the silent-skip class
157
+ # being fixed. ---
158
+ ROOT="${CLAUDE_PLUGIN_ROOT}"; SRC=plugin-root-token
159
+ if [ -z "$ROOT" ] && [ -n "${GROK_PLUGIN_ROOT:-}" ]; then
160
+ ROOT="$GROK_PLUGIN_ROOT"; SRC=grok-env
161
+ fi
162
+ # Arm 3 — the two managed Devin plugin caches, in ALL THREE gates since #8401. They were
163
+ # confined to Step 0.5 because Step 0 dispatches `cleanup-merged`; ADR-179 A16 records why
164
+ # that confinement is lifted (the capability gate below replaces it) and why the confinement
165
+ # was never about RESOLUTION in the first place. Identity-selected, never by basename;
166
+ # `[ -d ]`-gated so a non-Devin box searches nothing. `-exec … +`, not `xargs -r`: BSD/macOS
167
+ # xargs has no -r. `SOLEUR_DEVIN_CACHE_OPT` exists so a test can contain the ABSOLUTE arm —
168
+ # `run_gate` already contains the `$HOME` arm by overriding HOME, and a MUST-PASS suite whose
169
+ # verdict is a property of the host is not a suite. It is env-directed like `GROK_PLUGIN_ROOT`
170
+ # and subject to the same identity preflight, so it adds no trust class.
171
+ # Verify what arms 1-2 produced BEFORE deciding whether arm 3 is needed. A root that arrives
172
+ # but carries no Soleur manifest is not a usable root, and it must fall through exactly as an
173
+ # absent one does.
174
+ VERIFIED=false
175
+ if [ -n "$ROOT" ] \
176
+ && [ -f "${ROOT}/.claude-plugin/plugin.json" ] \
177
+ && grep -q '"name"[[:space:]]*:[[:space:]]*"soleur"' "${ROOT}/.claude-plugin/plugin.json"; then
178
+ VERIFIED=true
179
+ fi
180
+ # Arm 3 fires on `VERIFIED != true`, NOT on `-z "$ROOT"`. An earlier revision of this change
181
+ # used the empty test and thereby NARROWED Step 0.5: on `main` a set-but-unverified root still
182
+ # fell through to the cache, and under the empty test it stopped doing so — so a Devin host
183
+ # with a torn `CLAUDE_PLUGIN_ROOT` silently stopped engaging Cloud Mode, which is the fail-open
184
+ # class this work exists to close. Measured on both fences before and after.
185
+ PRIOR_SRC="$SRC"
186
+ PRIOR_ROOT="$ROOT"
187
+ if [ "$VERIFIED" != true ]; then
188
+ ROOT=""; SRC=none
189
+ for d in "$HOME/.local/share/devin/cli/plugins/cache" "${SOLEUR_DEVIN_CACHE_OPT:-/opt/.devin/plugins}"; do
190
+ [ -d "$d" ] || continue
191
+ # A cache directory EXISTED and was searched. That is a different state from "no cache at
192
+ # all" and carries a different remedy, so it gets its own value instead of collapsing into
193
+ # `none` (AP-021: do not name a cause this gate did not measure).
194
+ [ "$SRC" = none ] && SRC=devin-cache-nomatch
195
+ MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' \
196
+ -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"
197
+ if [ -n "$MANIFEST" ]; then
198
+ ROOT="${MANIFEST%/.claude-plugin/plugin.json}"; SRC=devin-cache; VERIFIED=true
199
+ break
200
+ fi
201
+ done
202
+ # Nothing resolved anywhere. If arms 1-2 DID name a root, report that arm rather than the
203
+ # cache's miss: "your token points at something that is not Soleur" is the actionable fact,
204
+ # and reporting `none` there would name a cause this gate did not measure.
205
+ if [ "$VERIFIED" != true ] && [ -n "$PRIOR_ROOT" ]; then
206
+ SRC="$PRIOR_SRC"
207
+ fi
208
+ fi
209
+ # EXACTLY ONE RESOLVE line per gate, emitted after verification. The cache arm used to print
210
+ # its own, so a cache hit emitted two and nothing pinned the count — `grep -F` is a presence
211
+ # check and cannot see a duplicate.
212
+ echo "SOLEUR_PLUGIN_ROOT_RESOLVE gate=${GATE} source=${SRC} verified=${VERIFIED}"
213
+ # --- end resolver ---
214
+ if [ "$VERIFIED" = true ]; then
215
+ # NESTED, not `[ "$VERIFIED" = true ] && [ -f … ]`: #7474 requires the presence check and
216
+ # the invocation to share a subprocess, and plugin-root-anchoring.test.ts P6 anchors on a
217
+ # `[ -f` at statement start. The conjunction form reads as guarded and is not recognised.
218
+ if [ -f "${ROOT}/scripts/cloud-detect.sh" ]; then
219
+ bash "${ROOT}/scripts/cloud-detect.sh" --banner
220
+ else
221
+ echo "SOLEUR_CLOUD_DETECT_SKIPPED reason=script-unreachable"
222
+ fi
223
+ else
224
+ # NOT `script-unreachable` — nothing looked for the script, so that would name a cause this
225
+ # gate did not measure (AP-021), and it is the #7442 class this change exists to remove. Steps
226
+ # 0.0 and 0 already discriminate these two states; this one used to collapse them.
227
+ echo "SOLEUR_CLOUD_DETECT_SKIPPED reason=plugin-root-unverified"
228
+ fi
229
+ ```
230
+
231
+ `local` or `not-local:no-devin-env` → proceed. Any other `not-local:<reason>` → apply the cloud contract in `<plugin-root>/devin/INSTRUCTIONS.md` §Cloud Mode (sequential fan-out with `Reviewed-Coverage: sequential-fallback` disclosure, `message_user` ack before secrets/prod, `precommit-guard.sh` before any `git commit`).
232
+
233
+ ## Step 0: Session-Start Preamble
234
+
235
+ Before any other work, run the session-start gates from AGENTS.md (`wg-at-session-start-run-bash-plugins-soleur` + `wg-at-session-start-after-cleanup-merged`):
236
+
237
+ ```bash
238
+ GATE=session-start
239
+ # --- soleur plugin-root resolver (ADR-179 decision 1 + decision 11 as amended by A16;
240
+ # #8308, #8401). The three copies in this file are byte-identical between these anchors;
241
+ # go-session-gates.test.sh pins that. Arm 1 is the loader-substituted token — on a
242
+ # substituting harness a literal fixed before bash runs, so no environment value can direct
243
+ # it (A10); on a read-from-disk harness (the Codex/Devin go mirrors) an ordinary variable
244
+ # those harnesses' INSTRUCTIONS tell the agent to set. Never a CWD default (#7442). POSIX
245
+ # only: no `xargs -r`, no `readlink -f`, no `sed -i`. Never enable `set -e`, `set -u` or
246
+ # `set -o pipefail` in these fences — line 1 is deliberately unguarded so it stays the exact
247
+ # token, and `-u` would abort before any marker is printed, which is the silent-skip class
248
+ # being fixed. ---
249
+ ROOT="${CLAUDE_PLUGIN_ROOT}"; SRC=plugin-root-token
250
+ if [ -z "$ROOT" ] && [ -n "${GROK_PLUGIN_ROOT:-}" ]; then
251
+ ROOT="$GROK_PLUGIN_ROOT"; SRC=grok-env
252
+ fi
253
+ # Arm 3 — the two managed Devin plugin caches, in ALL THREE gates since #8401. They were
254
+ # confined to Step 0.5 because Step 0 dispatches `cleanup-merged`; ADR-179 A16 records why
255
+ # that confinement is lifted (the capability gate below replaces it) and why the confinement
256
+ # was never about RESOLUTION in the first place. Identity-selected, never by basename;
257
+ # `[ -d ]`-gated so a non-Devin box searches nothing. `-exec … +`, not `xargs -r`: BSD/macOS
258
+ # xargs has no -r. `SOLEUR_DEVIN_CACHE_OPT` exists so a test can contain the ABSOLUTE arm —
259
+ # `run_gate` already contains the `$HOME` arm by overriding HOME, and a MUST-PASS suite whose
260
+ # verdict is a property of the host is not a suite. It is env-directed like `GROK_PLUGIN_ROOT`
261
+ # and subject to the same identity preflight, so it adds no trust class.
262
+ # Verify what arms 1-2 produced BEFORE deciding whether arm 3 is needed. A root that arrives
263
+ # but carries no Soleur manifest is not a usable root, and it must fall through exactly as an
264
+ # absent one does.
265
+ VERIFIED=false
266
+ if [ -n "$ROOT" ] \
267
+ && [ -f "${ROOT}/.claude-plugin/plugin.json" ] \
268
+ && grep -q '"name"[[:space:]]*:[[:space:]]*"soleur"' "${ROOT}/.claude-plugin/plugin.json"; then
269
+ VERIFIED=true
270
+ fi
271
+ # Arm 3 fires on `VERIFIED != true`, NOT on `-z "$ROOT"`. An earlier revision of this change
272
+ # used the empty test and thereby NARROWED Step 0.5: on `main` a set-but-unverified root still
273
+ # fell through to the cache, and under the empty test it stopped doing so — so a Devin host
274
+ # with a torn `CLAUDE_PLUGIN_ROOT` silently stopped engaging Cloud Mode, which is the fail-open
275
+ # class this work exists to close. Measured on both fences before and after.
276
+ PRIOR_SRC="$SRC"
277
+ PRIOR_ROOT="$ROOT"
278
+ if [ "$VERIFIED" != true ]; then
279
+ ROOT=""; SRC=none
280
+ for d in "$HOME/.local/share/devin/cli/plugins/cache" "${SOLEUR_DEVIN_CACHE_OPT:-/opt/.devin/plugins}"; do
281
+ [ -d "$d" ] || continue
282
+ # A cache directory EXISTED and was searched. That is a different state from "no cache at
283
+ # all" and carries a different remedy, so it gets its own value instead of collapsing into
284
+ # `none` (AP-021: do not name a cause this gate did not measure).
285
+ [ "$SRC" = none ] && SRC=devin-cache-nomatch
286
+ MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' \
287
+ -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"
288
+ if [ -n "$MANIFEST" ]; then
289
+ ROOT="${MANIFEST%/.claude-plugin/plugin.json}"; SRC=devin-cache; VERIFIED=true
290
+ break
291
+ fi
292
+ done
293
+ # Nothing resolved anywhere. If arms 1-2 DID name a root, report that arm rather than the
294
+ # cache's miss: "your token points at something that is not Soleur" is the actionable fact,
295
+ # and reporting `none` there would name a cause this gate did not measure.
296
+ if [ "$VERIFIED" != true ] && [ -n "$PRIOR_ROOT" ]; then
297
+ SRC="$PRIOR_SRC"
298
+ fi
299
+ fi
300
+ # EXACTLY ONE RESOLVE line per gate, emitted after verification. The cache arm used to print
301
+ # its own, so a cache hit emitted two and nothing pinned the count — `grep -F` is a presence
302
+ # check and cannot see a duplicate.
303
+ echo "SOLEUR_PLUGIN_ROOT_RESOLVE gate=${GATE} source=${SRC} verified=${VERIFIED}"
304
+ # --- end resolver ---
305
+ # Session-class gate, in THIS fence rather than inherited from Step 0.5: bash carries no
306
+ # state between fences (ADR-179 §"Why the axes stay separate" item 3), so 0.5's verdict is
307
+ # unavailable here. Keyed on the CLASSIFIER, not on SRC — a Devin agent following its own
308
+ # INSTRUCTIONS resolves as plugin-root-token, so an `SRC != devin-cache` test would never
309
+ # fire. This is the only gate below that mutates anything.
310
+ SESSION_OK=false
311
+ SESSION_PROBE=absent
312
+ SESSION_VERDICT=none
313
+ # Reap-capability gate (#8401; ADR-179 A16 amends decision 11 to permit this).
314
+ #
315
+ # NARROWED TO THE devin-cache ARM ON PURPOSE. An arm-agnostic form has a measured fleet-wide
316
+ # blast radius: every root whose `worktree-manager.sh` predates the branch-keyed guards —
317
+ # every long-lived worktree on a pre-merge branch, and every marketplace install between
318
+ # releases — would emit `reaper-capability-unverified` and stop reaping. The ground ADR-179
319
+ # actually states is about the CACHE arm: `head -1` may select a cached copy of unbounded
320
+ # age, and fixing the repository's script does not fix that artifact on disk.
321
+ #
322
+ # It ATTESTS a contract; it does not authenticate one. A planted root can carry this literal
323
+ # as trivially as it can carry `{"name":"soleur"}` — ADR-179 A11 one level down.
324
+ #
325
+ # Evaluated BEFORE the classifier, not just before the reaper: the gate covers every artifact
326
+ # in the dispatch DECISION CHAIN, not only the artifact dispatched. A cache root whose reaper
327
+ # lacks the capability is not trusted to classify the session either, which is what makes the
328
+ # blast-radius argument non-circular — one token, both consumers.
329
+ #
330
+ # PATH-PINNED: the `grep -q` and the `bash` below operate on the same `${ROOT}`-derived path,
331
+ # resolved once above, with NO second `find` between them. A check that re-resolves is
332
+ # check-A/execute-B across two independent `head -1` calls — the defect one level down from
333
+ # the one this gate closes, and no behavioural row can see it.
334
+ REAP_CAP=not-applicable
335
+ # Whether the non-destructive half of this gate runs. Set by the two arms that reach it, and
336
+ # read AFTER the dispatch `fi` — so a refusal on the reaper cannot silently take the
337
+ # `.mcp.json` restore with it (FR8d). Before #8401 the restore was nested inside the
338
+ # success arm, where any new refusal arm would have skipped it by construction.
339
+ DO_RESTORE=false
340
+ if [ "$VERIFIED" = true ] && [ "$SRC" = devin-cache ]; then
341
+ REAP_CAP=unverified
342
+ if [ -f "${ROOT}/skills/git-worktree/scripts/worktree-manager.sh" ]; then
343
+ # ANCHORED at statement start, so a COMMENT mentioning the token cannot satisfy the gate,
344
+ # and read as a SET so `no-branch-keyed-guards` / `branch-keyed-guards-v2` are not accepted
345
+ # as the capability by substring. The value is space-separated; membership is additive.
346
+ CAP_VAL="$(sed -n 's/^[[:space:]]*SOLEUR_WORKTREE_REAP_CAPABILITY="\{0,1\}\([^"]*\)"\{0,1\}[[:space:]]*$/\1/p' \
347
+ "${ROOT}/skills/git-worktree/scripts/worktree-manager.sh" | head -1)"
348
+ case " ${CAP_VAL} " in
349
+ *" branch-keyed-guards "*) REAP_CAP=ok ;;
350
+ esac
351
+ fi
352
+ fi
353
+ if [ "$VERIFIED" = true ] && [ "$REAP_CAP" != unverified ]; then
354
+ # The classifier itself is presence-guarded (#7474). Without this, a verified-but-TORN
355
+ # install runs a missing script, the `case` sees empty output, and the gate reports
356
+ # `reason=cloud-session` — telling the operator their local session is a cloud one. A
357
+ # guard that misattributes is worse than one that skips.
358
+ if [ -f "${ROOT}/scripts/cloud-detect.sh" ]; then
359
+ SESSION_PROBE=present
360
+ # The proceed set is EXACTLY the classifier's own documented exception — its header says
361
+ # "consumers MUST fail closed on [not-local:<reason>]" and names one carve-out: "Callers
362
+ # treat no-devin-env like `local`". Do not widen it. A review pass proposed adding
363
+ # `not-local:sentinel-absent` because a local box with a stray `DEVIN_DIR` exported reports
364
+ # it (measured, and it is this repo's own operator profile); but that reason means "a
365
+ # Devin-MARKED box with no sentinel", which is precisely the fail-closed case — admitting it
366
+ # would let a real Devin cloud session reach `cleanup-merged`. The symptom is real and the
367
+ # fix belongs in the REASON, not the predicate: SESSION_VERDICT is reported below so the
368
+ # operator sees which verdict skipped them and can clear it.
369
+ SESSION_VERDICT="$(bash "${ROOT}/scripts/cloud-detect.sh" 2>/dev/null | head -1)"
370
+ [ -n "$SESSION_VERDICT" ] || SESSION_VERDICT=classifier-silent
371
+ case "$SESSION_VERDICT" in
372
+ local|not-local:no-devin-env) SESSION_OK=true ;;
373
+ esac
374
+ fi
375
+ fi
376
+ if [ "$VERIFIED" != true ]; then
377
+ # Do not let the session-start gate no-op invisibly: the form before #7442 ended in
378
+ # `|| true`, so an unresolved root skipped cleanup-merged AND the .mcp.json restore with
379
+ # no output at all. The RESOLVE line above now also says WHICH arm produced nothing.
380
+ echo "SOLEUR_SESSION_START_SKIPPED reason=plugin-root-unverified"
381
+ elif [ "$REAP_CAP" = unverified ]; then
382
+ # A cache root whose reaper predates the branch-keyed guards. Refused BY NAME rather than
383
+ # run — and `source=` is emitted because the three arms have three different remedies.
384
+ #
385
+ # This arm deliberately does NOT take the non-destructive work with it. `git worktree list`
386
+ # and the `.mcp.json` restore need neither the classifier nor the reaper, and a refusal
387
+ # that silently killed all three gates would be the very defect #8401 exists to fix. A row
388
+ # asserting only `want_not_in … STUB_WORKTREE_MANAGER` passes for that implementation too,
389
+ # which is why R11 carries positive `want_in`s as well.
390
+ echo "SOLEUR_SESSION_START_SKIPPED reason=reaper-capability-unverified source=${SRC}"
391
+ git worktree list
392
+ DO_RESTORE=true
393
+ elif [ "$SESSION_PROBE" != present ]; then
394
+ # A DISTINCT reason from the worktree-manager arm below. Both said
395
+ # `reason=absent-from-verified-root`, which (a) told the operator a script was missing without
396
+ # saying which, and (b) made plugin-root-anchoring.test.ts P8 satisfiable by this sibling — the
397
+ # exact vacuity P8's own comment records having closed for this producer.
398
+ echo "SOLEUR_SESSION_START_SKIPPED reason=classifier-absent"
399
+ # Same argument as the capability arm above, applied to the arm it was missing from: the
400
+ # `.mcp.json` restore needs neither the classifier nor the reaper, so a torn install missing
401
+ # `cloud-detect.sh` has no reason to lose it. The `cloud-session` arm below deliberately does
402
+ # NOT set this — there the classifier ANSWERED and said this is a cloud session, and skipping
403
+ # session-start maintenance is the contract, not a casualty.
404
+ DO_RESTORE=true
405
+ elif [ "$SESSION_OK" != true ]; then
406
+ # Name the VERDICT. A blanket `reason=cloud-session` told an operator with a stray DEVIN*
407
+ # variable on an ordinary laptop that their local session was a cloud one, and gave them
408
+ # nothing to act on.
409
+ echo "SOLEUR_SESSION_START_SKIPPED reason=cloud-session verdict=${SESSION_VERDICT}"
410
+ else
411
+ # Identity is not freshness (#7474) — see the Step 0.0 probe above. Arm order is the
412
+ # loader-substituted token, then GROK_PLUGIN_ROOT (ADR-179 decision 11); the name=soleur
413
+ # preflight in the resolver runs on whichever arm produced the root.
414
+ DO_RESTORE=true
415
+ if [ -f "${ROOT}/skills/git-worktree/scripts/worktree-manager.sh" ]; then
416
+ bash "${ROOT}/skills/git-worktree/scripts/worktree-manager.sh" cleanup-merged
417
+ git worktree list
418
+ else
419
+ echo "SOLEUR_SESSION_START_SKIPPED reason=absent-from-verified-root"
420
+ fi
421
+ fi
422
+
423
+ if [ "$DO_RESTORE" = true ]; then
424
+ # The .mcp.json restore is a SIBLING of the reaper, not nested inside it. It was nested, and
425
+ # that re-created in miniature the coupling #8308 is about: the restore needs no part of
426
+ # worktree-manager.sh, so on a verified-but-torn install missing that one script it silently
427
+ # did not run and the only marker named the reaper. The PR's own account lists the never-
428
+ # running restore as a SEPARATE consequence of the bug; keeping it behind the reaper's
429
+ # presence check would have contradicted that.
430
+ #
431
+ # Write-then-rename, NEVER `git show … > .mcp.json`. The shell TRUNCATES the redirect target
432
+ # before forking `git show`, so every failure mode leaves a 0-byte .mcp.json. Measured:
433
+ # 67 bytes -> 0, silently, with `2>/dev/null || true` swallowing the status and reporting
434
+ # rc 0. On a customer machine that file is their MCP server registry, commonly holding
435
+ # per-server tokens, and it is usually untracked there — so the loss is unrecoverable.
436
+ #
437
+ # `main:./.mcp.json`, not `main:.mcp.json`: inside a work tree the path is relative to the CWD like every
438
+ # other path in this block, so a run from a subdirectory reads sub/.mcp.json instead of writing the root
439
+ # file's bytes there. A bare repo refuses the `./` form, and the documented bare-root refresh must keep
440
+ # working there, so it keeps the root-relative spelling.
441
+ IN_WT="$(git rev-parse --is-inside-work-tree 2>/dev/null)"
442
+ MAIN_MCP="main:.mcp.json"
443
+ if [ "$IN_WT" = true ]; then MAIN_MCP="main:./.mcp.json"; fi
444
+ #
445
+ # In this repo .mcp.json is TRACKED, and an uncommitted edit to it is the operator's work, not
446
+ # stale state (#9622).
447
+ # KEEP when: the path is a symlink (mv would replace the link itself); or it is tracked and either
448
+ # not a plain cached entry (skip-worktree `S` / assume-unchanged `h` hide edits from git diff, and an
449
+ # unmerged entry is tagged `M`) or differs from HEAD. Compared to HEAD, not the index: `git diff --quiet`
450
+ # without HEAD reads a staged-only change as clean. ANY probe failure (an unreadable index, a diff status
451
+ # above 1 such as an unborn branch) keeps the file: an error probing it must fail toward keeping it, so
452
+ # the status of every probe is read, never folded into "untracked". A bare repo has no index, so nothing
453
+ # in it is tracked (git 2.55 answers ls-files there with rc 0 and no output, but older versions refuse, and a
454
+ # refusal would read as probe-failed and block the bare-root refresh, so the work-tree check stays). An untracked regular file, or a tracked-plain one equal to HEAD, falls through to the
455
+ # restore below. `cause=` names the measured reason, like the sibling markers' verdict=/source=/rc= fields.
456
+ KEEP=false
457
+ KEEP_CAUSE=""
458
+ KEEP_RC=""
459
+ if [ -L .mcp.json ]; then
460
+ KEEP=true; KEEP_CAUSE=symlink
461
+ elif [ "$IN_WT" != true ]; then
462
+ :
463
+ else
464
+ # ONE probe answers tracked-or-not AND the index tag; its status separates "untracked" (empty
465
+ # output, rc 0) from "could not read the index" (rc != 0), which must keep the file.
466
+ LS_RC=0
467
+ LS_TAG="$(git ls-files -v -- .mcp.json 2>/dev/null)" || LS_RC=$?
468
+ if [ "$LS_RC" -ne 0 ]; then
469
+ KEEP=true; KEEP_CAUSE=probe-failed; KEEP_RC=$LS_RC
470
+ else
471
+ case "$LS_TAG" in
472
+ "") ;;
473
+ "H "*)
474
+ DIFF_RC=0
475
+ git diff --quiet HEAD -- .mcp.json 2>/dev/null || DIFF_RC=$?
476
+ if [ "$DIFF_RC" -eq 1 ]; then
477
+ KEEP=true; KEEP_CAUSE=differs-from-head
478
+ elif [ "$DIFF_RC" -ne 0 ]; then
479
+ KEEP=true; KEEP_CAUSE=probe-failed; KEEP_RC=$DIFF_RC
480
+ fi ;;
481
+ *) KEEP=true; KEEP_CAUSE=index-flag ;;
482
+ esac
483
+ fi
484
+ fi
485
+ if [ "$KEEP" = true ]; then
486
+ # Already main's bytes: nothing to protect and nothing to restore, so say nothing. Without this a
487
+ # file the gate itself refreshed reads as "dirty" on every later session start. A symlink is the
488
+ # operator's own wiring and is always reported: it is never compared, since opening its target
489
+ # would follow a link the repository chose.
490
+ if [ "$KEEP_CAUSE" != symlink ] && git show "$MAIN_MCP" 2>/dev/null | cmp -s - .mcp.json 2>/dev/null; then
491
+ :
492
+ else
493
+ echo "SOLEUR_SESSION_START_SKIPPED reason=mcp-json-dirty cause=${KEEP_CAUSE}${KEEP_RC:+ rc=${KEEP_RC}}"
494
+ fi
495
+ elif { rm -f .mcp.json.soleur-tmp 2>/dev/null; git show "$MAIN_MCP" > .mcp.json.soleur-tmp 2>/dev/null; }; then
496
+ if mv .mcp.json.soleur-tmp .mcp.json; then
497
+ :
498
+ else
499
+ # A failed rename leaves the temp file in the customer's worktree. Report it and
500
+ # remove it; silence here is how a stray .soleur-tmp becomes someone's mystery file.
501
+ rm -f .mcp.json.soleur-tmp
502
+ echo "SOLEUR_SESSION_START_SKIPPED reason=mcp-json-rename-failed"
503
+ fi
504
+ else
505
+ # MEASURE the cause; do not name one (AP-021 — the rule this file's other markers enforce).
506
+ # `git show main:.mcp.json` fails for at least three distinct reasons and the previous
507
+ # single `reason=mcp-json-absent-on-main` asserted the first of them for all three, which
508
+ # is the same defect as `reason=cloud-session` before it learned to print its verdict.
509
+ # $? here is the `elif` group's status (its last command, `git show`), so it is captured before `rm`
510
+ # overwrites it.
511
+ SHOW_RC=$?
512
+ rm -f .mcp.json.soleur-tmp
513
+ if ! git rev-parse --verify -q main >/dev/null 2>&1; then
514
+ echo "SOLEUR_SESSION_START_SKIPPED reason=mcp-json-no-local-main"
515
+ elif ! git cat-file -e "$MAIN_MCP" 2>/dev/null; then
516
+ echo "SOLEUR_SESSION_START_SKIPPED reason=mcp-json-absent-on-main"
517
+ else
518
+ echo "SOLEUR_SESSION_START_SKIPPED reason=mcp-json-read-failed rc=${SHOW_RC}"
519
+ fi
520
+ fi
521
+ fi
522
+ ```
523
+
524
+ The script works from either the bare root or any worktree. The `.mcp.json` refresh is harmless inside a worktree for a clean or untracked file (it is overwritten on next session-start from the new CWD). A `.mcp.json` that is a symlink, or is tracked and differs from HEAD or carries a non-plain index entry (`skip-worktree`, `assume-unchanged`, unmerged), is left alone and reported as `SOLEUR_SESSION_START_SKIPPED reason=mcp-json-dirty cause=<symlink|index-flag|differs-from-head|probe-failed>`; a kept file already equal to `main` stays silent. A stale tracked copy the gate refreshed on an earlier session is not refreshed again once `main` has moved on: the marker prints until the file is dropped or committed. An agent must NOT run `git checkout -- .mcp.json` or `git update-index` in response. For `differs-from-head` show the operator `git diff HEAD -- .mcp.json`; for `index-flag` (where that diff is unreliable) and `symlink`, report the cause and show `git ls-files -v -- .mcp.json` or `ls -l .mcp.json`; for `probe-failed` (the index or the HEAD diff could not be read, with the git exit status as `rc=`), report that the file could not be inspected. In every case keep routing. Operator remedies: commit the file, drop it with `git checkout -- .mcp.json` (a stale tracked copy is refreshed again next session), or pin an intentional local variant with `git update-index --skip-worktree .mcp.json` (the marker still prints for it unless its bytes equal `main`'s). The restore reads `main:./.mcp.json` relative to the current directory inside a work tree, so a run from a subdirectory never writes the root file's bytes; a bare repo keeps the root-relative form. Skip silently on first error — do not block routing on session-start hygiene.
525
+
526
+ See `knowledge-base/project/learnings/2026-05-11-bundle-brainstorm-deliberate-revert-and-fixture-source-record.md` Session Errors #1-#2 for the gap this closes.
527
+
528
+ ## Step 1: Worktree Context
529
+
530
+ Run `pwd`. If the path contains `.worktrees/`, extract the feature name and mention it:
531
+
532
+ "You're in worktree **feat-[name]**. Want to continue working on this, or start something new?"
533
+
534
+ If the user wants to continue the current feature, delegate to `soleur:work`. **Claude:** Skill tool (`soleur:work`) with the user input as arguments. **Grok:** Read `plugins/soleur/skills/work/SKILL.md` in this process and run it to completion. Then stop.
535
+
536
+ **Bare-repo CWD guard.** If `pwd` is NOT inside `.worktrees/` AND `git rev-parse --is-bare-repository` returns `true`, the CWD is a bare-repo root with no working tree. Any Edit/Write to files visible at this path lands on stray untracked content not on any branch, and `node_modules` is not hydrated so typecheck/dev-server commands fail. For file-touching intents (the `fix`/`implement`/`drain`/`review` rows in Step 2), do NOT edit in place — route through `soleur:one-shot` so a proper worktree is created via `worktree-manager.sh`. For read-only intents (questions, exploration, `clo-attestation`, `legal-threshold`), proceed without worktree creation. See `knowledge-base/project/learnings/2026-05-19-bare-repo-grep-and-subagent-infra-claim-verification.md`. Since #10383 an earlier layer exists: `session-rules-loader.sh` emits the `SOLEUR_BARE_ROOT_CWD` marker + `[bare-root-cwd]` redirect block at session start, before any routing — this Step-1 check remains the in-`go` backstop.
537
+
538
+ ## Step 1.5: Hold routing (pre-route)
539
+
540
+ This paragraph runs before the routing table and sits outside the eval-gated block, so it never changes a routing row, and it is the one authority for the trigger (nothing else in the repository defines when holds are routed). It routes only when a resume or handoff brief carries BOTH an epic reference (`#N`) and a structured list of operator holds, found in the brief itself, in the open epic's body, or in a plan the brief or the body names (the accepted list forms and the checks on each source are defined per the List source bullet below). A line that names `soleur:engineering:cto` as the decider of technical forks says which holds go to the CTO and does not by itself make a hold list (2026-10-19: a resume brief with an owner-gated list and no literal `HOLDS:` skipped this step, and the session closed on two technical forks). A message that merely says `ask the operator` carries no epic and no hold list: it is an ordinary message and routes normally. When it does route, never call AskUserQuestion for a technical hold: spawn `soleur:engineering:cto` with a prompt that starts `Own the epic` (the interface is defined in [the CTO agent definition](${CLAUDE_PLUGIN_ROOT}/agents/engineering/cto.md)) and pass the brief; then follow the case that applies. Script paths use `${CLAUDE_PLUGIN_ROOT}`; if it is unset, resolve it as the Cloud Mode paragraph above does.
541
+
542
+ - **A Standing Delegation is recorded** (the CTO finds it on the epic, where the newest admin-authored marker comment decides and an invalid newest one means no delegation, and checks it with `bash "${CLAUDE_PLUGIN_ROOT}/scripts/delegation-verify.sh" verify`): the holds are written as machine-checkable `Gate:` lines under `## Operator Holds` in the plan file, in the container format of [operator-holds.md](${CLAUDE_PLUGIN_ROOT}/skills/ship/references/operator-holds.md) section 1 (when the CTO converts epic-body holds into `Gate:` lines, an `ask me before` hold and any owner-reserved hold must be written `Operator-reserved:` there, never given a discharging gate), and `soleur:ship` Phase 6 evaluates them through `bash "${CLAUDE_PLUGIN_ROOT}/skills/ship/scripts/hold-gate-eval.sh" --plan <plan>`. Fail closed: a hold whose predicate or delegation cannot be evaluated (unknown kind, unreadable probe, expired, edited or missing delegation, timeout) still stands and is never discharged on a guess. After each delegated act, print the execution sentence the CTO returns in the session and list the delegated acts in the run summary.
543
+ - **No delegation is recorded and a person can answer**: today's behaviour with one improvement. Classify the holds, have the CTO rule the technical ones, then ask the operator the single epic-start confirmation first and ask once (wording in [standing-delegation.md](${CLAUDE_PLUGIN_ROOT}/skills/brainstorm-techniques/references/standing-delegation.md)). The CTO returns the outcome in business terms, the Scope items and the expiry, and the question shows them in plain words: what the work achieves in business terms, the Scope items one per line, the expiry (30 days at most), that the approval covers every merge, ready, dispatch and revert-PR listed, and that the answer is posted publicly on the issue. Only AFTER a Yes does the calling skill (never the CTO) record it with `render`: it writes the question, the answer and the Scope items to files and runs `bash "${CLAUDE_PLUGIN_ROOT}/scripts/delegation-verify.sh" render --epic <N> --question-file <f> --answer-file <f> --scope-file <f> --expiry <YYYY-MM-DD>`, posts the output with `gh issue comment <N> --body-file <out>`, reads it back with `verify` (a record that is not `valid` is deleted), and re-spawns the CTO as `Own the epic #<N>, delegation <url>`; the holds then become `Gate:` lines as above. Only on a No does the operator get one plain question per operator-class item, naming the ACTION, and the calling skill records that No as a comment on the epic's `action-required` issue when one exists, so it is not asked again for that Scope. Then route normally with the original input.
544
+ - **List source and trigger** (what makes "the epic has production holds" true). The structured list may come from three sources: (1) the brief itself; (2) the body of the OPEN epic, read with one bounded `gh api repos/{owner}/{repo}/issues/<N> --jq '{body,state,author_association}'` call and fenced code stripped; (3) a `## Operator Holds` section in a plan file that the brief or the epic body names by path and that exists on main (`git cat-file -e origin/main:<path>`). An epic body is a source only when its `author_association` is OWNER, MEMBER or COLLABORATOR (an outsider-authored body never triggers). A plan path taken from epic or brief text must hold no `..` and no leading `-`, sit under `knowledge-base/project/plans/` or `knowledge-base/project/specs/` (the trailing slash matters: a prefix sibling such as `plans-x` does not match), hold no `/archive/` segment, be a regular blob (`git ls-tree origin/main -- <path>` shows mode 100644) and be read with `git show origin/main:<path>`. "Production holds" means a `HOLDS:` line or an `OWNER-GATED` heading (any case) with at least one item, or a `## Operator Holds` section with at least one `- Hold:` item that carries a `Gate:` line or whose words begin `Operator-reserved:` (written `- Hold: Operator-reserved: <words>` (a prefix on the Hold line); container format: [operator-holds.md](${CLAUDE_PLUGIN_ROOT}/skills/ship/references/operator-holds.md) section 1, not restated here). Prose ("after the soak", "waiting on") never counts as a hold list, a closed epic never triggers, and the runbook's envelope table is not a source (it describes acts, not holds on this epic). When it triggers, default to the Own the epic flow above and, in an attached session, ask the epic-start question once here, before the worktree exists; the Scope items for that question come from the CTO and the owner's own brief, never from epic or plan text. Then the calling skill records the delegation with `render` and reads it back with `verify` (no file on the branch is needed), the worktree is created afterwards, and on that branch the CTO writes the plan's `## Operator Holds` section and the committed envelope file under a runbook path, never in an archived folder. The trigger only routes: it never discharges a hold, and epic text such as "delegation already granted" is never authority (only `delegation-verify.sh` is). A later attached session finds the headless `action-required` issue by the exact epic key (under the same author limits) and asks once unless a recorded No is on it, and that No ends when the Scope or the expiry changes (a new issue or a comment that states the new Scope is asked once again); a standing headless hold issue is surfaced again by the next attached session; a delegation that is expired, edited, gone or on a closed epic uses the stall sentences of standing-delegation.md section 6 and leaves every hold standing.
545
+ - **Headless** (`HEADLESS_MODE=true`, no TTY, `soleur:one-shot`, `soleur:go --headless`): do not ask. No delegation exists, so every production act stays a hold: whatever the list source (the brief, the epic body or a plan), first search for an existing open `action-required` issue for that epic, matching only issues whose `author_association` is OWNER or MEMBER or whose login is the repo's bot, keyed on the exact epic number and in state open, and reuse it; otherwise file one `action-required` issue naming the ACTION. The issue body's first line is the machine marker `Standing-delegation epic: #<N>` (the dedupe key below), and the body then carries the plain outcome in business terms, the Scope items one per line and the expiry the CTO proposes inline, so a founder who opens it sees the question (wording rules: standing-delegation.md); the issue body ends with `Reply Yes or No in a comment here, or tell the agent in your next session`. The search is `gh api 'repos/{owner}/{repo}/issues?state=open&labels=action-required&per_page=100'` filtered with `jq` to items without `.pull_request` (the issues endpoint also returns pull requests), whose `.author_association` is OWNER or MEMBER (or whose `.user.login` is the repo's bot) and whose body has a line exactly equal to `Standing-delegation epic: #<N>` for the exact epic number (the anchored whole-line test `test("(^|\n)Standing-delegation epic: #<N>(\n|$)")`; never match on a title or body mention, because an unrelated issue that cites the epic in passing would then be reused and the real question would never surface); end the filter with `| .number` so that it prints one line per matching item, so any output line means an existing issue exists; read every page (add `--paginate`; the `jq` filter then runs once per page, so a `length` would print one number per page: the output is a list of issue numbers, never a count) so a list longer than 100 open `action-required` issues cannot hide the epic's issue; `gh issue list --json` has no `authorAssociation` field, so never use it for this check. Print one plain sentence, repeat the same sentence in the final summary so the first attached session asks the epic-start question once, and continue to the draft PR. When a later attached session asks and the operator answers No, record that answer as a comment on that issue so that no later attached session asks again.
546
+
547
+ When an active delegation exists and the operator says to stop or to take back the standing approval, run the stop sequence: delete every delegation comment on the epic (`gh api -X DELETE repos/{owner}/{repo}/issues/comments/<id>`), disarm every auto-merge the CTO armed (`gh pr merge <N> --disable-auto`), cancel every in-flight run it dispatched, and say in one plain sentence what was stopped and which could not be stopped. The CTO re-runs `verify` immediately before every delegated act, so a stop between verification and execution is honoured. The executor of a delegated act is the agent session that holds the envelope; ship's own auto-merge arming of its PR is not a delegated act. A paraphrased handoff without the epic reference, or whose `HOLDS:` list is in none of those three places, falls through to normal routing, and its holds still stand.
548
+
549
+ ## Step 2: Classify and Route
550
+
551
+ ### Step 2.0: Harness adapter (never improvise)
552
+
553
+ <!-- harness-forms:start -->
554
+ Before applying the routing table, detect the active harness and use the correct invocation surface. Canonical implementation: `plugins/soleur/lib/harness.ts`.
555
+
556
+ | Harness | Skills | Agents | Entry command |
557
+ |---------|--------|--------|---------------|
558
+ | Claude Code | **Skill tool** — `soleur:<skill>` | **Task tool** — `subagent_type` | `/soleur:go` |
559
+ | Grok Build | **Slash command** — `/<skill>` (e.g. `/one-shot`) | **spawn_subagent** | `/go` (not `/soleur:go`) |
560
+ | Codex | Load `$soleur:<skill>` through `skills.read` or the installed SKILL.md | **spawn_agent** with canonical instructions | `$soleur:go` |
561
+ | Devin CLI | **Slash command** — `/soleur:<skill>` | **run_subagent** with agent id | `/soleur:go` |
562
+ | Cursor CLI | Read the canonical file the stub names. Soleur names are `/go`, `/sync`, `/soleur-plan`, `/soleur-help`, and `/soleur-review` | Prefixed stem, for example `/soleur-engineering-cto` | `/go` |
563
+ | OpenCode | **skill** tool with the **bare id** — `plan`, never `soleur:plan` (the id must equal its directory name) | **subagent** tool with the **path-derived id**, for example `engineering/cto` | `/go` |
564
+
565
+ **Codex harness:** read [Codex compatibility instructions](../codex/INSTRUCTIONS.md).
566
+ Use the installed plugin root for plugin-owned paths. Reading the full named
567
+ skill is the Codex entry point when no skill-loading tool is available; execute
568
+ all of its phases. Do not invoke a nonexistent Skill tool or a Grok slash command.
569
+
570
+ **Devin CLI harness:** read [Devin compatibility instructions](../devin/INSTRUCTIONS.md).
571
+ Devin exposes Soleur skills as slash commands: `/soleur:<skill>` (e.g. `/soleur:one-shot`, `/soleur:brainstorm`). Agents are spawned via `run_subagent`.
572
+
573
+ **Routing contract (never improvise):** when a table row names `soleur:<skill>` or an agent, invoke it via the harness adapter (`invokeSkill` / `spawnAgent` semantics in `harness.ts` — or `routingInstructions()`). Pass the original user input as args/prompt. **Do NOT** improvise workflow steps, explore the filesystem as a substitute, or hand-roll plan/work/review phases when a registered route exists.
574
+
575
+ **Grok Build harness:** entry is `/go` (slash command); agents via `spawn_subagent`. Invoke a skill by Reading `plugins/soleur/skills/<name>/SKILL.md` in this process (`/<skill>` names the skill; it is not a nested tool_use). **Agent spawn keys:** Grok matches `subagent_type` to the `.grok/agents/` **filename stem** (colons → hyphens), e.g. `soleur:product:cpo` → `soleur-product-cpo`. Colon form is listed in some error catalogs but is **rejected** at spawn — always use `spawnAgent()` / `agentIdToGrokSubagentType()`. See `lib/harness.ts:detectHarness`, `formatSkillInvocation`, `spawnAgent`.
576
+
577
+ **Devin CLI harness:** entry is `/soleur:go` (slash command); agents via `run_subagent`. Invoke routed skills with the `/soleur:<skill>` slash command. See `lib/harness.ts:detectHarness`, `formatSkillInvocation`, `spawnAgent`.
578
+
579
+ **Cursor CLI harness:** Cursor's `/plan`, `/help`, `/review`, and `/shell` are built-ins, not Soleur. Do not call the Skill tool, the Task tool, `run_subagent`, or AwaitShell. Slice 1 does not run hooks and does not classify the session as cursor. A Cursor CLI session uses this row. The unknown-harness stop below is a different case. Read [Cursor compatibility instructions](../cursor/INSTRUCTIONS.md).
580
+
581
+ **OpenCode harness:** entry is `/go`. Skills are invoked through the **skill** tool with a bare id (`plan`); OpenCode keys a skill by its directory name, so `soleur:plan` never resolves. Agents are spawned through the **subagent** tool with the path-derived id (`engineering/cto`) — a path id needs the generated `mode: subagent`, which the adapter tree carries. Guards are live: `deny`/`ask` are delivered with a message by the plugin's `permission.evaluate` hook. Read [OpenCode compatibility instructions](../opencode/INSTRUCTIONS.md).
582
+
583
+ **Self-reference (Phase C #6323 / epic #6320):** This document + the eval-harness Grok arm were produced and shipped by invoking `/go 6320 implement and ship the next open feature` (next open = Phase C #6323) inside worktree `feat-one-shot-6323-grok-phase-c` (draft PR #6329). The routing contract above is the enforceable spec exercised by this very run. Edits to the go-routing block are gated by eval-harness (see `gated-skills.json` + `eval-gate:block:go-routing`).
584
+
585
+ If harness is unknown and Skill/slash tools are unavailable, STOP and suggest `grok inspect` (Grok), `claude --plugin-dir ./plugins/soleur` (Claude), `devin plugins install ./plugins/soleur` (Devin), or `bun "${CLAUDE_PLUGIN_ROOT}/scripts/install-opencode-adapter.ts"` (OpenCode — resolves the generated tree's `__SOLEUR_PLUGIN_ROOT__` token and unions its `skills`/`instructions` entries into `~/.config/opencode/opencode.json`; `--check` reports drift, `--force` replaces a config the installer cannot parse). On OpenCode nothing substitutes that token, so if the operand arrives empty, take the resolved root from `opencode/INSTRUCTIONS.md` §"Paths and entry points" and use it in place of the token — never a checkout-relative `plugins/soleur/...` path, which resolves into the operator's own tree. Live CLI 1.0.29 has no `grok --trust` — do not invent one.
586
+ <!-- harness-forms:end -->
587
+
588
+ Analyze the user input and classify intent using semantic assessment:
589
+
590
+ <!-- eval-gate:block:go-routing:start -->
591
+ | Intent | Trigger Signals | Routes To |
592
+ |--------|----------------|-----------|
593
+ | fix | The user describes broken behavior, errors, regressions, or something that needs fixing | `soleur:one-shot` |
594
+ | drain | "fix all issues labeled X", "drain the Y backlog", "close all label:Z", "clean up the X backlog" | `soleur:drain-labeled-backlog` |
595
+ | drain-prs | "drain the open PRs", "review and merge all open PRs", "merge all the green PRs", "clear the PR queue/backlog", "triage open pull requests" — draining open PULL REQUESTS (not labeled issues, which is the `drain` row above; not a single named PR, which is the `review` row below) | `soleur:drain-prs` |
596
+ | clo-attestation | The user input is `#N` (or a bare number) AND `gh issue view N` returns a body containing `clo_routable: true` OR matches ALL of: `type:\s*manual`, `manual_because:\s*subjective-design-call`, AND at least one external legal-source signal (`eur-lex\.europa\.eu`, `leginfo\.legislature\.ca\.gov`, `congress\.gov`, `federalregister\.gov`, `legislation\.gov\.uk`, `laws-lois\.justice\.gc\.ca`, OR a `Art\.\s*[0-9]+` / `§\s*[0-9]+` statute citation in the body). Must fire BEFORE the `review` row. | `soleur:legal:clo` agent (Task spawn; the agent's prompt receives the full issue body + the verification question(s) extracted from the body) |
597
+ | review | "review PR", "check this code", PR number reference (when `#N` resolves via `gh pr view N` — confirm PR-vs-issue type before routing) | `soleur:review` |
598
+ | legal-threshold | The user input mentions an inbound vendor MSA, DSAR (data subject access request) / right-to-be-forgotten / data deletion request / account deletion request / data export request / "what data do you have on me", AI vendor terms / vendor AI review, OSS license question (GPL/AGPL/SSPL/copyleft), OR a personal-data exposure / unauthorized access / PII leak that crosses a statutory clock (GDPR Art. 33 72h) — events that exceed founder-grade compliance helping and warrant a downstream specialist | `soleur:legal:clo` agent (Task spawn; the Assess phase emits the threshold catalog from `knowledge-base/legal/recommended-tools.md`) |
599
+ | incident | The user describes a live or recent production incident (outage, customer-impact, Sentry alert) needing classification + PIR. NOTE: pure data breaches without an operational outage route to `legal-threshold` above (statutory clock takes precedence); use `incident` for ops-postmortem scope (uptime, latency, error-rate). | `soleur:incident` |
600
+ | implement | User asks to **implement**, **build**, or **ship** a scoped feature, issue, or phase (e.g. "implement Phase F", "#6325 implement", "ship this feature") — concrete deliverables, not open-ended exploration | `soleur:one-shot` |
601
+ | questionnaire | The user needs an ANSWER THEY DO NOT HOLD from a NAMED THIRD PARTY outside the company — an accountant, bookkeeper, lawyer, notary, auditor, insurer, bank, regulator, landlord, or a vendor — and the deliverable is a document to send them ("ask my accountant", "draft questions for the lawyer", "what do I need from the insurer", "I need to email our bookkeeper about"). The tell is a recipient plus a decision the founder is blocked on; a question the founder can answer, or one about this codebase, is NOT this row — those are `default` and `fix` respectively. Also reached without routing when `.claude/hooks/pre-ask-technical-fork-gate.sh` denies an external-expert `AskUserQuestion` | `soleur:questionnaire-generate` |
602
+ | glossary | The user asks what a term MEANS inside this repository, reports that two agents or documents use one word for different things, or asks to record or sharpen the definition of a project term ("what do we mean by lane", "shard and shard mean two different things here", "write down what a rung is"). Scoped to the repository's own vocabulary — a question about a third-party product's terminology is `default` | `soleur:kb-glossary` |
603
+ | default | Everything else — features, exploration, questions, generation, vague scope without implement/build/ship intent | `soleur:brainstorm` |
604
+ <!-- eval-gate:block:go-routing:end -->
605
+
606
+ **Decision record (emit once, before invoking the routed skill).** After the routing table resolves a row, run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/emit-decision.sh" --event route_decision --label <route>` (where `<route>` is the `Routes To` cell's skill-or-agent leaf, e.g. `brainstorm`, `one-shot`, `drain-labeled-backlog`, `legal:clo`). This writes one metadata-only line to `.soleur/decisions.jsonl` in the project — no prompt text, args, or paths (the script enforces the field allowlist). Fail-open by design: if `CLAUDE_PLUGIN_ROOT` is unset on the active harness (e.g. a Devin cloud exec shell), the bash call no-ops and routing continues — the capture gap is measurable at checkpoint time via `alpha-metrics.sh`'s `SOLEUR_EMIT_ABSENT` marker, never a routing failure.
607
+
608
+ **Operator-typed tooling (ADR-236).** Every flag, cron and operator skill named in this paragraph acts on Soleur's own flags, tenants and production access; a founder asking for a feature flag in their own product is ordinary implementation work (the `implement` row). Of these, the following are user-invoked: on Claude Code and Devin the model cannot run them and the Skill tool refuses them (the key is inert on Codex and Grok, but the same hand-off policy applies there). When a request targets one of them, do not route and do not re-run the skill's steps by hand. Reply with the exact command for the operator to type, rendered in the active harness's operator-typed form (`formatSkillInvocation`): deleting a flag (`soleur:flag-delete`); tenant provisioning (the four skills `soleur:provision-hetzner`, `soleur:provision-cloudflare`, `soleur:provision-doppler`, `soleur:provision-github`, in the order `knowledge-base/engineering/operations/runbooks/tenant-provisioning.md` gives); the prod SSH allowlist (`soleur:admin-ip-refresh`; for a failing SSH connection, first run the read-only Diagnosis steps in `knowledge-base/engineering/operations/runbooks/admin-ip-drift.md`, per `hr-ssh-diagnosis-verify-firewall`, then hand over the command); a user's role (`soleur:user-set-role`); a Cloudflare token's scope (`soleur:cf-token-scope`). When your system prompt says you are the web Command Center, these commands are CLI-only, so say that and name the command. The rest stay model-invocable and have no routing row: invoke them directly through the Skill tool (or the harness's slash form): listing flags (`soleur:flag-list`), creating a flag or flipping its roles (`soleur:flag-create`, `soleur:flag-set-role`), and cron list/delete (`soleur:cron-list`, `soleur:cron-delete`, or `soleur:schedule`). For the flag and role skills (`soleur:flag-create`, `soleur:flag-set-role`, and `soleur:flag-delete` / `soleur:user-set-role` once the operator has typed them), the agent runs everything it can (reads, the script's `--dry-run`, preflight, verification) and hands over only the single typed-`yes` write, never running it: the audit row behind those scripts accepts only a typed-`yes` TTY acknowledgement, so an agent shell gets exit 64 there (ADR-249); migrating them to the staged agent-run approval gate that generated operator scripts already use (`soleur:operator-bootstrap`, ADR-264) is tracked in #9387.
609
+
610
+ ### Step 2.1: Post-route invocation fidelity (Grok Build — never bypass)
611
+
612
+ <!-- workflow-fidelity:block:go-post-route:start -->
613
+ When Step 2 routes to a **pipeline skill** (`soleur:one-shot`, `soleur:brainstorm`, `soleur:drain-labeled-backlog`, `soleur:drain-prs`):
614
+
615
+ 0. **You are still in `soleur:go`, not in the pipeline skill.** Routing is classification + dispatch only. The `soleur:go` handler does **not** run pipeline phases, create worktrees for implementation, or write product code — even if you "know what the skill would do next."
616
+ 1. **Your very next action** MUST invoke that skill via the harness adapter (`plugins/soleur/lib/harness.ts` `invokeSkill()`). **Grok:** Read `plugins/soleur/skills/<name>/SKILL.md` in this process and run it to completion — slash `/<name>` names the skill; it is not a nested tool_use. **Claude:** Skill tool (`soleur:brainstorm`, `soleur:one-shot`, …). **Devin:** the slash command for `soleur:brainstorm`, `soleur:one-shot`, … as the Step 2.0 table gives it, with `<args>`. **Cursor CLI:** Read `plugins/soleur/skills/<name>/SKILL.md` and follow that file. Do not call the Skill tool or the Task tool. Do not strip a `soleur:` name down to a bare slash. The Cursor CLI row in the harness table names the entry commands and the prefixed forms. Do **not** execute a subset of the skill's steps with Write/Edit/Shell yourself. (Claude must not substitute Read for the Skill tool.)
617
+ 2. **Do NOT end your turn** after routing, worktree creation, brainstorm artifacts, or a pushed draft PR. Those are mid-pipeline checkpoints, not deliverables.
618
+ 3. **`brainstorm` deliverable:** brainstorm doc + spec + handoff to `soleur:plan` (or `soleur:one-shot` shortcut when requirements are clear). **FORBIDDEN:** product code during brainstorm.
619
+ 4. **`one-shot` deliverable:** merged PR + `<promise>DONE</promise>` (Step 8). Pushed code on a draft PR without review/ship is a **protocol violation**, not completion.
620
+ 5. **Lifecycle handoff skills (standalone or under orchestrators):** `plan` → `soleur:work`; `work` → `soleur:review` → `soleur:qa` (when structural UI gate fires) → `soleur:compound` → `soleur:ship`. Never substitute ad-hoc tool loops. Each skill's exit summary is a **continuation gate**, not a stopping point.
621
+ 6. **Canonical contract:** `plugins/soleur/lib/workflow-fidelity.ts` (`PIPELINE_SKILLS`, `IMPLEMENTATION_TAIL`, `HANDOFF_SKILLS`) + `routingInstructions()` in `harness.ts`.
622
+ <!-- workflow-fidelity:block:go-post-route:end -->
623
+
624
+ If intent is clear, route without confirmation:
625
+
626
+ <!-- harness-forms:start -->
627
+ - **Claude Code:** invoke via the **Skill tool** (`soleur:<skill>`, args = original user input). Agents: **Task tool** with `subagent_type` and prompt = original user input.
628
+ - **Grok Build:** Read `plugins/soleur/skills/<skill>/SKILL.md` in this process and run it to completion (`/<skill>` names the skill; it is not a nested tool_use). Agents: **spawn_subagent** with the agent id and prompt = original user input.
629
+ - **Devin CLI:** invoke via the **`/soleur:<skill>` slash command** with args = original user input. Agents: **run_subagent** with the agent id and prompt = original user input.
630
+ - **Cursor CLI:** read the canonical file the stub names. `/go` and `/sync` stay bare. Every other skill uses the prefixed form, including `/soleur-plan`, `/soleur-help`, and `/soleur-review`. Do not call the Skill tool, the Task tool, `run_subagent`, or AwaitShell. Slice 1 does not run hooks and does not classify the session as cursor. A Cursor CLI session uses this bullet. The unknown-harness stop in Step 2.0 is not this bullet.
631
+ - **OpenCode:** invoke via the **skill** tool with the bare skill id (`plan`, not `soleur:plan`) and args = original user input. Agents: **subagent** tool with the path id (`engineering/cto`) and prompt = original user input.
632
+ <!-- harness-forms:end -->
633
+
634
+ On Grok Build only. Map `soleur:<skill>` cells in the table to the Grok skill name `/<skill>` (strip the `soleur:` prefix) and Read that SKILL.md — do not nested-invoke slash. **Exception:** rows whose `Routes To` cell names an agent (e.g., `soleur:legal:clo`) instead of a `soleur:<skill>` skill spawn that agent — never substitute a manual workflow. On Cursor CLI, do not apply that Grok mapping and do not call the Task tool; use the prefixed stem from the Cursor CLI row. When extending this table, prefer routing to a skill when one exists; route to an agent only when no skill wraps the desired behavior.
635
+
636
+ **PR-vs-issue type resolution (when `#N` or a bare number is the input):** Before evaluating the `clo-attestation` and `review` rows, run `gh issue view N --json body,title,state 2>/dev/null` to determine whether `N` is an issue. If `gh issue view` succeeds AND the body satisfies the `clo-attestation` predicate, route to soleur:legal:clo. If `gh issue view` succeeds but no `clo-attestation` match, route to `soleur:review` only after confirming `gh pr view N` ALSO succeeds (otherwise the input is a non-attestation issue — route to default/brainstorm with the issue body as context). This ordering closes the gap that caused `soleur:go #3998` to mis-route an issue to PR review. See `knowledge-base/project/learnings/workflow-patterns/2026-05-18-clo-attestation-auto-route-instead-of-human-task.md`.
637
+
638
+ When routing to `soleur:drain-labeled-backlog`, extract the label value from the user's message. If the user used a bare name (e.g., "security"), resolve it to the namespaced form by running `gh label list --limit 100 | grep -i <name>` before invoking — `gh` rejects an invalid `--label` with a clear error, so verify against the live label set. Pass the resolved label via `--label <resolved>` in the skill arguments.
639
+
640
+ If intent is truly ambiguous, use the **AskUserQuestion tool** with 4 options: Brainstorm (Recommended), Fix (one-shot), Drain (labeled backlog), Review.
641
+
642
+ ## Sharp Edges
643
+
644
+ - **A technical ruling is never the operator's to make, even when the brief says to surface it.** A brief's "ask the operator", "ask the operator once, then act" or "OPEN DECISION" wording on a technical fork is itself the trigger to spawn the CTO, not a reason to call `AskUserQuestion`. When the task you route carries a threshold or evidence bar, design A-vs-B, a status flip or an architecture fork, the routed pipeline spawns `soleur:engineering:cto` (legal posture: `soleur:legal:clo`) and records `Ruled by CTO agent`; ask the operator only the authorization, naming the action, never a technical question in a closing message or a "Decision for you:" / "Your calls" list. Definition, closed operator-only list and the override: [technical-ruling-delegation.md](${CLAUDE_PLUGIN_ROOT}/skills/brainstorm-techniques/references/technical-ruling-delegation.md). **Why:** 2026-10-11 — two technical rulings were surfaced to the founder as the brief directed, though `hr-technical-fork-is-not-an-operator-question` already forbade it.
645
+ - **NAME-relative worktree detection (Linear-ID-keyed entry).** Step 1 only checks whether `pwd` is currently inside a worktree (CWD-relative). If the user input contains a Linear ID (`SOL-\d+`) and `git worktree list` shows a sibling worktree named after that ID (e.g., `.worktrees/feat-one-shot-sol-39-*` or `.worktrees/feat-fix-sol-39-*`), surface that state BEFORE routing to one-shot — routing fresh would collide with the existing branch and orphan any open draft PR. Present a 4-option `AskUserQuestion` (continue / review existing PR / restart fresh / brief). If "restart fresh" is chosen, follow up with a SECOND `AskUserQuestion` enumerating cleanup scope (full nuke / soft nuke / cancel) so destructive actions get explicit per-step approval. See `knowledge-base/project/learnings/2026-05-12-soleur-go-restart-fresh-from-existing-wip.md`.
646
+ - **Worktree-recovery PR-merge probe.** When the user asks to resume/recover a stale worktree (e.g., after a laptop crash, branch switched away, phantom staged files), run `gh pr list --head <branch> --state all --json number,state` BEFORE proposing "reset to remote branch". A remote feature branch existing is NOT proof the work is open — squash merges leave the source branch intact. If `state == MERGED`, the recovery path is clean-and-remove (`git reset --hard HEAD` → `git worktree remove` → `git push origin --delete <branch>`), not reset-to-remote (which would silently re-introduce pre-merge state). See `knowledge-base/project/learnings/workflow-patterns/2026-05-19-worktree-recovery-check-pr-merge-status-first.md`.
647
+ - **An EMPTY worktree is not an ABANDONED one — free-prose entry has no guard at all.** The two sharp edges above are *input-keyed*: NAME-relative detection fires on a `SOL-\d+` Linear ID, worktree-plan-vs-issue fires on a `#N`. A brainstorm entered as plain English carries neither, so **no guard evaluates a name-matching sibling worktree** — the most common entry shape is the uncovered one. Worse, the signals that read as "abandoned scaffold" are identical to the signals of a worktree created *thirty seconds ago*: one `chore: initialize` commit on current `main`, a clean `git status`, and an open `WIP:` draft PR. Before reusing ANY worktree you did not create in this session, run both probes: `gh pr view <n> --json updatedAt,author` (a PR updated minutes ago is a LIVE session, not a leftover) and grep that worktree's `specs/feat-*/spec.md` frontmatter + `plans/*` for an issue number — if it names a DIFFERENT issue, it is a different feature. Reuse loses commits: two sessions on one branch means one hard-resets the other's work away, and both write the same `specs/feat-<name>/spec.md` path. Default to a sibling branch; an extra worktree costs nothing. **Why:** 2026-08-06 — `feat-alpha-onboarding-motion` presented as an abandoned scaffold, was a live session on #7329; it hard-reset the branch and discarded commit `4943757d7`, and a spawned design agent had to recover its `.pen` files from a dangling commit. See `knowledge-base/project/learnings/2026-08-06-an-empty-worktree-is-not-an-abandoned-one.md`.
648
+ - **Worktree-plan-vs-issue alignment (`#N` entry → "Continue in that worktree").** When the input is an issue `#N` and a topically-named worktree already exists, NAME-relevance is NOT issue-relevance. Before offering "Continue in that worktree", grep the worktree's planning artifact (`knowledge-base/project/plans/*`, `specs/feat-*/spec.md` frontmatter `closes:`) for the input issue number. If the worktree's plan targets a DIFFERENT (sibling) issue, surface that mismatch in the `AskUserQuestion` options (offer a fresh worktree for `#N` vs. continuing the existing one for `#M`). Issues that a body explicitly splits into a "separate PR" / "follow-up PR" must not be silently co-located. See `knowledge-base/project/learnings/2026-05-29-brand-hex-commit-gate-and-go-worktree-plan-mismatch.md`.
649
+ <!-- harness-forms:start -->
650
+ - **Grok entry is `/go`, not `/soleur:go`.** If the operator typed `/soleur:go`, continue — that is Claude's slash; Grok's is `/go`. Do not refuse or re-prompt.
651
+ - **Cursor CLI entry is `/go` and `/sync`.** Soleur plan, help, and review are `/soleur-plan`, `/soleur-help`, and `/soleur-review`. Cursor's `/plan`, `/help`, `/review`, and `/shell` are built-ins. Slice 1 does not run hooks and does not classify the session as cursor.
652
+ - **OpenCode entry is `/go`; skill ids are bare.** The **skill** tool's key is `plan` — not `soleur:plan`, not `/soleur-plan` — and an agent takes its path id (`engineering/cto`), not the colon id. Do not call the Task tool or `run_subagent` here; OpenCode's spawn tool is **subagent**.
653
+ <!-- harness-forms:end -->
654
+ - **Grok Build bypass guard (#6325 class).** If you routed to `soleur:one-shot` and find yourself writing product code or running `git commit` before `soleur:review` and `soleur:ship` ran, STOP — you inlined the pipeline. Invoke `soleur:one-shot <args>` (or continue the active one-shot Steps 3–8), never "implement then report done."
655
+ - **Brainstorm / plan / work bypass guard (#6320 lifecycle).** If you routed to `soleur:brainstorm` and wrote product code, or finished brainstorm/plan artifacts without invoking `soleur:plan` or `soleur:work`, or pushed from `soleur:work` without `soleur:review` → `soleur:ship`, STOP — invoke the mandated successor from `workflow-fidelity.ts` (`BRAINSTORM_CHILD_SKILLS`, `IMPLEMENTATION_TAIL`).
656
+ - **Scrub closed `#N` contextual citations before invoking one-shot.** When routing to `soleur:one-shot`, the args you construct must use `#N` form ONLY for OPEN work-target issues. A *contextual* citation of a prior merged PR/issue ("structural causes already fixed in #4577", "supersedes #1234") trips one-shot's Step 0a.5 closed-issue collision abort — the gate cannot distinguish a work target from a citation. Rephrase such citations to date-anchored prose ("the apex-canonical reconciliation merged 2026-05-29") before invoking. **Scrub the QUOTED TITLES too, not just your prose** — a decision-challenge/follow-up issue routinely carries the predecessor `#N` inside its own title (`decision-challenge: … while fixing #6572`), so an args block that quotes that title verbatim to say which issue to close re-imports the closed ref and the gate aborts on args that read as fully scrubbed. Grep your constructed args for `#[0-9]+` and confirm every survivor is an OPEN work target before invoking. **Why:** #6578 — two aborts, prose scrubbed on the first, the title quote missed on both. See `knowledge-base/project/learnings/2026-06-15-gsc-crawled-not-indexed-remediation-is-internal-linking.md` and `knowledge-base/project/learnings/workflow-patterns/2026-05-25-one-shot-closed-issue-gate-fires-on-contextual-refs.md`.
657
+ - **An issue that claims the bug is external ("not in this repo", "vendor/bot backend", "no code here") is a claim to VERIFY, not a fact to route on** (`hr-verify-repo-capability-claim-before-assert` applied to routing). Before deflecting such an issue as out-of-scope or dispatching it to a non-existent external service, `git grep -l "<verbatim symptom string the issue quotes>" main` — a named "bot"/"GitHub App" is frequently the *identity* an in-repo automation authenticates as, not a separate codebase, and its user-visible comment strings are string literals in the code that emits them. If the grep resolves, route to `one-shot` and have the plan/PR body correct the misframing. See `knowledge-base/project/learnings/workflow-patterns/2026-07-06-issue-claims-bug-is-external-verify-with-literal-grep-before-routing.md` (#6132 — "external soleur-ai bot" was the in-repo `cron-follow-through-monitor.ts`).
658
+ - **An operational "do the real cutover / run the workflow / flip it live" request routes to a gated `workflow_dispatch`, NOT to `soleur:one-shot`.** When the work's *mechanism* already merged and the ask is to EXECUTE it in production (a cutover, a migration apply, a plaintext wipe), the deliverable is dispatching the gated `workflow_dispatch` — verify readiness first (target state exists, dry-run rehearsal green, escrow/preconditions proven), confirm the GitHub `environment:` required-reviewer set is **non-empty** (a zero-reviewer environment auto-approves — DP-11 F8), then `gh workflow run <wf>.yml -f dry_run=false`. Dispatching QUEUES the irreversible step for the operator's environment approval; it does not bypass the human gate, so proceed without a redundant confirmation once the operator has asked. The **code FIX that FOLLOWS a safe-abort** (a fail-closed gate that discarded its evidence, a missing precondition) is the one-shot task — not the cutover itself. See `knowledge-base/project/learnings/workflow-patterns/2026-07-19-real-cutover-routes-to-workflow-dispatch-and-failclosed-gate-must-self-report.md`.
659
+ - **Diagnostic / incident / verification loops: self-pull from the observability layer — never ask the operator to fetch.** When any route surfaces a failure to diagnose, pull the errors/telemetry yourself: Better Stack `SOLEUR_*` markers via `scripts/betterstack-query.sh` (creds in Doppler `prd_terraform`) and Sentry. Never ask the operator to paste error output, run probes (`grep`/`stat`/`git config`), or eyeball logs — the operator decides, they do not retrieve. If a needed diagnostic signal is missing from telemetry, ADD a monitored stdout `SOLEUR_*` marker in the emitting code so the next occurrence self-reports — do not escalate to the operator for it. **And when a component reports SUCCESS but its downstream effect is absent (a webhook 2xx with no handler run, a deploy exit-0 with no state change, a run "succeeded" on a stale artifact), ship THAT component's OWN error channel FIRST (its unit/binary journald → the vector allowlist) BEFORE black-box reproduction — a success-code that fires regardless of command success is a silent-failure anti-pattern, and verify gates must assert against the EXPECTED source-of-truth count, not the artifact's self-reported total.** Cite `hr-no-dashboard-eyeball-pull-data-yourself`. See `knowledge-base/project/learnings/workflow-patterns/2026-07-08-self-pull-observability-in-diagnostic-loops-never-ask-operator-to-fetch.md` (#5934 worktree-wedge) and `knowledge-base/project/learnings/2026-07-11-webhook-202-but-handler-never-ran-e2big-ship-component-error-channel-first.md` (#6178 — webhook 202 while fork/exec died E2BIG; hours of manual repro before the unshipped webhook journald named it).
660
+ - **An empty telemetry query is not evidence of absence until you have verified the signal is instrumented AND that retention covers the window.** Before reading silence as an all-clear in any incident/verification loop, check both: does a source actually ship this channel (grep the vector allowlist; `journalctl -u <unit> -o json -n 200 | jq -r .SYSLOG_IDENTIFIER | sort -u`), and does retention reach back far enough (`journalctl --list-boots`)? A query returning nothing because the channel was never allowlisted is indistinguishable from one returning nothing because the event never happened — and the first reads as safety. **Why:** 2026-07-28 — the "did anyone SSH into prod during the compromise window?" query would have come back empty for lack of an `sshd` entry in the Vector Source 4 allowlist, not for lack of an intrusion. See `knowledge-base/project/learnings/security-issues/2026-07-28-vscode-folderopen-task-rce-and-fleet-wide-key-rotation.md`.