@codyswann/lisa 4.54.13 → 4.55.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 (578) hide show
  1. package/all/copy-contents/.gitattributes +8 -0
  2. package/all/copy-overwrite/scripts/check-orphaned-branches.mjs +78 -9
  3. package/all/copy-overwrite/scripts/check-third-party-action-pins.mjs +17 -1
  4. package/all/copy-overwrite/scripts/lib/process-tree-runner.mjs +194 -7
  5. package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +31 -0
  6. package/all/copy-overwrite/scripts/lisa-hooks/block-blind-automerge.sh +81 -2
  7. package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +293 -8
  8. package/all/copy-overwrite/scripts/lisa-hooks/block-instruction-file-edits.sh +21 -0
  9. package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +78 -15
  10. package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +21 -0
  11. package/all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh +21 -0
  12. package/all/copy-overwrite/scripts/lisa-hooks/guard-dedupe.bash +340 -0
  13. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +29 -1
  14. package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.mjs +183 -1
  15. package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh +21 -0
  16. package/all/copy-overwrite/scripts/lisa-postinstall.mjs +21 -1
  17. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +100 -5
  18. package/all/copy-overwrite/scripts/lisa-work-item.mjs +1085 -80
  19. package/all/create-only/.github/workflows/continuous-gates.yml +7 -0
  20. package/cdk/create-only/.github/workflows/ci.yml +7 -0
  21. package/cdk/create-only/.github/workflows/deploy.yml +21 -0
  22. package/dist/cli/apply.d.ts.map +1 -1
  23. package/dist/cli/apply.js +9 -1
  24. package/dist/cli/apply.js.map +1 -1
  25. package/dist/cli/doctor-apply-deletions.d.ts +61 -0
  26. package/dist/cli/doctor-apply-deletions.d.ts.map +1 -0
  27. package/dist/cli/doctor-apply-deletions.js +137 -0
  28. package/dist/cli/doctor-apply-deletions.js.map +1 -0
  29. package/dist/cli/doctor-cdk-preset-adoption.d.ts +15 -0
  30. package/dist/cli/doctor-cdk-preset-adoption.d.ts.map +1 -0
  31. package/dist/cli/doctor-cdk-preset-adoption.js +316 -0
  32. package/dist/cli/doctor-cdk-preset-adoption.js.map +1 -0
  33. package/dist/cli/doctor-config-shadowing.d.ts +22 -0
  34. package/dist/cli/doctor-config-shadowing.d.ts.map +1 -0
  35. package/dist/cli/doctor-config-shadowing.js +123 -0
  36. package/dist/cli/doctor-config-shadowing.js.map +1 -0
  37. package/dist/cli/doctor-rails-deploy-intent.d.ts +15 -0
  38. package/dist/cli/doctor-rails-deploy-intent.d.ts.map +1 -0
  39. package/dist/cli/doctor-rails-deploy-intent.js +197 -0
  40. package/dist/cli/doctor-rails-deploy-intent.js.map +1 -0
  41. package/dist/cli/doctor-seeded-artifacts.d.ts +12 -0
  42. package/dist/cli/doctor-seeded-artifacts.d.ts.map +1 -0
  43. package/dist/cli/doctor-seeded-artifacts.js +54 -0
  44. package/dist/cli/doctor-seeded-artifacts.js.map +1 -0
  45. package/dist/cli/doctor-stale-banner-scan.d.ts +44 -0
  46. package/dist/cli/doctor-stale-banner-scan.d.ts.map +1 -0
  47. package/dist/cli/doctor-stale-banner-scan.js +152 -0
  48. package/dist/cli/doctor-stale-banner-scan.js.map +1 -0
  49. package/dist/cli/doctor-stale-managed-banner.d.ts +19 -0
  50. package/dist/cli/doctor-stale-managed-banner.d.ts.map +1 -0
  51. package/dist/cli/doctor-stale-managed-banner.js +198 -0
  52. package/dist/cli/doctor-stale-managed-banner.js.map +1 -0
  53. package/dist/cli/doctor.d.ts.map +1 -1
  54. package/dist/cli/doctor.js +16 -0
  55. package/dist/cli/doctor.js.map +1 -1
  56. package/dist/cli/ui-detected-stacks.d.ts.map +1 -1
  57. package/dist/cli/ui-detected-stacks.js +3 -2
  58. package/dist/cli/ui-detected-stacks.js.map +1 -1
  59. package/dist/cli/update-check.d.ts.map +1 -1
  60. package/dist/cli/update-check.js +14 -0
  61. package/dist/cli/update-check.js.map +1 -1
  62. package/dist/cli/worktree-liveness.d.ts +5 -0
  63. package/dist/cli/worktree-liveness.d.ts.map +1 -1
  64. package/dist/cli/worktree-liveness.js +7 -6
  65. package/dist/cli/worktree-liveness.js.map +1 -1
  66. package/dist/cli/worktree-ownership.d.ts +13 -0
  67. package/dist/cli/worktree-ownership.d.ts.map +1 -1
  68. package/dist/cli/worktree-ownership.js +14 -0
  69. package/dist/cli/worktree-ownership.js.map +1 -1
  70. package/dist/configs/eslint/base.d.ts +34 -0
  71. package/dist/configs/eslint/base.d.ts.map +1 -1
  72. package/dist/configs/eslint/base.js +34 -0
  73. package/dist/configs/eslint/base.js.map +1 -1
  74. package/dist/core/apply-receipt.d.ts +65 -0
  75. package/dist/core/apply-receipt.d.ts.map +1 -1
  76. package/dist/core/apply-receipt.js +62 -2
  77. package/dist/core/apply-receipt.js.map +1 -1
  78. package/dist/core/cdk-preset-adoption.d.ts +136 -0
  79. package/dist/core/cdk-preset-adoption.d.ts.map +1 -0
  80. package/dist/core/cdk-preset-adoption.js +135 -0
  81. package/dist/core/cdk-preset-adoption.js.map +1 -0
  82. package/dist/core/config-shadowing.d.ts +36 -0
  83. package/dist/core/config-shadowing.d.ts.map +1 -1
  84. package/dist/core/config-shadowing.js +38 -0
  85. package/dist/core/config-shadowing.js.map +1 -1
  86. package/dist/core/config.d.ts +11 -0
  87. package/dist/core/config.d.ts.map +1 -1
  88. package/dist/core/config.js.map +1 -1
  89. package/dist/core/learnings-merge-driver.d.ts +10 -0
  90. package/dist/core/learnings-merge-driver.d.ts.map +1 -1
  91. package/dist/core/learnings-merge-driver.js +18 -0
  92. package/dist/core/learnings-merge-driver.js.map +1 -1
  93. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  94. package/dist/core/lisa-owned-hash-ledger.js +136 -0
  95. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  96. package/dist/core/lisa.d.ts.map +1 -1
  97. package/dist/core/lisa.js +9 -1
  98. package/dist/core/lisa.js.map +1 -1
  99. package/dist/core/nightly-e2e-guard-behavior-certificate.d.ts +5 -5
  100. package/dist/core/nightly-e2e-guard-behavior-certificate.js +7 -7
  101. package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
  102. package/dist/core/ownership-header.d.ts +74 -0
  103. package/dist/core/ownership-header.d.ts.map +1 -0
  104. package/dist/core/ownership-header.js +76 -0
  105. package/dist/core/ownership-header.js.map +1 -0
  106. package/dist/core/rails-deploy-production-intent.d.ts +36 -0
  107. package/dist/core/rails-deploy-production-intent.d.ts.map +1 -0
  108. package/dist/core/rails-deploy-production-intent.js +79 -0
  109. package/dist/core/rails-deploy-production-intent.js.map +1 -0
  110. package/dist/core/stale-managed-banner.d.ts +78 -0
  111. package/dist/core/stale-managed-banner.d.ts.map +1 -0
  112. package/dist/core/stale-managed-banner.js +118 -0
  113. package/dist/core/stale-managed-banner.js.map +1 -0
  114. package/dist/core/two-channel-delivery-scan.d.ts +33 -1
  115. package/dist/core/two-channel-delivery-scan.d.ts.map +1 -1
  116. package/dist/core/two-channel-delivery-scan.js +133 -6
  117. package/dist/core/two-channel-delivery-scan.js.map +1 -1
  118. package/dist/core/two-channel-delivery.d.ts +101 -4
  119. package/dist/core/two-channel-delivery.d.ts.map +1 -1
  120. package/dist/core/two-channel-delivery.js +121 -13
  121. package/dist/core/two-channel-delivery.js.map +1 -1
  122. package/dist/core/two-channel-staleness.d.ts +137 -0
  123. package/dist/core/two-channel-staleness.d.ts.map +1 -0
  124. package/dist/core/two-channel-staleness.js +268 -0
  125. package/dist/core/two-channel-staleness.js.map +1 -0
  126. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  127. package/dist/core/upstream-evidence-manifest.js +265 -121
  128. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  129. package/dist/core/workflow-deletion-ownership.d.ts +6 -24
  130. package/dist/core/workflow-deletion-ownership.d.ts.map +1 -1
  131. package/dist/core/workflow-deletion-ownership.js +22 -42
  132. package/dist/core/workflow-deletion-ownership.js.map +1 -1
  133. package/dist/detection/detectors/cdk.d.ts.map +1 -1
  134. package/dist/detection/detectors/cdk.js +2 -1
  135. package/dist/detection/detectors/cdk.js.map +1 -1
  136. package/dist/health/template-inspection.d.ts.map +1 -1
  137. package/dist/health/template-inspection.js +2 -1
  138. package/dist/health/template-inspection.js.map +1 -1
  139. package/dist/migrations/ensure-lisa-postinstall.d.ts +16 -0
  140. package/dist/migrations/ensure-lisa-postinstall.d.ts.map +1 -1
  141. package/dist/migrations/ensure-lisa-postinstall.js +16 -0
  142. package/dist/migrations/ensure-lisa-postinstall.js.map +1 -1
  143. package/dist/migrations/ensure-pinned-reusable-workflow-refs.d.ts +2 -2
  144. package/dist/migrations/ensure-pinned-reusable-workflow-refs.d.ts.map +1 -1
  145. package/dist/migrations/ensure-pinned-reusable-workflow-refs.js +98 -34
  146. package/dist/migrations/ensure-pinned-reusable-workflow-refs.js.map +1 -1
  147. package/dist/migrations/ensure-playwright-dedicated-caller.d.ts.map +1 -1
  148. package/dist/migrations/ensure-playwright-dedicated-caller.js +1 -0
  149. package/dist/migrations/ensure-playwright-dedicated-caller.js.map +1 -1
  150. package/dist/opencode/hooks-installer.d.ts.map +1 -1
  151. package/dist/opencode/hooks-installer.js +1 -0
  152. package/dist/opencode/hooks-installer.js.map +1 -1
  153. package/dist/opencode/plugin-templates/block-managed-file-edits.sh +78 -15
  154. package/dist/opencode/plugin-templates/block-no-verify.sh +21 -0
  155. package/dist/opencode/plugin-templates/guard-dedupe.bash +337 -0
  156. package/dist/opencode/plugin-templates/lisa-block-direct-issue-create.ts +242 -55
  157. package/dist/opencode/plugin-templates/parity-safety-net.sh +29 -1
  158. package/dist/strategies/package-lisa.d.ts.map +1 -1
  159. package/dist/strategies/package-lisa.js +2 -1
  160. package/dist/strategies/package-lisa.js.map +1 -1
  161. package/dist/utils/path-utils.d.ts +29 -0
  162. package/dist/utils/path-utils.d.ts.map +1 -1
  163. package/dist/utils/path-utils.js +41 -0
  164. package/dist/utils/path-utils.js.map +1 -1
  165. package/expo/create-only/.github/workflows/ci.yml +21 -0
  166. package/expo/create-only/.github/workflows/deploy.yml +28 -0
  167. package/expo/create-only/.github/workflows/maestro-e2e.yml +7 -0
  168. package/expo/create-only/.github/workflows/nightly-e2e-bypass-reaper.yml +124 -13
  169. package/expo/create-only/.github/workflows/nightly-e2e-health.yml +7 -0
  170. package/expo/create-only/.github/workflows/nightly-e2e-report.yml +7 -0
  171. package/expo/create-only/.github/workflows/nightly-e2e-tracking.yml +8 -0
  172. package/expo/create-only/.github/workflows/playwright-e2e.yml +7 -0
  173. package/harper-fabric/copy-overwrite/.github/workflows/ci.yml +7 -0
  174. package/harper-fabric/create-only/.github/workflows/deploy.yml +14 -0
  175. package/nestjs/create-only/.github/workflows/ci.yml +14 -0
  176. package/nestjs/create-only/.github/workflows/deploy.yml +28 -0
  177. package/package.json +10 -5
  178. package/phaser/copy-overwrite/.github/workflows/ci.yml +7 -0
  179. package/plugins/lisa/.claude-plugin/plugin.json +28 -1
  180. package/plugins/lisa/.codex-plugin/hooks.json +27 -0
  181. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  182. package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  183. package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +27 -4
  184. package/plugins/lisa/.codex-plugin/skills/lisa-github-prd-intake/SKILL.md +1 -1
  185. package/plugins/lisa/.codex-plugin/skills/lisa-github-validate-issue/SKILL.md +22 -0
  186. package/plugins/lisa/.codex-plugin/skills/lisa-github-verify/SKILL.md +14 -0
  187. package/plugins/lisa/.codex-plugin/skills/lisa-github-write-issue/SKILL.md +51 -0
  188. package/plugins/lisa/.codex-plugin/skills/lisa-intake/SKILL.md +1 -1
  189. package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +27 -4
  190. package/plugins/lisa/.codex-plugin/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  191. package/plugins/lisa/.codex-plugin/skills/lisa-jira-verify/SKILL.md +14 -0
  192. package/plugins/lisa/.codex-plugin/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  193. package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +55 -2
  194. package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +27 -4
  195. package/plugins/lisa/.codex-plugin/skills/lisa-linear-prd-intake/SKILL.md +47 -30
  196. package/plugins/lisa/.codex-plugin/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  197. package/plugins/lisa/.codex-plugin/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  198. package/plugins/lisa/.codex-plugin/skills/lisa-linear-verify/SKILL.md +14 -0
  199. package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +54 -3
  200. package/plugins/lisa/.codex-plugin/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  201. package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/SKILL.md +19 -7
  202. package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +28 -3
  203. package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/SKILL.md +28 -3
  204. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +94 -24
  205. package/plugins/lisa/.codex-plugin/skills/lisa-rework-triage/SKILL.md +32 -2
  206. package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +4 -4
  207. package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +1 -1
  208. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  209. package/plugins/lisa/agents/linear-prd-intake.md +8 -8
  210. package/plugins/lisa/hooks/block-blind-automerge.sh +81 -2
  211. package/plugins/lisa/hooks/block-direct-issue-create.agy.sh +64 -16
  212. package/plugins/lisa/hooks/block-direct-issue-create.sh +293 -8
  213. package/plugins/lisa/hooks/block-instruction-file-edits.sh +21 -0
  214. package/plugins/lisa/hooks/block-managed-file-edits.sh +78 -15
  215. package/plugins/lisa/hooks/block-no-verify.sh +21 -0
  216. package/plugins/lisa/hooks/block-shell-json-parsing.sh +21 -0
  217. package/plugins/lisa/hooks/failure-signature-index.mjs +240 -5
  218. package/plugins/lisa/hooks/guard-dedupe.bash +337 -0
  219. package/plugins/lisa/hooks/inject-rules.sh +13 -5
  220. package/plugins/lisa/hooks/operational-hazards.mjs +736 -0
  221. package/plugins/lisa/hooks/operational-hazards.sh +28 -0
  222. package/plugins/lisa/hooks/parity-safety-net.sh +29 -1
  223. package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +102 -21
  224. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +130 -2
  225. package/plugins/lisa/hooks/threshold-ratchet.mjs +63 -13
  226. package/plugins/lisa/hooks/worktree-binding-guard.mjs +183 -1
  227. package/plugins/lisa/hooks/worktree-binding-guard.sh +21 -0
  228. package/plugins/lisa/rules/eager/00-rule-index.md +1 -0
  229. package/plugins/lisa/rules/eager/operational-hazards.md +50 -0
  230. package/plugins/lisa/rules/eager/tracked-work.md +1 -1
  231. package/plugins/lisa/rules/reference/config-resolution.md +1 -1
  232. package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +1 -1
  233. package/plugins/lisa/rules/reference/operational-hazards.md +115 -0
  234. package/plugins/lisa/rules/reference/work-item-trailer-definition.md +129 -0
  235. package/plugins/lisa/scripts/intake-blocker-reprobe.mjs +407 -26
  236. package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +507 -0
  237. package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  238. package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +27 -4
  239. package/plugins/lisa/skills/lisa-github-prd-intake/SKILL.md +1 -1
  240. package/plugins/lisa/skills/lisa-github-validate-issue/SKILL.md +22 -0
  241. package/plugins/lisa/skills/lisa-github-verify/SKILL.md +14 -0
  242. package/plugins/lisa/skills/lisa-github-write-issue/SKILL.md +51 -0
  243. package/plugins/lisa/skills/lisa-intake/SKILL.md +1 -1
  244. package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +27 -4
  245. package/plugins/lisa/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  246. package/plugins/lisa/skills/lisa-jira-verify/SKILL.md +14 -0
  247. package/plugins/lisa/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  248. package/plugins/lisa/skills/lisa-linear-access/SKILL.md +55 -2
  249. package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +27 -4
  250. package/plugins/lisa/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  251. package/plugins/lisa/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  252. package/plugins/lisa/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  253. package/plugins/lisa/skills/lisa-linear-verify/SKILL.md +14 -0
  254. package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +54 -3
  255. package/plugins/lisa/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  256. package/plugins/lisa/skills/lisa-qa-clear/SKILL.md +19 -7
  257. package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +28 -3
  258. package/plugins/lisa/skills/lisa-qa-queue/SKILL.md +28 -3
  259. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +94 -24
  260. package/plugins/lisa/skills/lisa-rework-triage/SKILL.md +32 -2
  261. package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +5 -5
  262. package/plugins/lisa/skills/lisa-track/SKILL.md +1 -1
  263. package/plugins/lisa/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  264. package/plugins/lisa-agy/agents/linear-prd-intake.md +8 -8
  265. package/plugins/lisa-agy/hooks/block-blind-automerge.sh +81 -2
  266. package/plugins/lisa-agy/hooks/block-direct-issue-create.agy.sh +64 -16
  267. package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +293 -8
  268. package/plugins/lisa-agy/hooks/block-instruction-file-edits.sh +21 -0
  269. package/plugins/lisa-agy/hooks/block-managed-file-edits.sh +78 -15
  270. package/plugins/lisa-agy/hooks/block-shell-json-parsing.sh +21 -0
  271. package/plugins/lisa-agy/hooks/guard-dedupe.bash +337 -0
  272. package/plugins/lisa-agy/hooks/parity-safety-net.sh +29 -1
  273. package/plugins/lisa-agy/hooks.json +1 -1
  274. package/plugins/lisa-agy/plugin.json +1 -1
  275. package/plugins/lisa-agy/scripts/intake-blocker-reprobe.mjs +407 -26
  276. package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +507 -0
  277. package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  278. package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +27 -4
  279. package/plugins/lisa-agy/skills/lisa-github-prd-intake/SKILL.md +1 -1
  280. package/plugins/lisa-agy/skills/lisa-github-validate-issue/SKILL.md +22 -0
  281. package/plugins/lisa-agy/skills/lisa-github-verify/SKILL.md +14 -0
  282. package/plugins/lisa-agy/skills/lisa-github-write-issue/SKILL.md +51 -0
  283. package/plugins/lisa-agy/skills/lisa-intake/SKILL.md +1 -1
  284. package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +27 -4
  285. package/plugins/lisa-agy/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  286. package/plugins/lisa-agy/skills/lisa-jira-verify/SKILL.md +14 -0
  287. package/plugins/lisa-agy/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  288. package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +55 -2
  289. package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +27 -4
  290. package/plugins/lisa-agy/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  291. package/plugins/lisa-agy/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  292. package/plugins/lisa-agy/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  293. package/plugins/lisa-agy/skills/lisa-linear-verify/SKILL.md +14 -0
  294. package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +54 -3
  295. package/plugins/lisa-agy/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  296. package/plugins/lisa-agy/skills/lisa-qa-clear/SKILL.md +19 -7
  297. package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +28 -3
  298. package/plugins/lisa-agy/skills/lisa-qa-queue/SKILL.md +28 -3
  299. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +94 -24
  300. package/plugins/lisa-agy/skills/lisa-rework-triage/SKILL.md +32 -2
  301. package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +5 -5
  302. package/plugins/lisa-agy/skills/lisa-track/SKILL.md +1 -1
  303. package/plugins/lisa-agy/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  304. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  305. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  306. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  307. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  308. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  309. package/plugins/lisa-copilot/.claude-plugin/plugin.json +19 -1
  310. package/plugins/lisa-copilot/agents/linear-prd-intake.agent.md +8 -8
  311. package/plugins/lisa-copilot/hooks/block-blind-automerge.sh +81 -2
  312. package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +293 -8
  313. package/plugins/lisa-copilot/hooks/block-instruction-file-edits.sh +21 -0
  314. package/plugins/lisa-copilot/hooks/block-managed-file-edits.sh +78 -15
  315. package/plugins/lisa-copilot/hooks/block-no-verify.sh +21 -0
  316. package/plugins/lisa-copilot/hooks/block-shell-json-parsing.sh +21 -0
  317. package/plugins/lisa-copilot/hooks/failure-signature-index.mjs +240 -5
  318. package/plugins/lisa-copilot/hooks/guard-dedupe.bash +337 -0
  319. package/plugins/lisa-copilot/hooks/inject-rules.sh +13 -5
  320. package/plugins/lisa-copilot/hooks/operational-hazards.mjs +736 -0
  321. package/plugins/lisa-copilot/hooks/operational-hazards.sh +28 -0
  322. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +29 -1
  323. package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +102 -21
  324. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +130 -2
  325. package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +63 -13
  326. package/plugins/lisa-copilot/hooks/worktree-binding-guard.mjs +183 -1
  327. package/plugins/lisa-copilot/hooks/worktree-binding-guard.sh +21 -0
  328. package/plugins/lisa-copilot/rules/eager/00-rule-index.md +1 -0
  329. package/plugins/lisa-copilot/rules/eager/operational-hazards.md +50 -0
  330. package/plugins/lisa-copilot/rules/eager/tracked-work.md +1 -1
  331. package/plugins/lisa-copilot/rules/reference/config-resolution.md +1 -1
  332. package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +1 -1
  333. package/plugins/lisa-copilot/rules/reference/operational-hazards.md +115 -0
  334. package/plugins/lisa-copilot/rules/reference/work-item-trailer-definition.md +129 -0
  335. package/plugins/lisa-copilot/scripts/intake-blocker-reprobe.mjs +407 -26
  336. package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +507 -0
  337. package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  338. package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +27 -4
  339. package/plugins/lisa-copilot/skills/lisa-github-prd-intake/SKILL.md +1 -1
  340. package/plugins/lisa-copilot/skills/lisa-github-validate-issue/SKILL.md +22 -0
  341. package/plugins/lisa-copilot/skills/lisa-github-verify/SKILL.md +14 -0
  342. package/plugins/lisa-copilot/skills/lisa-github-write-issue/SKILL.md +51 -0
  343. package/plugins/lisa-copilot/skills/lisa-intake/SKILL.md +1 -1
  344. package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +27 -4
  345. package/plugins/lisa-copilot/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  346. package/plugins/lisa-copilot/skills/lisa-jira-verify/SKILL.md +14 -0
  347. package/plugins/lisa-copilot/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  348. package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +55 -2
  349. package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +27 -4
  350. package/plugins/lisa-copilot/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  351. package/plugins/lisa-copilot/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  352. package/plugins/lisa-copilot/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  353. package/plugins/lisa-copilot/skills/lisa-linear-verify/SKILL.md +14 -0
  354. package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +54 -3
  355. package/plugins/lisa-copilot/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  356. package/plugins/lisa-copilot/skills/lisa-qa-clear/SKILL.md +19 -7
  357. package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +28 -3
  358. package/plugins/lisa-copilot/skills/lisa-qa-queue/SKILL.md +28 -3
  359. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +94 -24
  360. package/plugins/lisa-copilot/skills/lisa-rework-triage/SKILL.md +32 -2
  361. package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +5 -5
  362. package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +1 -1
  363. package/plugins/lisa-copilot/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  364. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  365. package/plugins/lisa-cursor/agents/linear-prd-intake.md +8 -8
  366. package/plugins/lisa-cursor/hooks/block-blind-automerge.sh +81 -2
  367. package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +293 -8
  368. package/plugins/lisa-cursor/hooks/block-instruction-file-edits.sh +21 -0
  369. package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +78 -15
  370. package/plugins/lisa-cursor/hooks/block-no-verify.sh +21 -0
  371. package/plugins/lisa-cursor/hooks/block-shell-json-parsing.sh +21 -0
  372. package/plugins/lisa-cursor/hooks/failure-signature-index.mjs +240 -5
  373. package/plugins/lisa-cursor/hooks/guard-dedupe.bash +337 -0
  374. package/plugins/lisa-cursor/hooks/hooks.json +10 -0
  375. package/plugins/lisa-cursor/hooks/operational-hazards.mjs +736 -0
  376. package/plugins/lisa-cursor/hooks/operational-hazards.sh +28 -0
  377. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +29 -1
  378. package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +102 -21
  379. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +130 -2
  380. package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +63 -13
  381. package/plugins/lisa-cursor/hooks/worktree-binding-guard.mjs +183 -1
  382. package/plugins/lisa-cursor/hooks/worktree-binding-guard.sh +21 -0
  383. package/plugins/lisa-cursor/rules/00-rule-index.mdc +1 -0
  384. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +1 -1
  385. package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +1 -1
  386. package/plugins/lisa-cursor/rules/operational-hazards-reference.mdc +120 -0
  387. package/plugins/lisa-cursor/rules/operational-hazards.mdc +55 -0
  388. package/plugins/lisa-cursor/rules/tracked-work.mdc +1 -1
  389. package/plugins/lisa-cursor/rules/work-item-trailer-definition-reference.mdc +134 -0
  390. package/plugins/lisa-cursor/scripts/intake-blocker-reprobe.mjs +407 -26
  391. package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +507 -0
  392. package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  393. package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +27 -4
  394. package/plugins/lisa-cursor/skills/lisa-github-prd-intake/SKILL.md +1 -1
  395. package/plugins/lisa-cursor/skills/lisa-github-validate-issue/SKILL.md +22 -0
  396. package/plugins/lisa-cursor/skills/lisa-github-verify/SKILL.md +14 -0
  397. package/plugins/lisa-cursor/skills/lisa-github-write-issue/SKILL.md +51 -0
  398. package/plugins/lisa-cursor/skills/lisa-intake/SKILL.md +1 -1
  399. package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +27 -4
  400. package/plugins/lisa-cursor/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  401. package/plugins/lisa-cursor/skills/lisa-jira-verify/SKILL.md +14 -0
  402. package/plugins/lisa-cursor/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  403. package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +55 -2
  404. package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +27 -4
  405. package/plugins/lisa-cursor/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  406. package/plugins/lisa-cursor/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  407. package/plugins/lisa-cursor/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  408. package/plugins/lisa-cursor/skills/lisa-linear-verify/SKILL.md +14 -0
  409. package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +54 -3
  410. package/plugins/lisa-cursor/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  411. package/plugins/lisa-cursor/skills/lisa-qa-clear/SKILL.md +19 -7
  412. package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +28 -3
  413. package/plugins/lisa-cursor/skills/lisa-qa-queue/SKILL.md +28 -3
  414. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +94 -24
  415. package/plugins/lisa-cursor/skills/lisa-rework-triage/SKILL.md +32 -2
  416. package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +5 -5
  417. package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +1 -1
  418. package/plugins/lisa-cursor/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  419. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  420. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  421. package/plugins/lisa-expo-agy/plugin.json +1 -1
  422. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  423. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  424. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  425. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  426. package/plugins/lisa-harper-fabric/hooks/inject-rules.sh +14 -3
  427. package/plugins/lisa-harper-fabric/rules/eager/harper-fabric.md +31 -0
  428. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  429. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  430. package/plugins/lisa-harper-fabric-copilot/hooks/inject-rules.sh +14 -3
  431. package/plugins/lisa-harper-fabric-copilot/rules/eager/harper-fabric.md +31 -0
  432. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  433. package/plugins/lisa-harper-fabric-cursor/rules/harper-fabric-reference.mdc +57 -0
  434. package/plugins/lisa-harper-fabric-cursor/rules/harper-fabric.mdc +32 -53
  435. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  436. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  437. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  438. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  439. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  440. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  441. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  442. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  443. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  444. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  445. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  446. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  447. package/plugins/lisa-phaser/hooks/inject-rules.sh +14 -3
  448. package/plugins/lisa-phaser/rules/eager/phaser.md +44 -0
  449. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  450. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  451. package/plugins/lisa-phaser-copilot/hooks/inject-rules.sh +14 -3
  452. package/plugins/lisa-phaser-copilot/rules/eager/phaser.md +44 -0
  453. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  454. package/plugins/lisa-phaser-cursor/rules/phaser-reference.mdc +189 -0
  455. package/plugins/lisa-phaser-cursor/rules/phaser.mdc +45 -185
  456. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  457. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  458. package/plugins/lisa-rails/hooks/inject-rules.sh +14 -4
  459. package/plugins/lisa-rails/rules/eager/rails-conventions.md +23 -0
  460. package/plugins/lisa-rails-agy/plugin.json +1 -1
  461. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  462. package/plugins/lisa-rails-copilot/hooks/inject-rules.sh +14 -4
  463. package/plugins/lisa-rails-copilot/rules/eager/rails-conventions.md +23 -0
  464. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  465. package/plugins/lisa-rails-cursor/rules/rails-conventions-reference.mdc +181 -0
  466. package/plugins/lisa-rails-cursor/rules/rails-conventions.mdc +24 -177
  467. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  468. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  469. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  470. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  471. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  472. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  473. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  474. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  475. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  476. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  477. package/plugins/materialized-artifacts.json +1 -0
  478. package/plugins/src/base/.claude-plugin/plugin.json +27 -0
  479. package/plugins/src/base/agents/linear-prd-intake.md +8 -8
  480. package/plugins/src/base/hooks/block-blind-automerge.sh +81 -2
  481. package/plugins/src/base/hooks/block-direct-issue-create.agy.sh +64 -16
  482. package/plugins/src/base/hooks/block-direct-issue-create.sh +293 -8
  483. package/plugins/src/base/hooks/block-instruction-file-edits.sh +21 -0
  484. package/plugins/src/base/hooks/block-managed-file-edits.sh +78 -15
  485. package/plugins/src/base/hooks/block-no-verify.sh +21 -0
  486. package/plugins/src/base/hooks/block-shell-json-parsing.sh +21 -0
  487. package/plugins/src/base/hooks/failure-signature-index.mjs +240 -5
  488. package/plugins/src/base/hooks/guard-dedupe.bash +337 -0
  489. package/plugins/src/base/hooks/inject-rules.sh +13 -5
  490. package/plugins/src/base/hooks/operational-hazards.mjs +736 -0
  491. package/plugins/src/base/hooks/operational-hazards.sh +28 -0
  492. package/plugins/src/base/hooks/parity-safety-net.sh +29 -1
  493. package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +102 -21
  494. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +130 -2
  495. package/plugins/src/base/hooks/threshold-ratchet.mjs +63 -13
  496. package/plugins/src/base/hooks/worktree-binding-guard.mjs +183 -1
  497. package/plugins/src/base/hooks/worktree-binding-guard.sh +21 -0
  498. package/plugins/src/base/rules/eager/00-rule-index.md +1 -0
  499. package/plugins/src/base/rules/eager/operational-hazards.md +50 -0
  500. package/plugins/src/base/rules/eager/tracked-work.md +1 -1
  501. package/plugins/src/base/rules/reference/config-resolution.md +1 -1
  502. package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +1 -1
  503. package/plugins/src/base/rules/reference/operational-hazards.md +115 -0
  504. package/plugins/src/base/rules/reference/work-item-trailer-definition.md +129 -0
  505. package/plugins/src/base/scripts/intake-blocker-reprobe.mjs +407 -26
  506. package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +507 -0
  507. package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  508. package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +27 -4
  509. package/plugins/src/base/skills/lisa-github-prd-intake/SKILL.md +1 -1
  510. package/plugins/src/base/skills/lisa-github-validate-issue/SKILL.md +22 -0
  511. package/plugins/src/base/skills/lisa-github-verify/SKILL.md +14 -0
  512. package/plugins/src/base/skills/lisa-github-write-issue/SKILL.md +51 -0
  513. package/plugins/src/base/skills/lisa-intake/SKILL.md +1 -1
  514. package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +27 -4
  515. package/plugins/src/base/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  516. package/plugins/src/base/skills/lisa-jira-verify/SKILL.md +14 -0
  517. package/plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  518. package/plugins/src/base/skills/lisa-linear-access/SKILL.md +55 -2
  519. package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +27 -4
  520. package/plugins/src/base/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  521. package/plugins/src/base/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  522. package/plugins/src/base/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  523. package/plugins/src/base/skills/lisa-linear-verify/SKILL.md +14 -0
  524. package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +54 -3
  525. package/plugins/src/base/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  526. package/plugins/src/base/skills/lisa-qa-clear/SKILL.md +19 -7
  527. package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +28 -3
  528. package/plugins/src/base/skills/lisa-qa-queue/SKILL.md +28 -3
  529. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +94 -24
  530. package/plugins/src/base/skills/lisa-rework-triage/SKILL.md +32 -2
  531. package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +5 -5
  532. package/plugins/src/base/skills/lisa-track/SKILL.md +1 -1
  533. package/plugins/src/base/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  534. package/plugins/src/harper-fabric/hooks/inject-rules.sh +14 -3
  535. package/plugins/src/harper-fabric/rules/eager/harper-fabric.md +31 -0
  536. package/plugins/src/phaser/hooks/inject-rules.sh +14 -3
  537. package/plugins/src/phaser/rules/eager/phaser.md +44 -0
  538. package/plugins/src/rails/hooks/inject-rules.sh +14 -4
  539. package/plugins/src/rails/rules/eager/rails-conventions.md +23 -0
  540. package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +63 -13
  541. package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +102 -21
  542. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +130 -2
  543. package/rails/create-only/.github/workflows/ci.yml +8 -0
  544. package/rails/create-only/.github/workflows/deploy.yml +22 -0
  545. package/scripts/build-plugins.sh +2 -1
  546. package/scripts/check-engine-floor.mjs +361 -0
  547. package/scripts/check-guard-parity-notes.mjs +709 -0
  548. package/scripts/check-template-workflow-refs.mjs +9 -0
  549. package/scripts/check-third-party-action-pins.mjs +17 -1
  550. package/scripts/check-workflow-contract-assertions.mjs +480 -0
  551. package/scripts/copy-opencode-plugin-templates.mjs +1 -0
  552. package/scripts/deployed-guard-advice.mjs +636 -0
  553. package/scripts/generate-agy-plugin-artifacts.mjs +35 -10
  554. package/scripts/generate-export-surface.mjs +105 -19
  555. package/scripts/generate-two-channel-couplings.ts +143 -212
  556. package/scripts/lisa-enforcement-fallback.sh +31 -0
  557. package/scripts/measure-scripts-profile-gap.mts +361 -0
  558. package/scripts/mutation-performance-measure.mjs +21 -5
  559. package/scripts/reconcile-release-tags.mjs +65 -84
  560. package/scripts/two-channel-couplings.json +302 -70
  561. package/scripts/workflow-contract-assertion.sh +47 -0
  562. package/typescript/copy-overwrite/.lintstagedrc.json +1 -0
  563. package/typescript/copy-overwrite/eslint.ignore.config.json +1 -0
  564. package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +527 -53
  565. package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +301 -13
  566. package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +63 -13
  567. package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +102 -21
  568. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +130 -2
  569. package/typescript/create-only/.github/workflows/ci.yml +7 -0
  570. /package/plugins/lisa-harper-fabric/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
  571. /package/plugins/lisa-harper-fabric-copilot/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
  572. /package/plugins/lisa-phaser/rules/{phaser.md → reference/phaser.md} +0 -0
  573. /package/plugins/lisa-phaser-copilot/rules/{phaser.md → reference/phaser.md} +0 -0
  574. /package/plugins/lisa-rails/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
  575. /package/plugins/lisa-rails-copilot/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
  576. /package/plugins/src/harper-fabric/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
  577. /package/plugins/src/phaser/rules/{phaser.md → reference/phaser.md} +0 -0
  578. /package/plugins/src/rails/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
