@getarbiter/cli 0.5.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 (989) hide show
  1. package/CHANGELOG.md +713 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +31 -0
  4. package/PRIVACY.md +111 -0
  5. package/README.md +237 -0
  6. package/THIRD_PARTY_LICENSES.md +472 -0
  7. package/dist/.src-manifest.json +1 -0
  8. package/dist/capabilities/host-probe.js +3 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +87 -0
  11. package/dist/commands/adopt-policy.js +3 -0
  12. package/dist/commands/configure-interactive.js +3 -0
  13. package/dist/commands/configure.js +5 -0
  14. package/dist/commands/cross-model-review.js +3 -0
  15. package/dist/commands/diff.js +20 -0
  16. package/dist/commands/doc-set.js +3 -0
  17. package/dist/commands/doctor/clean.js +2 -0
  18. package/dist/commands/doctor/fail-open-census.js +12 -0
  19. package/dist/commands/doctor/health.js +11 -0
  20. package/dist/commands/doctor/prove-gates.js +13 -0
  21. package/dist/commands/doctor/recover-lock.js +12 -0
  22. package/dist/commands/doctor/repair-state.js +6 -0
  23. package/dist/commands/doctor/tool-pin-extract.js +4 -0
  24. package/dist/commands/doctor/tool-pins.js +9 -0
  25. package/dist/commands/doctor-interactive.js +2 -0
  26. package/dist/commands/doctor.js +2 -0
  27. package/dist/commands/explain.js +19 -0
  28. package/dist/commands/gate-exec.js +4 -0
  29. package/dist/commands/gold-audit.js +14 -0
  30. package/dist/commands/graph.js +5 -0
  31. package/dist/commands/init/build-arbiter-config.js +1 -0
  32. package/dist/commands/init/generate.js +42 -0
  33. package/dist/commands/init/github-setup.js +5 -0
  34. package/dist/commands/init/maturity-gates.js +10 -0
  35. package/dist/commands/init/resolve-config.js +3 -0
  36. package/dist/commands/init/toolchain.js +10 -0
  37. package/dist/commands/init/types.js +1 -0
  38. package/dist/commands/init.js +17 -0
  39. package/dist/commands/method-interactive.js +4 -0
  40. package/dist/commands/method.js +11 -0
  41. package/dist/commands/obsidian.js +2 -0
  42. package/dist/commands/plugin.js +8 -0
  43. package/dist/commands/pr-merged.js +2 -0
  44. package/dist/commands/retire-policy.js +3 -0
  45. package/dist/commands/review-diff.js +3 -0
  46. package/dist/commands/settings.js +7 -0
  47. package/dist/commands/ship-config.js +2 -0
  48. package/dist/commands/ship-profile.js +2 -0
  49. package/dist/commands/ship-review.js +1 -0
  50. package/dist/commands/ship-tier.js +2 -0
  51. package/dist/commands/ship-train.js +2 -0
  52. package/dist/commands/task-mark.js +2 -0
  53. package/dist/commands/task-note.js +3 -0
  54. package/dist/commands/task-record-red.js +2 -0
  55. package/dist/commands/task-record-tech-debt.js +4 -0
  56. package/dist/commands/task-ship.js +3 -0
  57. package/dist/commands/task-state.js +6 -0
  58. package/dist/commands/task.js +59 -0
  59. package/dist/commands/update.js +60 -0
  60. package/dist/commands/upgrade-level-interactive.js +2 -0
  61. package/dist/commands/upgrade-level.js +7 -0
  62. package/dist/commands/verify-plan.js +8 -0
  63. package/dist/commands/verify-tdd.js +2 -0
  64. package/dist/commands/verify.js +7 -0
  65. package/dist/commands/wizard/coherence.js +1 -0
  66. package/dist/commands/worktree-prune.js +4 -0
  67. package/dist/commands/worktree.js +39 -0
  68. package/dist/compatibility/cross-language-matrix.json +540 -0
  69. package/dist/compatibility/index.d.ts +4 -0
  70. package/dist/compatibility/index.js +2 -0
  71. package/dist/compatibility/matcher.js +1 -0
  72. package/dist/compatibility/matrix.json +27 -0
  73. package/dist/compatibility/parsers.d.ts +38 -0
  74. package/dist/compatibility/parsers.js +1 -0
  75. package/dist/compatibility/probe.d.ts +41 -0
  76. package/dist/compatibility/probe.js +4 -0
  77. package/dist/compatibility/report.js +2 -0
  78. package/dist/compatibility/schema.d.ts +80 -0
  79. package/dist/compatibility/schema.js +1 -0
  80. package/dist/compatibility/skills-matrix.json +98 -0
  81. package/dist/compatibility/skills-validator.d.ts +30 -0
  82. package/dist/compatibility/skills-validator.js +4 -0
  83. package/dist/compatibility/tooling-proposals.json +5 -0
  84. package/dist/config/arbiter-ignore.js +3 -0
  85. package/dist/config/collaboration-mode-defaults.js +1 -0
  86. package/dist/config/diff.js +1 -0
  87. package/dist/config/env-overrides.js +3 -0
  88. package/dist/config/env-registry.js +2 -0
  89. package/dist/config/levels.js +1 -0
  90. package/dist/config/migrations/index.js +2 -0
  91. package/dist/config/migrations/v0-to-v1.js +2 -0
  92. package/dist/config/migrations/v1-to-v2.js +2 -0
  93. package/dist/config/migrations/v2-to-v3.js +2 -0
  94. package/dist/config/migrations/v3-to-v4.js +2 -0
  95. package/dist/config/override-resolver.js +2 -0
  96. package/dist/config/resolve-project-config.js +2 -0
  97. package/dist/config/resolve-project-name.js +2 -0
  98. package/dist/config/schema.d.ts +480 -0
  99. package/dist/config/schema.js +1 -0
  100. package/dist/config/test-pyramid-profiles.js +1 -0
  101. package/dist/config/thresholds.js +2 -0
  102. package/dist/conformance/dimensions.js +3 -0
  103. package/dist/conformance/engine.js +7 -0
  104. package/dist/conformance/gate-proofs.js +4 -0
  105. package/dist/conformance/shared.js +2 -0
  106. package/dist/detectors/axis.js +1 -0
  107. package/dist/detectors/build.js +2 -0
  108. package/dist/detectors/existing.js +2 -0
  109. package/dist/detectors/external-model.js +2 -0
  110. package/dist/detectors/framework.js +2 -0
  111. package/dist/detectors/git.js +11 -0
  112. package/dist/detectors/github.js +2 -0
  113. package/dist/detectors/lanes.js +5 -0
  114. package/dist/detectors/language-hooks.js +117 -0
  115. package/dist/detectors/language.js +2 -0
  116. package/dist/detectors/package-manager.js +2 -0
  117. package/dist/detectors/package.js +2 -0
  118. package/dist/detectors/scaffold-wiring.js +2 -0
  119. package/dist/detectors/workflow-collision.js +4 -0
  120. package/dist/evidence/gate-binding.js +4 -0
  121. package/dist/evidence/git-checks.js +3 -0
  122. package/dist/evidence/load.js +2 -0
  123. package/dist/evidence/provenance.js +2 -0
  124. package/dist/evidence/summary.js +2 -0
  125. package/dist/evidence/tdd-reexecute.js +2 -0
  126. package/dist/evidence/tdd.js +4 -0
  127. package/dist/experimental/index.js +2 -0
  128. package/dist/experimental/parse-argv.js +2 -0
  129. package/dist/experimental/registry.js +2 -0
  130. package/dist/generators/agents-claude.js +2 -0
  131. package/dist/generators/agents-md.js +2 -0
  132. package/dist/generators/anti-drift-validators.js +3 -0
  133. package/dist/generators/anti-proforma.js +2 -0
  134. package/dist/generators/api-e2e.js +2 -0
  135. package/dist/generators/api-middleware.js +2 -0
  136. package/dist/generators/archunit.js +2 -0
  137. package/dist/generators/audit-toolchain.js +2 -0
  138. package/dist/generators/auth.js +2 -0
  139. package/dist/generators/behavioral-tests.js +2 -0
  140. package/dist/generators/boundaries.js +2 -0
  141. package/dist/generators/check-all.js +2 -0
  142. package/dist/generators/check-stack-conformity.js +2 -0
  143. package/dist/generators/ci-five-lane.js +2 -0
  144. package/dist/generators/ci-tier.js +2 -0
  145. package/dist/generators/claude.js +3 -0
  146. package/dist/generators/codex-hooks.js +2 -0
  147. package/dist/generators/codex-known-limitations.js +2 -0
  148. package/dist/generators/codex.js +15 -0
  149. package/dist/generators/commit-footer.js +2 -0
  150. package/dist/generators/compliance-menu.js +2 -0
  151. package/dist/generators/compliance.js +2 -0
  152. package/dist/generators/conformance.js +2 -0
  153. package/dist/generators/contract-testing.js +2 -0
  154. package/dist/generators/coverage.js +2 -0
  155. package/dist/generators/debt-gates.js +24 -0
  156. package/dist/generators/debt-ratchet.js +2 -0
  157. package/dist/generators/derived-class.js +2 -0
  158. package/dist/generators/doc-set.js +4 -0
  159. package/dist/generators/docs.js +2 -0
  160. package/dist/generators/duplication.js +2 -0
  161. package/dist/generators/e2e-constitution.js +2 -0
  162. package/dist/generators/env-template.js +2 -0
  163. package/dist/generators/evidence-retention.js +2 -0
  164. package/dist/generators/feature-matrix.js +2 -0
  165. package/dist/generators/frontend-governance.js +2 -0
  166. package/dist/generators/frontend-quality.js +2 -0
  167. package/dist/generators/gap.js +2 -0
  168. package/dist/generators/gdpr.js +2 -0
  169. package/dist/generators/githooks.js +2 -0
  170. package/dist/generators/github-setup.js +2 -0
  171. package/dist/generators/github.js +2 -0
  172. package/dist/generators/gitignore.js +2 -0
  173. package/dist/generators/global-invariants.js +3 -0
  174. package/dist/generators/go-boundaries.js +2 -0
  175. package/dist/generators/gold-kit.js +2 -0
  176. package/dist/generators/infra.js +2 -0
  177. package/dist/generators/integration-testing.js +7 -0
  178. package/dist/generators/iso27001.js +2 -0
  179. package/dist/generators/iso9001.js +2 -0
  180. package/dist/generators/labels.js +2 -0
  181. package/dist/generators/local-wrapper.js +2 -0
  182. package/dist/generators/modulith.js +2 -0
  183. package/dist/generators/mutation.js +2 -0
  184. package/dist/generators/observability.js +2 -0
  185. package/dist/generators/operations.js +2 -0
  186. package/dist/generators/perf-k6.js +2 -0
  187. package/dist/generators/pharma.js +2 -0
  188. package/dist/generators/playwright-python.js +2 -0
  189. package/dist/generators/playwright-ts.js +2 -0
  190. package/dist/generators/pr-tooling.js +2 -0
  191. package/dist/generators/python-boundaries.js +2 -0
  192. package/dist/generators/quality.js +2 -0
  193. package/dist/generators/registry.js +2 -0
  194. package/dist/generators/regulated.js +2 -0
  195. package/dist/generators/resilience.js +2 -0
  196. package/dist/generators/risk-register.js +2 -0
  197. package/dist/generators/root.js +2 -0
  198. package/dist/generators/rust-boundaries.js +2 -0
  199. package/dist/generators/safety-class.js +2 -0
  200. package/dist/generators/security.js +2 -0
  201. package/dist/generators/seed.js +2 -0
  202. package/dist/generators/self-validation.js +2 -0
  203. package/dist/generators/ship-driver.js +2 -0
  204. package/dist/generators/skill-names.json +17 -0
  205. package/dist/generators/skills.js +2 -0
  206. package/dist/generators/smoke-journeys.js +2 -0
  207. package/dist/generators/solo-exception.js +2 -0
  208. package/dist/generators/ssot.js +2 -0
  209. package/dist/generators/stride-enforcement.js +2 -0
  210. package/dist/generators/suppressions.js +2 -0
  211. package/dist/generators/test-pyramid-manifest.js +3 -0
  212. package/dist/generators/test-taxonomy.js +2 -0
  213. package/dist/generators/wiki.js +2 -0
  214. package/dist/github/branch-protection.js +2 -0
  215. package/dist/github/classify-gh-error.js +2 -0
  216. package/dist/github/labels.js +2 -0
  217. package/dist/github/project-board.js +2 -0
  218. package/dist/graph/builders/adr.js +4 -0
  219. package/dist/graph/builders/ast.js +3 -0
  220. package/dist/graph/builders/canon.js +2 -0
  221. package/dist/graph/builders/evidence.js +2 -0
  222. package/dist/graph/builders/inv.js +1 -0
  223. package/dist/graph/builders/req.js +3 -0
  224. package/dist/graph/builders/test-nodes.js +3 -0
  225. package/dist/graph/builders/utils.js +2 -0
  226. package/dist/graph/load.js +2 -0
  227. package/dist/graph/model.js +2 -0
  228. package/dist/graph/query.js +3 -0
  229. package/dist/graph/store.js +1 -0
  230. package/dist/i18n/en.json +293 -0
  231. package/dist/i18n/index.js +4 -0
  232. package/dist/i18n/types.js +2 -0
  233. package/dist/integrations/companions.js +2 -0
  234. package/dist/integrations/external-review.js +10 -0
  235. package/dist/integrations/plugin-schema.js +2 -0
  236. package/dist/integrations/skill-detector.js +7 -0
  237. package/dist/integrations/skills-matrix.js +2 -0
  238. package/dist/integrations/types.d.ts +23 -0
  239. package/dist/integrations/types.js +2 -0
  240. package/dist/internal/cli-deprecation-registry.js +2 -0
  241. package/dist/internal/deprecate.js +3 -0
  242. package/dist/internal/experimental-warn.js +3 -0
  243. package/dist/invariants/catalog.d.ts +2 -0
  244. package/dist/invariants/catalog.js +1 -0
  245. package/dist/invariants/filter.d.ts +28 -0
  246. package/dist/invariants/filter.js +1 -0
  247. package/dist/invariants/index.d.ts +4 -0
  248. package/dist/invariants/index.js +2 -0
  249. package/dist/invariants/tiers.js +1 -0
  250. package/dist/invariants/types.d.ts +1 -0
  251. package/dist/invariants/types.js +1 -0
  252. package/dist/kit/applicability.js +3 -0
  253. package/dist/kit/audit-report.js +3 -0
  254. package/dist/kit/brownfield-detect.js +4 -0
  255. package/dist/kit/canonical-mapping.json +1 -0
  256. package/dist/kit/catalog.js +2 -0
  257. package/dist/kit/catalog.json +1 -0
  258. package/dist/kit/derived.json +1 -0
  259. package/dist/kit/emit-issues.js +8 -0
  260. package/dist/kit/measure.js +5 -0
  261. package/dist/kit/redaction.js +3 -0
  262. package/dist/kit/schema.js +2 -0
  263. package/dist/kit/taxonomy.js +2 -0
  264. package/dist/kit/thresholds.d.ts +12 -0
  265. package/dist/kit/thresholds.js +2 -0
  266. package/dist/kit/wave-engine.js +1 -0
  267. package/dist/recipes/loader.js +6 -0
  268. package/dist/recipes/schema.js +2 -0
  269. package/dist/risk/classifier.js +2 -0
  270. package/dist/risk/sha-check.js +2 -0
  271. package/dist/state/backups.js +2 -0
  272. package/dist/state/envelope.js +2 -0
  273. package/dist/state/generated-manifest.js +3 -0
  274. package/dist/state/manifest-key.js +2 -0
  275. package/dist/state/migrations/index.js +1 -0
  276. package/dist/state/migrations/v0-to-v1.js +2 -0
  277. package/dist/state/retired-renders.js +2 -0
  278. package/dist/templates/.nvmrc.ejs +1 -0
  279. package/dist/templates/HANDOFF.template.md +45 -0
  280. package/dist/templates/__tests__/contract/error-shape.contract.test.ts.ejs +47 -0
  281. package/dist/templates/agents-md/AGENTS.md.ejs +517 -0
  282. package/dist/templates/api-e2e/README.md.ejs +33 -0
  283. package/dist/templates/api-e2e/go-httptest.go.ejs +43 -0
  284. package/dist/templates/api-e2e/java-restassured.java.ejs +28 -0
  285. package/dist/templates/api-e2e/kotlin-restassured.kt.ejs +30 -0
  286. package/dist/templates/api-e2e/manifest.json.ejs +8 -0
  287. package/dist/templates/api-e2e/postman.collection.json.ejs +30 -0
  288. package/dist/templates/api-e2e/python-httpx.py.ejs +17 -0
  289. package/dist/templates/api-e2e/run.sh.ejs +61 -0
  290. package/dist/templates/api-e2e/ts-supertest.test.ts.ejs +18 -0
  291. package/dist/templates/archunit/AntiCyclicTest.java.ejs +29 -0
  292. package/dist/templates/archunit/AntiProformaExempt.java.ejs +35 -0
  293. package/dist/templates/archunit/AntiProformaTest.java.ejs +104 -0
  294. package/dist/templates/archunit/ArchitectureTest.java.ejs +87 -0
  295. package/dist/templates/archunit/DependencyFlowTest.java.ejs +55 -0
  296. package/dist/templates/archunit/DomainPurityTest.java.ejs +47 -0
  297. package/dist/templates/archunit/NamingConventionsTest.java.ejs +54 -0
  298. package/dist/templates/archunit/NoH2ArchTest.java.ejs +30 -0
  299. package/dist/templates/archunit/NoMockMvcTest.java.ejs +71 -0
  300. package/dist/templates/archunit/PortsIndependenceTest.java.ejs +55 -0
  301. package/dist/templates/archunit/RestAssuredArchTest.java.ejs +32 -0
  302. package/dist/templates/archunit/RestAssuredBaseIT.java.ejs +66 -0
  303. package/dist/templates/archunit/TestCoverageArchTest.java.ejs +29 -0
  304. package/dist/templates/archunit/arch-test-deps-maven.md.ejs +42 -0
  305. package/dist/templates/archunit/arch-test-deps.gradle.ejs +14 -0
  306. package/dist/templates/audit/gdpr/check-gdpr-controls.mjs.ejs +102 -0
  307. package/dist/templates/audit/gdpr/controls-to-gates.md.ejs +42 -0
  308. package/dist/templates/audit/gdpr/data-flow-map.md.ejs +30 -0
  309. package/dist/templates/audit/gdpr/dpia.md.ejs +45 -0
  310. package/dist/templates/audit/generic/audit-gate-rules.md.ejs +24 -0
  311. package/dist/templates/audit/generic/audit-trail-policy.md.ejs +38 -0
  312. package/dist/templates/audit/iso27001/iso27001-controls-gate-map.md.ejs +60 -0
  313. package/dist/templates/auth/setup.md.ejs +661 -0
  314. package/dist/templates/behavioral-tests/ExampleBehavioralTest.java.ejs +67 -0
  315. package/dist/templates/behavioral-tests/TESTING_POLICY.md.ejs +116 -0
  316. package/dist/templates/behavioral-tests/bdd/ExampleBddIT.java.ejs +19 -0
  317. package/dist/templates/behavioral-tests/bdd/ExampleSteps.java.ejs +61 -0
  318. package/dist/templates/behavioral-tests/bdd/example.feature.ejs +14 -0
  319. package/dist/templates/behavioral-tests/bdd/example.steps.ts.ejs +37 -0
  320. package/dist/templates/behavioral-tests/bdd/example_bdd_test.rs.ejs +64 -0
  321. package/dist/templates/behavioral-tests/bdd/example_test.go.ejs +80 -0
  322. package/dist/templates/behavioral-tests/bdd/test_example_bdd.py.ejs +47 -0
  323. package/dist/templates/behavioral-tests/eslint-playwright.json.ejs +10 -0
  324. package/dist/templates/behavioral-tests/eslint.config.playwright.mjs.ejs +29 -0
  325. package/dist/templates/behavioral-tests/example.behavioral.test.ts.ejs +47 -0
  326. package/dist/templates/behavioral-tests/example_behavioral_test.go.ejs +51 -0
  327. package/dist/templates/behavioral-tests/example_behavioral_test.rs.ejs +47 -0
  328. package/dist/templates/behavioral-tests/test_example_behavioral.py.ejs +40 -0
  329. package/dist/templates/boundaries/.eslintrc-boundaries.cjs.ejs +81 -0
  330. package/dist/templates/boundaries/.eslintrc-frontend-spa.cjs.ejs +79 -0
  331. package/dist/templates/boundaries/.importlinter.ejs +48 -0
  332. package/dist/templates/boundaries/check-boundaries-go.mjs.ejs +94 -0
  333. package/dist/templates/boundaries/check-boundaries-python.mjs.ejs +118 -0
  334. package/dist/templates/boundaries/check-boundaries-rust.mjs.ejs +111 -0
  335. package/dist/templates/boundaries/check-boundaries.mjs.ejs +34 -0
  336. package/dist/templates/boundaries/clippy.toml.ejs +50 -0
  337. package/dist/templates/boundaries/deny.toml.ejs +56 -0
  338. package/dist/templates/boundaries/eslint.config.boundaries.mjs.ejs +112 -0
  339. package/dist/templates/boundaries/eslint.config.frontend-spa.mjs.ejs +93 -0
  340. package/dist/templates/boundaries/golangci-boundaries.yml.ejs +70 -0
  341. package/dist/templates/boundaries/ruff-boundaries.toml.ejs +32 -0
  342. package/dist/templates/claude/CLAUDE.md.ejs +78 -0
  343. package/dist/templates/claude/agents/agent-write-classes.json +30 -0
  344. package/dist/templates/claude/agents/bridge-reviewer.md.ejs +68 -0
  345. package/dist/templates/claude/agents/codebase-scanner.md.ejs +69 -0
  346. package/dist/templates/claude/agents/context-checker.md.ejs +73 -0
  347. package/dist/templates/claude/agents/red-team.md.ejs +134 -0
  348. package/dist/templates/claude/commands/close-gold-gap.md.ejs +43 -0
  349. package/dist/templates/claude/commands/drain.md.ejs +81 -0
  350. package/dist/templates/claude/commands/gold-audit.md.ejs +43 -0
  351. package/dist/templates/claude/commands/impact.md.ejs +39 -0
  352. package/dist/templates/claude/commands/levelup.md.ejs +61 -0
  353. package/dist/templates/claude/commands/ship.md.ejs +902 -0
  354. package/dist/templates/claude/commands/tabletop.md.ejs +46 -0
  355. package/dist/templates/claude/commands/task.md.ejs +87 -0
  356. package/dist/templates/claude/commands/wt-close.md.ejs +58 -0
  357. package/dist/templates/claude/commands/wt-list.md.ejs +48 -0
  358. package/dist/templates/claude/commands/wt-open.md.ejs +61 -0
  359. package/dist/templates/claude/commands/wt-prune.md.ejs +38 -0
  360. package/dist/templates/claude/hooks/check-circular-deps.mjs.ejs +56 -0
  361. package/dist/templates/claude/hooks/check-no-orphan-todo.mjs.ejs +45 -0
  362. package/dist/templates/claude/hooks/check-no-pii.mjs.ejs +121 -0
  363. package/dist/templates/claude/hooks/check-no-placeholders.mjs.ejs +71 -0
  364. package/dist/templates/claude/hooks/check-no-skipped-tests.mjs +80 -0
  365. package/dist/templates/claude/hooks/check-no-unused-exports.mjs +62 -0
  366. package/dist/templates/claude/hooks/closer-mode-guard.mjs.ejs +102 -0
  367. package/dist/templates/claude/hooks/debug-state-on-failure.mjs.ejs +98 -0
  368. package/dist/templates/claude/hooks/enforce-gate-before-pr.mjs +142 -0
  369. package/dist/templates/claude/hooks/enforce-read-only.mjs +28 -0
  370. package/dist/templates/claude/hooks/exitplanmode-banner.mjs.ejs +43 -0
  371. package/dist/templates/claude/hooks/guard-done-evidence.mjs.ejs +85 -0
  372. package/dist/templates/claude/hooks/guard-task-completion.mjs.ejs +56 -0
  373. package/dist/templates/claude/hooks/hooks.mjs.ejs +127 -0
  374. package/dist/templates/claude/hooks/lib.mjs.ejs +523 -0
  375. package/dist/templates/claude/hooks/post-brainstorm-stop.mjs +48 -0
  376. package/dist/templates/claude/hooks/post-commit-check.mjs.ejs +65 -0
  377. package/dist/templates/claude/hooks/post-commit-checklists/go/backend.ejs +4 -0
  378. package/dist/templates/claude/hooks/post-commit-checklists/go/docs.ejs +4 -0
  379. package/dist/templates/claude/hooks/post-commit-checklists/go/frontend.ejs +4 -0
  380. package/dist/templates/claude/hooks/post-commit-checklists/java/backend.ejs +4 -0
  381. package/dist/templates/claude/hooks/post-commit-checklists/java/docs.ejs +4 -0
  382. package/dist/templates/claude/hooks/post-commit-checklists/java/frontend.ejs +4 -0
  383. package/dist/templates/claude/hooks/post-commit-checklists/python/backend.ejs +4 -0
  384. package/dist/templates/claude/hooks/post-commit-checklists/python/docs.ejs +4 -0
  385. package/dist/templates/claude/hooks/post-commit-checklists/python/frontend.ejs +4 -0
  386. package/dist/templates/claude/hooks/post-commit-checklists/rust/backend.ejs +5 -0
  387. package/dist/templates/claude/hooks/post-commit-checklists/rust/docs.ejs +4 -0
  388. package/dist/templates/claude/hooks/post-commit-checklists/rust/frontend.ejs +4 -0
  389. package/dist/templates/claude/hooks/post-commit-checklists/ts/backend.ejs +4 -0
  390. package/dist/templates/claude/hooks/post-commit-checklists/ts/docs.ejs +4 -0
  391. package/dist/templates/claude/hooks/post-commit-checklists/ts/frontend.ejs +5 -0
  392. package/dist/templates/claude/hooks/post-edit-dispatch.mjs.ejs +73 -0
  393. package/dist/templates/claude/hooks/post-subagent-release.mjs +80 -0
  394. package/dist/templates/claude/hooks/pre-compact.mjs.ejs +79 -0
  395. package/dist/templates/claude/hooks/pre-edit-plan-anchor.mjs.ejs +225 -0
  396. package/dist/templates/claude/hooks/pre-edit-ssot-guard.mjs +204 -0
  397. package/dist/templates/claude/hooks/pre-spawn-worktree-guard.mjs +129 -0
  398. package/dist/templates/claude/hooks/skill-forced-eval.mjs.ejs +281 -0
  399. package/dist/templates/claude/hooks/stop-dangerous.mjs +86 -0
  400. package/dist/templates/claude/hooks/stop-evidence-guard.mjs.ejs +245 -0
  401. package/dist/templates/claude/hooks/stop-finding-loss.mjs.ejs +168 -0
  402. package/dist/templates/claude/hooks/wiki-on-commit.mjs.ejs +38 -0
  403. package/dist/templates/claude/knowledge-map.json.ejs +26 -0
  404. package/dist/templates/claude/rules/05-agent-lifecycle.md +7 -0
  405. package/dist/templates/claude/rules/25-todo-folder-policy.md +5 -0
  406. package/dist/templates/claude/rules/40-context-economy.md +32 -0
  407. package/dist/templates/claude/rules/45-mcp-fallback.md +25 -0
  408. package/dist/templates/claude/rules/50-batch-execution.md +75 -0
  409. package/dist/templates/claude/rules/55-brainstorm-terminal-state.md +44 -0
  410. package/dist/templates/claude/rules/60-incidental-capture.md +43 -0
  411. package/dist/templates/claude/rules/75-impact-vault-reading.md +43 -0
  412. package/dist/templates/claude/rules/90-exec-protocol.md.ejs +40 -0
  413. package/dist/templates/claude/rules/95-closer-mode.md +45 -0
  414. package/dist/templates/claude/settings.json.ejs +165 -0
  415. package/dist/templates/claude/skills/architect-review/SKILL.md.ejs +82 -0
  416. package/dist/templates/claude/skills/brainstorming/SKILL.md.ejs +86 -0
  417. package/dist/templates/claude/skills/clean-code/SKILL.md.ejs +39 -0
  418. package/dist/templates/claude/skills/close-gold-gap/SKILL.md.ejs +58 -0
  419. package/dist/templates/claude/skills/codebase-audit/SKILL.md.ejs +88 -0
  420. package/dist/templates/claude/skills/configure/SKILL.md.ejs +72 -0
  421. package/dist/templates/claude/skills/epic-decompose/SKILL.md.ejs +86 -0
  422. package/dist/templates/claude/skills/gold-audit/SKILL.md.ejs +91 -0
  423. package/dist/templates/claude/skills/impact/SKILL.md.ejs +104 -0
  424. package/dist/templates/claude/skills/levelup/SKILL.md.ejs +146 -0
  425. package/dist/templates/claude/skills/tabletop/SKILL.md.ejs +118 -0
  426. package/dist/templates/claude/skills/tdd/SKILL.md.ejs +157 -0
  427. package/dist/templates/claude/skills/understand-code/SKILL.md.ejs +93 -0
  428. package/dist/templates/claude/skills/verification/SKILL.md.ejs +68 -0
  429. package/dist/templates/claude/skills/wave-drain/SKILL.md.ejs +491 -0
  430. package/dist/templates/codex/CODEX.md.ejs +140 -0
  431. package/dist/templates/codex/codex-adapter.mjs +132 -0
  432. package/dist/templates/codex/config.toml.ejs +189 -0
  433. package/dist/templates/compliance/compliance-mapping.md.ejs +124 -0
  434. package/dist/templates/compliance/compliance-menu.md.ejs +89 -0
  435. package/dist/templates/contract-testing/CONTRACTS_POLICY.md.ejs +30 -0
  436. package/dist/templates/contract-testing/api-snapshots/config-keys-baseline.json.ejs +1 -0
  437. package/dist/templates/contract-testing/api-snapshots/config-response-baseline.json.ejs +1 -0
  438. package/dist/templates/contract-testing/api-snapshots/enum-values-baseline.json.ejs +1 -0
  439. package/dist/templates/contract-testing/api-snapshots/error-shape-baseline.json.ejs +6 -0
  440. package/dist/templates/contract-testing/api-snapshots/openapi-baseline.json.ejs +12 -0
  441. package/dist/templates/contract-testing/api-snapshots/openapi-content-types-baseline.json.ejs +3 -0
  442. package/dist/templates/contract-testing/api-snapshots/openapi-paths-baseline.json.ejs +1 -0
  443. package/dist/templates/contract-testing/api-snapshots/openapi-required-fields-baseline.json.ejs +1 -0
  444. package/dist/templates/contract-testing/api-snapshots/openapi-response-status-baseline.json.ejs +3 -0
  445. package/dist/templates/contract-testing/api-snapshots/test-snapshot.json.ejs +4 -0
  446. package/dist/templates/contract-testing/env/.env.pact.ejs +4 -0
  447. package/dist/templates/contract-testing/graphql/GraphqlSchemaTest.java.ejs +29 -0
  448. package/dist/templates/contract-testing/graphql/graphql-inspector.test.ts.ejs +20 -0
  449. package/dist/templates/contract-testing/graphql/graphql_schema_test.go.ejs +27 -0
  450. package/dist/templates/contract-testing/graphql/graphql_schema_test.rs.ejs +27 -0
  451. package/dist/templates/contract-testing/graphql/test_graphql_schema.py.ejs +21 -0
  452. package/dist/templates/contract-testing/grpc/GrpcContractTest.java.ejs +23 -0
  453. package/dist/templates/contract-testing/grpc/buf-breaking.yml.ejs +6 -0
  454. package/dist/templates/contract-testing/grpc/buf.yaml.ejs +11 -0
  455. package/dist/templates/contract-testing/grpc/grpc-contract.test.ts.ejs +16 -0
  456. package/dist/templates/contract-testing/grpc/grpc_contract_test.go.ejs +22 -0
  457. package/dist/templates/contract-testing/grpc/grpc_contract_test.rs.ejs +22 -0
  458. package/dist/templates/contract-testing/grpc/test_grpc_contract.py.ejs +18 -0
  459. package/dist/templates/contract-testing/message-queue/SchemaRegistryCheckIT.java.ejs +44 -0
  460. package/dist/templates/contract-testing/message-queue/schema-registry-check.ts.ejs +42 -0
  461. package/dist/templates/contract-testing/message-queue/schema_registry_test.go.ejs +71 -0
  462. package/dist/templates/contract-testing/message-queue/schema_registry_test.rs.ejs +61 -0
  463. package/dist/templates/contract-testing/message-queue/test_schema_registry.py.ejs +31 -0
  464. package/dist/templates/contract-testing/pact-samples/assignment-response.json.ejs +7 -0
  465. package/dist/templates/contract-testing/pact-samples/availability-response.json.ejs +13 -0
  466. package/dist/templates/contract-testing/pact-samples/availability-rule-response.json.ejs +8 -0
  467. package/dist/templates/contract-testing/pact-samples/capacity-response.json.ejs +11 -0
  468. package/dist/templates/contract-testing/pact-samples/fully-booked-response.json.ejs +6 -0
  469. package/dist/templates/contract-testing/pact-samples/schedule-override-response.json.ejs +7 -0
  470. package/dist/templates/contract-testing/rest-owned/PactVerificationIT.java.ejs +31 -0
  471. package/dist/templates/contract-testing/rest-owned/pact-consumer.test.ts.ejs +36 -0
  472. package/dist/templates/contract-testing/rest-owned/pact-deps.gradle.ejs +15 -0
  473. package/dist/templates/contract-testing/rest-owned/pact_consumer_test.go.ejs +48 -0
  474. package/dist/templates/contract-testing/rest-owned/pact_consumer_test.rs.ejs +23 -0
  475. package/dist/templates/contract-testing/rest-owned/test_pact_consumer.py.ejs +35 -0
  476. package/dist/templates/contract-testing/rest-public/OpenApiDiffIT.java.ejs +44 -0
  477. package/dist/templates/contract-testing/rest-public/export-openapi-java.gradle.ejs +13 -0
  478. package/dist/templates/contract-testing/rest-public/export-openapi.mjs.ejs +21 -0
  479. package/dist/templates/contract-testing/rest-public/export_openapi.go.ejs +30 -0
  480. package/dist/templates/contract-testing/rest-public/export_openapi.py.ejs +27 -0
  481. package/dist/templates/contract-testing/rest-public/export_openapi.rs.ejs +32 -0
  482. package/dist/templates/contract-testing/rest-public/openapi-diff.ts.ejs +42 -0
  483. package/dist/templates/contract-testing/rest-public/openapi_diff_test.go.ejs +35 -0
  484. package/dist/templates/contract-testing/rest-public/openapi_diff_test.rs.ejs +36 -0
  485. package/dist/templates/contract-testing/rest-public/test_openapi_diff.py.ejs +32 -0
  486. package/dist/templates/coverage/.coveragerc.ejs +26 -0
  487. package/dist/templates/coverage/.tarpaulin.toml.ejs +30 -0
  488. package/dist/templates/coverage/Cargo.toml.profile.release.ejs +24 -0
  489. package/dist/templates/coverage/jacoco-maven-setup.md.ejs +72 -0
  490. package/dist/templates/coverage/jacoco.gradle.ejs +49 -0
  491. package/dist/templates/coverage/kover.gradle.ejs +35 -0
  492. package/dist/templates/coverage/vitest.browser.config.ts.ejs +47 -0
  493. package/dist/templates/coverage/vitest.config.ts.ejs +47 -0
  494. package/dist/templates/docs/CODING_STANDARDS.md.ejs +81 -0
  495. package/dist/templates/docs/FEATURE_MATRIX.md.ejs +84 -0
  496. package/dist/templates/docs/GAP.md.ejs +58 -0
  497. package/dist/templates/docs/ISO27001_ANNEX_A.md.ejs +144 -0
  498. package/dist/templates/docs/MASTER_TEST_PLAN.md.ejs +52 -0
  499. package/dist/templates/docs/POST_MERGE_REVIEW_TEMPLATE.md.ejs +63 -0
  500. package/dist/templates/docs/SECURE_CODING_CHECKLIST.md.ejs +61 -0
  501. package/dist/templates/docs/adr/ADR-000_template.md.ejs +28 -0
  502. package/dist/templates/docs/bugs/bug-analysis.md.ejs +47 -0
  503. package/dist/templates/docs/bugs/bug-report.md.ejs +51 -0
  504. package/dist/templates/docs/bugs/bug-verification.md.ejs +42 -0
  505. package/dist/templates/docs/runbooks/deployment.md.ejs +119 -0
  506. package/dist/templates/docs/runbooks/prod-checklist.md.ejs +90 -0
  507. package/dist/templates/docs/runbooks/rollback.md.ejs +124 -0
  508. package/dist/templates/docs/runbooks/troubleshooting.md.ejs +130 -0
  509. package/dist/templates/docs/skeletons/arc42-canvas.md.ejs +46 -0
  510. package/dist/templates/docs/skeletons/arc42-full.md.ejs +59 -0
  511. package/dist/templates/docs/skeletons/decision-registry.md.ejs +38 -0
  512. package/dist/templates/docs/skeletons/er-model.md.ejs +19 -0
  513. package/dist/templates/docs/skeletons/glossary.md.ejs +8 -0
  514. package/dist/templates/docs/skeletons/governance.md.ejs +13 -0
  515. package/dist/templates/docs/skeletons/slo.md.ejs +21 -0
  516. package/dist/templates/docs/skeletons/technical-debt.md.ejs +8 -0
  517. package/dist/templates/docs/skeletons/test-strategy.md.ejs +14 -0
  518. package/dist/templates/docs/skeletons/threat-model-4q.md.ejs +20 -0
  519. package/dist/templates/docs/skeletons/threat-model-stride.md.ejs +22 -0
  520. package/dist/templates/docs/specs/atomic-task-list.md.ejs +57 -0
  521. package/dist/templates/docs/steering/product.md.ejs +44 -0
  522. package/dist/templates/docs/steering/structure.md.ejs +49 -0
  523. package/dist/templates/docs/steering/tech.md.ejs +53 -0
  524. package/dist/templates/documentation/cli-catalog.md.ejs +21 -0
  525. package/dist/templates/e2e/E2E_CONSTITUTION.md.ejs +77 -0
  526. package/dist/templates/e2e/playwright-python/conftest.py.ejs +22 -0
  527. package/dist/templates/e2e/playwright-python/run_axe.py.ejs +99 -0
  528. package/dist/templates/e2e/playwright-python/test_a11y.py.ejs +38 -0
  529. package/dist/templates/e2e/playwright-python/test_smoke.py.ejs +28 -0
  530. package/dist/templates/e2e/playwright-ts/a11y.spec.ts.ejs +20 -0
  531. package/dist/templates/e2e/playwright-ts/render-smoke.spec.ts.ejs +90 -0
  532. package/dist/templates/e2e/playwright-ts/run-axe.ts.ejs +74 -0
  533. package/dist/templates/e2e/smoke-journeys/journeys.spec.ts.ejs +53 -0
  534. package/dist/templates/evidence-files.json.ejs +13 -0
  535. package/dist/templates/frontend/FE_DESIGN_PRINCIPLES.md.ejs +115 -0
  536. package/dist/templates/frontend/FRONTEND_CONSTITUTION.md.ejs +170 -0
  537. package/dist/templates/frontend/design-tokens.json.ejs +107 -0
  538. package/dist/templates/frontend/vrt-setup.md.ejs +83 -0
  539. package/dist/templates/githooks/commit-msg.ejs +60 -0
  540. package/dist/templates/githooks/pre-commit.ejs +95 -0
  541. package/dist/templates/githooks/pre-push.ejs +251 -0
  542. package/dist/templates/githooks/setup-hooks.sh.ejs +8 -0
  543. package/dist/templates/github/PULL_REQUEST_TEMPLATE.md +37 -0
  544. package/dist/templates/github/PULL_REQUEST_TEMPLATE.md.ejs +52 -0
  545. package/dist/templates/github/actions/build-cache/action.yml.ejs +84 -0
  546. package/dist/templates/github/actions/nas-ssh/action.yml.ejs +53 -0
  547. package/dist/templates/github/actions/setup-java-maven/action.yml.ejs +53 -0
  548. package/dist/templates/github/actions/setup-node-pnpm/action.yml.ejs +39 -0
  549. package/dist/templates/github/actions/sign-and-attest/action.yml.ejs +53 -0
  550. package/dist/templates/github/dependabot.yml.ejs +66 -0
  551. package/dist/templates/github/extended-ci-paths.txt.ejs +38 -0
  552. package/dist/templates/github/issue-templates/bug-report.yml +72 -0
  553. package/dist/templates/github/issue-templates/compliance-item.yml.ejs +75 -0
  554. package/dist/templates/github/issue-templates/config.yml +2 -0
  555. package/dist/templates/github/issue-templates/epic.yml +66 -0
  556. package/dist/templates/github/issue-templates/feature-request.yml +24 -0
  557. package/dist/templates/github/issue-templates/task-brief.yml.ejs +125 -0
  558. package/dist/templates/github/labels.yml.ejs +161 -0
  559. package/dist/templates/github/scripts/sticky-failure-issue.sh.ejs +61 -0
  560. package/dist/templates/github/workflows/01-pr-fast.yml.ejs +1089 -0
  561. package/dist/templates/github/workflows/02-pr-extended.yml.ejs +512 -0
  562. package/dist/templates/github/workflows/03-human-approval.yml.ejs +76 -0
  563. package/dist/templates/github/workflows/04-deploy-test.yml.ejs +425 -0
  564. package/dist/templates/github/workflows/05-release.yml.ejs +813 -0
  565. package/dist/templates/github/workflows/06-nightly-lite.yml.ejs +125 -0
  566. package/dist/templates/github/workflows/06-nightly.yml.ejs +25 -0
  567. package/dist/templates/github/workflows/07-weekly-lite.yml.ejs +221 -0
  568. package/dist/templates/github/workflows/07-weekly.yml.ejs +23 -0
  569. package/dist/templates/github/workflows/08-monthly.yml.ejs +23 -0
  570. package/dist/templates/github/workflows/09-heartbeat.yml.ejs +268 -0
  571. package/dist/templates/github/workflows/10-deploy-prod.yml.ejs +144 -0
  572. package/dist/templates/github/workflows/11-k6-on-demand.yml.ejs +43 -0
  573. package/dist/templates/github/workflows/12-mutation-scheduled.yml.ejs +100 -0
  574. package/dist/templates/github/workflows/13-archunit-extended.yml.ejs +33 -0
  575. package/dist/templates/github/workflows/14-license-scan.yml.ejs +45 -0
  576. package/dist/templates/github/workflows/15-codeql.yml.ejs +117 -0
  577. package/dist/templates/github/workflows/16-frontend-quality.yml.ejs +154 -0
  578. package/dist/templates/github/workflows/17-ossf-scorecard.yml.ejs +46 -0
  579. package/dist/templates/github/workflows/18-frontend-lane.yml.ejs +50 -0
  580. package/dist/templates/github/workflows/_ai-draft-check.yml.ejs +44 -0
  581. package/dist/templates/github/workflows/_contract-postman.yml.ejs +93 -0
  582. package/dist/templates/github/workflows/_cosign-copy/aws-ecs.ejs +90 -0
  583. package/dist/templates/github/workflows/_cosign-copy/azure-container-app.ejs +97 -0
  584. package/dist/templates/github/workflows/_cosign-copy/gcp-cloud-run.ejs +102 -0
  585. package/dist/templates/github/workflows/_cosign-copy/ghcr.ejs +76 -0
  586. package/dist/templates/github/workflows/_cosign-copy/nas-compose.ejs +69 -0
  587. package/dist/templates/github/workflows/_deploy/aws-ecs.ejs +78 -0
  588. package/dist/templates/github/workflows/_deploy/azure-container-app.ejs +59 -0
  589. package/dist/templates/github/workflows/_deploy/gcp-cloud-run.ejs +71 -0
  590. package/dist/templates/github/workflows/_deploy/ghcr.ejs +19 -0
  591. package/dist/templates/github/workflows/_deploy/nas-compose.ejs +45 -0
  592. package/dist/templates/github/workflows/_k6-runner.yml.ejs +107 -0
  593. package/dist/templates/github/workflows/_label-on-approve.yml.ejs +44 -0
  594. package/dist/templates/github/workflows/_label-sync.yml.ejs +58 -0
  595. package/dist/templates/github/workflows/_monthly.yml.ejs +343 -0
  596. package/dist/templates/github/workflows/_nightly.yml.ejs +826 -0
  597. package/dist/templates/github/workflows/_notify.yml.ejs +96 -0
  598. package/dist/templates/github/workflows/_partials/macos-keychain-bypass.ejs +6 -0
  599. package/dist/templates/github/workflows/_partials/macos-keychain-restore.ejs +6 -0
  600. package/dist/templates/github/workflows/_partials/scheduled-heavy-jobs.ejs +117 -0
  601. package/dist/templates/github/workflows/_partials/sigstore-preflight.ejs +8 -0
  602. package/dist/templates/github/workflows/_partials/trivy-fs-java.ejs +27 -0
  603. package/dist/templates/github/workflows/_post-merge-notify.yml.ejs +228 -0
  604. package/dist/templates/github/workflows/_pr-staleness.yml.ejs +85 -0
  605. package/dist/templates/github/workflows/_shared-security.yml.ejs +132 -0
  606. package/dist/templates/github/workflows/_sigstore-retry-sign.yml.ejs +102 -0
  607. package/dist/templates/github/workflows/_weekly.yml.ejs +313 -0
  608. package/dist/templates/github/workflows/drift-shadow.yml.ejs +51 -0
  609. package/dist/templates/github/workflows/five-lane/ci.yml.ejs +54 -0
  610. package/dist/templates/github/workflows/five-lane/nightly.yml.ejs +70 -0
  611. package/dist/templates/github/workflows/five-lane/release.yml.ejs +53 -0
  612. package/dist/templates/github/workflows/five-lane/weekly.yml.ejs +72 -0
  613. package/dist/templates/github/workflows/issue-state.yml.ejs +93 -0
  614. package/dist/templates/global-invariants/GLOBAL_INVARIANTS.md.ejs +34 -0
  615. package/dist/templates/governance/RACI.md.ejs +21 -0
  616. package/dist/templates/governance/ci-mental-model.md.ejs +268 -0
  617. package/dist/templates/governance/contract-integrity-policy.md.ejs +116 -0
  618. package/dist/templates/governance/enterprise-compliance-baseline.md.ejs +111 -0
  619. package/dist/templates/governance/evidence-retention.md.ejs +43 -0
  620. package/dist/templates/governance/gdpr-erasure-runbook.md.ejs +165 -0
  621. package/dist/templates/governance/qa-audit-phases.md.ejs +129 -0
  622. package/dist/templates/governance/risk-assessment-template.md.ejs +105 -0
  623. package/dist/templates/governance/risk-register.md.ejs +76 -0
  624. package/dist/templates/governance/solo-dev-exception.md.ejs +96 -0
  625. package/dist/templates/governance/validation-evidence.md.ejs +131 -0
  626. package/dist/templates/infra/azure/containerapp.tpl.yaml.ejs +74 -0
  627. package/dist/templates/infra/nas-compose/deploy.sh.ejs +114 -0
  628. package/dist/templates/integration-testing/AbstractIntegrationTest.java.ejs +36 -0
  629. package/dist/templates/integration-testing/NoH2ArchTest.java.ejs +24 -0
  630. package/dist/templates/integration-testing/conftest.py.ejs +20 -0
  631. package/dist/templates/integration-testing/db_fixture.rs.ejs +48 -0
  632. package/dist/templates/integration-testing/eslint-no-fake-db.json.ejs +19 -0
  633. package/dist/templates/integration-testing/eslint.config.no-fake-db.mjs.ejs +46 -0
  634. package/dist/templates/integration-testing/main_test.go.ejs +53 -0
  635. package/dist/templates/integration-testing/main_test_sqlite.go.ejs +37 -0
  636. package/dist/templates/integration-testing/test-setup.ts.ejs +26 -0
  637. package/dist/templates/integration-testing/testcontainers-deps.gradle.ejs +9 -0
  638. package/dist/templates/java/DeprecationInterceptor.java.ejs +50 -0
  639. package/dist/templates/java/archunit-hexagonal.ejs +69 -0
  640. package/dist/templates/java/modulith/ApplicationModulesTest.java.ejs +21 -0
  641. package/dist/templates/java/modulith/modulith-deps.gradle.ejs +13 -0
  642. package/dist/templates/java/modulith/modulith-maven-setup.md.ejs +21 -0
  643. package/dist/templates/java/pharma/AuditEvent.java.ejs +138 -0
  644. package/dist/templates/java/pharma/AuditMapper.java.ejs +60 -0
  645. package/dist/templates/java/pharma/archunit-pharma.ejs +128 -0
  646. package/dist/templates/kit/GLOBAL_KIT.md.ejs +11 -0
  647. package/dist/templates/kit/dim.md.ejs +33 -0
  648. package/dist/templates/llms-txt.config.json.ejs +22 -0
  649. package/dist/templates/local-wrapper/.env.example.ejs +15 -0
  650. package/dist/templates/local-wrapper/Makefile.ejs +44 -0
  651. package/dist/templates/local-wrapper/run.sh.ejs +5 -0
  652. package/dist/templates/middleware/410-gone-handler.ts.ejs +41 -0
  653. package/dist/templates/middleware/correlation-id.ts.ejs +32 -0
  654. package/dist/templates/middleware/deprecation.ts.ejs +45 -0
  655. package/dist/templates/middleware/error-handler.ts.ejs +73 -0
  656. package/dist/templates/middleware/payload-size-limit.ts.ejs +51 -0
  657. package/dist/templates/mutation/README.md.ejs +67 -0
  658. package/dist/templates/mutation/cargo-mutants.toml.ejs +9 -0
  659. package/dist/templates/mutation/mutmut-config.toml.ejs +7 -0
  660. package/dist/templates/mutation/parse-mutants.mjs.ejs +44 -0
  661. package/dist/templates/mutation/parse-mutmut.py.ejs +44 -0
  662. package/dist/templates/mutation/pitest-l2-setup.md.ejs +66 -0
  663. package/dist/templates/mutation/pitest-maven-setup.md.ejs +64 -0
  664. package/dist/templates/mutation/pitest.gradle.ejs +23 -0
  665. package/dist/templates/mutation/stryker.conf.json.ejs +17 -0
  666. package/dist/templates/observability/setup.md.ejs +495 -0
  667. package/dist/templates/operations/handbook.md.ejs +217 -0
  668. package/dist/templates/perf/bundle-budget.json.ejs +29 -0
  669. package/dist/templates/perf/k6/reports/csv-report.py.ejs +91 -0
  670. package/dist/templates/perf/k6/reports/html-report.py.ejs +114 -0
  671. package/dist/templates/perf/k6/reports/json-report.py.ejs +74 -0
  672. package/dist/templates/perf/k6/scenarios/breakpoint.js.ejs +26 -0
  673. package/dist/templates/perf/k6/scenarios/burst.js.ejs +43 -0
  674. package/dist/templates/perf/k6/scenarios/endurance.js.ejs +36 -0
  675. package/dist/templates/perf/k6/scenarios/load.js.ejs +26 -0
  676. package/dist/templates/perf/k6/scenarios/ramp-down.js.ejs +29 -0
  677. package/dist/templates/perf/k6/scenarios/ramp-up.js.ejs +32 -0
  678. package/dist/templates/perf/k6/scenarios/smoke.js.ejs +23 -0
  679. package/dist/templates/perf/k6/scenarios/soak.js.ejs +26 -0
  680. package/dist/templates/perf/k6/scenarios/spike.js.ejs +29 -0
  681. package/dist/templates/perf/k6/scenarios/steady-state.js.ejs +31 -0
  682. package/dist/templates/perf/k6/scenarios/stress.js.ejs +29 -0
  683. package/dist/templates/perf/k6/scenarios/volume.js.ejs +36 -0
  684. package/dist/templates/perf/k6/seed/test-data.sql.ejs +59 -0
  685. package/dist/templates/perf/lighthouserc.json.ejs +41 -0
  686. package/dist/templates/quality/iso9001/CAPA_LOG.md.ejs +36 -0
  687. package/dist/templates/quality/iso9001/DOCUMENT_CONTROL.md.ejs +36 -0
  688. package/dist/templates/quality/iso9001/REQUIREMENTS_TRACEABILITY.md.ejs +61 -0
  689. package/dist/templates/regulated/overlay.json.ejs +26 -0
  690. package/dist/templates/regulated/regulated-overlay.md.ejs +40 -0
  691. package/dist/templates/resilience/RESILIENCE.md.ejs +310 -0
  692. package/dist/templates/root/.gitignore.ejs +85 -0
  693. package/dist/templates/root/CODEOWNERS.ejs +18 -0
  694. package/dist/templates/root/CONTRIBUTING.md.ejs +62 -0
  695. package/dist/templates/root/SECURITY.md.ejs +19 -0
  696. package/dist/templates/root/TEST_TAXONOMY.md.ejs +100 -0
  697. package/dist/templates/root/commitlint.config.js.ejs +4 -0
  698. package/dist/templates/root/docs/METHOD/CANONICAL_PATHS.md.ejs +24 -0
  699. package/dist/templates/root/docs/METHOD/ENGINEERING_DEFAULTS.md.ejs +136 -0
  700. package/dist/templates/root/docs/METHOD/KNOWLEDGE_MAP.md.ejs +90 -0
  701. package/dist/templates/root/docs/METHOD/PATTERNS_CATALOG.md.ejs +51 -0
  702. package/dist/templates/root/docs/METHOD/REUSE_REGISTRY.md.ejs +26 -0
  703. package/dist/templates/root/docs/METHOD/REUSE_REGISTRY_SPEC.md.ejs +80 -0
  704. package/dist/templates/root/docs/METHOD/SSOT_CORE_SET.md.ejs +62 -0
  705. package/dist/templates/root/docs/METHOD/TRACK_ROUTER.md.ejs +39 -0
  706. package/dist/templates/root/docs/SYSTEM/CANON.md.ejs +359 -0
  707. package/dist/templates/root/docs/SYSTEM/FAIL_CLOSED.md.ejs +171 -0
  708. package/dist/templates/root/editorconfig.ejs +39 -0
  709. package/dist/templates/root/tsconfig.json.ejs +21 -0
  710. package/dist/templates/rust/clippy.toml.ejs +14 -0
  711. package/dist/templates/schemas/milestone.schema.json.ejs +164 -0
  712. package/dist/templates/schemas/rtm-verdict.schema.json.ejs +52 -0
  713. package/dist/templates/schemas/source-record.schema.json.ejs +91 -0
  714. package/dist/templates/schemas/tabletop-evidence.schema.json.ejs +53 -0
  715. package/dist/templates/schemas/use-case.schema.json.ejs +59 -0
  716. package/dist/templates/scripts/apply-branch-protection.mjs.ejs +70 -0
  717. package/dist/templates/scripts/audit-toolchain.mjs.ejs +112 -0
  718. package/dist/templates/scripts/bg-run.sh.ejs +59 -0
  719. package/dist/templates/scripts/capacity-probe.mjs.ejs +147 -0
  720. package/dist/templates/scripts/capture-debt-baseline.mjs.ejs +99 -0
  721. package/dist/templates/scripts/check-acceptance.mjs.ejs +298 -0
  722. package/dist/templates/scripts/check-action-pins.mjs.ejs +215 -0
  723. package/dist/templates/scripts/check-agent-return.mjs.ejs +177 -0
  724. package/dist/templates/scripts/check-all.mjs.ejs +1746 -0
  725. package/dist/templates/scripts/check-anti-fake-green.mjs.ejs +80 -0
  726. package/dist/templates/scripts/check-anti-proforma.mjs.ejs +547 -0
  727. package/dist/templates/scripts/check-api-e2e.mjs.ejs +106 -0
  728. package/dist/templates/scripts/check-arc42-slots.mjs.ejs +25 -0
  729. package/dist/templates/scripts/check-assertion-delta.mjs.ejs +287 -0
  730. package/dist/templates/scripts/check-audit-dry-pass.mjs.ejs +176 -0
  731. package/dist/templates/scripts/check-bundle-size.mjs.ejs +151 -0
  732. package/dist/templates/scripts/check-canonical-paths.mjs.ejs +39 -0
  733. package/dist/templates/scripts/check-ci-tiers.mjs.ejs +111 -0
  734. package/dist/templates/scripts/check-claude-md-lint.mjs.ejs +142 -0
  735. package/dist/templates/scripts/check-collab-mode-wired.mjs.ejs +60 -0
  736. package/dist/templates/scripts/check-commit-footer-rationale.mjs.ejs +170 -0
  737. package/dist/templates/scripts/check-constraint-scan.mjs.ejs +681 -0
  738. package/dist/templates/scripts/check-consumer-audit.mjs.ejs +414 -0
  739. package/dist/templates/scripts/check-continue-on-error.mjs.ejs +227 -0
  740. package/dist/templates/scripts/check-cross-model-review.mjs.ejs +458 -0
  741. package/dist/templates/scripts/check-decision-registry.mjs.ejs +101 -0
  742. package/dist/templates/scripts/check-doc-freshness.mjs.ejs +17 -0
  743. package/dist/templates/scripts/check-doc-links.mjs.ejs +98 -0
  744. package/dist/templates/scripts/check-doc-set.mjs.ejs +18 -0
  745. package/dist/templates/scripts/check-docs.mjs.ejs +71 -0
  746. package/dist/templates/scripts/check-domain-api-surface.mjs.ejs +80 -0
  747. package/dist/templates/scripts/check-drift.mjs.ejs +167 -0
  748. package/dist/templates/scripts/check-duplication.mjs.ejs +45 -0
  749. package/dist/templates/scripts/check-e2e-escalation.mjs.ejs +199 -0
  750. package/dist/templates/scripts/check-e2e-quarantine.mjs.ejs +68 -0
  751. package/dist/templates/scripts/check-emission-parity.mjs.ejs +91 -0
  752. package/dist/templates/scripts/check-exit-code-contract.mjs.ejs +138 -0
  753. package/dist/templates/scripts/check-fail-closed-audit.mjs.ejs +389 -0
  754. package/dist/templates/scripts/check-fe-boundaries.mjs.ejs +184 -0
  755. package/dist/templates/scripts/check-feature-matrix.mjs.ejs +835 -0
  756. package/dist/templates/scripts/check-frontend-lane.mjs.ejs +73 -0
  757. package/dist/templates/scripts/check-grace-window.mjs.ejs +102 -0
  758. package/dist/templates/scripts/check-handoff-doc.mjs.ejs +192 -0
  759. package/dist/templates/scripts/check-hook-routing.mjs.ejs +224 -0
  760. package/dist/templates/scripts/check-image-pins.mjs.ejs +90 -0
  761. package/dist/templates/scripts/check-inline-suppressions.mjs.ejs +153 -0
  762. package/dist/templates/scripts/check-iso9001.mjs.ejs +146 -0
  763. package/dist/templates/scripts/check-knowledge-map.mjs.ejs +49 -0
  764. package/dist/templates/scripts/check-local-ci-parity.mjs.ejs +382 -0
  765. package/dist/templates/scripts/check-m16-handoff.mjs.ejs +112 -0
  766. package/dist/templates/scripts/check-merge-method.mjs.ejs +92 -0
  767. package/dist/templates/scripts/check-milestones.mjs.ejs +678 -0
  768. package/dist/templates/scripts/check-min-test-execution.mjs.ejs +225 -0
  769. package/dist/templates/scripts/check-muted-test.mjs.ejs +270 -0
  770. package/dist/templates/scripts/check-no-stub-redirects.mjs.ejs +154 -0
  771. package/dist/templates/scripts/check-no-tracked-artifacts.mjs.ejs +134 -0
  772. package/dist/templates/scripts/check-oracle-discrimination.mjs.ejs +244 -0
  773. package/dist/templates/scripts/check-pii-scan.mjs.ejs +67 -0
  774. package/dist/templates/scripts/check-pipe-tee-hazard.mjs.ejs +85 -0
  775. package/dist/templates/scripts/check-pr-size-gate.mjs.ejs +85 -0
  776. package/dist/templates/scripts/check-refutation-verdicts.mjs.ejs +256 -0
  777. package/dist/templates/scripts/check-regulated-overlay.mjs.ejs +158 -0
  778. package/dist/templates/scripts/check-render-smoke.mjs.ejs +100 -0
  779. package/dist/templates/scripts/check-reuse-registry.mjs.ejs +44 -0
  780. package/dist/templates/scripts/check-review-completion.mjs.ejs +708 -0
  781. package/dist/templates/scripts/check-safety-adopt-ratchet.mjs.ejs +142 -0
  782. package/dist/templates/scripts/check-secret-presence.mjs.ejs +191 -0
  783. package/dist/templates/scripts/check-secret-scan.mjs.ejs +82 -0
  784. package/dist/templates/scripts/check-skip-critical-e2e.mjs.ejs +142 -0
  785. package/dist/templates/scripts/check-smoke-journeys.mjs.ejs +272 -0
  786. package/dist/templates/scripts/check-solo-reactivation.mjs.ejs +102 -0
  787. package/dist/templates/scripts/check-sources.mjs.ejs +245 -0
  788. package/dist/templates/scripts/check-ssot-core.mjs.ejs +45 -0
  789. package/dist/templates/scripts/check-stack-conformity.mjs.ejs +160 -0
  790. package/dist/templates/scripts/check-stride-traceability.mjs.ejs +101 -0
  791. package/dist/templates/scripts/check-suppression-expiry.mjs.ejs +79 -0
  792. package/dist/templates/scripts/check-suppression-rationale.mjs.ejs +76 -0
  793. package/dist/templates/scripts/check-suppressions.mjs.ejs +150 -0
  794. package/dist/templates/scripts/check-tabletop-evidence.mjs.ejs +499 -0
  795. package/dist/templates/scripts/check-tdd-evidence.mjs.ejs +381 -0
  796. package/dist/templates/scripts/check-test-naming.mjs.ejs +151 -0
  797. package/dist/templates/scripts/check-test-pyramid.mjs.ejs +170 -0
  798. package/dist/templates/scripts/check-test-scope-tier.mjs.ejs +208 -0
  799. package/dist/templates/scripts/check-tier-coverage.mjs.ejs +71 -0
  800. package/dist/templates/scripts/check-todo-max-age.mjs.ejs +205 -0
  801. package/dist/templates/scripts/check-touched-vs-manifest.mjs.ejs +179 -0
  802. package/dist/templates/scripts/check-unwired-guards.mjs.ejs +367 -0
  803. package/dist/templates/scripts/check-use-cases.mjs.ejs +345 -0
  804. package/dist/templates/scripts/check-validator-helptext.mjs.ejs +80 -0
  805. package/dist/templates/scripts/check-wiki-lint.mjs.ejs +162 -0
  806. package/dist/templates/scripts/check-workflow-docs-sync.mjs.ejs +91 -0
  807. package/dist/templates/scripts/check-workflow-job-naming.mjs.ejs +102 -0
  808. package/dist/templates/scripts/check-workflow-perms.mjs.ejs +54 -0
  809. package/dist/templates/scripts/check-workflow-runners.mjs.ejs +87 -0
  810. package/dist/templates/scripts/check-workflow-sha-pinning.mjs.ejs +89 -0
  811. package/dist/templates/scripts/check-workflow-test-integrity.mjs.ejs +235 -0
  812. package/dist/templates/scripts/checks/check-rust-no-unsafe.mjs.ejs +58 -0
  813. package/dist/templates/scripts/checks/check-rust-no-unwrap.mjs.ejs +61 -0
  814. package/dist/templates/scripts/ci-classify-changes.mjs.ejs +119 -0
  815. package/dist/templates/scripts/conformance.mjs.ejs +37 -0
  816. package/dist/templates/scripts/constraint-map.json.ejs +25 -0
  817. package/dist/templates/scripts/debt-lib.mjs.ejs +1015 -0
  818. package/dist/templates/scripts/debt-report.mjs.ejs +199 -0
  819. package/dist/templates/scripts/domain-api-surface.json.ejs +23 -0
  820. package/dist/templates/scripts/done-evidence.mjs.ejs +359 -0
  821. package/dist/templates/scripts/evidence-collect.mjs.ejs +264 -0
  822. package/dist/templates/scripts/evidence-prune.mjs.ejs +96 -0
  823. package/dist/templates/scripts/evidence-rotate.mjs.ejs +53 -0
  824. package/dist/templates/scripts/evidence-writer.sh.ejs +220 -0
  825. package/dist/templates/scripts/gate-registry.yml.ejs +286 -0
  826. package/dist/templates/scripts/gen-doc-index.mjs.ejs +19 -0
  827. package/dist/templates/scripts/gen-gap.mjs.ejs +153 -0
  828. package/dist/templates/scripts/gen-llms-txt.mjs.ejs +18 -0
  829. package/dist/templates/scripts/gen-wiki.mjs.ejs +196 -0
  830. package/dist/templates/scripts/gh-cleanup-expired-artifacts.mjs.ejs +134 -0
  831. package/dist/templates/scripts/gold-audit.mjs.ejs +19 -0
  832. package/dist/templates/scripts/i18n-literal-scanner.mjs.ejs +175 -0
  833. package/dist/templates/scripts/ingest-zap-report.mjs.ejs +107 -0
  834. package/dist/templates/scripts/inject-pact-samples.sh.ejs +96 -0
  835. package/dist/templates/scripts/issue-readiness.mjs.ejs +84 -0
  836. package/dist/templates/scripts/knowledge-map-update.mjs.ejs +32 -0
  837. package/dist/templates/scripts/lib/acceptance-criteria.mjs.ejs +213 -0
  838. package/dist/templates/scripts/lib/agent-return-validate.mjs.ejs +481 -0
  839. package/dist/templates/scripts/lib/coverage-gate.mjs.ejs +54 -0
  840. package/dist/templates/scripts/lib/e2e-reliability.mjs.ejs +207 -0
  841. package/dist/templates/scripts/lib/ephemeral-server.mjs.ejs +148 -0
  842. package/dist/templates/scripts/lib/evidence-binding.mjs.ejs +140 -0
  843. package/dist/templates/scripts/lib/exact-sha-policy.mjs.ejs +233 -0
  844. package/dist/templates/scripts/lib/gate-args.mjs.ejs +20 -0
  845. package/dist/templates/scripts/lib/gate-evidence.mjs.ejs +622 -0
  846. package/dist/templates/scripts/lib/gate-mutex.mjs.ejs +340 -0
  847. package/dist/templates/scripts/lib/glob-walk.mjs.ejs +148 -0
  848. package/dist/templates/scripts/lib/run-helpers.mjs.ejs +416 -0
  849. package/dist/templates/scripts/lib/seed-common.sh.ejs +105 -0
  850. package/dist/templates/scripts/lib/waiter-count.mjs.ejs +62 -0
  851. package/dist/templates/scripts/muted-tests-baseline.json.ejs +4 -0
  852. package/dist/templates/scripts/optional-emissions.json.ejs +117 -0
  853. package/dist/templates/scripts/oracle-discrimination-baseline.json.ejs +6 -0
  854. package/dist/templates/scripts/pid-watch.sh.ejs +78 -0
  855. package/dist/templates/scripts/pii-scan.mjs.ejs +125 -0
  856. package/dist/templates/scripts/pr-merge-watch.mjs.ejs +445 -0
  857. package/dist/templates/scripts/record-agent-return.mjs.ejs +279 -0
  858. package/dist/templates/scripts/record-journey-evidence.mjs.ejs +69 -0
  859. package/dist/templates/scripts/rework-log.mjs.ejs +172 -0
  860. package/dist/templates/scripts/run-postman-tests.sh.ejs +112 -0
  861. package/dist/templates/scripts/schemas/agent-return-external.schema.json +74 -0
  862. package/dist/templates/scripts/schemas/agent-return.schema.json.ejs +181 -0
  863. package/dist/templates/scripts/schemas/cross-model-dispatch.schema.json +95 -0
  864. package/dist/templates/scripts/seed-test-data.sh.ejs +99 -0
  865. package/dist/templates/scripts/self-validation.mjs.ejs +126 -0
  866. package/dist/templates/scripts/setup-repo.sh.ejs +78 -0
  867. package/dist/templates/scripts/spotbugs-baseline.json.ejs +4 -0
  868. package/dist/templates/scripts/test-gate-layering.mjs.ejs +92 -0
  869. package/dist/templates/scripts/validate-api-snapshots.mjs.ejs +86 -0
  870. package/dist/templates/scripts/validate-k6-scenarios.mjs.ejs +96 -0
  871. package/dist/templates/scripts/validate-openapi-field-types.mjs.ejs +124 -0
  872. package/dist/templates/scripts/validate-postman-collection.mjs.ejs +159 -0
  873. package/dist/templates/scripts/verify-fe-coverage.mjs.ejs +138 -0
  874. package/dist/templates/scripts/verify-i18n-parity.mjs.ejs +114 -0
  875. package/dist/templates/scripts/verify-module-coverage.mjs.ejs +207 -0
  876. package/dist/templates/scripts/verify-mutation-baseline.mjs.ejs +209 -0
  877. package/dist/templates/scripts/verify-spotbugs.mjs.ejs +216 -0
  878. package/dist/templates/scripts/verify-tokens.mjs.ejs +177 -0
  879. package/dist/templates/security/RISK_ASSESSMENT.md.ejs +35 -0
  880. package/dist/templates/security/STRIDE.md.ejs +24 -0
  881. package/dist/templates/security/gitleaks.toml.ejs +21 -0
  882. package/dist/templates/security/zap/baseline-auth.context.ejs +58 -0
  883. package/dist/templates/security/zap/rules.tsv.ejs +100 -0
  884. package/dist/templates/ship/TICK_PROMPT.md.ejs +55 -0
  885. package/dist/templates/ship/supervisor.sh.ejs +46 -0
  886. package/dist/templates/smoke-journeys/manifest.json.ejs +1 -0
  887. package/dist/templates/sonar-project.properties.ejs +25 -0
  888. package/dist/templates/standards/doc-profile.ejs +27 -0
  889. package/dist/templates/standards/gold-doc-set.yml.ejs +528 -0
  890. package/dist/templates/standards/gold-registry.java.yml.ejs +266 -0
  891. package/dist/templates/standards/gold-registry.typescript.yml.ejs +104 -0
  892. package/dist/templates/standards/gold-registry.yml.ejs +119 -0
  893. package/dist/templates/standards/thresholds.yml.ejs +86 -0
  894. package/dist/templates/static-analysis/.dependency-cruiser.cjs.ejs +78 -0
  895. package/dist/templates/static-analysis/.golangci.yml.ejs +70 -0
  896. package/dist/templates/static-analysis/.shellcheckrc.ejs +13 -0
  897. package/dist/templates/static-analysis/.yamllint.yml.ejs +41 -0
  898. package/dist/templates/static-analysis/checkstyle.xml.ejs +83 -0
  899. package/dist/templates/static-analysis/detekt.yml.ejs +26 -0
  900. package/dist/templates/static-analysis/eslint.config.mjs.ejs +54 -0
  901. package/dist/templates/static-analysis/eslint.config.static.mjs.ejs +38 -0
  902. package/dist/templates/static-analysis/eslintrc-static.json.ejs +30 -0
  903. package/dist/templates/static-analysis/jscpd.json.ejs +25 -0
  904. package/dist/templates/static-analysis/knip.json.ejs +26 -0
  905. package/dist/templates/static-analysis/pmd-ruleset.xml.ejs +92 -0
  906. package/dist/templates/static-analysis/prettierignore.ejs +59 -0
  907. package/dist/templates/static-analysis/prettierrc.json.ejs +10 -0
  908. package/dist/templates/static-analysis/requirements-dev.txt.ejs +11 -0
  909. package/dist/templates/static-analysis/ruff.toml.ejs +40 -0
  910. package/dist/templates/static-analysis/rustfmt.toml.ejs +3 -0
  911. package/dist/templates/static-analysis/spotbugs-exclude.xml.ejs +120 -0
  912. package/dist/templates/static-analysis/spotbugs.gradle.ejs +18 -0
  913. package/dist/templates/static-analysis/spotless.gradle.ejs +38 -0
  914. package/dist/templates/static-analysis/stylelintrc.json.ejs +16 -0
  915. package/dist/templates/suppressions/archunit-baseline.json.ejs +1 -0
  916. package/dist/templates/suppressions/consumer-audit-allowlist.json.ejs +1 -0
  917. package/dist/templates/suppressions/gitleaksignore.ejs +20 -0
  918. package/dist/templates/suppressions/pii-allowlist.json.ejs +1 -0
  919. package/dist/templates/suppressions/suppressions-schema.json.ejs +39 -0
  920. package/dist/templates/suppressions/trivyignore.ejs +17 -0
  921. package/dist/templates/testing/test-taxonomy.md.ejs +120 -0
  922. package/dist/test/example.behavioral.test.js +2 -0
  923. package/dist/types/memory.d.ts +19 -0
  924. package/dist/types/memory.js +1 -0
  925. package/dist/types/plan.d.ts +102 -0
  926. package/dist/types/plan.js +2 -0
  927. package/dist/types/plugin.d.ts +45 -0
  928. package/dist/types/plugin.js +1 -0
  929. package/dist/utils/canon-loader.js +2 -0
  930. package/dist/utils/channel.js +1 -0
  931. package/dist/utils/config.d.ts +79 -0
  932. package/dist/utils/config.js +5 -0
  933. package/dist/utils/confirm-downgrade.js +5 -0
  934. package/dist/utils/env.js +2 -0
  935. package/dist/utils/error-catalog.js +2 -0
  936. package/dist/utils/errors.js +2 -0
  937. package/dist/utils/evidence-log.js +3 -0
  938. package/dist/utils/file-lock.js +2 -0
  939. package/dist/utils/first-run.js +8 -0
  940. package/dist/utils/fs.js +3 -0
  941. package/dist/utils/github-issue-helper.js +4 -0
  942. package/dist/utils/gradle.js +21 -0
  943. package/dist/utils/json-output.js +2 -0
  944. package/dist/utils/logger-config.js +4 -0
  945. package/dist/utils/logger.js +3 -0
  946. package/dist/utils/maturity-check.js +2 -0
  947. package/dist/utils/pkg.js +3 -0
  948. package/dist/utils/platform.js +2 -0
  949. package/dist/utils/plugin-loader.js +2 -0
  950. package/dist/utils/plugin-worker.js +2 -0
  951. package/dist/utils/prettier-format.js +2 -0
  952. package/dist/utils/profiler.js +2 -0
  953. package/dist/utils/render.js +2 -0
  954. package/dist/utils/replay.js +3 -0
  955. package/dist/utils/run-cli.js +6 -0
  956. package/dist/utils/run-id.js +3 -0
  957. package/dist/utils/safe-read.js +2 -0
  958. package/dist/utils/task-id.js +2 -0
  959. package/dist/utils/today.js +2 -0
  960. package/dist/utils/tty.js +2 -0
  961. package/dist/utils/walk-dir.js +2 -0
  962. package/dist/verify/rules/drive-by-scope.js +1 -0
  963. package/dist/verify/rules/orphan-todos.js +1 -0
  964. package/dist/verify/rules/registry.js +1 -0
  965. package/dist/verify/rules/skip-patterns.js +1 -0
  966. package/dist/verify/rules/types.d.ts +15 -0
  967. package/dist/verify/rules/types.js +1 -0
  968. package/dist/verify/rules/ui-language.js +1 -0
  969. package/dist/verify/run.js +3 -0
  970. package/dist/wizard/archetype-defaults.js +1 -0
  971. package/dist/wizard/presets.js +1 -0
  972. package/dist/wizard/prompts.js +44 -0
  973. package/dist/wizard/types.d.ts +637 -0
  974. package/dist/wizard/types.js +1 -0
  975. package/dist/worktree/harvest.js +2 -0
  976. package/dist/worktree/links.js +2 -0
  977. package/dist/worktree/paths.js +2 -0
  978. package/dist/worktree/validate.js +3 -0
  979. package/package.json +124 -0
  980. package/scripts/check-arc42-slots.mjs +738 -0
  981. package/scripts/check-doc-freshness.mjs +236 -0
  982. package/scripts/check-doc-set.mjs +243 -0
  983. package/scripts/check-doc-style.mjs +228 -0
  984. package/scripts/gold-audit.mjs +319 -0
  985. package/scripts/lib/doc-gate-allowlist.mjs +123 -0
  986. package/scripts/lib/doc-set-resolve.mjs +274 -0
  987. package/scripts/lib/glob-walk.mjs +148 -0
  988. package/scripts/lib/gold-audit-lib.mjs +1260 -0
  989. package/scripts/lib/run-helpers.mjs +413 -0
