@soleur/opencode 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (812) hide show
  1. package/.claude-plugin/agents.manifest.json +476 -0
  2. package/.claude-plugin/plugin.json +42 -0
  3. package/README.md +44 -2
  4. package/agents/community/.gitkeep +0 -0
  5. package/agents/engineering/cto.md +87 -0
  6. package/agents/engineering/design/ddd-architect.md +95 -0
  7. package/agents/engineering/discovery/agent-finder.md +214 -0
  8. package/agents/engineering/discovery/functional-discovery.md +182 -0
  9. package/agents/engineering/infra/infra-security.md +151 -0
  10. package/agents/engineering/infra/platform-strategist.md +109 -0
  11. package/agents/engineering/infra/terraform-architect.md +171 -0
  12. package/agents/engineering/prompt-engineer.md +37 -0
  13. package/agents/engineering/research/best-practices-researcher.md +115 -0
  14. package/agents/engineering/research/framework-docs-researcher.md +93 -0
  15. package/agents/engineering/research/git-history-analyzer.md +53 -0
  16. package/agents/engineering/research/learnings-researcher.md +285 -0
  17. package/agents/engineering/research/repo-research-analyst.md +118 -0
  18. package/agents/engineering/review/agent-native-reviewer.md +279 -0
  19. package/agents/engineering/review/architecture-strategist.md +61 -0
  20. package/agents/engineering/review/code-quality-analyst.md +92 -0
  21. package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
  22. package/agents/engineering/review/data-integrity-guardian.md +82 -0
  23. package/agents/engineering/review/data-migration-expert.md +98 -0
  24. package/agents/engineering/review/deployment-verification-agent.md +183 -0
  25. package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
  26. package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
  27. package/agents/engineering/review/legacy-code-expert.md +55 -0
  28. package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
  29. package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
  30. package/agents/engineering/review/performance-oracle.md +130 -0
  31. package/agents/engineering/review/security-sentinel.md +167 -0
  32. package/agents/engineering/review/semgrep-sast.md +36 -0
  33. package/agents/engineering/review/test-design-reviewer.md +150 -0
  34. package/agents/engineering/review/user-impact-reviewer.md +70 -0
  35. package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
  36. package/agents/finance/budget-analyst.md +29 -0
  37. package/agents/finance/cfo.md +44 -0
  38. package/agents/finance/financial-reporter.md +30 -0
  39. package/agents/finance/revenue-analyst.md +30 -0
  40. package/agents/legal/clo.md +115 -0
  41. package/agents/legal/legal-compliance-auditor.md +110 -0
  42. package/agents/legal/legal-document-generator.md +134 -0
  43. package/agents/marketing/analytics-analyst.md +25 -0
  44. package/agents/marketing/brand-architect.md +181 -0
  45. package/agents/marketing/cmo.md +76 -0
  46. package/agents/marketing/conversion-optimizer.md +19 -0
  47. package/agents/marketing/copywriter.md +20 -0
  48. package/agents/marketing/fact-checker.md +70 -0
  49. package/agents/marketing/growth-strategist.md +145 -0
  50. package/agents/marketing/paid-media-strategist.md +28 -0
  51. package/agents/marketing/pricing-strategist.md +17 -0
  52. package/agents/marketing/programmatic-seo-specialist.md +25 -0
  53. package/agents/marketing/retention-strategist.md +23 -0
  54. package/agents/marketing/seo-aeo-analyst.md +164 -0
  55. package/agents/operations/coo.md +50 -0
  56. package/agents/operations/ops-advisor.md +78 -0
  57. package/agents/operations/ops-provisioner.md +101 -0
  58. package/agents/operations/ops-research.md +52 -0
  59. package/agents/operations/service-automator.md +278 -0
  60. package/agents/product/business-validator.md +206 -0
  61. package/agents/product/competitive-intelligence.md +89 -0
  62. package/agents/product/cpo.md +63 -0
  63. package/agents/product/design/ux-design-lead.md +209 -0
  64. package/agents/product/spec-flow-analyzer.md +122 -0
  65. package/agents/sales/cro.md +44 -0
  66. package/agents/sales/deal-architect.md +29 -0
  67. package/agents/sales/outbound-strategist.md +29 -0
  68. package/agents/sales/pipeline-analyst.md +29 -0
  69. package/agents/support/cco.md +48 -0
  70. package/agents/support/community-manager.md +570 -0
  71. package/agents/support/ticket-triage.md +70 -0
  72. package/bin/soleur-opencode.js +29 -0
  73. package/commands/go.md +659 -0
  74. package/commands/help.md +273 -0
  75. package/commands/sync.md +977 -0
  76. package/commands/version.md +103 -0
  77. package/hooks/antigravity-hooks.json +84 -0
  78. package/hooks/antigravity-session-start.sh +15 -0
  79. package/hooks/bare-root-cwd-guard.sh +131 -0
  80. package/hooks/browser-snapshot-credential-guard.sh +200 -0
  81. package/hooks/codex-session-start.sh +9 -0
  82. package/hooks/compaction-state.sh +525 -0
  83. package/hooks/destructive-command-guard.sh +1387 -0
  84. package/hooks/devin-session-start.sh +90 -0
  85. package/hooks/ext-filter-detect.sh +171 -0
  86. package/hooks/hooks.json +133 -0
  87. package/hooks/lib/hook-tool-kind.sh +24 -0
  88. package/hooks/lib/log-rotation.sh +176 -0
  89. package/hooks/lib/shell-argv.pl +576 -0
  90. package/hooks/memory-backstop.sh +1114 -0
  91. package/hooks/operator-stage-approval.sh +391 -0
  92. package/hooks/stop-hook.sh +367 -0
  93. package/hooks/unkept-promise-hook.sh +383 -0
  94. package/hooks/version-banner.sh +127 -0
  95. package/hooks/welcome-hook.sh +50 -0
  96. package/install.js +108 -0
  97. package/lib/agent-registry.ts +154 -0
  98. package/lib/c4-canonical-cli.mjs +34 -0
  99. package/lib/c4-canonical.mjs +46 -0
  100. package/lib/c4-from-components.ts +554 -0
  101. package/lib/go-routing.ts +81 -0
  102. package/lib/grok-inspect-contract.ts +311 -0
  103. package/lib/harness-model-map.ts +101 -0
  104. package/lib/harness-parity.ts +726 -0
  105. package/lib/harness-tool-map.ts +180 -0
  106. package/lib/harness.ts +716 -0
  107. package/lib/heartbeat-live-reconcile.ts +1153 -0
  108. package/lib/heartbeat-manifest.ts +342 -0
  109. package/lib/kb-coverage.ts +252 -0
  110. package/lib/pr-merge-poll.ts +103 -0
  111. package/lib/workflow-fidelity.ts +388 -0
  112. package/opencode/INSTRUCTIONS.md +152 -0
  113. package/opencode/agents/engineering/cto.md +10 -0
  114. package/opencode/agents/engineering/design/ddd-architect.md +10 -0
  115. package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
  116. package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
  117. package/opencode/agents/engineering/infra/infra-security.md +10 -0
  118. package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
  119. package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
  120. package/opencode/agents/engineering/prompt-engineer.md +10 -0
  121. package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
  122. package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
  123. package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
  124. package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
  125. package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
  126. package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
  127. package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
  128. package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
  129. package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
  130. package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
  131. package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
  132. package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
  133. package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
  134. package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
  135. package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
  136. package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
  137. package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
  138. package/opencode/agents/engineering/review/performance-oracle.md +10 -0
  139. package/opencode/agents/engineering/review/security-sentinel.md +10 -0
  140. package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
  141. package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
  142. package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
  143. package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
  144. package/opencode/agents/finance/budget-analyst.md +10 -0
  145. package/opencode/agents/finance/cfo.md +10 -0
  146. package/opencode/agents/finance/financial-reporter.md +10 -0
  147. package/opencode/agents/finance/revenue-analyst.md +10 -0
  148. package/opencode/agents/legal/clo.md +10 -0
  149. package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
  150. package/opencode/agents/legal/legal-document-generator.md +10 -0
  151. package/opencode/agents/marketing/analytics-analyst.md +10 -0
  152. package/opencode/agents/marketing/brand-architect.md +10 -0
  153. package/opencode/agents/marketing/cmo.md +10 -0
  154. package/opencode/agents/marketing/conversion-optimizer.md +10 -0
  155. package/opencode/agents/marketing/copywriter.md +10 -0
  156. package/opencode/agents/marketing/fact-checker.md +10 -0
  157. package/opencode/agents/marketing/growth-strategist.md +10 -0
  158. package/opencode/agents/marketing/paid-media-strategist.md +10 -0
  159. package/opencode/agents/marketing/pricing-strategist.md +10 -0
  160. package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
  161. package/opencode/agents/marketing/retention-strategist.md +10 -0
  162. package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
  163. package/opencode/agents/operations/coo.md +10 -0
  164. package/opencode/agents/operations/ops-advisor.md +10 -0
  165. package/opencode/agents/operations/ops-provisioner.md +10 -0
  166. package/opencode/agents/operations/ops-research.md +10 -0
  167. package/opencode/agents/operations/service-automator.md +10 -0
  168. package/opencode/agents/product/business-validator.md +10 -0
  169. package/opencode/agents/product/competitive-intelligence.md +10 -0
  170. package/opencode/agents/product/cpo.md +10 -0
  171. package/opencode/agents/product/design/ux-design-lead.md +10 -0
  172. package/opencode/agents/product/spec-flow-analyzer.md +10 -0
  173. package/opencode/agents/sales/cro.md +10 -0
  174. package/opencode/agents/sales/deal-architect.md +10 -0
  175. package/opencode/agents/sales/outbound-strategist.md +10 -0
  176. package/opencode/agents/sales/pipeline-analyst.md +10 -0
  177. package/opencode/agents/support/cco.md +10 -0
  178. package/opencode/agents/support/community-manager.md +10 -0
  179. package/opencode/agents/support/ticket-triage.md +10 -0
  180. package/opencode/commands/go.md +10 -0
  181. package/opencode/commands/help.md +10 -0
  182. package/opencode/commands/sync.md +10 -0
  183. package/opencode/commands/version.md +11 -0
  184. package/opencode/opencode.json +8 -0
  185. package/opencode/plugin.ts +493 -0
  186. package/package.json +36 -4
  187. package/scripts/admin-merge-ready.sh +545 -0
  188. package/scripts/admin-merge-ready.test.sh +753 -0
  189. package/scripts/affected-tests.sh +908 -0
  190. package/scripts/affected-tests.test.sh +1797 -0
  191. package/scripts/alpha-metrics.sh +78 -0
  192. package/scripts/alpha-metrics.test.sh +115 -0
  193. package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
  194. package/scripts/audit-flag-flip.sh +107 -0
  195. package/scripts/check-red-on-main.sh +316 -0
  196. package/scripts/ci-head-verdict.sh +363 -0
  197. package/scripts/cloud-detect.sh +193 -0
  198. package/scripts/delegation-verify.sh +657 -0
  199. package/scripts/delegation-verify.test.sh +1424 -0
  200. package/scripts/deploy-arm.sh +475 -0
  201. package/scripts/domain-model-drift.sh +419 -0
  202. package/scripts/emit-decision.sh +144 -0
  203. package/scripts/emit-decision.test.sh +144 -0
  204. package/scripts/ext-filter-divergence-corpus.txt +15 -0
  205. package/scripts/ext-filter-divergence.sh +189 -0
  206. package/scripts/generate-c4-from-components.ts +442 -0
  207. package/scripts/grok-fidelity-gate.sh +68 -0
  208. package/scripts/grok-pre-push-gate.sh +232 -0
  209. package/scripts/harness-discovery-smoke.ts +906 -0
  210. package/scripts/harness-parity-census.ts +92 -0
  211. package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
  212. package/scripts/install-opencode-adapter.ts +520 -0
  213. package/scripts/lib/affected-tests/common.sh +365 -0
  214. package/scripts/lib/affected-tests/go.sh +157 -0
  215. package/scripts/lib/affected-tests/js.sh +188 -0
  216. package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
  217. package/scripts/lib/affected-tests/python.sh +185 -0
  218. package/scripts/lib/context-sanitize.sh +49 -0
  219. package/scripts/lib/domain-model-lib.sh +180 -0
  220. package/scripts/lib/ext-filter-grammar.tsv +34 -0
  221. package/scripts/lib/operator-script.sh +1236 -0
  222. package/scripts/lib/proc.sh +580 -0
  223. package/scripts/lib/session-state.sh +748 -0
  224. package/scripts/lib/tmp-classify.sh +843 -0
  225. package/scripts/lib/wrapper-boundary.sh +47 -0
  226. package/scripts/lint-ratchet.py +1547 -0
  227. package/scripts/monitor-pr-checks.sh +441 -0
  228. package/scripts/pipeline-tally.sh +756 -0
  229. package/scripts/pipeline-tally.test.sh +740 -0
  230. package/scripts/plugin-version.sh +528 -0
  231. package/scripts/precommit-guard.sh +113 -0
  232. package/scripts/precommit-guard.test.sh +254 -0
  233. package/scripts/reconcile-live-heartbeats.ts +705 -0
  234. package/scripts/render-c4-model.sh +217 -0
  235. package/scripts/resolve-git-root.sh +55 -0
  236. package/scripts/resolve-regenerable-conflicts.sh +363 -0
  237. package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
  238. package/scripts/ruff-requirements.txt +22 -0
  239. package/scripts/run-in-pid-namespace.sh +98 -0
  240. package/scripts/run-in-pid-namespace.test.sh +290 -0
  241. package/scripts/scan-ancestor-signal-helpers.py +556 -0
  242. package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
  243. package/scripts/setup-ralph-loop.sh +238 -0
  244. package/scripts/sync-cursor-name-map.ts +316 -0
  245. package/scripts/sync-grok-agent-compat.ts +188 -0
  246. package/scripts/sync-npm-package.ts +178 -0
  247. package/scripts/sync-opencode-adapter.ts +479 -0
  248. package/scripts/sync-pr-behind.sh +534 -0
  249. package/scripts/sync-pr-behind.test.sh +252 -0
  250. package/scripts/taste-profile-update.sh +180 -0
  251. package/scripts/taste-profile-update.test.sh +167 -0
  252. package/scripts/write-budget-marker.sh +23 -0
  253. package/scripts/write-kb-coverage.ts +113 -0
  254. package/skills/admin-ip-refresh/SKILL.md +81 -0
  255. package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
  256. package/skills/agent-browser/SKILL.md +698 -0
  257. package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
  258. package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
  259. package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
  260. package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
  261. package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
  262. package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
  263. package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
  264. package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
  265. package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
  266. package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
  267. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
  268. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
  269. package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
  270. package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
  271. package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
  272. package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
  273. package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
  274. package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
  275. package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
  276. package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
  277. package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
  278. package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
  279. package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
  280. package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
  281. package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
  282. package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
  283. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
  284. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
  285. package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
  286. package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
  287. package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
  288. package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
  289. package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
  290. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
  291. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
  292. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
  293. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
  294. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
  295. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
  296. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
  297. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
  298. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
  299. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
  300. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
  301. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
  302. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
  303. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
  304. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
  305. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
  306. package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
  307. package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
  308. package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
  309. package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
  310. package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
  311. package/skills/agent-native-architecture/SKILL.md +479 -0
  312. package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
  313. package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
  314. package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
  315. package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
  316. package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
  317. package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
  318. package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
  319. package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
  320. package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
  321. package/skills/agent-native-architecture/references/product-implications.md +478 -0
  322. package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
  323. package/skills/agent-native-architecture/references/self-modification.md +294 -0
  324. package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
  325. package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
  326. package/skills/agent-native-audit/SKILL.md +300 -0
  327. package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
  328. package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
  329. package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  330. package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  331. package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  332. package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
  333. package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  334. package/skills/architecture/SKILL.md +436 -0
  335. package/skills/architecture/references/adr-template.md +154 -0
  336. package/skills/architecture/references/likec4-reference.md +136 -0
  337. package/skills/architecture/references/nfr-reference.md +126 -0
  338. package/skills/archive-kb/SKILL.md +86 -0
  339. package/skills/archive-kb/scripts/archive-kb.sh +300 -0
  340. package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
  341. package/skills/atdd-developer/SKILL.md +65 -0
  342. package/skills/brainstorm/SKILL.md +701 -0
  343. package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
  344. package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
  345. package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
  346. package/skills/brainstorm/references/ui-surface-terms.md +42 -0
  347. package/skills/brainstorm-techniques/SKILL.md +231 -0
  348. package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
  349. package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
  350. package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
  351. package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
  352. package/skills/campaign-calendar/SKILL.md +145 -0
  353. package/skills/cf-token-scope/SKILL.md +164 -0
  354. package/skills/cf-token-scope/references/widen-playbook.md +114 -0
  355. package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
  356. package/skills/changelog/SKILL.md +142 -0
  357. package/skills/code-to-prd/SKILL.md +66 -0
  358. package/skills/code-to-prd/references/banner-template.md +12 -0
  359. package/skills/code-to-prd/references/prd-template.md +41 -0
  360. package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
  361. package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
  362. package/skills/code-to-prd/test/fixture/.env.example +7 -0
  363. package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
  364. package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
  365. package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
  366. package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
  367. package/skills/code-to-prd/test/fixture/package.json +6 -0
  368. package/skills/cohort-status/SKILL.md +62 -0
  369. package/skills/community/SKILL.md +210 -0
  370. package/skills/community/scripts/bsky-community.sh +644 -0
  371. package/skills/community/scripts/bsky-setup.sh +631 -0
  372. package/skills/community/scripts/community-router.sh +93 -0
  373. package/skills/community/scripts/discord-community.sh +487 -0
  374. package/skills/community/scripts/discord-setup.sh +784 -0
  375. package/skills/community/scripts/github-community.sh +706 -0
  376. package/skills/community/scripts/hn-community.sh +233 -0
  377. package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
  378. package/skills/community/scripts/linkedin-community.sh +750 -0
  379. package/skills/community/scripts/linkedin-setup.sh +758 -0
  380. package/skills/community/scripts/x-community.sh +890 -0
  381. package/skills/community/scripts/x-setup.sh +713 -0
  382. package/skills/community/test/community-argv.test.sh +2922 -0
  383. package/skills/community/test/github-community.test.sh +981 -0
  384. package/skills/competitive-analysis/SKILL.md +69 -0
  385. package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
  386. package/skills/compound/SKILL.md +673 -0
  387. package/skills/compound/scripts/token-efficiency-report.sh +334 -0
  388. package/skills/compound/test/phase-16.test.sh +379 -0
  389. package/skills/compound-capture/SKILL.md +791 -0
  390. package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
  391. package/skills/compound-capture/assets/resolution-template.md +116 -0
  392. package/skills/compound-capture/references/yaml-schema.md +67 -0
  393. package/skills/compound-capture/schema.yaml +181 -0
  394. package/skills/constraint-scaffold/SKILL.md +175 -0
  395. package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
  396. package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
  397. package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
  398. package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
  399. package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
  400. package/skills/constraint-scaffold/references/shared-runner.template +135 -0
  401. package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
  402. package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
  403. package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
  404. package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
  405. package/skills/constraint-scaffold/test/generator.test.sh +93 -0
  406. package/skills/constraint-scaffold/test/parity.test.sh +285 -0
  407. package/skills/content-writer/SKILL.md +242 -0
  408. package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
  409. package/skills/cron-delete/SKILL.md +56 -0
  410. package/skills/cron-list/SKILL.md +54 -0
  411. package/skills/deepen-plan/SKILL.md +937 -0
  412. package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
  413. package/skills/deploy/SKILL.md +115 -0
  414. package/skills/deploy/references/hetzner-setup.md +65 -0
  415. package/skills/deploy/scripts/deploy.sh +37 -0
  416. package/skills/deploy-docs/SKILL.md +95 -0
  417. package/skills/dhh-rails-style/SKILL.md +203 -0
  418. package/skills/dhh-rails-style/references/architecture.md +717 -0
  419. package/skills/dhh-rails-style/references/controllers.md +323 -0
  420. package/skills/dhh-rails-style/references/frontend.md +556 -0
  421. package/skills/dhh-rails-style/references/gems.md +316 -0
  422. package/skills/dhh-rails-style/references/models.md +388 -0
  423. package/skills/dhh-rails-style/references/testing.md +354 -0
  424. package/skills/discord-content/SKILL.md +126 -0
  425. package/skills/docs-site/SKILL.md +214 -0
  426. package/skills/drain-labeled-backlog/SKILL.md +203 -0
  427. package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
  428. package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
  429. package/skills/drain-prs/SKILL.md +142 -0
  430. package/skills/drain-prs/scripts/triage-prs.sh +192 -0
  431. package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
  432. package/skills/dspy-ruby/SKILL.md +634 -0
  433. package/skills/dspy-ruby/assets/config-template.rb +359 -0
  434. package/skills/dspy-ruby/assets/module-template.rb +326 -0
  435. package/skills/dspy-ruby/assets/signature-template.rb +143 -0
  436. package/skills/dspy-ruby/references/core-concepts.md +268 -0
  437. package/skills/dspy-ruby/references/optimization.md +623 -0
  438. package/skills/dspy-ruby/references/providers.md +335 -0
  439. package/skills/eval-harness/README.md +194 -0
  440. package/skills/eval-harness/SKILL.md +157 -0
  441. package/skills/eval-harness/enums/go-routes.json +13 -0
  442. package/skills/eval-harness/enums/incident-threshold.json +5 -0
  443. package/skills/eval-harness/enums/lane.json +5 -0
  444. package/skills/eval-harness/enums/tool-selection.json +20 -0
  445. package/skills/eval-harness/enums/triage-levels.json +5 -0
  446. package/skills/eval-harness/gated-skills.json +34 -0
  447. package/skills/eval-harness/models.generated.json +5 -0
  448. package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
  449. package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
  450. package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
  451. package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
  452. package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
  453. package/skills/eval-harness/prompts/go-baseline.txt +6 -0
  454. package/skills/eval-harness/prompts/go-skill.txt +21 -0
  455. package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
  456. package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
  457. package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
  458. package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
  459. package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
  460. package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
  461. package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
  462. package/skills/eval-harness/prompts/triage-skill.txt +10 -0
  463. package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
  464. package/skills/eval-harness/scripts/extract-block.cjs +87 -0
  465. package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
  466. package/skills/eval-harness/scripts/gen-models.sh +41 -0
  467. package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
  468. package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
  469. package/skills/eval-harness/scripts/parse-label.cjs +93 -0
  470. package/skills/eval-harness/scripts/verdict.cjs +132 -0
  471. package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
  472. package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
  473. package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
  474. package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
  475. package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
  476. package/skills/eval-harness/test/eval-gate.test.sh +132 -0
  477. package/skills/eval-harness/test/extract-block.test.sh +87 -0
  478. package/skills/eval-harness/test/gate-classification.test.sh +77 -0
  479. package/skills/eval-harness/test/gen-models.test.sh +75 -0
  480. package/skills/eval-harness/test/measure-classification.test.sh +74 -0
  481. package/skills/eval-harness/test/parse-label.test.sh +129 -0
  482. package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
  483. package/skills/eval-harness/test/verdict.test.sh +123 -0
  484. package/skills/every-style-editor/SKILL.md +142 -0
  485. package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  486. package/skills/feature-tweet/SKILL.md +199 -0
  487. package/skills/feature-video/SKILL.md +412 -0
  488. package/skills/feature-video/scripts/check_deps.sh +281 -0
  489. package/skills/file-todos/SKILL.md +267 -0
  490. package/skills/file-todos/assets/todo-template.md +166 -0
  491. package/skills/fix-issue/SKILL.md +278 -0
  492. package/skills/fix-issue/references/agent-authored-exclusion.md +118 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -0
  494. package/skills/flag-bootstrap/SETUP.md +142 -0
  495. package/skills/flag-create/SKILL.md +145 -0
  496. package/skills/flag-create/scripts/create.sh +273 -0
  497. package/skills/flag-delete/SKILL.md +167 -0
  498. package/skills/flag-delete/scripts/delete.sh +288 -0
  499. package/skills/flag-list/SKILL.md +99 -0
  500. package/skills/flag-list/scripts/list.sh +275 -0
  501. package/skills/flag-set-role/SKILL.md +229 -0
  502. package/skills/flag-set-role/scripts/flip.sh +774 -0
  503. package/skills/frontend-anti-slop/SKILL.md +106 -0
  504. package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
  505. package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
  506. package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
  507. package/skills/frontend-design/SKILL.md +77 -0
  508. package/skills/gdpr-gate/NOTICE +136 -0
  509. package/skills/gdpr-gate/SKILL.md +341 -0
  510. package/skills/gdpr-gate/references/fields.md +160 -0
  511. package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
  512. package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
  513. package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
  514. package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
  515. package/skills/gdpr-gate/references/layers/frontend.md +249 -0
  516. package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
  517. package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
  518. package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
  519. package/skills/gdpr-gate/references/legal-consent.md +140 -0
  520. package/skills/gdpr-gate/references/non-negotiables.md +60 -0
  521. package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
  522. package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
  523. package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
  524. package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
  525. package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
  526. package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
  527. package/skills/gemini-imagegen/SKILL.md +283 -0
  528. package/skills/gemini-imagegen/requirements.txt +5 -0
  529. package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
  530. package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
  531. package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
  532. package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
  533. package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  534. package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
  535. package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
  536. package/skills/git-worktree/SKILL.md +534 -0
  537. package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
  538. package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
  539. package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
  540. package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
  541. package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
  542. package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
  543. package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
  544. package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
  545. package/skills/go/SKILL.md +54 -0
  546. package/skills/growth/SKILL.md +164 -0
  547. package/skills/harvest-debt/SKILL.md +78 -0
  548. package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
  549. package/skills/heal-skill/SKILL.md +173 -0
  550. package/skills/help/SKILL.md +46 -0
  551. package/skills/incident/NOTICE +39 -0
  552. package/skills/incident/SKILL.md +395 -0
  553. package/skills/incident/scripts/dry-run.sh +448 -0
  554. package/skills/incident/scripts/redact-engine.py +412 -0
  555. package/skills/incident/scripts/redact-sentinel.sh +44 -0
  556. package/skills/incident/templates/pir.md +139 -0
  557. package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
  558. package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
  559. package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
  560. package/skills/incident/test/fixtures/positive-corpus.md +87 -0
  561. package/skills/incident/test/redact-sentinel.test.sh +1420 -0
  562. package/skills/invoice/SKILL.md +206 -0
  563. package/skills/kb-glossary/SKILL.md +71 -0
  564. package/skills/kb-glossary/references/glossary-format.md +111 -0
  565. package/skills/kb-glossary/references/rejected-request-register.md +115 -0
  566. package/skills/kb-search/SKILL.md +276 -0
  567. package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
  568. package/skills/legal-audit/SKILL.md +161 -0
  569. package/skills/legal-generate/NOTICE +242 -0
  570. package/skills/legal-generate/SKILL.md +244 -0
  571. package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
  572. package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
  573. package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
  574. package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
  575. package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
  576. package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
  577. package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
  578. package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
  579. package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
  580. package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
  581. package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
  582. package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
  583. package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
  584. package/skills/linear-fetch/SKILL.md +247 -0
  585. package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
  586. package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
  587. package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
  588. package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
  589. package/skills/linear-fetch/test/parity.test.sh +112 -0
  590. package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
  591. package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
  592. package/skills/merge-pr/SKILL.md +668 -0
  593. package/skills/model-launch-review/SKILL.md +255 -0
  594. package/skills/model-launch-review/scripts/audit-models.sh +501 -0
  595. package/skills/one-shot/SKILL.md +316 -0
  596. package/skills/one-shot/references/token-discipline.md +74 -0
  597. package/skills/operator-bootstrap/SKILL.md +412 -0
  598. package/skills/operator-bootstrap/template.sh +439 -0
  599. package/skills/operator-digest/SKILL.md +287 -0
  600. package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
  601. package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
  602. package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
  603. package/skills/operator-rephrase/SKILL.md +98 -0
  604. package/skills/pencil-setup/SKILL.md +201 -0
  605. package/skills/pencil-setup/scripts/check_deps.sh +556 -0
  606. package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
  607. package/skills/pencil-setup/scripts/package-lock.json +1172 -0
  608. package/skills/pencil-setup/scripts/package.json +14 -0
  609. package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
  610. package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
  611. package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
  612. package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
  613. package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
  614. package/skills/plan/SKILL.md +1140 -0
  615. package/skills/plan/references/differential-migration-testing.md +185 -0
  616. package/skills/plan/references/plan-community-discovery.md +42 -0
  617. package/skills/plan/references/plan-founder-check.md +137 -0
  618. package/skills/plan/references/plan-functional-overlap.md +25 -0
  619. package/skills/plan/references/plan-host-fanout.md +51 -0
  620. package/skills/plan/references/plan-issue-templates.md +779 -0
  621. package/skills/plan/references/plan-network-outage-checklist.md +131 -0
  622. package/skills/plan/references/plan-scope-check.md +126 -0
  623. package/skills/plan/references/plan-sharp-edges.md +325 -0
  624. package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
  625. package/skills/plan/references/webapp-cwv-observability.md +143 -0
  626. package/skills/plan-review/SKILL.md +91 -0
  627. package/skills/plan-review/lib/named-panel.mjs +58 -0
  628. package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
  629. package/skills/postmerge/SKILL.md +642 -0
  630. package/skills/postmerge/references/deploy-status-debugging.md +138 -0
  631. package/skills/postmerge/references/graceful-degradation.md +20 -0
  632. package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
  633. package/skills/preflight/SKILL.md +1553 -0
  634. package/skills/preflight/references/check-13-founder-check.md +286 -0
  635. package/skills/preflight/scripts/founder-check.py +1640 -0
  636. package/skills/preflight/scripts/parse-form-a.awk +107 -0
  637. package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
  638. package/skills/product-roadmap/SKILL.md +357 -0
  639. package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
  640. package/skills/provision-cloudflare/SKILL.md +67 -0
  641. package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
  642. package/skills/provision-doppler/SKILL.md +58 -0
  643. package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
  644. package/skills/provision-github/SKILL.md +59 -0
  645. package/skills/provision-github/scripts/provision-github.sh +300 -0
  646. package/skills/provision-hetzner/SKILL.md +76 -0
  647. package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
  648. package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
  649. package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
  650. package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
  651. package/skills/qa/SKILL.md +263 -0
  652. package/skills/qa/references/browser-preflight.md +22 -0
  653. package/skills/questionnaire-generate/SKILL.md +328 -0
  654. package/skills/questionnaire-generate/references/questionnaire.template +60 -0
  655. package/skills/rclone/SKILL.md +162 -0
  656. package/skills/rclone/scripts/check_setup.sh +63 -0
  657. package/skills/release-announce/SKILL.md +65 -0
  658. package/skills/release-docs/SKILL.md +92 -0
  659. package/skills/reproduce-bug/SKILL.md +358 -0
  660. package/skills/resolve-debt/SKILL.md +85 -0
  661. package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
  662. package/skills/resolve-parallel/SKILL.md +45 -0
  663. package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
  664. package/skills/resolve-pr-parallel/SKILL.md +68 -0
  665. package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
  666. package/skills/resolve-todo-parallel/SKILL.md +57 -0
  667. package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
  668. package/skills/review/SKILL.md +1621 -0
  669. package/skills/review/references/anti-slop-scanner-hook.md +40 -0
  670. package/skills/review/references/defect-classes-migrations.md +9 -0
  671. package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
  672. package/skills/review/references/review-e2e-testing.md +116 -0
  673. package/skills/review/references/review-todo-structure.md +165 -0
  674. package/skills/review/references/risk-tier-and-fix-rounds.md +95 -0
  675. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  676. package/skills/review/references/ultrathink-phases.md +98 -0
  677. package/skills/review/references/wfs.md +6 -0
  678. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  679. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  680. package/skills/review/scripts/fix-round-seats.sh +197 -0
  681. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  682. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  683. package/skills/review/test/fix-round-seats.test.sh +237 -0
  684. package/skills/review/workflows/README.md +147 -0
  685. package/skills/review/workflows/review.workflow.js +667 -0
  686. package/skills/schedule/SKILL.md +796 -0
  687. package/skills/seo-aeo/SKILL.md +139 -0
  688. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  689. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  690. package/skills/ship/SKILL.md +3022 -0
  691. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  692. package/skills/ship/references/affected-gate-contract.md +115 -0
  693. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  694. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  695. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  696. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  697. package/skills/ship/references/decision-challenges-render.md +71 -0
  698. package/skills/ship/references/detached-battery-verdict.md +13 -0
  699. package/skills/ship/references/feature-tweet-draft.md +42 -0
  700. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  701. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  702. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  703. package/skills/ship/references/operator-holds.md +149 -0
  704. package/skills/ship/references/pipeline-tally-render.md +43 -0
  705. package/skills/ship/references/pr-overlap.md +153 -0
  706. package/skills/ship/references/queue-mode.md +7 -0
  707. package/skills/ship/references/ready-run-wait.md +36 -0
  708. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  709. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  710. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  711. package/skills/ship/references/supabase-column-probe.md +13 -0
  712. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  713. package/skills/ship/scripts/battery-owed.sh +403 -0
  714. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  715. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  716. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  717. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  718. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  719. package/skills/skill-creator/SKILL.md +299 -0
  720. package/skills/skill-creator/references/api-security.md +248 -0
  721. package/skills/skill-creator/references/authoring-levers.md +110 -0
  722. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  723. package/skills/skill-creator/references/best-practices.md +431 -0
  724. package/skills/skill-creator/references/common-patterns.md +639 -0
  725. package/skills/skill-creator/references/core-principles.md +193 -0
  726. package/skills/skill-creator/references/executable-code.md +188 -0
  727. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  728. package/skills/skill-creator/references/official-spec.md +193 -0
  729. package/skills/skill-creator/references/recommended-structure.md +180 -0
  730. package/skills/skill-creator/references/skill-structure.md +396 -0
  731. package/skills/skill-creator/references/using-scripts.md +122 -0
  732. package/skills/skill-creator/references/using-templates.md +120 -0
  733. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  734. package/skills/skill-creator/scripts/init_skill.py +322 -0
  735. package/skills/skill-creator/scripts/package_skill.py +110 -0
  736. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  737. package/skills/skill-creator/templates/router-skill.md +73 -0
  738. package/skills/skill-creator/templates/simple-skill.md +34 -0
  739. package/skills/skill-creator/workflows/add-reference.md +96 -0
  740. package/skills/skill-creator/workflows/add-script.md +104 -0
  741. package/skills/skill-creator/workflows/add-template.md +83 -0
  742. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  743. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  744. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  745. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  746. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  747. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  748. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  749. package/skills/skill-security-scan/SKILL.md +145 -0
  750. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  751. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  752. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  753. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  754. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  755. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  756. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  757. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  758. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  759. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  760. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  761. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  762. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  763. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  764. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  765. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  766. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  767. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  768. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  769. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  770. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  771. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  772. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  773. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  774. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  775. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  776. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  777. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  778. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  779. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  780. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  781. package/skills/social-distribute/SKILL.md +485 -0
  782. package/skills/spec-templates/SKILL.md +274 -0
  783. package/skills/sync/SKILL.md +49 -0
  784. package/skills/test-browser/SKILL.md +464 -0
  785. package/skills/test-browser/references/feature-map.md +161 -0
  786. package/skills/test-fix-loop/SKILL.md +159 -0
  787. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  788. package/skills/triage/SKILL.md +402 -0
  789. package/skills/trigger-cron/SKILL.md +136 -0
  790. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  791. package/skills/user-set-role/SKILL.md +147 -0
  792. package/skills/user-set-role/scripts/set-role.sh +218 -0
  793. package/skills/user-story-writer/SKILL.md +77 -0
  794. package/skills/ux-audit/SKILL.md +251 -0
  795. package/skills/ux-audit/references/finding.schema.json +62 -0
  796. package/skills/ux-audit/references/route-list.yaml +95 -0
  797. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  798. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  799. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  800. package/skills/work/SKILL.md +1479 -0
  801. package/skills/work/references/end-of-work-resume.md +7 -0
  802. package/skills/work/references/hook-test-main-cwd.md +24 -0
  803. package/skills/work/references/key-principles.md +83 -0
  804. package/skills/work/references/property-testing.md +122 -0
  805. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  806. package/skills/work/references/work-agent-teams.md +97 -0
  807. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  808. package/skills/work/references/work-lockfile-bumps.md +97 -0
  809. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  810. package/skills/work/references/work-subagent-fanout.md +61 -0
  811. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  812. package/skills/xcode-test/SKILL.md +360 -0
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env bash
2
+ # render-c4-model.sh — Render the compiled LikeC4 model artifact from a repo's .c4 sources.
3
+ #
4
+ # Usage: bash <plugin>/scripts/render-c4-model.sh [--root DIR] [--out PATH] [--help]
5
+ #
6
+ # Compiles every LikeC4 DSL source (*.c4) under <root>/knowledge-base/engineering/
7
+ # architecture/diagrams/ into the layouted model.likec4.json that the web Knowledge
8
+ # Base viewer renders at runtime (the browser ships @likec4/diagram WITHOUT the
9
+ # compiler, so the JSON must be precompiled and committed).
10
+ #
11
+ # PLUGIN-OWNED (ADR-235 amendment, #8542 follow-up). It lived at the Soleur repo's
12
+ # scripts/regenerate-c4-model.sh, which a self-hosted install does not have, so the
13
+ # merge resolver could never regenerate in a customer repo. That path is now a thin
14
+ # wrapper for this repo's own callers; this file is the one renderer.
15
+ #
16
+ # --root DIR The repository whose diagrams to render. Default: the git top level of
17
+ # the current directory. The CODE comes from beside this script; only the
18
+ # DATA comes from --root (ADR-179's code-root / data-root split).
19
+ # --out PATH Write the validated, canonicalized model to PATH instead of the tracked
20
+ # artifact. Used by plugins/soleur/test/c4-model-freshness.test.sh to render
21
+ # to a temp path with identical logic, then byte-diff against the committed
22
+ # artifact. Default: <root>/.../diagrams/model.likec4.json.
23
+ #
24
+ # Pinned to likec4@1.50.0 — MUST match apps/web-platform/Dockerfile +
25
+ # package.json @likec4/core/@likec4/diagram (guarded by c4-likec4-version-pin.test.ts).
26
+ # A CLI/client version skew silently desyncs the rendered diagram.
27
+ #
28
+ # BUMPING LIKEC4 — the version is half of a pair with LIKEC4_BEFORE. The version pins ONE
29
+ # package; `--before=<date>` resolves its ~190 transitive deps as of that date, so a
30
+ # tarball published minutes ago (which npm's CDN can 404, #9300) is never requested.
31
+ # 1. Pick the new version, then a date that is the day AFTER its publish day and >= 3 days
32
+ # old (a date-only --before is midnight UTC and EXCLUSIVE: a version published at 17:11Z
33
+ # on day D is invisible to --before=D and fails with ETARGET; claude-code 2.1.284 is a
34
+ # live example of that arithmetic, not a likec4 fact):
35
+ # npm view likec4@<version> time --json
36
+ # 2. Move LIKEC4_VERSION and LIKEC4_BEFORE together in EVERY site in one commit: this
37
+ # script, plugins/soleur/lib/c4-from-components.ts, the `Install likec4 CLI` steps
38
+ # in .github/workflows/ci.yml and main-health-monitor.yml, and the `cli-tools` stage
39
+ # of apps/web-platform/Dockerfile (the date is a literal there). Every one of those
40
+ # installs must be exactly `npm install -g likec4@<version> --before=<date>
41
+ # --ignore-scripts` (a Dockerfile one prefixed `RUN `): the tests exercise the binary a
42
+ # scripts-off install makes, so the shipped one must match. The claude-code install is the
43
+ # exception (its postinstall places the binary). Sweep with: git grep 'likec4@1\.'
44
+ # c4-likec4-version-pin.test.ts asserts parity, the age floor, the flag and the exact form.
45
+ # Deliberately version-only (no --before): package.json (installed by lock-based
46
+ # `npm ci --ignore-scripts`) and the interactive `validate` recipes in the architecture skill docs,
47
+ # which also run scripts-on (they are asserted for the version only).
48
+ # A claude-code bump needs no date (its tree is exact-pinned platform packages with
49
+ # nothing floating) but claude-cli-pin-knows-models.test.ts must stay green.
50
+ # Policy: the date moves with a likec4 bump, or sooner if a transitive advisory affects
51
+ # the CLI; the tree is otherwise frozen on purpose. A version bump that forgets the date
52
+ # fails the install with ETARGET (the registry knows publish times; the offline guard
53
+ # does not). A private registry mirror that serves metadata WITHOUT per-version publish
54
+ # times does not fail: npm silently ignores --before there (measured against
55
+ # npm-pick-manifest), so the pin is inert on that mirror and the tree floats again.
56
+ #
57
+ # Renders OFF-TREE to a temp path and validates structurally BEFORE publishing:
58
+ # `likec4 export json` exits 0 even on an unresolved-reference / empty model, so
59
+ # an exit-0 check is NOT proof of a good artifact — see learnings
60
+ # 2026-06-05-external-cli-exit-0-is-not-proof-validate-the-artifact.md and
61
+ # apps/web-platform/server/c4-render.ts. Three publish gates below: a clean
62
+ # diagnostic stream, a non-empty object-typed elements map, and a non-empty
63
+ # object-typed views map — so neither a broken .c4 source nor a failed layout
64
+ # can clobber the good committed artifact.
65
+ #
66
+ # WRITES EXACTLY ONE FILE, the output path. The merge resolver commits whatever this
67
+ # changes, and asserts nothing else moved (resolve-regenerable-conflicts.sh, D4).
68
+ #
69
+ # Idempotent: rerunning against unchanged sources produces byte-identical output.
70
+
71
+ set -euo pipefail
72
+
73
+ LIKEC4_VERSION="1.50.0"
74
+ LIKEC4_BEFORE="2026-09-28"
75
+
76
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
77
+ CANONICAL_CLI="$SCRIPT_DIR/../lib/c4-canonical-cli.mjs"
78
+ ROOT=""
79
+ OUT=""
80
+
81
+ while [[ $# -gt 0 ]]; do
82
+ case "$1" in
83
+ --help)
84
+ sed -n '2,/^$/s/^# \{0,1\}//p' "${BASH_SOURCE[0]}"
85
+ exit 0
86
+ ;;
87
+ --root)
88
+ [[ -n "${2:-}" ]] || { echo "ERROR: --root requires a DIR argument" >&2; exit 2; }
89
+ ROOT="$2"
90
+ shift 2
91
+ ;;
92
+ --out)
93
+ [[ -n "${2:-}" ]] || { echo "ERROR: --out requires a PATH argument" >&2; exit 2; }
94
+ OUT="$2"
95
+ shift 2
96
+ ;;
97
+ *)
98
+ echo "ERROR: unknown argument: $1 (try --help)" >&2
99
+ exit 2
100
+ ;;
101
+ esac
102
+ done
103
+
104
+ if [[ -z "$ROOT" ]]; then
105
+ ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" \
106
+ || { echo "ERROR: not inside a git work tree and no --root given" >&2; exit 2; }
107
+ fi
108
+ ROOT="$(cd "$ROOT" 2>/dev/null && pwd)" || { echo "ERROR: --root is not a directory" >&2; exit 2; }
109
+ DIAGRAMS_DIR="$ROOT/knowledge-base/engineering/architecture/diagrams"
110
+ [[ -n "$OUT" ]] || OUT="$DIAGRAMS_DIR/model.likec4.json"
111
+
112
+ if [[ ! -d "$DIAGRAMS_DIR" ]]; then
113
+ echo "ERROR: diagrams directory not found at $DIAGRAMS_DIR" >&2
114
+ exit 1
115
+ fi
116
+
117
+ # Guard: at least one DSL source. NOT "spec.c4 + model.c4 + views.c4": soleur:sync writes
118
+ # generated-components.c4, spec.c4 and views.c4 into a customer repo and never model.c4
119
+ # (that one belongs to soleur:architecture), so the all-three form refused every plainly
120
+ # synced repo. What makes a render trustworthy is the two gates below, not a file list.
121
+ # Every extension likec4 1.50.0 compiles, at any depth — likec4 walks the whole directory.
122
+ if [[ -z "$(find "$DIAGRAMS_DIR" -type f \( -name '*.c4' -o -name '*.likec4' -o -name '*.like-c4' \) -print -quit)" ]]; then
123
+ echo "ERROR: no .c4 source (*.c4, *.likec4 or *.like-c4) in $DIAGRAMS_DIR" >&2
124
+ exit 1
125
+ fi
126
+
127
+ [[ -f "$CANONICAL_CLI" ]] || { echo "ERROR: canonicalizer not found beside this script at $CANONICAL_CLI" >&2; exit 1; }
128
+
129
+ # A missing tool is a machine problem, not a fault in the .c4 source: name it (rc 2, like a usage error).
130
+ for _tool in jq node npx mktemp; do
131
+ command -v "$_tool" >/dev/null 2>&1 \
132
+ || { echo "ERROR: rendering the C4 model needs jq, node and npx on PATH; '$_tool' is missing" >&2; exit 2; }
133
+ done
134
+
135
+ TMP="$(mktemp -d)"
136
+ PUBLISH_TMP=""
137
+ trap 'rm -rf "$TMP"; [[ -n "$PUBLISH_TMP" ]] && rm -f "$PUBLISH_TMP"' EXIT
138
+ RENDER_LOG="$TMP/render.log"
139
+
140
+ # Render off-tree with the pinned CLI, capturing all diagnostics. A non-zero
141
+ # exit is a hard failure; but likec4 ALSO exits 0 on broken sources, so the
142
+ # exit code alone is never sufficient (see the three gates below).
143
+ # CI is UNSET for the child and colour forced off: under CI likec4 switches to a timestamped,
144
+ # ANSI-coloured reporter that the anchored DIAG_RE below cannot match, and a syntax error
145
+ # would then publish a truncated model at rc 0 (measured under CI=true). ANSI is also
146
+ # stripped from the log as a second line of defence.
147
+ if ! ( cd "$DIAGRAMS_DIR" && env -u CI -u FORCE_COLOR NO_COLOR=1 npx -y --ignore-scripts --before="${LIKEC4_BEFORE}" "likec4@${LIKEC4_VERSION}" export json --no-use-dot -o "$TMP/model.likec4.json" . ) >"$RENDER_LOG" 2>&1; then
148
+ echo "ERROR: likec4 export exited non-zero — refusing to overwrite $OUT" >&2
149
+ cat "$RENDER_LOG" >&2
150
+ exit 1
151
+ fi
152
+
153
+ # exit-0 is NOT proof. likec4@1.50.0 has TWO source-fault modes that both exit 0:
154
+ # (1) unresolved reference / missing spec.c4 -> an EMPTY-elements model
155
+ # (the #4966 case; see apps/web-platform/server/c4-render.ts).
156
+ # (2) a syntax error -> likec4 recovers by dropping the bad fragment, prints
157
+ # `Invalid <file>` + `Line N:` (or `Could not resolve …`), and STILL emits
158
+ # a non-empty (now-incomplete) model — so element-count alone misses it.
159
+ # Gate on ALL of: a clean diagnostic stream, a non-empty elements map, and a
160
+ # non-empty views map. Element-count is the version-robust backstop; the
161
+ # diagnostic grep catches mode (2); the views gate catches the container/
162
+ # graphviz-fallback shape (#8861). On error we never publish, so a broken .c4
163
+ # can never clobber the good committed artifact.
164
+ # Anchors keep the markers off the workspace-path line likec4 echoes (`workspace:
165
+ # /abs/path …`): `^Invalid ` and the indented `Line N:` form (` Line 274:`)
166
+ # can't match a repo path, so a checkout dir containing those substrings can't
167
+ # false-FAIL. `Could not resolve` is a distinctive likec4 phrase.
168
+ DIAG_RE='^([0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)? +[A-Z]+ +[^ ]+ +)?Invalid |Could not resolve|^[[:space:]]+Line [0-9]+:'
169
+ _esc="$(printf '\033')"
170
+ sed "s/${_esc}\[[0-9;]*m//g" "$RENDER_LOG" >"$RENDER_LOG.plain" && mv -f "$RENDER_LOG.plain" "$RENDER_LOG"
171
+ if grep -qE "$DIAG_RE" "$RENDER_LOG"; then
172
+ echo "ERROR: likec4 reported a source validation error — refusing to overwrite $OUT" >&2
173
+ grep -E "$DIAG_RE" "$RENDER_LOG" >&2
174
+ echo " Fix the .c4 source (run: cd $DIAGRAMS_DIR && npx -y likec4@${LIKEC4_VERSION} validate --no-use-dot .)" >&2
175
+ exit 1
176
+ fi
177
+ if ! jq -e '(.elements | objects | length) > 0' "$TMP/model.likec4.json" >/dev/null 2>&1; then
178
+ echo "ERROR: likec4 produced an empty/degenerate model — refusing to overwrite $OUT" >&2
179
+ echo " Fix the .c4 source (run: cd $DIAGRAMS_DIR && npx -y likec4@${LIKEC4_VERSION} validate --no-use-dot .)" >&2
180
+ exit 1
181
+ fi
182
+ # Elements-but-no-views is OUR layout failing, never the user's source (#8740):
183
+ # a successful layout always emits at least `index`, even with no `views {}`
184
+ # block. `objects | length` shares the server's plain-object semantics — a
185
+ # non-object `views` (string/array) counts 0 here as it does in
186
+ # c4ModelCounts/plainObjectSize — so a malformed export is refused, not
187
+ # published. Keep both writers' predicates strict in lockstep.
188
+ if ! jq -e '(.views | objects | length) > 0' "$TMP/model.likec4.json" >/dev/null 2>&1; then
189
+ echo "ERROR: likec4 produced a model with elements but no views — a layout failure, not a .c4 source fault — refusing to overwrite $OUT" >&2
190
+ tail -20 "$RENDER_LOG" >&2
191
+ echo " Do NOT edit the .c4 source: retry the render; if it persists, reproduce with: cd $DIAGRAMS_DIR && npx -y likec4@${LIKEC4_VERSION} export json --no-use-dot ." >&2
192
+ exit 1
193
+ fi
194
+
195
+ # Canonicalize AFTER all gates (never instead of them): one JSON value per
196
+ # line with every view `hash` blanked, so git can merge two regenerations whose
197
+ # edits touch different values (ADR-235, #8542). Node serializes, never jq —
198
+ # jq reformats numbers. The web app (c4-render.ts) and the plugin
199
+ # (generate-c4-from-components.ts) emit these same bytes through the same
200
+ # module, so no writer reformats another's file.
201
+ if ! node "$CANONICAL_CLI" "$TMP/model.likec4.json" >"$TMP/canonical.json"; then
202
+ echo "ERROR: could not canonicalize the rendered model — refusing to overwrite $OUT" >&2
203
+ exit 1
204
+ fi
205
+
206
+ # Publish only on success, atomically: copy into the destination directory then
207
+ # rename. An intra-filesystem rename is atomic, so a crash mid-write can never
208
+ # leave a truncated model.likec4.json on the tracked path (a bare `cp` onto $OUT
209
+ # is not atomic). The temp lands beside $OUT (a dotfile, never a tracked .c4) so
210
+ # the rename stays on one filesystem; the EXIT trap reaps it if cp/mv aborts.
211
+ OUT_DIR="$(dirname "$OUT")"
212
+ mkdir -p "$OUT_DIR"
213
+ PUBLISH_TMP="$(mktemp "$OUT_DIR/.model.likec4.json.XXXXXX")"
214
+ cp "$TMP/canonical.json" "$PUBLISH_TMP"
215
+ mv -f "$PUBLISH_TMP" "$OUT"
216
+ PUBLISH_TMP="" # renamed onto $OUT — nothing left for the trap to clean
217
+ echo "Regenerated $OUT ($(jq '.elements | length' "$OUT") elements, $(jq '.relations | length' "$OUT") relations, $(jq '.views | length' "$OUT") views)"
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # resolve-git-root.sh -- Sourceable helper to detect bare repos and resolve GIT_ROOT
4
+ #
5
+ # Usage: source this file. It sets GIT_ROOT, GIT_COMMON_ROOT, and IS_BARE.
6
+ # Do NOT execute directly.
7
+ #
8
+ # Variables set:
9
+ # GIT_ROOT -- absolute path to the repository root (bare or non-bare)
10
+ # GIT_COMMON_ROOT -- absolute path to the shared repo root across all worktrees
11
+ # (equals GIT_ROOT when not in a worktree)
12
+ # IS_BARE -- "true" or "false"
13
+ #
14
+ # On error (not inside a git repo), returns 1 without calling exit.
15
+ # Does not call set or modify the caller's shell options.
16
+
17
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
18
+ echo "Error: resolve-git-root.sh must be sourced, not executed." >&2
19
+ echo "Usage: source path/to/resolve-git-root.sh" >&2
20
+ exit 1
21
+ fi
22
+
23
+ IS_BARE=false
24
+ if [[ "$(git rev-parse --is-bare-repository 2>/dev/null)" == "true" ]]; then
25
+ IS_BARE=true
26
+ _resolve_git_dir=$(git rev-parse --absolute-git-dir 2>/dev/null)
27
+ if [[ "$_resolve_git_dir" == */.git ]]; then
28
+ GIT_ROOT="${_resolve_git_dir%/.git}"
29
+ else
30
+ GIT_ROOT="$_resolve_git_dir"
31
+ fi
32
+ unset _resolve_git_dir
33
+ else
34
+ GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || {
35
+ echo "Error: Not inside a git repository." >&2
36
+ return 1
37
+ }
38
+ fi
39
+
40
+ # Validate that GIT_ROOT resolves to an actual directory
41
+ if [[ ! -d "$GIT_ROOT" ]]; then
42
+ echo "Error: GIT_ROOT resolved to non-existent path: $GIT_ROOT" >&2
43
+ return 1
44
+ fi
45
+
46
+ # Resolve common root (shared across worktrees)
47
+ # git rev-parse --git-common-dir returns the shared .git dir; may be relative,
48
+ # so cd+pwd resolves to absolute. Strip trailing /.git for the repo root.
49
+ _resolve_common_dir=$(cd "$(git rev-parse --git-common-dir 2>/dev/null)" && pwd)
50
+ if [[ "$_resolve_common_dir" == */.git ]]; then
51
+ GIT_COMMON_ROOT="${_resolve_common_dir%/.git}"
52
+ else
53
+ GIT_COMMON_ROOT="$_resolve_common_dir"
54
+ fi
55
+ unset _resolve_common_dir
@@ -0,0 +1,363 @@
1
+ #!/usr/bin/env bash
2
+ # resolve-regenerable-conflicts.sh — complete a merge whose ONLY conflicts are on generated
3
+ # artifacts, by regenerating them from the merged sources.
4
+ #
5
+ # Usage: bash "${CLAUDE_PLUGIN_ROOT}/scripts/resolve-regenerable-conflicts.sh" <base-ref>
6
+ # (run from inside the repository being merged)
7
+ #
8
+ # WHY THIS EXISTS (#8377, ADR-235). A generated file that is COMMITTED conflicts with every
9
+ # other branch that regenerates it, and side-picking is always wrong: `--ours` and `--theirs`
10
+ # each produce an artifact that matches neither side's sources. The correct resolution is to
11
+ # take the merged SOURCES and re-run the generator over them. The one such product is
12
+ # knowledge-base/engineering/architecture/diagrams/model.likec4.json, which the web-platform C4
13
+ # viewer fetches as a committed blob (apps/web-platform/app/api/kb/c4/project/route.ts).
14
+ #
15
+ # ── THE CONTRACT: TWO OUTCOMES ─────────────────────────────────────────────────────────────
16
+ # exit 0 the merge completed and was COMMITTED. The caller may push.
17
+ # exit non-0 nothing was touched. The tree is byte-identical to entry.
18
+ # Every exit prints one stdout line `SOLEUR_REGEN_ON_CONFLICT … rc=N` (rc=1 carries
19
+ # class=na|failed|interrupted and a reason slug) and, on refusal, one human line on stderr
20
+ # prefixed `[regen-on-conflict]` naming the next action.
21
+ #
22
+ # ── HOW: RENDER FROM GIT OBJECTS FIRST, TOUCH THE WORKTREE LAST (ADR-235 amendment 2026-09-23)
23
+ # 1. `git merge-tree` computes the merge without touching anything and yields the merged TREE.
24
+ # 2. The tracked, cleanly-merged LikeC4 sources are copied out of that tree's OBJECTS into a
25
+ # private staging dir, and the renderer runs there. Nothing untracked, ignored, symlinked
26
+ # or configured in the worktree can reach the render, and the renderer cannot write the
27
+ # worktree. Every render failure, timeout or kill therefore happens with the tree untouched.
28
+ # 3. Only then: re-check nothing moved, `git merge --no-commit`, write the rendered bytes,
29
+ # assert the index is exactly the merged tree plus those bytes, commit, and assert no commit
30
+ # hook changed the result.
31
+ #
32
+ # NEVER PUSHES — callers own the push. NO LOCK — per-worktree index/HEAD/MERGE_HEAD serialise
33
+ # runs within a worktree; the HEAD and clean-tree re-checks make a lost race refuse.
34
+ set -uo pipefail
35
+
36
+ # The PLUGIN directory: this script's own, made absolute before any `cd` (ADR-179 A17).
37
+ _plugin_scripts_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd -P)" || _plugin_scripts_dir=""
38
+ readonly PLUGIN_SCRIPTS_DIR="$_plugin_scripts_dir"
39
+
40
+ # Shared context-sanitize lib (#10395), beside this script under lib/. When it
41
+ # is unreadable the same-name fallbacks carry each site's pre-change strip set —
42
+ # never weaker than today.
43
+ _ctx_lib="${PLUGIN_SCRIPTS_DIR:-/nonexistent}/lib/context-sanitize.sh"
44
+ # shellcheck source=/dev/null
45
+ [[ -r "$_ctx_lib" ]] && . "$_ctx_lib" || true
46
+ declare -F soleur_ctx_sanitize >/dev/null 2>&1 \
47
+ || soleur_ctx_sanitize() { LC_ALL=C tr -d '\000-\037\177'; }
48
+ declare -F soleur_ctx_sanitize_nl >/dev/null 2>&1 \
49
+ || soleur_ctx_sanitize_nl() { LC_ALL=C tr -d '\000-\011\013-\037\177'; }
50
+ # The REPO: the caller's, from the CWD — never BASH_SOURCE/../.., which is the plugin.
51
+ REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
52
+
53
+ # The render budget, matching generate-c4-from-components.ts (a cold npx install measured 151s).
54
+ REGEN_TIMEOUT_S=600
55
+ BASE=""; BASE_SHA=""; HEAD_SHA=""; ARM=""; ROOT_SRC="-"
56
+ WORK=""; RENDER_PID=""; MERGING=0
57
+
58
+ # One line per exit for machines (stdout), one for humans (stderr).
59
+ _marker() { printf 'SOLEUR_REGEN_ON_CONFLICT rc=1 class=%s reason=%s\n' "$1" "$2"; }
60
+ # Strip control characters: the tail of a renderer log is attacker-influenced text.
61
+ _clean() { soleur_ctx_sanitize_nl | tail -n 4 | tr '\n' '|' | sed 's/|$//; s/|/ | /g'; }
62
+
63
+ # na <slug> <message> — refuse before anything was touched.
64
+ na() { _marker na "$1"; echo "[regen-on-conflict] not applicable: $2" >&2; exit 1; }
65
+ # fail <slug> <message> — a regeneration problem, still before anything was touched.
66
+ fail() { _marker failed "$1"; echo "[regen-on-conflict] regen failed: $2" >&2; exit 1; }
67
+ # bail <slug> <message> — refuse AFTER the merge started: unwind, and VERIFY the unwind.
68
+ # BAIL_CLASS is `failed` except for a signal, which reports `interrupted` wherever it lands.
69
+ BAIL_CLASS=failed
70
+ bail() {
71
+ _marker "$BAIL_CLASS" "$1"
72
+ local unwound="merge aborted, nothing committed"
73
+ [[ -n "$REPO_ROOT" ]] && git -C "$REPO_ROOT" merge --abort 2>/dev/null
74
+ if [[ -n "$REPO_ROOT" && -f "$(git -C "$REPO_ROOT" rev-parse --git-dir 2>/dev/null)/MERGE_HEAD" ]]; then
75
+ unwound="could NOT unwind: a merge is still in progress — run: git merge --abort"
76
+ fi
77
+ echo "[regen-on-conflict] regen failed: $2 — $unwound" >&2
78
+ exit 1
79
+ }
80
+
81
+ # Canonical copy of test-helpers.sh's assert_fixture_dir (P1a pins every tracked copy byte-equal;
82
+ # the P1b scanner recognises only this name). Here it backstops the staging parent, which the
83
+ # explicit `case` before it already refuses with a marker — its bare exit 2 is not reached.
84
+ assert_fixture_dir() {
85
+ case "${1-}" in
86
+ "") printf 'FATAL: fixture dir is EMPTY; git -C "" would operate on %s\n' "$PWD" >&2; exit 2 ;;
87
+ */../*|*/..) printf 'FATAL: fixture dir %s contains ..; refusing\n' "$1" >&2; exit 2 ;;
88
+ /proc/*|/sys/*|/dev/*) printf 'FATAL: fixture dir %s is a synthetic-fs path; refusing\n' "$1" >&2; exit 2 ;;
89
+ /|//|/.) printf 'FATAL: fixture dir resolves to the filesystem root; refusing\n' >&2; exit 2 ;;
90
+ /*) : ;;
91
+ *) printf 'FATAL: fixture dir %s is RELATIVE; refusing\n' "$1" >&2; exit 2 ;;
92
+ esac
93
+ }
94
+
95
+ _cleanup() {
96
+ [[ -n "$RENDER_PID" ]] && kill -TERM "$RENDER_PID" 2>/dev/null
97
+ [[ -n "$WORK" && -d "$WORK" ]] && rm -rf -- "$WORK"
98
+ }
99
+ _on_signal() {
100
+ if [[ "$MERGING" -eq 1 ]]; then
101
+ BAIL_CLASS=interrupted; bail interrupted "interrupted during the merge"
102
+ fi
103
+ _cleanup
104
+ _marker interrupted signal
105
+ echo "[regen-on-conflict] interrupted — nothing was touched; re-run when ready" >&2
106
+ exit 1
107
+ }
108
+ trap _cleanup EXIT
109
+ trap _on_signal INT TERM HUP
110
+
111
+ [[ -n "$REPO_ROOT" ]] || na not-a-repo "not inside a git work tree — cd into the repository being merged and re-run"
112
+
113
+ # plugin_root -> sets PLUGIN_ROOT and ROOT_SRC (no subshell, so both survive), or returns 1 with
114
+ # the reason in PLUGIN_ROOT_WHY. The sibling wins; a bare ${CLAUDE_PLUGIN_ROOT}
115
+ # (no `:-`, ADR-179 A12) is read only when it is absent. The plugin.json check is a sanity
116
+ # check, not a boundary (ADR-179 A11, A17).
117
+ PLUGIN_ROOT=""; PLUGIN_ROOT_WHY=""
118
+ plugin_root() {
119
+ local root=""
120
+ if [[ -n "$PLUGIN_SCRIPTS_DIR" && -f "$PLUGIN_SCRIPTS_DIR/render-c4-model.sh" ]]; then
121
+ root="$(cd "$PLUGIN_SCRIPTS_DIR/.." 2>/dev/null && pwd -P)" || root=""
122
+ ROOT_SRC="sibling"
123
+ elif [[ -n "${CLAUDE_PLUGIN_ROOT+set}" && "${CLAUDE_PLUGIN_ROOT}" == /* ]]; then
124
+ root="$(cd "${CLAUDE_PLUGIN_ROOT}" 2>/dev/null && pwd -P)" || root=""
125
+ ROOT_SRC="env"
126
+ if [[ -z "$root" || ! -f "$root/scripts/render-c4-model.sh" ]]; then
127
+ PLUGIN_ROOT_WHY="CLAUDE_PLUGIN_ROOT=${CLAUDE_PLUGIN_ROOT} has no scripts/render-c4-model.sh"
128
+ return 1
129
+ fi
130
+ else
131
+ PLUGIN_ROOT_WHY="no render-c4-model.sh beside this resolver and no absolute CLAUDE_PLUGIN_ROOT"
132
+ return 1
133
+ fi
134
+ [[ -n "$root" ]] || { PLUGIN_ROOT_WHY="could not resolve the plugin root"; return 1; }
135
+ if ! grep -q '"name"[[:space:]]*:[[:space:]]*"soleur"' "$root/.claude-plugin/plugin.json" 2>/dev/null; then
136
+ PLUGIN_ROOT_WHY="$root/.claude-plugin/plugin.json does not name soleur"
137
+ return 1
138
+ fi
139
+ PLUGIN_ROOT="$root"
140
+ }
141
+
142
+ # ── THE RESOLVABLE SET ─────────────────────────────────────────────────────────────────────
143
+ # One hardcoded member, not a manifest (ADR-235: a manifest is a parse surface and invites
144
+ # re-tracking generated files). The test seam is ARGV-only (--test-resolvable <tsv>): an
145
+ # inherited env var reaching an unattended commit was a demonstrated command channel (#8384).
146
+ # Each argv-producing line carries an ARGV-SOURCE marker; the suite pins the set. An arm's argv
147
+ # is a PREFIX: the resolver appends `--root <staging> --out <file>`.
148
+ RESOLVABLE_PATHS=()
149
+ RESOLVABLE_ARGVS=() # one TAB-joined argv prefix per path, index-aligned with the above
150
+ if [[ "${1:-}" == "--test-resolvable" ]]; then
151
+ _tsv="${2:-}"
152
+ [[ -f "$_tsv" ]] || na bad-args "--test-resolvable: '$_tsv' is not a file"
153
+ while IFS=$'\t' read -r _p _rest; do
154
+ [[ -n "$_p" ]] || continue
155
+ RESOLVABLE_PATHS+=("$_p"); RESOLVABLE_ARGVS+=("$_rest") # ARGV-SOURCE: test-seam
156
+ done < "$_tsv"
157
+ shift 2
158
+ ARM="test-seam"
159
+ else
160
+ RESOLVABLE_PATHS=("knowledge-base/engineering/architecture/diagrams/model.likec4.json") # RESOLVABLE-SET: default
161
+ ARM="plugin"
162
+ fi
163
+
164
+ BASE="${1:-}"
165
+ [[ -n "$BASE" ]] || na bad-args "no base ref given — re-run as: resolve-regenerable-conflicts.sh <base-ref> (e.g. origin/main)"
166
+ cd "$REPO_ROOT" || na not-a-repo "cannot enter repo root $REPO_ROOT"
167
+ BASE_SHA="$(git rev-parse --verify --quiet "$BASE^{commit}")" \
168
+ || na bad-base "base ref '$BASE' does not resolve to a commit — git fetch it first"
169
+ HEAD_SHA="$(git rev-parse --verify --quiet HEAD)" || na no-head "HEAD does not resolve to a commit"
170
+
171
+ # _clean_or_why -> empty when the tree is clean for our purposes, else the reason.
172
+ # MERGE_HEAD first (its remedy differs). `-uall` so status.showUntrackedFiles=no cannot hide an
173
+ # untracked file; `--ignored` is NOT used — ignored files are invisible to the merge unless the
174
+ # merged tree adds the same path, which _collisions checks.
175
+ _clean_or_why() {
176
+ [[ ! -f "$(git rev-parse --git-dir)/MERGE_HEAD" ]] || { printf 'a merge is already in progress — finish it or run git merge --abort'; return; }
177
+ local st; st="$(git status --porcelain --untracked-files=all)"
178
+ [[ -z "$st" ]] || printf 'working tree is not clean (%s) — commit or discard your changes' \
179
+ "$(printf '%s\n' "$st" | head -n1 | cut -c4- | soleur_ctx_sanitize | cut -c1-200)"
180
+ }
181
+ _why="$(_clean_or_why)"; [[ -z "$_why" ]] || na dirty-tree "$_why, then re-run"
182
+
183
+ # ── CLASSIFY: merge-tree, NUL-framed ───────────────────────────────────────────────────────
184
+ # A relative XDG_CACHE_HOME is invalid and ignored (XDG Base Directory spec): relative to which cwd?
185
+ _cache="${XDG_CACHE_HOME:-}"; [[ "$_cache" == /* ]] || _cache="${HOME:-/nonexistent}/.cache"
186
+ case "$_cache" in
187
+ */../*|*/..|/proc/*|/sys/*|/dev/*|/|//|/.) fail no-staging "unusable cache dir for staging ($_cache) — set XDG_CACHE_HOME to a normal absolute directory" ;;
188
+ /*) : ;;
189
+ *) fail no-staging "HOME is not an absolute path ($_cache)" ;;
190
+ esac
191
+ assert_fixture_dir "$_cache"
192
+ WORK_PARENT="$_cache/soleur"
193
+ if mkdir -p "$WORK_PARENT" 2>/dev/null && chmod 700 "$WORK_PARENT" 2>/dev/null && WORK="$(mktemp -d "$WORK_PARENT/regen.XXXXXX")"; then :
194
+ else fail no-staging "cannot create a private staging dir under $WORK_PARENT"; fi
195
+ chmod 700 "$WORK"
196
+
197
+ mt_rc=0
198
+ git merge-tree --write-tree -z --name-only "$BASE_SHA" "$HEAD_SHA" >"$WORK/mt" 2>"$WORK/mt.err" || mt_rc=$?
199
+ [[ "$mt_rc" -ne 0 ]] || na no-conflict "no conflict between HEAD and $BASE — nothing to resolve; merge it normally"
200
+ if [[ "$mt_rc" -ge 2 ]]; then
201
+ grep -q 'unknown option\|usage: git merge-tree' "$WORK/mt.err" 2>/dev/null \
202
+ && na old-git "git merge-tree --write-tree needs git >= 2.38 (you have $(git --version | cut -d' ' -f3)) — upgrade git, or resolve by hand"
203
+ na merge-tree-failed "git merge-tree failed (rc=$mt_rc): $(_clean <"$WORK/mt.err")"
204
+ fi
205
+
206
+ # Records: <tree> NUL, conflicted paths NUL…, empty NUL, then messages as
207
+ # <N> NUL <N paths> NUL <type> NUL <text> NUL. Only a CONFLICT (contents) is resolvable: every
208
+ # other kind (modify/delete, rename/rename, add/add, distinct types) decides whether a file
209
+ # should EXIST, which regenerating cannot answer.
210
+ TREE=""; conflicted=(); content_ok=$'\x1f'
211
+ _state=tree; _n=0; _mpaths=()
212
+ while IFS= read -r -d '' rec; do
213
+ case "$_state" in
214
+ tree) TREE="$rec"; _state=paths ;;
215
+ paths) if [[ -z "$rec" ]]; then _state=count; else conflicted+=("$rec"); fi ;;
216
+ count)
217
+ _n="$rec"; _mpaths=()
218
+ [[ "$_n" =~ ^[0-9]+$ ]] || na merge-tree-format "unparseable merge-tree output"
219
+ if [[ "$_n" -eq 0 ]]; then _state="type"; else _state="mpath"; fi ;;
220
+ mpath) _mpaths+=("$rec"); [[ "${#_mpaths[@]}" -lt "$_n" ]] || _state="type" ;;
221
+ type) _type="$rec"; _state=text ;;
222
+ text)
223
+ case "$_type" in
224
+ "CONFLICT (contents)") for _mp in ${_mpaths[@]+"${_mpaths[@]}"}; do content_ok+="$_mp"$'\x1f'; done ;;
225
+ CONFLICT*) na unresolvable-kind "$(printf '%s' "$rec" | _clean) — resolve this merge by hand" ;;
226
+ esac
227
+ _state=count ;;
228
+ esac
229
+ done <"$WORK/mt"
230
+ [[ "$TREE" =~ ^[0-9a-f]{40,64}$ && "${#conflicted[@]}" -gt 0 ]] \
231
+ || na merge-tree-format "merge-tree reported rc=$mt_rc but no conflicted path was parsed"
232
+
233
+ _argv_for() { # <path> -> echoes the TAB-joined argv prefix, or returns 1
234
+ local i
235
+ for i in "${!RESOLVABLE_PATHS[@]}"; do
236
+ [[ "${RESOLVABLE_PATHS[$i]}" == "$1" ]] && { printf '%s' "${RESOLVABLE_ARGVS[$i]:-}"; return 0; }
237
+ done
238
+ return 1
239
+ }
240
+ for p in "${conflicted[@]}"; do
241
+ [[ "$content_ok" == *$'\x1f'"$p"$'\x1f'* ]] \
242
+ || na unresolvable-kind "$p is not a plain content conflict — resolve this merge by hand"
243
+ _argv_for "$p" >/dev/null || na not-regenerable "conflicted path is not regenerable: $p — resolve this merge by hand"
244
+ done
245
+
246
+ # The production arm is resolved only now that a regenerable conflict exists.
247
+ if [[ "$ARM" == "plugin" ]]; then
248
+ plugin_root \
249
+ || fail no-plugin-root "no usable Soleur plugin root ($PLUGIN_ROOT_WHY) — set CLAUDE_PLUGIN_ROOT to the installed plugin (the directory whose .claude-plugin/plugin.json names soleur) and re-run"
250
+ RESOLVABLE_ARGVS=("$(printf 'bash\t%s' "$PLUGIN_ROOT/scripts/render-c4-model.sh")") # ARGV-SOURCE: plugin
251
+ fi
252
+
253
+ # ── STAGE: tracked sources out of the merged tree's objects ────────────────────────────────
254
+ # Allowlist, not blocklist: only regular-file LikeC4 sources are copied. A symlink or gitlink
255
+ # anywhere under the directory, or a likec4 config (which likec4 would load, the js/ts forms as
256
+ # code), is REFUSED rather than skipped — rendering without it would not be the repo's model.
257
+ assert_fixture_dir "$_cache"; assert_fixture_dir "$REPO_ROOT" # re-stated for fixture-scan's window
258
+ STAGE="$WORK/root"; OUT="$WORK/out"; mkdir -p "$STAGE" "$OUT"
259
+ _staged_dirs=$'\x1f'
260
+ for p in "${conflicted[@]}"; do
261
+ _dir="$(dirname -- "$p")"
262
+ [[ "$_staged_dirs" == *$'\x1f'"$_dir"$'\x1f'* ]] && continue
263
+ _staged_dirs+="$_dir"$'\x1f'
264
+ git ls-tree -r -z --full-tree "$TREE" -- "$_dir/" >"$WORK/ls" 2>/dev/null \
265
+ || fail stage-failed "could not list $_dir in the merged tree"
266
+ while IFS= read -r -d '' ent; do
267
+ _meta="${ent%%$'\t'*}"; _path="${ent#*$'\t'}"
268
+ _mode="${_meta%% *}"; _obj="${_meta##* }"
269
+ case "/$_path/" in */../*|*/./*) na unsafe-path "refusing path $_path in the merged tree" ;; esac
270
+ case "$_mode" in
271
+ 120000) na symlink-source "$_path is a symlink in the merged tree — the renderer would follow it outside the merge; replace it with a regular file" ;;
272
+ 160000) na gitlink-source "$_path is a submodule in the merged tree — its sources are not part of the merge" ;;
273
+ esac
274
+ case "${_path##*/}" in
275
+ likec4.config.*|.likec4rc|.likec4.config.json)
276
+ na likec4-config "$_path would configure the render (the .js/.ts forms run as code) — regenerate by hand" ;;
277
+ esac
278
+ [[ "$_mode" == 100644 || "$_mode" == 100755 ]] || continue
279
+ case "$_path" in
280
+ *.c4|*.likec4|*.like-c4)
281
+ mkdir -p "$STAGE/$(dirname -- "$_path")"
282
+ git cat-file blob "$_obj" >"$STAGE/$_path" || fail stage-failed "could not read $_path from the merged tree"
283
+ chmod 600 "$STAGE/$_path" ;;
284
+ esac
285
+ done <"$WORK/ls"
286
+ done
287
+ for p in "${conflicted[@]}"; do
288
+ _m="$(git ls-tree -z --full-tree "$TREE" -- "$p" | cut -d' ' -f1)"
289
+ [[ "$_m" == 100644 || "$_m" == 100755 ]] || na not-a-file "$p is not a regular file in the merged tree — resolve this merge by hand"
290
+ done
291
+
292
+ # ── RENDER, in the background so a signal is handled at once ──────────────────────────────
293
+ _to=()
294
+ if command -v timeout >/dev/null 2>&1; then _to=(timeout -k 10 "$REGEN_TIMEOUT_S")
295
+ elif command -v gtimeout >/dev/null 2>&1; then _to=(gtimeout -k 10 "$REGEN_TIMEOUT_S"); fi
296
+ outs=()
297
+ for i in "${!conflicted[@]}"; do
298
+ p="${conflicted[$i]}"
299
+ IFS=$'\t' read -r -a _argv <<<"$(_argv_for "$p")"
300
+ [[ "${#_argv[@]}" -gt 0 ]] || fail empty-command "empty regeneration command for $p"
301
+ out="$OUT/$i"; outs+=("$out")
302
+ echo "[regen-on-conflict] regenerating $p (runs likec4 through npx; a cold cache takes minutes)" >&2
303
+ ${_to[@]+"${_to[@]}"} "${_argv[@]}" --root "$STAGE" --out "$out" >"$WORK/log.$i" 2>&1 &
304
+ RENDER_PID=$!
305
+ _rc=0; wait "$RENDER_PID" || _rc=$?
306
+ RENDER_PID=""
307
+ if [[ "$_rc" -ne 0 ]]; then
308
+ _w="exited $_rc"; [[ "$_rc" -eq 124 && "${#_to[@]}" -gt 0 ]] && _w="timed out after ${REGEN_TIMEOUT_S}s"
309
+ fail render-failed "the renderer $_w for $p: $(_clean <"$WORK/log.$i")"
310
+ fi
311
+ [[ -s "$out" ]] || fail no-output "the renderer did not produce $p"
312
+ ! grep -qE '^(<{7}|={7}|>{7})( |$)' -- "$out" || fail markers "the rendered $p still contains conflict markers"
313
+ done
314
+
315
+ # ── APPLY: only now is the worktree touched ────────────────────────────────────────────────
316
+ [[ "$(git rev-parse --verify --quiet HEAD)" == "$HEAD_SHA" ]] \
317
+ || na head-moved "HEAD moved during the render — nothing was touched; re-run"
318
+ _why="$(_clean_or_why)"; [[ -z "$_why" ]] || na dirty-tree "the worktree changed during the render ($_why) — nothing was touched; re-run"
319
+ # A path the merge ADDS that exists on disk (untracked or ignored) would be overwritten.
320
+ while IFS= read -r -d '' _a; do
321
+ [[ -e "$_a" || -L "$_a" ]] && na would-overwrite "the merge adds $_a, which exists here untracked or ignored — move it aside and re-run"
322
+ done < <(git diff -z --name-only --diff-filter=A "$HEAD_SHA" "$TREE")
323
+
324
+ MERGING=1
325
+ merge_err="$(git merge --no-ff --no-commit -m "Merge $BASE (${BASE_SHA:0:12}); regenerated ${conflicted[*]}" "$BASE_SHA" 2>&1 >/dev/null)" || true
326
+ if [[ ! -f "$(git rev-parse --git-dir)/MERGE_HEAD" ]]; then
327
+ bail merge-not-started "the merge did not start: $(printf '%s' "${merge_err:-no output}" | _clean)"
328
+ fi
329
+ for i in "${!conflicted[@]}"; do
330
+ p="${conflicted[$i]}"
331
+ [[ ! -L "$p" ]] || bail symlink-artifact "refusing to write through symlink $p"
332
+ cp -- "$OUT/$i" "$REPO_ROOT/$p" && git add -- "$p" || bail stage-failed "could not write $p"
333
+ [[ "$(git rev-parse ":$p")" == "$(git hash-object --path="$p" -- "${outs[$i]}")" ]] \
334
+ || bail staged-mismatch "the staged $p is not the rendered bytes"
335
+ done
336
+ [[ -z "$(git diff --name-only --diff-filter=U)" ]] || bail residual-conflict "conflicts remain after regeneration"
337
+ # The index must be exactly the merged tree plus the regenerated paths — nothing else.
338
+ _want="$(printf '%s\n' "${conflicted[@]}" | LC_ALL=C sort)"
339
+ _got="$(git diff --cached -z --name-only "$TREE" | tr '\0' '\n' | LC_ALL=C sort)"
340
+ [[ "$_got" == "$_want" ]] || bail index-mismatch "the index differs from the merged tree beyond the regenerated paths: $(printf '%s' "$_got" | _clean)"
341
+
342
+ _expect_tree="$(git write-tree)" || bail write-tree "could not write the index tree"
343
+ # From here a signal is RECORDED, not acted on: the commit either lands or fails on its own, and
344
+ # the marker must describe the repo as it is. The default disposition would exit with no marker.
345
+ _sig_late=""
346
+ trap '_sig_late=1' INT TERM HUP
347
+ commit_err="$(git commit --no-edit 2>&1 >/dev/null)" \
348
+ || bail commit-failed "the merge commit failed: $(printf '%s' "$commit_err" | _clean)"
349
+ MERGING=0
350
+ if [[ "$(git rev-parse "HEAD^{tree}")" != "$_expect_tree" || "$(git rev-parse HEAD^1)" != "$HEAD_SHA" \
351
+ || "$(git rev-parse HEAD^2 2>/dev/null)" != "$BASE_SHA" ]]; then
352
+ _undone="it was undone"
353
+ if ! git reset -q --keep "$HEAD_SHA" 2>/dev/null || [[ "$(git rev-parse HEAD)" != "$HEAD_SHA" ]]; then
354
+ _undone="could NOT undo it (reset --keep refused; the hook left local edits) — HEAD is the rejected merge commit; review, then run: git reset --keep $HEAD_SHA"
355
+ fi
356
+ _marker failed commit-hook-changed-tree
357
+ echo "[regen-on-conflict] regen failed: a commit hook changed the merge commit — $_undone; resolve by hand" >&2
358
+ exit 1
359
+ fi
360
+ [[ -z "$_sig_late" ]] || echo "[regen-on-conflict] a signal arrived during git commit; the commit had already completed and is verified" >&2
361
+
362
+ csv="$(IFS=,; printf '%s' "${conflicted[*]}")"
363
+ printf 'SOLEUR_REGEN_ON_CONFLICT paths=%s arm=%s root_src=%s rc=0\n' "$csv" "$ARM" "$ROOT_SRC"