@@ -1,189 +1,49 @@
1
1
  ---
2
- description: "Phaser 4 Project Rules"
2
+ description: "Phaser 4 Project Rules (load-bearing)"
3
3
  alwaysApply: true
4
4
  ---
5
5
 
6
- # Phaser 4 Project Rules
7
-
8
- This is a **Phaser 4** (v4.2+, npm `phaser@^4.2.0`) TypeScript game project built
9
- on the official `template-vite-ts` layout (Vite + TypeScript 6). Phaser 4 is the
10
- only supported target — never introduce Phaser 3 idioms. These decisions are
11
- **locked** and most are **lint-enforced**; do not disable a rule, fix the code.
12
-
13
- ## Official Phaser skills — use these for API knowledge
14
-
15
- Phaser ships **28 official, authoritative agent skills** inside the installed
16
- package at **`node_modules/phaser/skills/<topic>/SKILL.md`** — e.g. `scenes`,
17
- `sprites-and-images`, `physics-arcade`, `physics-matter`, `tweens`, `particles`,
18
- `filters-and-postfx`, `loading-assets`, `animations`, `tilemaps`, `cameras`,
19
- `input-keyboard-mouse-touch`, `audio-and-sound`, `game-object-components`,
20
- `v3-to-v4-migration`, `v4-new-features`, and more. The Phaser team maintains them
21
- in lockstep with the engine, and they cite exact `src/...` source paths.
22
-
23
- **For any Phaser API or subsystem question, read the matching official skill
24
- first.** Do not rely on memory, and do not expect Lisa to duplicate that
25
- knowledge the `lisa-phaser` skills intentionally cover only the opinionated,
26
- project-specific, and lint-enforced layer (project structure, services, asset
27
- pipeline, i18n, accessibility, build/deploy, testing gates) that the official
28
- skills do not. When this file points at a Phaser subsystem (physics, rendering,
29
- scenes, …) the authority is the official skill of that name.
30
-
31
- An optional **Phaser Editor MCP server** (`@phaserjs/editor-mcp-server`, 40+
32
- tools for scenes/assets/tilemaps) is defined for this project type but
33
- **disabled by default** enable it only when working with Phaser Editor v5. See
34
- `.mcp.json` and `disabledMcpjsonServers` in `.claude/settings.json`.
35
-
36
- ## Locked architecture decisions
37
-
38
- 1. **Thin scenes over a pure-logic core.** Scenes and GameObjects are thin
39
- adapters that wire pure logic to the engine. All game rules live in
40
- `src/logic/**` as plain TypeScript with **zero `phaser` imports** (data in,
41
- data out). This is what makes the game unit-testable. ECS (bitECS / Miniplex)
42
- is an opt-in option, not the default reach for it only at high entity
43
- counts. See `phaser-project-structure` and `phaser-testing`.
44
- 2. **Canvas-only, framework-agnostic UI.** UI is plain TS + DOM/canvas (the
45
- `template-vite-ts` baseline). A React/Vue EventBus bridge is documented only
46
- as an upgrade path — it is not the default and is not added unless required.
47
- 3. **Arcade physics by default; Matter is opt-in.** Matter is heavier and does
48
- not interop with Arcade. Switching is a one-line config swap. See
49
- the official `physics-arcade` skill.
50
- 4. **Determinism.** No `Math.random()`, `Date.now()`, or `performance.now()` in
51
- game code. Use the seeded `Phaser.Math.RandomDataGenerator` (`Phaser.Math.RND`
52
- or a local instance seeded from one place) so replays and tests reproduce.
53
- 5. **State and events.** Global state goes through a **typed wrapper over the
54
- registry**; cross-cutting events go through a **single dedicated
55
- EventsCenter** (`new Phaser.Events.EventEmitter()`) — **never reuse
56
- `game.events`**. Every external `.on()` (`this.input` / `scale` / `time` /
57
- `window` / the custom bus) must have a matching `.off()` in the scene's
58
- `shutdown`. See `phaser-services`.
59
- 6. **Performance.** Pool transient objects via `Group`s; make **no allocations
60
- and create no objects/tweens/timers inside `update()`**; atlas everything; use
61
- `BitmapText` for high-churn text; use `SpriteGPULayer` / `TilemapGPULayer` for
62
- mass rendering. See the official `game-object-components` skill.
63
- 7. **Baked-in asset pipeline with REAL art.** Raw art in `assets/src` is packed
64
- at build time (free-tex-packer-core atlases, audiosprite, BMFont) into
65
- `public/assets`, and a codegen step emits typed keys to `src/assets.ts` so a
66
- missing or renamed key is a **compile error**. No raw string asset / scene /
67
- event keys anywhere. The art itself must be **real and licensed** — sourced
68
- per `phaser-asset-sourcing` (CC0-or-equivalent only, with an exact license
69
- quote + evidence URL in `assets/LICENSES.md` and committed provenance).
70
- Procedural `generateTexture` placeholders are **tracked art debt**: a scene
71
- may ship them **only** with a linked art-debt issue, never as the finished
72
- state and never described as "zero-asset best practice." Characters ship real
73
- idle+walk animation, not static frames. See `phaser-asset-sourcing` and
74
- `phaser-asset-pipeline`.
75
- 8. **PWA on by default** via `vite-plugin-pwa` (`registerType: "autoUpdate"`,
76
- `globPatterns` extended to cover game assets). See `phaser-build-deploy`.
77
- 9. **Cross-cutting services are scaffolded** in `src/services/**`: SoundService
78
- (mobile audio unlock on first gesture), InputService (semantic actions, not
79
- raw keys), SaveService (typed `localStorage` with a schema `VERSION` +
80
- migration chain — never raw `localStorage`), a typed i18n string catalog (no
81
- hardcoded user-facing strings), accessibility (prefers-reduced-motion,
82
- pause-on-blur, keyboard-navigable menus, screen-reader live region), and a
83
- vendor-neutral telemetry/analytics abstraction. In-game errors are wired to
84
- the observability sink. See `phaser-services`, `phaser-i18n`,
85
- `phaser-accessibility`.
86
- 10. **Testing is a pyramid.** Pure logic is unit-tested with Vitest;
87
- scenes/entities are excluded from unit coverage and verified by **runtime
88
- gates** in CI (boot smoke, allocation/perf budget, leak gate, determinism
89
- gate, deterministic visual regression, bundle-size budget). See
90
- `phaser-testing`. Build pins: `phaser ^4.2.0`, Vite, TypeScript 6.
91
-
92
- ## Enforced lint rules (prose must match machine enforcement)
93
-
94
- The lint config enforces the rules below. Each exists because the prose above
95
- relies on it — keep them in sync.
96
-
97
- **`no-restricted-imports`**
98
-
99
- - Importing `phaser` anywhere under `src/logic/**` is banned. The logic core
100
- stays engine-free so Vitest runs it without a browser.
101
-
102
- **`no-restricted-syntax`** bans:
103
-
104
- - Removed v3 idioms: `setPipeline` / `setPostPipeline` / `resetPipeline`,
105
- `setTintFill`, `preFX` / `postFX`, `Phaser.Geom.Point`, `Phaser.Struct`,
106
- `BitmapMask`, `Mesh`, `Plane`, `Camera3D`. Use the v4 replacements
107
- (RenderNodes, Filters, `Phaser.Math.Vector2`, native `Set`/`Map`, GPU layers).
108
- - `Math.random()` / `Date.now()` / `performance.now()` in `src` game code — use
109
- the seeded RND and the scene clock (`this.time.now`).
110
- - Reusing `game.events` for app messaging — use the dedicated EventsCenter.
111
- - `debug: true` inside a physics/game config object literal — debug stays off in
112
- committed code (toggle locally, never commit it on).
113
-
114
- **Direct-`localStorage` ban**
115
-
116
- - Direct `localStorage` access outside `src/services/**` is banned. Persist
117
- through SaveService (versioned + migrated).
118
-
119
- **Custom `eslint-plugin-phaser` rules**
120
-
121
- - `no-create-in-update` — no `this.add.*`, `tweens.add`, `time.addEvent`,
122
- `physics.add.*`, or `new Phaser.*` inside an `update()` method. Create in
123
- `create()`; in the loop, reuse and pool.
124
- - `no-allocation-in-update` — no object/array literals, closures, or
125
- `.map`/`.filter`/`.reduce` chains inside `update()`. Hoist scratch objects.
126
- - `require-shutdown-cleanup` — a `Scene` that registers persistent external
127
- listeners must define a `shutdown` handler that removes them.
128
-
129
- ## Architecture
130
-
131
- - **One scene class per file** under `src/scenes/`, named after the scene key.
132
- The scene flow is `Boot → Preloader → MainMenu → Game` (plus overlays). Boot
133
- loads only what the Preloader needs; the Preloader loads everything else.
134
- - **Pure game logic lives in `src/logic/**`** with no `phaser` imports — plain
135
- TypeScript that takes and returns data. Scenes/entities are thin orchestrators
136
- that wire that logic to GameObjects. See `phaser-testing`.
137
- - **Keys are typed constants** generated into `src/assets.ts` — never inline
138
- magic strings for texture/audio/animation/scene/event keys. Load via asset-pack
139
- manifests (`this.load.pack`), not ad-hoc `load.image` lists.
140
-
141
- ## Performance
142
-
143
- - **No allocations in `update()`** and **no object/tween/timer creation in
144
- `update()`** (both lint-enforced) — hoist scratch objects, reuse vectors.
145
- - **Pool, don't churn.** Bullets, enemies, particles, and pickups come from
146
- `Group` pools (`get` / `killAndHide`), never `new` / `destroy` per spawn.
147
- - **Mass rendering uses the GPU layers.** Large sprite fields → `SpriteGPULayer`;
148
- large tile maps → `TilemapGPULayer`. Atlas everything (see
149
- `phaser-asset-pipeline`); `BitmapText` for high-churn text.
150
- - Target WebGL; the Canvas renderer is deprecated in v4 and acceptable only as an
151
- explicit, documented fallback.
152
-
153
- ## Verification
154
-
155
- Before reporting any change complete: run `bun run typecheck`, `bun run lint`,
156
- `bun run test`, and `bun run build`. For changes that affect rendering or input,
157
- verify in the real browser — `bun run dev` plus a Playwright check (the game
158
- boots, the canvas renders, no console errors). CI additionally runs the runtime
159
- gates (`phaser-testing`). A green typecheck alone is not proof a game works.
160
-
161
- ## Game-development personas (subagents)
162
-
163
- This plugin ships **game-development persona subagents** under `agents/` —
164
- reusable *roles* (a publisher, a game designer, a target player, …) that
165
- critique the game from a non-engineering seat. They complement, and never
166
- duplicate, Lisa's engineering specialists (architecture, quality, test,
167
- security, performance). Most are **critics** (they review the design and report
168
- findings); a couple (`narrative-designer`, `target-player`) also **generate**
169
- content.
170
-
171
- **Role vs. instance.** The persona *role* lives here (genre-neutral, reusable
172
- across every Phaser game). The persona *instance data* — this game's actual
173
- target-player archetypes, art direction, economy spec, publisher constraints —
174
- lives in the project's wiki. Each subagent reads its source-of-truth wiki docs
175
- (`wiki/design/**`, `wiki/narrative/**`, `wiki/production/**`,
176
- `wiki/personas/**`, …) and degrades to genre-neutral best practice, saying so,
177
- when those docs are absent.
178
-
179
- | Tier | Personas |
180
- |------|----------|
181
- | **Core** (most games) | `game-designer`, `player-advocate`, `narrative-designer`, `level-designer`, `ux-ui-designer`, `game-feel-specialist`, `qa-playtester`, `producer` |
182
- | **Business & audience** | `publisher`, `marketing-strategist`, `target-player`, `accessibility-advocate` |
183
- | **Specialist** (opt-in per project) | `combat-designer`, `economy-designer`, `art-director`, `audio-director`, `monetization-designer`, `localization-manager`, `onboarding-advocate`, `product-analyst` |
184
-
185
- Invoke a persona as a subagent (e.g. via the Agent tool / `@`-mention) during
186
- planning and review. Specialist personas are opt-in — enable the ones the
187
- project's genre warrants (a puzzle game does not need a `combat-designer`); the
188
- `monetization-designer` should stay off for premium/offline titles.
189
-
6
+ # Phaser 4 Project Rules (load-bearing)
7
+
8
+ This is a **Phaser 4** (npm `phaser@^4.2.0`) TypeScript game project on the
9
+ official `template-vite-ts` layout. Phaser 4 is the only supported target —
10
+ never introduce Phaser 3 idioms. These decisions are **locked** and most are
11
+ **lint-enforced**; do not disable a rule, fix the code.
12
+
13
+ ## Read the official skills first
14
+
15
+ Phaser ships 28 authoritative agent skills inside the installed package at
16
+ `node_modules/phaser/skills/<topic>/SKILL.md` (`scenes`, `physics-arcade`,
17
+ `tweens`, `tilemaps`, `v3-to-v4-migration`, …). **For any Phaser API or
18
+ subsystem question, read the matching official skill rather than relying on
19
+ memory.** The `lisa-phaser` skills deliberately cover only the opinionated,
20
+ lint-enforced project layer.
21
+
22
+ ## Mandatory
23
+
24
+ 1. **Thin scenes over a pure-logic core.** All game rules live in `src/logic/**`
25
+ as plain TypeScript with **zero `phaser` imports** lint-enforced, and it is
26
+ what makes the game unit-testable.
27
+ 2. **Determinism.** No `Math.random()`, `Date.now()`, or `performance.now()` in
28
+ game code. Use the seeded `Phaser.Math.RND` and the scene clock.
29
+ 3. **Nothing created or allocated inside `update()`** no `this.add.*`,
30
+ `tweens.add`, `time.addEvent`, `new Phaser.*`, object/array literals, or
31
+ `map`/`filter`/`reduce` chains. Create in `create()`; pool via `Group`s.
32
+ 4. **Events and state.** Cross-cutting events go through one dedicated
33
+ `EventsCenter`; **never reuse `game.events`**. Every external `.on()` needs a
34
+ matching `.off()` in the scene's `shutdown`. Global state goes through the
35
+ typed registry wrapper; persistence goes through SaveService, never raw
36
+ `localStorage`.
37
+ 5. **No raw keys, no placeholder art.** Texture/audio/animation/scene/event keys
38
+ are typed constants generated into `src/assets.ts`. Art must be real and
39
+ licensed per `phaser-asset-sourcing`; procedural `generateTexture`
40
+ placeholders are tracked art debt and need a linked issue.
41
+ 6. **No hardcoded user-facing strings** use the typed i18n catalog.
42
+ 7. **Verify before reporting complete:** `bun run typecheck`, `bun run lint`,
43
+ `bun run test`, `bun run build`. For rendering or input changes, also verify
44
+ in a real browser (`bun run dev` plus a Playwright check). A green typecheck
45
+ alone is not proof a game works.
46
+
47
+ Full prose the ten locked architecture decisions, the enforced lint rules, the
48
+ performance contract, and the game-development persona subagents:
49
+ [reference/phaser.md](phaser-reference.mdc).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,7 +1,17 @@
1
1
  #!/usr/bin/env bash