@@ -0,0 +1,1089 @@
1
+ <% const _lanes = Array.isArray(lanes) ? lanes : []; const _multiLane = _lanes.length >= 2; const _bs = (typeof branchingStrategy !== 'undefined' ? branchingStrategy : 'github-flow'); %><% const _collabMode = (typeof collaborationMode !== 'undefined' && collaborationMode) ? collaborationMode : undefined; const _humanApproval = _collabMode !== 'trunk-solo'; /* trunk-solo: the sole human is the PR author and cannot self-approve — drop the impossible gate (INV-74) */ %># Reference: docs/REFERENCE/workflow-pr-fast.md
2
+ name: PR Fast (T1)
3
+
4
+ permissions:
5
+ contents: read
6
+
7
+ on:
8
+ push:
9
+ <% if (_bs === 'github-flow-with-develop') { %>
10
+ branches: [main, develop]
11
+ <% } else { %>
12
+ branches: [main]
13
+ <% } %>
14
+ workflow_dispatch:
15
+ # #2476 — deliberately NO `branches:` filter on this trigger. On a pull_request
16
+ # event `branches:` filters the BASE branch, not the head, so the former
17
+ # `branches: [main]` created NO WORKFLOW RUN AT ALL for a pull request stacked on
18
+ # a task or train branch: it displayed no failing checks because it had no checks,
19
+ # and any "no failing checks ⇒ mergeable" read was satisfied by a pull request
20
+ # that was never tested. Branch protection is no backstop — protection is
21
+ # configured on the BASE branch and a task/train branch carries none. Run creation
22
+ # is therefore unconditional in the base branch; per-branch economy stays INSIDE
23
+ # the workflow, in the job-level `if:` guards below, where a skipped job still
24
+ # reports a result the `ci-required` aggregator reads. The `push:` trigger above
25
+ # keeps its branch list: that lane is the post-merge catch-net for long-lived
26
+ # branches, and widening it would multiply runner cost on every task-branch push
27
+ # for coverage this pull_request trigger already provides. #2486 separately keys
28
+ # PR concurrency by head AND base while preserving the push key. Base-trigger
29
+ # coverage is enforced by scripts/check-workflow-test-integrity.mjs.
30
+ pull_request:
31
+ types: [opened, synchronize, reopened, labeled, ready_for_review, unlabeled]
32
+
33
+ # Cancel in-progress runs on the same ref; main always completes (#357).
34
+ concurrency:
35
+ group: pr-fast-${{ github.head_ref || github.ref_name }}${{ github.base_ref && format('-{0}', github.base_ref) || '' }}
36
+ <% if (_bs === 'github-flow-with-develop') { %>
37
+ cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/develop' }}
38
+ <% } else { %>
39
+ cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
40
+ <% } %>
41
+
42
+ jobs:
43
+ config-lint:
44
+ name: Config Lint (yaml + shell)
45
+ # gold-align (#1506 yamllint / #1507 shellcheck): a language-agnostic style/
46
+ # structure lint lane. yamllint checks non-workflow YAML (indentation, duplicate
47
+ # keys, trailing spaces, document structure) — complementary to actionlint, which
48
+ # owns .github/workflows *semantics*. shellcheck checks generated *.sh for unquoted
49
+ # expansions / unsafe word-splitting at warning severity. Both BLOCKING; both
50
+ # version-pinned for reproducibility. Each linter no-ops cleanly (green) when the
51
+ # repo carries no matching files. Committed .yamllint.yml / .shellcheckrc (when
52
+ # present) are auto-discovered and make the rules explicit + tunable.
53
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
54
+ timeout-minutes: 60
55
+ permissions:
56
+ contents: read
57
+ steps:
58
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
59
+ - name: Install shellcheck (pinned)
60
+ run: |
61
+ mkdir -p "$RUNNER_TEMP/bin"
62
+ curl -sSfL https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz \
63
+ | tar -xJ -C "$RUNNER_TEMP/bin" --strip-components=1 shellcheck-v0.10.0/shellcheck
64
+ echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
65
+ - name: shellcheck (generated shell, blocking at warning severity)
66
+ # .shellcheckrc (when present) is auto-discovered. No *.sh ⇒ no-op (green).
67
+ run: |
68
+ files=$(git ls-files '*.sh')
69
+ if [ -n "$files" ]; then
70
+ echo "$files" | xargs shellcheck --severity=warning
71
+ else
72
+ echo "shellcheck: no *.sh files — skipping"
73
+ fi
74
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
75
+ with:
76
+ python-version: '3.12'
77
+ - name: Install yamllint (pinned)
78
+ run: pip install yamllint==1.35.1
79
+ - name: yamllint (non-workflow YAML, blocking on errors)
80
+ # actionlint owns .github/workflows semantics; exclude them to avoid overlap.
81
+ # A committed .yamllint.yml (when present) is auto-discovered and authoritative;
82
+ # otherwise fall back to yamllint's built-in `relaxed` preset — both block on
83
+ # ERRORS only (line-length etc. stay advisory warnings). No matching YAML ⇒ no-op.
84
+ run: |
85
+ files=$(git ls-files '*.yml' '*.yaml' ':!.github/workflows/**')
86
+ if [ -n "$files" ]; then
87
+ if [ -f .yamllint.yml ] || [ -f .yamllint.yaml ] || [ -f .yamllint ]; then
88
+ echo "$files" | xargs yamllint
89
+ else
90
+ echo "$files" | xargs yamllint -d relaxed
91
+ fi
92
+ else
93
+ echo "yamllint: no non-workflow YAML — skipping"
94
+ fi
95
+ <% if (locals.enableSoloDevMode) { %>
96
+ solo-dev-gate:
97
+ name: Solo-Dev Gate (INV-59)
98
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
99
+ timeout-minutes: 60
100
+ steps:
101
+ - run: echo "solo-dev mode — local L2 gate guards merge via INV-59 parity check"
102
+ <% } else { %><% if (enableSecurityScanning) { %>
103
+ security-early-fail:
104
+ name: Security (PII + Secrets)
105
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
106
+ timeout-minutes: 60
107
+ steps:
108
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
109
+ with:
110
+ fetch-depth: 0
111
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
112
+ with:
113
+ node-version-file: '.nvmrc'
114
+ package-manager-cache: false
115
+ - name: PII scan (INV-12, HARD)
116
+ run: node scripts/pii-scan.mjs
117
+ - name: Install gitleaks
118
+ run: |
119
+ mkdir -p "$RUNNER_TEMP/bin"
120
+ curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.27.2/gitleaks_8.27.2_linux_x64.tar.gz | tar -xz -C "$RUNNER_TEMP/bin" gitleaks
121
+ echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
122
+ - name: Gitleaks secrets scan (INV-11)
123
+ # --log-opts="HEAD" (#1908): without it, gitleaks defaults to scanning
124
+ # ALL refs reachable in the checkout's object DB (fetch-depth: 0 above
125
+ # fetches every remote branch, not just this one). That let an unrelated,
126
+ # unmerged branch's commit cross-contaminate every other PR's scan.
127
+ # Scoping to HEAD still walks this ref's FULL history (no depth lost) —
128
+ # it just stops other branches' commits from being scanned here. The
129
+ # nightly `gitleaks-history` job intentionally keeps `--all --full-history`
130
+ # as the deep, cross-branch safety net.
131
+ run: |
132
+ gitleaks detect --source . --config .gitleaks.toml \
133
+ --gitleaks-ignore-path suppressions/.gitleaksignore \
134
+ --log-opts="HEAD" \
135
+ --exit-code 1 --redact
136
+ <% } %>
137
+ <% if (governanceLevel !== 'L1' || _multiLane) { %>
138
+ classify-changes:
139
+ name: Classify Changes
140
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
141
+ timeout-minutes: 60
142
+ outputs:
143
+ docs_only: ${{ steps.classify.outputs.docs_only }}
144
+ backend_changed: ${{ steps.classify.outputs.backend_changed }}
145
+ frontend_changed: ${{ steps.classify.outputs.frontend_changed }}
146
+ infra_changed: ${{ steps.classify.outputs.infra_changed }}
147
+ high_risk: ${{ steps.classify.outputs.high_risk }}
148
+ steps:
149
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
150
+ with:
151
+ fetch-depth: 0
152
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
153
+ with:
154
+ node-version-file: '.nvmrc'
155
+ package-manager-cache: false
156
+ - id: classify
157
+ if: hashFiles('scripts/ci-classify-changes.mjs') != ''
158
+ run: node scripts/ci-classify-changes.mjs
159
+ env:
160
+ BASE_SHA: ${{ github.event.pull_request.base.sha || 'origin/main' }}
161
+ HEAD_SHA: ${{ github.sha }}
162
+ <% } %>
163
+ <% if (_multiLane) { %>
164
+ cross-stack-guard:
165
+ name: Cross-Stack Guard
166
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
167
+ timeout-minutes: 60
168
+ needs: [classify-changes]
169
+ if: github.event_name == 'pull_request'
170
+ permissions:
171
+ pull-requests: write
172
+ steps:
173
+ <% if (isL3Plus) { %>
174
+ - name: Enforce cross-stack split
175
+ if: needs.classify-changes.outputs.backend_changed == 'true' && needs.classify-changes.outputs.frontend_changed == 'true'
176
+ run: |
177
+ echo "::error::This PR touches both frontend and backend lanes. Split into separate PRs."
178
+ exit 1
179
+ <% } else { %>
180
+ - name: Warn cross-stack changes
181
+ if: needs.classify-changes.outputs.backend_changed == 'true' && needs.classify-changes.outputs.frontend_changed == 'true'
182
+ continue-on-error: true
183
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
184
+ with:
185
+ github-token: ${{ secrets.GITHUB_TOKEN }}
186
+ script: |
187
+ github.rest.issues.createComment({
188
+ issue_number: context.issue.number,
189
+ owner: context.repo.owner,
190
+ repo: context.repo.repo,
191
+ body: '> [!WARNING]\n> This PR touches both **frontend** and **backend** lanes. Consider splitting into separate PRs for cleaner review and safer deployment.'
192
+ })
193
+ <% } %>
194
+ <% } %>
195
+ <% if (enableSecurityScanning) { %> dependency-review:
196
+ name: Dependency Review (supply-chain)
197
+ # A1 (#1502): the canonical FAST PR supply-chain gate. dependency-review-action
198
+ # diffs the PR's dependency-manifest changes and fails on a newly-introduced
199
+ # vulnerable dependency — keeping slow full-tree scanners off the always-path.
200
+ # PR-only (the action diffs base...head and errors on push). Fail severity is
201
+ # configurable via the DEPENDENCY_REVIEW_FAIL_SEVERITY repo variable (default: high).
202
+ # Floor: enableSecurityScanning — the same always-path gate as security-early-fail.
203
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
204
+ timeout-minutes: 60
205
+ # PR-only AND GHAS-gated (#1685): dependency-review-action HARD-errors when the
206
+ # repo lacks Dependency Graph + GitHub Advanced Security, which reds every PR
207
+ # while GHAS is off. A JOB-LEVEL guard makes the job SKIP (result=skipped, which
208
+ # the ci-required aggregator treats as non-failure) until GHAS is enabled by
209
+ # setting the GHAS_ENABLED repo variable to 'true'. NOT step-level
210
+ # continue-on-error: that would violate INV-80 and silently neuter the gate once
211
+ # GHAS is on. With the var set, a real finding still fails the job and blocks.
212
+ if: github.event_name == 'pull_request' && vars.GHAS_ENABLED == 'true'
213
+ permissions:
214
+ contents: read
215
+ steps:
216
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
217
+ - name: Dependency review (fail on newly-introduced high-severity deps)
218
+ uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
219
+ with:
220
+ fail-on-severity: ${{ vars.DEPENDENCY_REVIEW_FAIL_SEVERITY || 'high' }}
221
+ <% } %>
222
+ <% if (governanceLevel !== 'L1' || _multiLane) { %> iac-scan:
223
+ name: IaC Scan (infra-changed)
224
+ # A1 (#1502): consume the classify-changes `infra_changed` signal (previously
225
+ # classified but UNUSED) — scan terraform / kubernetes / dockerfile only when the
226
+ # PR actually touches infrastructure-as-code, keeping the always-path lean.
227
+ # #1785: was pinned to a LITERAL `runs-on: ubuntu-latest` on the (disproven)
228
+ # assumption that GitHub-hosted runners are never containerized (#1756).
229
+ # Evidence (run 28693108584) showed a job pinned to literal `ubuntu-latest`
230
+ # actually serviced by self-hosted `arbiter-slot-build-3` — the label alone
231
+ # never guaranteed real GitHub-hosted infra here. Rather than keep trusting
232
+ # an unverified runner label, Checkov now runs as a plain pip-installed CLI
233
+ # (bridgecrewio/checkov-action was only a Docker convenience wrapper around
234
+ # it) — no docker-container action, no workspace bind-mount, the whole
235
+ # defect class sidestepped entirely (same pattern as the osv-scanner static-
236
+ # binary fix, #1767). Enforced by scripts/check-docker-action-runner-safety.mjs.
237
+ # #1894: routed through the same `RUNNER_LABELS_TEST` expression as every other
238
+ # job. The former literal `ubuntu-latest` used to be intercepted by the self-
239
+ # hosted fleet (#1785 evidence), but the fleet dropped the `ubuntu-latest`
240
+ # label, so the literal pin fell through to real GitHub-hosted infra and failed
241
+ # (spending-limit block). The expression defaults to `["ubuntu-latest"]` when
242
+ # the var is unset (consumers unaffected); arbiter's own repo sets it to the
243
+ # self-hosted labels. Checkov/tflint are plain CLIs (no docker-action), so the
244
+ # runner class remains moot for the #1785 safety class either way.
245
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
246
+ timeout-minutes: 60
247
+ needs: [classify-changes]
248
+ if: needs.classify-changes.outputs.infra_changed == 'true'
249
+ permissions:
250
+ contents: read
251
+ steps:
252
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
253
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
254
+ with:
255
+ python-version: '3.12'
256
+ - name: Install Checkov (pinned, no Docker — #1785)
257
+ run: pip install checkov==3.3.7
258
+ - name: Checkov IaC scan (<%= locals.checkovSelfScope ? 'terraform/kubernetes/dockerfile' : 'all frameworks' %>)
259
+ run: |
260
+ <% if (locals.checkovSelfScope) { -%>
261
+ # #1685 (arbiter self-scan): `all` over-scoped THIS repo (github_actions
262
+ # + secrets policies across dozens of workflows/fixtures) even though
263
+ # arbiter carries ZERO terraform/kubernetes/dockerfile IaC — redding
264
+ # self-CI. `--framework` takes repeated values (checkov's own nargs='+'
265
+ # CLI, no word-splitting footgun now that the docker-action wrapper is
266
+ # gone, #1785): 0 findings — honestly SCOPED, not soft-fail-suppressed.
267
+ # Hard-fail stays checkov's default (no soft-fail flag passed): a real
268
+ # misconfig would still block (INV-80). Self-only; consumers (the
269
+ # shipped template's `else` branch below) are NOT affected.
270
+ checkov --directory . --framework terraform kubernetes dockerfile --quiet --compact
271
+ <% } else { -%>
272
+ # #1685: `all` is checkov's documented-valid multi-framework value (also
273
+ # its own default scope). Hard-fail stays the default (no soft-fail
274
+ # flag passed): a real misconfiguration must block (INV-80).
275
+ checkov --directory . --framework all --quiet --compact
276
+ <% } -%>
277
+ # #1509 gold-align: Checkov scans for known misconfigurations; tflint is the
278
+ # Terraform-specific *linter* (provider-aware deprecations, invalid arg
279
+ # combinations, unused declarations). Reference-grade IaC pipelines run it
280
+ # BLOCKING — no soft-fail. `--recursive` exits 0 when the repo carries no
281
+ # `.tf` files, so non-Terraform infra changes (k8s/dockerfile) stay green.
282
+ - name: Setup tflint (Terraform linter)
283
+ uses: terraform-linters/setup-tflint@6e1e0642c0289bd619021bf6b34e3c08ed1e005a # v6.3.0
284
+ - name: tflint (Terraform lint, blocking)
285
+ run: tflint --recursive --no-color
286
+ <% } %>
287
+ <% if (language === 'typescript') { %>
288
+ <% const _tsNeeds=[]; if(enableSecurityScanning) _tsNeeds.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _tsNeeds.push('classify-changes'); %>
289
+ <% if (locals.ciPreTestBuild) { %> build-workspace:
290
+ name: Build Workspace (cache)
291
+ # E2 (#1500): build dist ONCE and share it run-id-keyed via the build-cache
292
+ # composite, instead of unit/contract/integration/behavioral each re-running
293
+ # `npm run build`. The composite's restore is non-blocking (cache miss ⇒ rebuild).
294
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
295
+ timeout-minutes: 60
296
+ <% { const _bwNeeds=[]; if(governanceLevel !== 'L1' || _multiLane) _bwNeeds.push('classify-changes'); if(_bwNeeds.length){ %> needs: [<%= _bwNeeds.join(', ') %>]
297
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
298
+ <% } } %> steps:
299
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
300
+ - uses: ./.github/actions/setup-node-pnpm
301
+ - name: Build + cache workspace (shared via run-id key)
302
+ uses: ./.github/actions/build-cache
303
+ with:
304
+ op: save
305
+
306
+ <% } %> gate:
307
+ name: Lint + Typecheck
308
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
309
+ timeout-minutes: 60
310
+ <% if(_tsNeeds.length){ %> needs: [<%= _tsNeeds.join(', ') %>]
311
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
312
+ <% } %> steps:
313
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
314
+ - uses: ./.github/actions/setup-node-pnpm
315
+ - run: npm run typecheck
316
+ - run: npm run lint
317
+ <% if (enableSecurityScanning) { %>
318
+ - name: Dep audit (INV-13)
319
+ run: npm audit --omit=dev --audit-level=high
320
+ <% } %>
321
+
322
+ <% if (!locals.enableNativeBakeE2E) { %> unit-tests:
323
+ name: Unit Tests
324
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
325
+ timeout-minutes: 60
326
+ needs: [gate<% if (language === 'typescript' && locals.ciPreTestBuild) { %>, build-workspace<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
327
+ strategy:
328
+ max-parallel: 2
329
+ <% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
330
+ <% } %> steps:
331
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
332
+ with:
333
+ # TDD evidence can name an older commit; reachability requires history.
334
+ fetch-depth: 0
335
+ - uses: ./.github/actions/setup-node-pnpm
336
+ <% if (locals.ciPreTestBuild) { %> - name: Restore cached workspace build (non-blocking)
337
+ uses: ./.github/actions/build-cache
338
+ with:
339
+ op: restore
340
+ - run: node scripts/build-kit.mjs
341
+ <% } %> - name: Install psmisc (fuser — #2098 gate-exec queue-depth advisory)
342
+ # scripts/lib/waiter-count.mjs shells out to `fuser` to count real flock
343
+ # waiters; unlike gitleaks/actionlint (single-binary GitHub-release
344
+ # tarballs, pinned in scripts/ci-tools.json), psmisc has no such release
345
+ # artifact, so apt is the install path here. flock itself (util-linux)
346
+ # is already present on the runner image; only fuser (psmisc) is missing.
347
+ # Root (self-hosted) uses apt-get directly; non-root (e.g. GitHub-hosted
348
+ # ubuntu-latest, where every consumer of this template lands by default)
349
+ # needs sudo. Skip entirely if fuser is already on PATH.
350
+ run: |
351
+ if ! command -v fuser >/dev/null 2>&1; then
352
+ if [ "$(id -u)" -eq 0 ]; then
353
+ apt-get update -qq && apt-get install -y -qq psmisc
354
+ else
355
+ sudo apt-get update -qq && sudo apt-get install -y -qq psmisc
356
+ fi
357
+ fi
358
+ # `--reporter=junit` ALONE replaces the console reporter, so a failing run
359
+ # names no test in the job log — the only record is the uploaded junit.xml,
360
+ # which is unreadable from a webhook or a log tail. Both reporters are
361
+ # passed so the log stays diagnosable and the artifact keeps its schema;
362
+ # `--outputFile.junit=` is the per-reporter form vitest requires once more
363
+ # than one reporter is active.
364
+ - run: npm run test:unit<% if (enableDebtGates) { %> -- --reporter=default --reporter=junit --outputFile.junit=test-results/junit.xml<% } %>
365
+ <% if (enableDebtGates) { %>
366
+ - name: Upload test results
367
+ id: upload-test-results
368
+ if: always()
369
+ # Supplementary artifact — never let an Artifacts-quota hiccup fail the
370
+ # job whose actual signal (the test run above) already passed.
371
+ continue-on-error: true
372
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
373
+ with:
374
+ name: test-results-unit-${{ github.run_id }}
375
+ path: test-results/
376
+ retention-days: 7
377
+ <% } %>
378
+ <% } -%>
379
+ <%# #1875: contract-tests/integration-tests/behavioral-tests moved OFF the
380
+ always-run T1 lane to 02-pr-extended.yml.ejs (T2, conditionally triggered).
381
+ They used to fan out from `gate` unconditionally on every PR — on arbiter's
382
+ own dogfooded CI, `contract-tests` alone measured ~12min, blowing the
383
+ 15min T1 budget (ADR-090). docs/REFERENCE/ci-tier-workflows.md already
384
+ documented the "Extended gate" tier as the correct home for this suite;
385
+ the template just hadn't caught up. -%>
386
+
387
+ <% } %><% if (language === 'rust') { %>
388
+ gate:
389
+ name: Lint + Test (Rust)
390
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
391
+ timeout-minutes: 60
392
+ <% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _n.push('classify-changes'); if(_n.length){ %> needs: [<%= _n.join(', ') %>]
393
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
394
+ <% } } %> steps:
395
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
396
+ - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
397
+ with:
398
+ components: clippy, rustfmt
399
+ - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
400
+ - run: cargo fmt --check
401
+ - run: cargo clippy -- -D warnings
402
+ - run: cargo test
403
+ <% if (enableSecurityScanning) { %>
404
+ - name: Dep audit (INV-13)
405
+ uses: rustsec/audit-check@e9159ac5f7d7d873ce074ca134da2f445c0a4a61 # v1
406
+ with:
407
+ token: ${{ secrets.GITHUB_TOKEN }}
408
+ <% } %>
409
+ <% } %><% if (language === 'java') { %>
410
+ <% const _javaNeeds=[]; if(enableSecurityScanning) _javaNeeds.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _javaNeeds.push('classify-changes'); %>
411
+ <% /* #1278: build-reactor runs in PARALLEL with security-early-fail (not after it) to keep the maven critical path under the 15m T1 budget. security still HARD-blocks merge via ci-required, and `gate` (lint) still gates on it, preserving the early-fail signal on the lint lane. Tradeoff: wasted compile compute on a security-failing PR — not lost coverage or developer feedback. */ const _reactorNeeds=[]; if(governanceLevel !== 'L1' || _multiLane) _reactorNeeds.push('classify-changes'); %>
412
+ <% if (buildTool === 'maven') { %> build-reactor:
413
+ name: Build Maven Reactor (#1226)
414
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
415
+ permissions:
416
+ contents: read
417
+ <% if(_reactorNeeds.length){ %> needs: [<%= _reactorNeeds.join(', ') %>]
418
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
419
+ <% } %> steps:
420
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
421
+ - uses: ./.github/actions/setup-java-maven
422
+ - name: Pre-fetch plugins and dependencies (offline cache)
423
+ run: mvn dependency:go-offline --batch-mode -q
424
+ - name: Build reactor (compile main + test classes, skip test execution)
425
+ # -DskipTests runs the test-compile phase but skips execution, so
426
+ # target/classes and target/test-classes are produced once here and
427
+ # reused by every test job below — no per-job recompile (#1278).
428
+ run: mvn --batch-mode -DskipTests install
429
+ - name: Pack M2 repository + compiled target/ trees
430
+ # m2-reactor.tar stays byte-identical to its prior form (rooted at $HOME/.m2).
431
+ # target-reactor.tar is additive (#1278): every module's compiled target/
432
+ # (main + test classes) in its own tar rooted at the workspace, so downstream
433
+ # run-only test goals (surefire:test) never recompile.
434
+ run: |
435
+ mkdir -p "${{ runner.temp }}/.m2-reactor"
436
+ tar -cf "${{ runner.temp }}/.m2-reactor/m2-reactor.tar" -C "$HOME/.m2" repository
437
+ find . -type d -name target -prune -print0 \
438
+ | tar -cf "${{ runner.temp }}/.m2-reactor/target-reactor.tar" --null -T -
439
+ - name: Upload reactor M2 + target artifact
440
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
441
+ with:
442
+ name: reactor-m2-${{ github.run_id }}
443
+ path: ${{ runner.temp }}/.m2-reactor/*.tar
444
+ retention-days: 7
445
+ overwrite: true
446
+
447
+ <% } %> gate:
448
+ name: Lint (Java)
449
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
450
+ <% { const _gateNeeds=[..._javaNeeds]; if(buildTool === 'maven') _gateNeeds.push('build-reactor'); if(_gateNeeds.length){ %> needs: [<%= _gateNeeds.join(', ') %>]
451
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
452
+ <% } } %> steps:
453
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
454
+ - uses: ./.github/actions/setup-java-maven
455
+ <% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
456
+ - run: ./gradlew checkstyleMain
457
+ <%# E1 (#1502): Trivy fs (dep CVE) runs at nightly cadence in 06-nightly
458
+ `dep-cve-refresh`, not on the PR gate. The INV-13 dep-audit floor for java is
459
+ preserved there. -%>
460
+ <% } else { %> - name: Download reactor M2 artifact
461
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
462
+ with:
463
+ name: reactor-m2-${{ github.run_id }}
464
+ path: ${{ runner.temp }}/.m2-reactor
465
+ - run: mvn checkstyle:check --offline
466
+ <%# E1 (#1502): Trivy fs (dep CVE) runs at nightly cadence in 06-nightly `dep-cve-refresh`. -%>
467
+ <% } %>
468
+
469
+ unit-tests:
470
+ name: Unit Tests (Java)
471
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
472
+ timeout-minutes: 60
473
+ <% if(buildTool === 'maven'){ /* tests need compiled classes from build-reactor, not lint; off the gate hop (#1278) */ %> needs: [build-reactor<% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
474
+ <% } else { %> needs: [gate<% if (language === 'typescript' && locals.ciPreTestBuild) { %>, build-workspace<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
475
+ <% } %> strategy:
476
+ max-parallel: 2
477
+ <% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
478
+ <% } %> steps:
479
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
480
+ - uses: ./.github/actions/setup-java-maven
481
+ <% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
482
+ - run: ./gradlew test
483
+ <% if (enableDebtGates) { %>
484
+ - name: Upload test results
485
+ id: upload-test-results
486
+ if: always()
487
+ # Supplementary artifact — never let an Artifacts-quota hiccup fail the
488
+ # job whose actual signal (the test run above) already passed.
489
+ continue-on-error: true
490
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
491
+ with:
492
+ name: test-results-unit-${{ github.run_id }}
493
+ path: build/test-results/
494
+ retention-days: 7
495
+ <% } %>
496
+ <% } else { %> - name: Download reactor M2 artifact
497
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
498
+ with:
499
+ name: reactor-m2-${{ github.run_id }}
500
+ path: ${{ runner.temp }}/.m2-reactor
501
+ - run: mvn surefire:test -Punit --offline
502
+ <% if (enableDebtGates) { %>
503
+ - name: Upload test results
504
+ id: upload-test-results
505
+ if: always()
506
+ # Supplementary artifact — never let an Artifacts-quota hiccup fail the
507
+ # job whose actual signal (the test run above) already passed.
508
+ continue-on-error: true
509
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
510
+ with:
511
+ name: test-results-unit-${{ github.run_id }}
512
+ path: target/surefire-reports/
513
+ retention-days: 7
514
+ <% } %>
515
+ <% } %>
516
+
517
+ <% if (governanceLevel !== 'L1') { %> archunit-tests:
518
+ name: ArchUnit Architecture Tests (Java)
519
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
520
+ timeout-minutes: 30
521
+ # #1512 gold-align: the lightweight *ArchTest JUnit5 architecture rules
522
+ # (dependency-direction / layering / package-boundary) run BLOCKING on EVERY PR.
523
+ # Previously they ran only on the weekly 13-archunit-extended cron, leaving up to a
524
+ # 7-day fake-green window for a merged architecture regression. The heavier
525
+ # full module-graph analysis (the Modulith suite) stays on that weekly cron.
526
+ <% if(buildTool === 'maven'){ %> needs: [build-reactor<% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
527
+ <% } else { %> needs: [gate<% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
528
+ <% } %><% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
529
+ <% } %> steps:
530
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
531
+ - uses: ./.github/actions/setup-java-maven
532
+ <% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
533
+ - run: ./gradlew test --tests "*ArchTest"
534
+ <% } else { %> - name: Download reactor M2 artifact
535
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
536
+ with:
537
+ name: reactor-m2-${{ github.run_id }}
538
+ path: ${{ runner.temp }}/.m2-reactor
539
+ - run: mvn surefire:test -Dtest="*ArchTest" --offline
540
+ <% } %>
541
+ <% } %>
542
+ <%# #1875: contract-tests/integration-tests/behavioral-tests (Java) moved OFF
543
+ the always-run T1 lane to 02-pr-extended.yml.ejs (T2, conditionally
544
+ triggered) — mirrors the TypeScript move above. -%>
545
+
546
+ <% } %><% if (language === 'go') { %>
547
+ gate:
548
+ name: Lint + Test (Go)
549
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
550
+ timeout-minutes: 60
551
+ <% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _n.push('classify-changes'); if(_n.length){ %> needs: [<%= _n.join(', ') %>]
552
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
553
+ <% } } %> steps:
554
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
555
+ - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
556
+ with:
557
+ go-version-file: 'go.mod'
558
+ - run: go vet ./...
559
+ - run: golangci-lint run
560
+ - run: go test ./... -race -coverprofile=coverage.out
561
+ <% if (enableSecurityScanning) { %>
562
+ - name: Dep audit govulncheck (INV-13)
563
+ uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1
564
+ with:
565
+ # The action re-checkouts by default; after the explicit checkout above the
566
+ # second internal checkout adds a duplicate Authorization extraheader and
567
+ # git fails with 400 "Duplicate header" on private repos (#1865).
568
+ repo-checkout: false
569
+ <% } %>
570
+ <% } %><% if (language === 'python') { %>
571
+ gate:
572
+ name: Lint + Test (Python)
573
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
574
+ timeout-minutes: 60
575
+ <% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); if(governanceLevel !== 'L1' || _multiLane) _n.push('classify-changes'); if(_n.length){ %> needs: [<%= _n.join(', ') %>]
576
+ <% } if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
577
+ <% } } %> steps:
578
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
579
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
580
+ with:
581
+ python-version: '3.12'
582
+ cache: 'pip'
583
+ - run: pip install -e ".[dev]"
584
+ - run: ruff check .
585
+ - run: ruff format --check .
586
+ - run: pytest --cov --junitxml=test-results/junit.xml
587
+ <% if (enableSecurityScanning) { %>
588
+ - name: Dep audit (INV-13)
589
+ run: pip-audit
590
+ <% } %>
591
+ <% if (enableDebtGates) { %>
592
+ - name: Upload test results
593
+ id: upload-test-results
594
+ if: always()
595
+ # Supplementary artifact — never let an Artifacts-quota hiccup fail the
596
+ # job whose actual signal (the test run above) already passed.
597
+ continue-on-error: true
598
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
599
+ with:
600
+ name: test-results-${{ github.run_id }}
601
+ path: test-results/
602
+ retention-days: 7
603
+ <% } %>
604
+ <% } %>
605
+
606
+ <% if (governanceLevel !== 'L1') { %>
607
+ docs-check:
608
+ name: Docs Check
609
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
610
+ timeout-minutes: 60
611
+ if: github.event_name == 'pull_request'
612
+ steps:
613
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
614
+ with:
615
+ fetch-depth: 0
616
+ - name: Check docs updated with code changes
617
+ env:
618
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
619
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
620
+ run: |
621
+ # #356: rebased-aware via merge-base; bypass via [skip-docs] commit token.
622
+ MB=$(git merge-base "$BASE_SHA" "$HEAD_SHA" || echo "$BASE_SHA")
623
+ CHANGED=$(git diff --name-only "$MB" "$HEAD_SHA")
624
+ LOG=$(git log --format=%B "$MB..$HEAD_SHA" || true)
625
+
626
+ HAS_CODE=$(echo "$CHANGED" | grep -E '^(src/|__tests__/)' || true)
627
+ HAS_DOCS=$(echo "$CHANGED" | grep -E '^(docs/|README\.md)' || true)
628
+ BYPASS=$(echo "$LOG" | grep -F '[skip-docs]' || true)
629
+
630
+ if [ -n "$HAS_CODE" ] && [ -z "$HAS_DOCS" ] && [ -z "$BYPASS" ]; then
631
+ echo "::error::Code changed without documentation update"
632
+ echo ""
633
+ echo "Files changed in src/ or __tests__/:"
634
+ echo "$HAS_CODE"
635
+ echo ""
636
+ echo "Please update docs/ or README.md, or add [skip-docs] to a commit message to bypass."
637
+ exit 1
638
+ fi
639
+ echo "Docs check passed."
640
+ <% } %>
641
+
642
+ <% if (enableDebtGates) { %>
643
+ debt-gates:
644
+ name: Tech Debt Gates
645
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
646
+ timeout-minutes: 60
647
+ needs: [gate]
648
+ # E1 (#1502): the PR leg keeps only the FAST static-analysis gates
649
+ # (knip/madge/pmd/spotbugs/clippy/ruff/golangci). The whole-suite coverage
650
+ # re-run that used to live here was a SECOND full test execution on the PR
651
+ # (the unit/integration jobs already ran the suite, and `gate-full` runs
652
+ # check-all L2 which enforces the coverage threshold). The threshold floor is
653
+ # therefore preserved on PR via gate-full; the heavy coverage report (HTML/lcov
654
+ # artifact) is produced at nightly cadence in 06-nightly `coverage-report`.
655
+ steps:
656
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
657
+ <% if (language === 'typescript') { %>
658
+ - uses: ./.github/actions/setup-node-pnpm
659
+ <% if (locals.ciPreTestBuild) { %> - run: npm run build && node scripts/build-kit.mjs
660
+ <% } %> - run: npx knip
661
+ - run: npx madge --circular --extensions ts,tsx,js,jsx src
662
+ <% } %><% if (language === 'rust') { %>
663
+ - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
664
+ with:
665
+ components: clippy
666
+ - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
667
+ - run: cargo clippy -- -W clippy::pedantic -D warnings
668
+ <% } %><% if (language === 'java') { %>
669
+ - uses: ./.github/actions/setup-java-maven
670
+ <% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
671
+ - run: ./gradlew pmdMain
672
+ - run: ./gradlew spotbugsMain
673
+ <% } else { %> - name: Download reactor M2 artifact
674
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
675
+ with:
676
+ name: reactor-m2-${{ github.run_id }}
677
+ path: ${{ runner.temp }}/.m2-reactor
678
+ - run: mvn pmd:check --offline
679
+ - run: mvn spotbugs:check --offline
680
+ <% } %><% } %><% if (language === 'go') { %>
681
+ - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
682
+ with:
683
+ go-version-file: 'go.mod'
684
+ - run: golangci-lint run --enable gocyclo,gocognit,deadcode,unused
685
+ <% } %><% if (language === 'python') { %>
686
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
687
+ with:
688
+ python-version: '3.12'
689
+ cache: 'pip'
690
+ - run: pip install -e ".[dev]"
691
+ - run: ruff check --select C901,PLR0911,PLR0912,PLR0913,PLR0915 .
692
+ - run: ruff check --select F401,F811 .
693
+ <% } %>
694
+ <% } %>
695
+
696
+ <% if (governanceLevel !== 'L1') { %>
697
+ sonar-scan:
698
+ name: SonarCloud Scan
699
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
700
+ timeout-minutes: 60
701
+ needs: [gate]
702
+ steps:
703
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
704
+ with:
705
+ fetch-depth: 0
706
+ <% if (language === 'java') { %>
707
+ - uses: ./.github/actions/setup-java-maven
708
+ <% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
709
+ <% } %><% } else if (language === 'typescript') { %>
710
+ - uses: ./.github/actions/setup-node-pnpm
711
+ <% } %>
712
+ <% const _sonarCmd = (language === 'java' && buildTool === 'gradle') ? './gradlew sonarqube' : (language === 'java') ? 'mvn sonar:sonar' : 'npx sonar-scanner'; %>
713
+ - name: SonarCloud Scan (PR decoration — incremental new-code analysis)
714
+ # E1 (#1502): on PRs Sonar runs in pull-request mode — it decorates the PR
715
+ # with new-code findings only (incremental), NOT a full deep scan. The full
716
+ # branch baseline runs on merge-to-main below and nightly (06-nightly
717
+ # `sonar-deep-scan`), keeping the PR path fast.
718
+ if: env.SONAR_TOKEN != '' && github.event_name == 'pull_request'
719
+ env:
720
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
721
+ # untrusted refs pass through env (never inlined into the script body).
722
+ PR_KEY: ${{ github.event.pull_request.number }}
723
+ PR_BRANCH: ${{ github.head_ref }}
724
+ PR_BASE: ${{ github.base_ref }}
725
+ run: |
726
+ <%= _sonarCmd %> -Dsonar.token="$SONAR_TOKEN" \
727
+ -Dsonar.pullrequest.key="$PR_KEY" \
728
+ -Dsonar.pullrequest.branch="$PR_BRANCH" \
729
+ -Dsonar.pullrequest.base="$PR_BASE"
730
+ - name: SonarCloud Scan (full branch baseline)
731
+ # Push to a long-lived branch refreshes the full-project baseline so the
732
+ # PR decoration above has a fresh reference to diff new code against.
733
+ if: env.SONAR_TOKEN != '' && github.event_name != 'pull_request'
734
+ env:
735
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
736
+ run: |
737
+ <%= _sonarCmd %> -Dsonar.token="$SONAR_TOKEN"
738
+ <% } %>
739
+
740
+ <% if (contractType && contractType !== 'none' && governanceLevel !== 'L1') { %>
741
+
742
+ contract-verify:
743
+ name: Contract Verify
744
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
745
+ timeout-minutes: 60
746
+ needs: [gate]
747
+ steps:
748
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
749
+ <% if (language === 'typescript') { %>
750
+ - uses: ./.github/actions/setup-node-pnpm
751
+ <% if (contractType === 'rest-owned' || contractType === 'rest-public') { %>
752
+ - name: Run Pact contract tests
753
+ if: vars.PACT_BROKER_BASE_URL != ''
754
+ run: npx pact-broker can-i-deploy --pacticipant <%= projectName %> --latest
755
+ env:
756
+ PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }}
757
+ PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
758
+ <% } else if (contractType === 'graphql') { %>
759
+ - name: Run GraphQL schema contract tests
760
+ run: npx graphql-inspector diff schema.graphql
761
+ <% } else if (contractType === 'grpc') { %>
762
+ - name: Run gRPC contract tests
763
+ run: npx buf breaking --against .git#branch=main
764
+ <% } else if (contractType === 'message-queue') { %>
765
+ - name: Run Pact messaging contract tests
766
+ if: vars.PACT_BROKER_BASE_URL != ''
767
+ run: npx pact-broker can-i-deploy --pacticipant <%= projectName %> --latest
768
+ env:
769
+ PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }}
770
+ PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
771
+ <% } %>
772
+ <% } else if (language === 'java') { %>
773
+ - uses: ./.github/actions/setup-java-maven
774
+ <% if (buildTool === 'gradle') { %> - uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3
775
+ <% } %>
776
+ <% if (contractType === 'rest-owned' || contractType === 'rest-public' || contractType === 'message-queue') { %>
777
+ - name: Run Pact contract tests
778
+ if: vars.PACT_BROKER_BASE_URL != ''
779
+ run: <%= buildTool === 'gradle' ? './gradlew pactPublish pactVerify' : 'mvn pact:publish pact:verify' %>
780
+ env:
781
+ PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }}
782
+ PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
783
+ <% } else if (contractType === 'graphql') { %>
784
+ - name: Run GraphQL contract tests
785
+ run: <%= buildTool === 'gradle' ? './gradlew test --tests *.graphql.*' : 'mvn test -Dtest=*GraphQL*' %>
786
+ <% } else if (contractType === 'grpc') { %>
787
+ - name: Run gRPC contract tests
788
+ run: <%= buildTool === 'gradle' ? './gradlew test --tests *.grpc.*' : 'mvn test -Dtest=*Grpc*' %>
789
+ <% } %>
790
+ <% } else if (language === 'rust') { %>
791
+ - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
792
+ - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
793
+ - name: Run contract tests
794
+ run: cargo test --test '*contract*'
795
+ <% } else if (language === 'go') { %>
796
+ - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
797
+ with:
798
+ go-version-file: 'go.mod'
799
+ - name: Run contract tests
800
+ run: go test -tags contract -run Contract ./...
801
+ <% } else if (language === 'python') { %>
802
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
803
+ with:
804
+ python-version: '3.12'
805
+ cache: 'pip'
806
+ - run: pip install -e ".[dev]"
807
+ - name: Run contract tests
808
+ run: pytest tests/contract/
809
+ <% } %>
810
+ <% } %>
811
+ <% if (governanceLevel !== 'L1') { %>
812
+ gate-full:
813
+ name: Full Gate (L2, INV-59)
814
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
815
+ <% { const _n=[]; if(enableSecurityScanning) _n.push('security-early-fail'); _n.push('classify-changes'); %>
816
+ needs: [<%= _n.join(', ') %>]
817
+ if: needs.classify-changes.outputs.docs_only != 'true'
818
+ <% } %>
819
+ timeout-minutes: 60
820
+ steps:
821
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
822
+ with:
823
+ fetch-depth: 0
824
+ <% if (language === 'typescript') { %>
825
+ - uses: ./.github/actions/setup-node-pnpm
826
+ <% } else { %>
827
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
828
+ with:
829
+ node-version-file: '.nvmrc'
830
+ package-manager-cache: false
831
+ <% } %>
832
+ - name: Install gitleaks
833
+ run: |
834
+ mkdir -p "$RUNNER_TEMP/bin"
835
+ curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.27.2/gitleaks_8.27.2_linux_x64.tar.gz | tar -xz -C "$RUNNER_TEMP/bin" gitleaks
836
+ echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
837
+ - name: Install actionlint
838
+ run: |
839
+ mkdir -p "$RUNNER_TEMP/bin"
840
+ curl -sSfL https://github.com/rhysd/actionlint/releases/download/v1.7.3/actionlint_1.7.3_linux_amd64.tar.gz | tar -xz -C "$RUNNER_TEMP/bin" actionlint
841
+ echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
842
+ - name: Install psmisc (fuser — #2098 gate-exec queue-depth advisory)
843
+ # Mirrors the identical step in the Unit Tests job (see there for the
844
+ # full rationale) so this job's own gate-exec queue-depth advisory
845
+ # works too, independent of whether Unit Tests already ran on this
846
+ # runner. For arbiter's own repo, `check-all.mjs L2` below also runs
847
+ # the waiter-count/gate-exec test suite directly.
848
+ run: |
849
+ if ! command -v fuser >/dev/null 2>&1; then
850
+ if [ "$(id -u)" -eq 0 ]; then
851
+ apt-get update -qq && apt-get install -y -qq psmisc
852
+ else
853
+ sudo apt-get update -qq && sudo apt-get install -y -qq psmisc
854
+ fi
855
+ fi
856
+ - name: Build
857
+ run: npm run build<% if (locals.ciPreTestBuild) { %> && node scripts/build-kit.mjs<% } %>
858
+ - name: Gate-spine erosion ratchet (#2291)
859
+ # DELIBERATELY its own step, ahead of and independent of check-all.mjs.
860
+ # This gate fails when `arbiter update` had to WITHHOLD a protected file —
861
+ # most importantly scripts/check-all.mjs itself, the file where this project
862
+ # wires its own checks. Registering it only in gate-registry.yml would deliver
863
+ # it through scripts/check-all.mjs, i.e. through the very file being withheld:
864
+ # on a project whose spine is frozen the ratchet would never run, and the
865
+ # erosion it exists to catch would stay invisible for exactly as long as it
866
+ # matters. Workflows are arbiter-owned and are not withheld, so this step
867
+ # reaches a frozen consumer. Do not fold it into the gate step below.
868
+ run: node scripts/check-safety-adopt-ratchet.mjs
869
+ - name: Run full L2 gate (== pre-push)
870
+ run: node scripts/check-all.mjs L2 --json gate-result.json
871
+ - name: Upload gate-result artifact (activates INV-59 runtime parity)
872
+ id: upload-gate-result
873
+ if: always()
874
+ # check-local-ci-parity.mjs already treats a missing gate-result artifact
875
+ # as a graceful skip, not a hard failure — an Artifacts-quota hiccup on
876
+ # this upload must not fail the job the real gate already ran in.
877
+ continue-on-error: true
878
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
879
+ with:
880
+ name: gate-result
881
+ path: gate-result.json
882
+ retention-days: 7
883
+ <% } %>
884
+
885
+ <% if (_humanApproval) { %> human-approval-required:
886
+ name: Human Approval Required (INV-74)
887
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
888
+ if: github.event_name == 'pull_request'
889
+ steps:
890
+ - name: Assert approved-by-human label (anti-bot gate)
891
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
892
+ with:
893
+ github-token: ${{ secrets.GITHUB_TOKEN }}
894
+ script: |
895
+ const labels = context.payload.pull_request.labels.map(l => l.name);
896
+ if (!labels.includes('approved-by-human')) {
897
+ core.setFailed(
898
+ 'PR requires the "approved-by-human" label applied by a human reviewer. ' +
899
+ 'See 03-human-approval.yml — a bot approval does not satisfy this check.'
900
+ );
901
+ }
902
+ <% } %>
903
+ <% if (language === 'typescript' && locals.enableNativeBakeE2E) { %> generated-gate-min:
904
+ name: Generated-gate min cell (TS, the gate-thesis on every PR)
905
+ # B5 (arbiter audit, gate-thesis reliability): arbiter's core promise —
906
+ # `arbiter init` on a project → the GENERATED project's own gate is green out
907
+ # of the box — was proven only nightly (generated-gate-e2e in _nightly.yml,
908
+ # VITEST_L2=1) or weekly (generator-matrix.yml). A regression in that promise
909
+ # could land on main and ride unnoticed for up to 24h. This is the minimal,
910
+ # fast slice of that same proof (ts-backend-web-db + ts-library — the two
911
+ # TypeScript functional-tier fixtures, ~25-30s locally) promoted to a
912
+ # PR-required check so the thesis is verified on every merge, not just at
913
+ # night. The other 4 languages' cells stay nightly-only (their toolchain
914
+ # install cost does not belong on the always-path of every PR). Self-only
915
+ # (enableNativeBakeE2E): downstream-generated projects do not ship arbiter's
916
+ # own __tests__/fixtures/real-projects/ harness, so this never renders for them.
917
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
918
+ timeout-minutes: 15
919
+ needs: [gate<% if (locals.ciPreTestBuild) { %>, build-workspace<% } %><% if(governanceLevel !== 'L1' || _multiLane){ %>, classify-changes<% } %>]
920
+ <% if(governanceLevel !== 'L1' || _multiLane){ %> if: needs.classify-changes.outputs.docs_only != 'true'
921
+ <% } %> steps:
922
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
923
+ - uses: ./.github/actions/setup-node-pnpm
924
+ <% if (locals.ciPreTestBuild) { %> - name: Restore cached workspace build (non-blocking)
925
+ uses: ./.github/actions/build-cache
926
+ with:
927
+ op: restore
928
+ - run: node scripts/build-kit.mjs
929
+ <% } %> - name: Generated-gate e2e — TypeScript cell (VITEST_L2=1)
930
+ env:
931
+ VITEST_L2: "1"
932
+ run: |
933
+ npx vitest run --config vitest.integration.config.ts \
934
+ __tests__/integration/e2e/functional/fixture-functional.test.ts \
935
+ -t typescript
936
+
937
+ <% } %> ci-required:
938
+ name: CI Required
939
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
940
+ timeout-minutes: 60
941
+ <%
942
+ const _ciNeeds = ['gate'];
943
+ if (_humanApproval) _ciNeeds.push('human-approval-required');
944
+ if (language === 'java' && buildTool === 'maven') _ciNeeds.push('build-reactor');
945
+ // #1875: contract-tests/integration-tests/behavioral-tests moved to the T2
946
+ // (02-pr-extended) conditional lane — only unit-tests stays on the always-run
947
+ // T1 path.
948
+ if ((language === 'typescript' || language === 'java') && !locals.enableNativeBakeE2E) {
949
+ _ciNeeds.push('unit-tests');
950
+ }
951
+ if (language === 'typescript' && locals.enableNativeBakeE2E) _ciNeeds.push('generated-gate-min');
952
+ // #1512: the per-PR ArchUnit (*ArchTest) lane is a BLOCKING required check for Java L2+.
953
+ if (language === 'java' && governanceLevel !== 'L1') _ciNeeds.push('archunit-tests');
954
+ if (enableSecurityScanning) _ciNeeds.push('security-early-fail', 'dependency-review');
955
+ if (governanceLevel !== 'L1' || _multiLane) _ciNeeds.push('iac-scan');
956
+ if (governanceLevel !== 'L1') _ciNeeds.push('docs-check', 'sonar-scan', 'gate-full');
957
+ if (enableDebtGates) _ciNeeds.push('debt-gates');
958
+ if (contractType && contractType !== 'none' && governanceLevel !== 'L1') _ciNeeds.push('contract-verify');
959
+ if (governanceLevel !== 'L1' || _multiLane) _ciNeeds.push('classify-changes');
960
+ if (_multiLane) _ciNeeds.push('cross-stack-guard');
961
+ %>
962
+ <%
963
+ // #1296 — docs-only PRs SKIP the code jobs (classify-changes gating); the
964
+ // aggregator accepts `skipped` for those jobs ONLY under docs_only=true, and
965
+ // requires the classification itself to have succeeded (fail-closed).
966
+ const _hasClassify = (governanceLevel !== 'L1' || _multiLane);
967
+ %> needs: [<%= _ciNeeds.join(', ') %>]
968
+ if: always()
969
+ steps:
970
+ <% if (_hasClassify) { %> - env:
971
+ DOCS_ONLY: ${{ needs.classify-changes.outputs.docs_only }}
972
+ run: |
973
+ <% } else { %> - run: |
974
+ <% } %>
975
+ <% if (_hasClassify) { %> if [[ "${{ needs.classify-changes.result }}" != "success" ]]; then
976
+ echo "classify-changes failed — cannot trust docs_only, failing closed"
977
+ exit 1
978
+ fi
979
+ # success, or skipped ONLY when the docs-only classification skipped the job
980
+ ok() { [[ "$1" == "success" || ( "$DOCS_ONLY" == "true" && "$1" == "skipped" ) ]]; }
981
+ <% } else { %> ok() { [[ "$1" == "success" ]]; }
982
+ <% } %> if ! ok "${{ needs.gate.result }}"; then
983
+ echo "gate failed"
984
+ exit 1
985
+ fi
986
+ <% if (language === 'java' && buildTool === 'maven') { %>
987
+ if ! ok "${{ needs.build-reactor.result }}"; then
988
+ echo "build-reactor failed"
989
+ exit 1
990
+ fi
991
+ <% } if ((language === 'typescript' || language === 'java') && !locals.enableNativeBakeE2E) { %>
992
+ if ! ok "${{ needs.unit-tests.result }}"; then
993
+ echo "unit-tests failed"
994
+ exit 1
995
+ fi
996
+ <% } %><% if (language === 'typescript' && locals.enableNativeBakeE2E) { %>
997
+ if ! ok "${{ needs.generated-gate-min.result }}"; then
998
+ echo "generated-gate-min failed — the generated-project gate-thesis cell is red"
999
+ exit 1
1000
+ fi
1001
+ <% } %><% if (language === 'java' && governanceLevel !== 'L1') { %>
1002
+ if ! ok "${{ needs.archunit-tests.result }}"; then
1003
+ echo "archunit-tests failed"
1004
+ exit 1
1005
+ fi
1006
+ <% } %><% if (enableSecurityScanning) { %>
1007
+ if [[ "${{ needs.security-early-fail.result }}" != "success" ]]; then
1008
+ echo "security-early-fail failed"
1009
+ exit 1
1010
+ fi
1011
+ # dependency-review skips on push (PR-only) — only a real finding blocks.
1012
+ if [[ "${{ needs.dependency-review.result }}" == "failure" ]]; then
1013
+ echo "dependency-review failed — a newly-introduced dependency exceeds the severity floor"
1014
+ exit 1
1015
+ fi<% } %><% if (_hasClassify) { %>
1016
+ # iac-scan skips when no infra changed — only a real IaC finding blocks.
1017
+ if [[ "${{ needs.iac-scan.result }}" == "failure" ]]; then
1018
+ echo "iac-scan failed — an infrastructure-as-code misconfiguration was found"
1019
+ exit 1
1020
+ fi<% } %><% if (governanceLevel !== 'L1') { %>
1021
+ if [[ "${{ needs.docs-check.result }}" == "failure" ]]; then
1022
+ echo "docs-check failed"
1023
+ exit 1
1024
+ fi
1025
+ if [[ "${{ needs.sonar-scan.result }}" == "failure" ]]; then
1026
+ echo "sonar-scan failed"
1027
+ exit 1
1028
+ fi<% } %><% if (enableDebtGates) { %>
1029
+ if ! ok "${{ needs.debt-gates.result }}"; then
1030
+ echo "debt-gates failed"
1031
+ exit 1
1032
+ fi
1033
+ <% } %><% if (governanceLevel !== 'L1') { %>
1034
+ if [[ "${{ needs.gate-full.result }}" != "success" && "${{ needs.gate-full.result }}" != "skipped" ]]; then
1035
+ echo "gate-full (L2) failed or was cancelled"
1036
+ exit 1
1037
+ fi<% } %><% if (contractType && contractType !== 'none' && governanceLevel !== 'L1') { %>
1038
+ if ! ok "${{ needs.contract-verify.result }}"; then
1039
+ echo "contract-verify failed"
1040
+ exit 1
1041
+ fi<% } %><% if (_multiLane) { %>
1042
+ if [[ "${{ needs.cross-stack-guard.result }}" == "failure" ]]; then
1043
+ echo "cross-stack-guard failed"
1044
+ exit 1
1045
+ fi<% } %>
1046
+ <% if (_humanApproval) { %> if [[ "${{ needs.human-approval-required.result }}" == "failure" ]]; then
1047
+ echo "human-approval-required failed — PR needs approved-by-human label"
1048
+ exit 1
1049
+ fi
1050
+ <% } %>
1051
+ <% if (governanceLevel !== 'L1') { %>
1052
+ post-merge-gate:
1053
+ name: D4-LITE post-merge gate (main)
1054
+ needs: [classify-changes, gate-full]
1055
+ if: >
1056
+ always() &&
1057
+ github.event_name == 'push' &&
1058
+ github.ref == 'refs/heads/main' &&
1059
+ needs.classify-changes.result == 'success' &&
1060
+ needs.classify-changes.outputs.docs_only != 'true'
1061
+ runs-on: ${{ fromJSON(vars.RUNNER_LABELS_TEST || '["ubuntu-latest"]') }}
1062
+ timeout-minutes: 60
1063
+ steps:
1064
+ - name: Verify Full Gate outcome
1065
+ env:
1066
+ GATE_FULL_RESULT: ${{ needs.gate-full.result }}
1067
+ run: |
1068
+ if [[ "$GATE_FULL_RESULT" == "success" ]]; then
1069
+ exit 0
1070
+ fi
1071
+ echo "Full Gate result was $GATE_FULL_RESULT; D4 fails closed." >&2
1072
+ exit 1
1073
+
1074
+ post-merge-notify:
1075
+ name: D4-LITE notify on failure
1076
+ needs: [post-merge-gate]
1077
+ if: always() && needs.post-merge-gate.result == 'failure'
1078
+ permissions:
1079
+ issues: write
1080
+ uses: ./.github/workflows/_notify.yml
1081
+ with:
1082
+ workflow_name: D4-LITE post-merge gate
1083
+ area: ci
1084
+ severity: P1
1085
+ branch: main
1086
+ run_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1087
+ failure_summary: Post-merge L2 gate failed on main — a change merged without full verification.
1088
+ status: failure
1089
+ <% } %><% } -%>