2
- # Reads all .md files from the plugin's rules/ directory and injects them
3
- # into the session context via hookSpecificOutput.additionalContext.
4
- # Used by SessionStart and SubagentStart hooks.
2
+ # Reads the plugin's EAGER rules and injects them into the session context.
3
+ #
4
+ # `rules/eager/` only, and deliberately with NO fallback to a flat `rules/`.
5
+ # This plugin's rules and this script ship in the same directory and are
6
+ # installed as one unit, so there is no vintage in which a split script meets an
7
+ # unsplit rules tree. A fallback here would buy nothing and cost the thing it
8
+ # already cost once: this plugin shipped its whole rule body flat for months and
9
+ # no surface complained, because a fallback that quietly succeeds is
10
+ # indistinguishable from a tree that was never split (#3993). With the branch
11
+ # gone, an unsplit tree injects nothing and is noticed.
12
+ #
13
+ # Reference bodies under `rules/reference/` install alongside and are read only
14
+ # when an eager breadcrumb points at one.
5
15
  set -euo pipefail
6
16
 
7
17
  INPUT=$(cat 2>/dev/null || true)
@@ -12,7 +22,7 @@ else
12
22
  fi
13
23
 
14
24
  ROOT="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}}"
15
- RULES_DIR="$ROOT/rules"
25
+ RULES_DIR="$ROOT/rules/eager"
16
26
 
17
27
  # Bail silently if no rules directory
18
28
  [ -d "$RULES_DIR" ] || exit 0
@@ -0,0 +1,23 @@
1
+ # Rails Coding Conventions (load-bearing)
2
+
3
+ Rails-specific standards for this project. The head below is what changes
4
+ behaviour in a session that never asks for it; the worked examples for every
5
+ point live in the reference body.
6
+
7
+ ## Mandatory
8
+
9
+ 1. **Fat models, skinny controllers.** Controllers handle HTTP concerns only.
10
+ Business logic belongs in a model or a service object under `app/services/`.
11
+ 2. **Strong parameters always, `permit!` never.** Enumerate the permitted keys.
12
+ 3. **No N+1 queries.** Use `includes` / `preload` / `eager_load` on any
13
+ association you iterate. Bullet is installed to catch the ones you miss.
14
+ 4. **Never edit `db/schema.rb` by hand.** Change it through a migration, honour
15
+ the `strong_migrations` constraints, and index every foreign key and
16
+ commonly-queried column.
17
+ 5. **Scopes, not class methods,** for chainable queries. Prefer built-in
18
+ validators; keep callbacks to simple normalization and push complex side
19
+ effects into a service object.
20
+ 6. **RSpec with `factory_bot` and `shoulda-matchers`,** not fixtures. Use
21
+ `described_class` and keep one assertion concept per example.
22
+
23
+ Full prose and Ruby examples: [reference/rails-conventions.md](../reference/rails-conventions.md).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,7 +1,17 @@
1
1
  #!/usr/bin/env bash
2
- # Reads all .md files from the plugin's rules/ directory and injects them
3
- # into the session context via hookSpecificOutput.additionalContext.
4
- # Used by SessionStart and SubagentStart hooks.
2
+ # Reads the plugin's EAGER rules and injects them into the session context.
3
+ #
4
+ # `rules/eager/` only, and deliberately with NO fallback to a flat `rules/`.
5
+ # This plugin's rules and this script ship in the same directory and are
6
+ # installed as one unit, so there is no vintage in which a split script meets an
7
+ # unsplit rules tree. A fallback here would buy nothing and cost the thing it
8
+ # already cost once: this plugin shipped its whole rule body flat for months and
9
+ # no surface complained, because a fallback that quietly succeeds is
10
+ # indistinguishable from a tree that was never split (#3993). With the branch
11
+ # gone, an unsplit tree injects nothing and is noticed.
12
+ #
13
+ # Reference bodies under `rules/reference/` install alongside and are read only
14
+ # when an eager breadcrumb points at one.
5
15
  set -euo pipefail
6
16
 
7
17
  INPUT=$(cat 2>/dev/null || true)
@@ -12,7 +22,7 @@ else
12
22
  fi
13
23
 
14
24
  ROOT="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}}"
15
- RULES_DIR="$ROOT/rules"
25
+ RULES_DIR="$ROOT/rules/eager"
16
26
 
17
27
  # Bail silently if no rules directory
18
28
  [ -d "$RULES_DIR" ] || exit 0
@@ -0,0 +1,23 @@
1
+ # Rails Coding Conventions (load-bearing)
2
+
3
+ Rails-specific standards for this project. The head below is what changes
4
+ behaviour in a session that never asks for it; the worked examples for every
5
+ point live in the reference body.
6
+
7
+ ## Mandatory
8
+
9
+ 1. **Fat models, skinny controllers.** Controllers handle HTTP concerns only.
10
+ Business logic belongs in a model or a service object under `app/services/`.
11
+ 2. **Strong parameters always, `permit!` never.** Enumerate the permitted keys.
12
+ 3. **No N+1 queries.** Use `includes` / `preload` / `eager_load` on any
13
+ association you iterate. Bullet is installed to catch the ones you miss.
14
+ 4. **Never edit `db/schema.rb` by hand.** Change it through a migration, honour
15
+ the `strong_migrations` constraints, and index every foreign key and
16
+ commonly-queried column.
17
+ 5. **Scopes, not class methods,** for chainable queries. Prefer built-in
18
+ validators; keep callbacks to simple normalization and push complex side
19
+ effects into a service object.
20
+ 6. **RSpec with `factory_bot` and `shoulda-matchers`,** not fixtures. Use
21
+ `described_class` and keep one assertion concept per example.
22
+
23
+ Full prose and Ruby examples: [reference/rails-conventions.md](../reference/rails-conventions.md).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -0,0 +1,181 @@
1
+ ---
2
+ description: "Rails Coding Conventions"
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Rails Coding Conventions
7
+
8
+ This rule enforces Rails-specific coding standards for consistency, maintainability, and performance.
9
+
10
+ ## Fat Models, Skinny Controllers
11
+
12
+ Controllers handle HTTP concerns only. Business logic belongs in models or service objects.
13
+
14
+ ```ruby
15
+ # Correct — controller delegates to model
16
+ class OrdersController < ApplicationController
17
+ def create
18
+ @order = Order.place(order_params, current_user)
19
+ redirect_to @order
20
+ end
21
+ end
22
+
23
+ # Wrong — business logic in controller
24
+ class OrdersController < ApplicationController
25
+ def create
26
+ @order = Order.new(order_params)
27
+ @order.user = current_user
28
+ @order.total = @order.line_items.sum(&:price)
29
+ @order.apply_discount(current_user.discount_rate)
30
+ @order.save!
31
+ OrderMailer.confirmation(@order).deliver_later
32
+ redirect_to @order
33
+ end
34
+ end
35
+ ```
36
+
37
+ ## Service Objects
38
+
39
+ Extract complex business logic into service objects when a model method would be too large or spans multiple models.
40
+
41
+ ```ruby
42
+ # app/services/order_placement_service.rb
43
+ class OrderPlacementService
44
+ def initialize(user:, params:)
45
+ @user = user
46
+ @params = params
47
+ end
48
+
49
+ def call
50
+ order = Order.new(@params)
51
+ order.user = @user
52
+ order.calculate_total
53
+ order.save!
54
+ OrderMailer.confirmation(order).deliver_later
55
+ order
56
+ end
57
+ end
58
+ ```
59
+
60
+ ## Concerns
61
+
62
+ Use concerns to share behavior across models or controllers. Keep concerns focused on a single responsibility.
63
+
64
+ ```ruby
65
+ # app/models/concerns/searchable.rb
66
+ module Searchable
67
+ extend ActiveSupport::Concern
68
+
69
+ included do
70
+ scope :search, ->(query) { where("name ILIKE ?", "%#{query}%") }
71
+ end
72
+ end
73
+ ```
74
+
75
+ ## ActiveRecord Patterns
76
+
77
+ ### Scopes over class methods for chainable queries
78
+
79
+ ```ruby
80
+ # Correct — scope
81
+ scope :active, -> { where(active: true) }
82
+ scope :recent, -> { order(created_at: :desc) }
83
+
84
+ # Wrong — class method for simple query
85
+ def self.active
86
+ where(active: true)
87
+ end
88
+ ```
89
+
90
+ ### Validations
91
+
92
+ ```ruby
93
+ # Use built-in validators
94
+ validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }
95
+ validates :age, numericality: { greater_than: 0 }
96
+ ```
97
+
98
+ ### Callbacks — use sparingly
99
+
100
+ Prefer explicit service objects over callbacks for complex side effects. Callbacks are acceptable for simple data normalization.
101
+
102
+ ```ruby
103
+ # Acceptable — simple normalization
104
+ before_validation :normalize_email
105
+
106
+ private
107
+
108
+ def normalize_email
109
+ self.email = email&.downcase&.strip
110
+ end
111
+ ```
112
+
113
+ ## N+1 Query Prevention
114
+
115
+ Always use `includes`, `preload`, or `eager_load` to prevent N+1 queries. The Bullet gem is included to detect these in development.
116
+
117
+ ```ruby
118
+ # Correct — eager loading
119
+ @posts = Post.includes(:author, :comments).where(published: true)
120
+
121
+ # Wrong — N+1 query
122
+ @posts = Post.where(published: true)
123
+ @posts.each { |post| post.author.name } # N+1!
124
+ ```
125
+
126
+ ## Strong Parameters
127
+
128
+ Always use strong parameters in controllers. Never use `permit!`.
129
+
130
+ ```ruby
131
+ # Correct
132
+ def order_params
133
+ params.require(:order).permit(:product_id, :quantity, :notes)
134
+ end
135
+
136
+ # Wrong — permits everything
137
+ def order_params
138
+ params.require(:order).permit!
139
+ end
140
+ ```
141
+
142
+ ## Database Migrations
143
+
144
+ - Use `strong_migrations` gem constraints (included via Gemfile.lisa)
145
+ - Never modify `db/schema.rb` directly
146
+ - Always add indexes for foreign keys and commonly queried columns
147
+ - Use `change` method when the migration is reversible; use `up`/`down` when it is not
148
+
149
+ ```ruby
150
+ class AddIndexToOrdersUserId < ActiveRecord::Migration[7.2]
151
+ def change
152
+ add_index :orders, :user_id
153
+ end
154
+ end
155
+ ```
156
+
157
+ ## Testing with RSpec
158
+
159
+ - Use `let` and `let!` for test setup
160
+ - Use `described_class` instead of repeating the class name
161
+ - Use `factory_bot` for test data, not fixtures
162
+ - Use `shoulda-matchers` for model validation tests
163
+ - Keep tests focused — one assertion concept per example
164
+
165
+ ```ruby
166
+ RSpec.describe Order, type: :model do
167
+ describe "validations" do
168
+ it { is_expected.to validate_presence_of(:user) }
169
+ it { is_expected.to validate_numericality_of(:total).is_greater_than(0) }
170
+ end
171
+
172
+ describe ".recent" do
173
+ it "returns orders in descending creation order" do
174
+ old_order = create(:order, created_at: 1.day.ago)
175
+ new_order = create(:order, created_at: 1.hour.ago)
176
+
177
+ expect(described_class.recent).to eq([new_order, old_order])
178
+ end
179
+ end
180
+ end
181
+ ```