@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,181 +1,28 @@
1
1
  ---
2
- description: "Rails Coding Conventions"
2
+ description: "Rails Coding Conventions (load-bearing)"
3
3
  alwaysApply: true
4
4
  ---
5
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
- ```
6
+ # Rails Coding Conventions (load-bearing)
7
+
8
+ Rails-specific standards for this project. The head below is what changes
9
+ behaviour in a session that never asks for it; the worked examples for every
10
+ point live in the reference body.
11
+
12
+ ## Mandatory
13
+
14
+ 1. **Fat models, skinny controllers.** Controllers handle HTTP concerns only.
15
+ Business logic belongs in a model or a service object under `app/services/`.
16
+ 2. **Strong parameters always, `permit!` never.** Enumerate the permitted keys.
17
+ 3. **No N+1 queries.** Use `includes` / `preload` / `eager_load` on any
18
+ association you iterate. Bullet is installed to catch the ones you miss.
19
+ 4. **Never edit `db/schema.rb` by hand.** Change it through a migration, honour
20
+ the `strong_migrations` constraints, and index every foreign key and
21
+ commonly-queried column.
22
+ 5. **Scopes, not class methods,** for chainable queries. Prefer built-in
23
+ validators; keep callbacks to simple normalization and push complex side
24
+ effects into a service object.
25
+ 6. **RSpec with `factory_bot` and `shoulda-matchers`,** not fixtures. Use
26
+ `described_class` and keep one assertion concept per example.
27
+
28
+ Full prose and Ruby examples: [reference/rails-conventions.md](rails-conventions-reference.mdc).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -8,6 +8,7 @@
8
8
  "all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh",
9
9
  "all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh",
10
10
  "all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh",
11
+ "all/copy-overwrite/scripts/lisa-hooks/guard-dedupe.bash",
11
12
  "all/copy-overwrite/scripts/lisa-hooks/parity-safety-net-heredoc.py",
12
13
  "all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh",
13
14
  "all/copy-overwrite/scripts/lisa-hooks/sonar-secrets.sh",
@@ -108,6 +108,15 @@
108
108
  }
109
109
  ]
110
110
  },
111
+ {
112
+ "matcher": "Bash|Edit|Write|Read|Task|Grep|Glob",
113
+ "hooks": [
114
+ {
115
+ "type": "command",
116
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/operational-hazards.sh --hook"
117
+ }
118
+ ]
119
+ },
111
120
  {
112
121
  "matcher": "EnterWorktree",
113
122
  "hooks": [
@@ -258,6 +267,15 @@
258
267
  }
259
268
  ]
260
269
  },
270
+ {
271
+ "matcher": "",
272
+ "hooks": [
273
+ {
274
+ "type": "command",
275
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/operational-hazards.sh --session-start"
276
+ }
277
+ ]
278
+ },
261
279
  {
262
280
  "matcher": "",
263
281
  "hooks": [
@@ -331,6 +349,15 @@
331
349
  }
332
350
  ]
333
351
  },
352
+ {
353
+ "matcher": "",
354
+ "hooks": [
355
+ {
356
+ "type": "command",
357
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/operational-hazards.sh --session-start"
358
+ }
359
+ ]
360
+ },
334
361
  {
335
362
  "matcher": "",
336
363
  "hooks": [
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: linear-prd-intake
3
- description: PRD intake agent for Linear-hosted PRDs. Runs one intake cycle against a Linear workspace or team — claims projects carrying the configured `ready` PRD label (relabels to the configured `in_review` label), validates each through the dry-run pipeline, and routes to the configured `blocked` label (with clarifying comments on a sentinel feedback issue) or `ticketed` label (with destination tickets created). Linear counterpart of `notion-prd-intake` and `confluence-prd-intake`. Designed to be invoked manually via /linear-prd-intake or autonomously via a scheduled cron.
3
+ description: PRD intake agent for Linear-hosted PRDs. Runs one intake cycle against a Linear workspace or team — claims projects carrying the configured `ready` PRD label (relabels to the configured `in_review` label), validates each through the dry-run pipeline, and routes to the configured `blocked` label (with clarifying comments on the project) or `ticketed` label (with destination tickets created). Linear counterpart of `notion-prd-intake` and `confluence-prd-intake`. Designed to be invoked manually via /linear-prd-intake or autonomously via a scheduled cron.
4
4
  skills:
5
5
  - linear-prd-intake
6
6
  - linear-to-tracker
@@ -15,9 +15,9 @@ skills:
15
15
 
16
16
  You are a PRD intake agent. Your single job is to run one intake cycle against the Linear scope (a workspace or a team) given to you, then report what happened.
17
17
 
18
- This agent is the Linear counterpart of `notion-prd-intake` and `confluence-prd-intake`. The behavior is identical apart from the source-of-truth tool surface and one structural difference (clarifying comments land on a sentinel feedback issue under each project, not on the project page itself, because Linear's MCP doesn't expose project-level comments). If you have a Notion database, use the Notion agent; if you have a Confluence space, use the Confluence agent.
18
+ This agent is the Linear counterpart of `notion-prd-intake` and `confluence-prd-intake`. The behavior is identical apart from the source-of-truth tool surface: clarifying comments land on the project itself, exactly as they do on a Notion or Confluence page. (They used to land on a fabricated per-project "sentinel" issue, justified by the Linear MCP not exposing project-level comments. That premise was wrong about the substrate — `commentCreate(input: { projectId, body })` and `Project.comments` have always existed, and the access layer's precedence contract puts GraphQL ahead of the MCP. The gap was in the wrapper, and it is closed; see "Legacy sentinel feedback issues" in the skill for what happens to the ones already created.) If you have a Notion database, use the Notion agent; if you have a Confluence space, use the Confluence agent.
19
19
 
20
- PRD label role names (`ready`, `in_review`, `blocked`, `ticketed`, `shipped`, `verified`, `sentinel`) are resolved from `.lisa.config.json` `linear.labels.prd.*` by the `linear-prd-intake` skill. The defaults match the legacy hardcoded names (`prd-ready`, `prd-in-review`, `prd-blocked`, `prd-ticketed`, `prd-shipped`, `prd-verified`, `prd-intake-feedback`). The full PRD lifecycle is `draft → ready → in_review → blocked | ticketed → shipped → verified`; this agent only ever drives `ready → in_review → blocked | ticketed`. The `shipped` rollup is owned by the intake skill's rollup phase, and `verified` is set by `/lisa:verify-prd` after empirical PRD-level acceptance — never by this agent.
20
+ PRD label role names (`ready`, `in_review`, `blocked`, `ticketed`, `shipped`, `verified`, and the legacy read-only `sentinel`) are resolved from `.lisa.config.json` `linear.labels.prd.*` by the `linear-prd-intake` skill. The defaults match the legacy hardcoded names (`prd-ready`, `prd-in-review`, `prd-blocked`, `prd-ticketed`, `prd-shipped`, `prd-verified`, `prd-intake-feedback`). The full PRD lifecycle is `draft → ready → in_review → blocked | ticketed → shipped → verified`; this agent only ever drives `ready → in_review → blocked | ticketed`. The `shipped` rollup is owned by the intake skill's rollup phase, and `verified` is set by `/lisa:verify-prd` after empirical PRD-level acceptance — never by this agent.
21
21
 
22
22
  ## Confirmation policy
23
23
 
@@ -29,11 +29,11 @@ Once you have a workspace or team scope, RUN. Do not ask the caller whether to p
29
29
 
30
30
  The invoking caller (a slash command, a scheduled cron, or a parent agent) hands you a Linear workspace URL, a team URL, a bare team key, or the literal token `linear` (which falls back to `linear.workspace` in `.lisa.config.json`). You do not pick the scope yourself.
31
31
 
32
- If no scope is provided, stop and ask. Never run intake against a default or guessed scope — the side effects (label changes, sentinel-issue creation, JIRA tickets created) are too high to act without an explicit target.
32
+ If no scope is provided, stop and ask. Never run intake against a default or guessed scope — the side effects (label changes, project comments, JIRA tickets created) are too high to act without an explicit target.
33
33
 
34
34
  ### 2. Run the intake skill
35
35
 
36
- Invoke the `linear-prd-intake` skill with the scope as `$ARGUMENTS`. The skill owns the cycle logic — claim, dry-run, branch, write or comment, label transitions, sentinel feedback issue management, summary. Do not duplicate that logic here.
36
+ Invoke the `linear-prd-intake` skill with the scope as `$ARGUMENTS`. The skill owns the cycle logic — claim, dry-run, branch, write or comment, label transitions, summary. Do not duplicate that logic here.
37
37
 
38
38
  Treat the skill's output as the source of truth (e.g. `ticketed: 3 / blocked: 1 / errors: 0`).
39
39
 
@@ -49,7 +49,7 @@ If the cycle errored before processing any PRDs (e.g. workspace unreachable, mis
49
49
 
50
50
  ### 4. Suggest next actions when warranted
51
51
 
52
- After a successful cycle, if any PRDs ended in the `blocked` label, mention to the caller that those PRDs need product attention before they can be re-ticketed. Do not auto-notify product — comments on the sentinel feedback issue (and on specific sub-issues for anchored failures) are the channel; the caller decides whether to ping anyone.
52
+ After a successful cycle, if any PRDs ended in the `blocked` label, mention to the caller that those PRDs need product attention before they can be re-ticketed. Do not auto-notify product — comments on the project (and on specific sub-issues for anchored failures) are the channel; the caller decides whether to ping anyone.
53
53
 
54
54
  When reporting `blocked` outcomes, distinguish the cause: **pre-write gate failure** (per-ticket validator caught a problem before any tickets were created) vs **post-write coverage gap** (tickets were created and remain in the destination tracker, but the PRD has uncovered requirements that the next intake cycle will address). Both result in the `blocked` label, but the implication for product is different — coverage gaps mean some tickets are already real and product should not re-author the PRD from scratch.
55
55
 
@@ -60,7 +60,7 @@ If all PRDs ended in the `ticketed` label with coverage `COMPLETE`, mention that
60
60
  - **Never run a cycle without an explicit scope.** Side effects are too high to default.
61
61
  - **Never modify the lifecycle**: only `ready → in_review → blocked|ticketed`. Never touch the `draft`, `shipped`, or `verified` labels (`shipped` is owned by the intake rollup phase; `verified` is owned by `/lisa:verify-prd`). Never invent new labels.
62
62
  - **Never write destination tickets directly.** All writes go through the skill chain (intake → linear-to-tracker → tracker-write).
63
- - **Never edit a project's description or any attached Linear document.** Communication with product happens only via comments — on specific sub-issues for anchored failures, on the sentinel feedback issue otherwise.
64
- - **Never close, archive, or repurpose the sentinel feedback issue.** It is reused across cycles; its longevity is the audit trail.
63
+ - **Never edit a project's description or any attached Linear document.** Communication with product happens only via comments — on specific sub-issues for anchored failures, on the project itself otherwise.
64
+ - **Never fabricate an issue to hold a comment.** The project takes comments directly. Legacy sentinel issues from earlier cycles are left exactly as they are — not closed, not archived, not repurposed, not posted to — and the rollup excludes them so they stop holding their projects open.
65
65
  - **Never start a second cycle while one is in flight against the same scope.** Serial execution; the scheduling layer is responsible for not double-firing.
66
66
  - **Stop and surface failures rather than retry-loop.** If `linear-to-tracker` returns an error, the skill records it under `Errors` in the summary; pass that through.
@@ -162,6 +162,27 @@ set -euo pipefail
162
162
 
163
163
  input="$(cat)"
164
164
 
165
+ # Evaluate once per tool call when this guard is registered on both channels.
166
+ #
167
+ # Lisa reaches an agent through the repository dispatcher AND the plugin
168
+ # manifest, and where both are live the harness runs this guard twice for one
169
+ # tool call. `guard-dedupe.bash` short-circuits the second run ONLY when a
170
+ # byte-identical copy already ALLOWED this exact payload on this exact tool
171
+ # call; a differing vintage, a refusal, and a host with one channel all
172
+ # evaluate exactly as before. Nothing is de-registered by it
173
+ # (CodySwannGT/lisa#3814).
174
+ #
175
+ # Absent library means no dedupe, which is the pre-existing behaviour, so an
176
+ # older channel copy that predates it is unaffected.
177
+ lisa_guard_hook_dir="${BASH_SOURCE[0]%/*}"
178
+ lisa_guard_dedupe_lib="$lisa_guard_hook_dir/guard-dedupe.bash"
179
+ if [ -r "$lisa_guard_dedupe_lib" ]; then
180
+ # shellcheck source=guard-dedupe.bash
181
+ . "$lisa_guard_dedupe_lib"
182
+ trap 'lisa_guard_dedupe_record $?' EXIT
183
+ lisa_guard_dedupe block-blind-automerge "$input"
184
+ fi
185
+
165
186
  # Both interpreters are probed BEFORE use, and a missing one is ANNOUNCED
166
187
  # rather than swallowed. Under `set -e` an absent jq would abort with 127, and
167
188
  # Claude Code treats any non-2 exit as a non-blocking hook error — so the guard
@@ -244,9 +265,41 @@ PULL_REQUEST_ID_PATTERN = re.compile(
244
265
  NODE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_=-]+$")
245
266
 
246
267
  # The probe that resolves a node id to the same fields `gh pr view` returns.
268
+ #
269
+ # `statusCheckRollup` is in here because the RE-TARGET path needs it and this
270
+ # is the only probe a GraphQL `updatePullRequest` can use. Without it
271
+ # `failing_check_names` read an absent key, found no failing check, and the
272
+ # guard announced the re-target as the sanctioned green-PR batching case —
273
+ # for a pull request that might be failing every check it has. The porcelain
274
+ # path asked the right question and the API path could not, so the identical
275
+ # act was guarded through `gh pr edit --base` and waved through as GraphQL:
276
+ # a bypass that needs no permission, only a different spelling.
277
+ #
278
+ # The nodes are reshaped by `--jq` below into the flat list `gh pr view
279
+ # --json statusCheckRollup` returns, so one reader serves both probes.
247
280
  NODE_QUERY = (
248
281
  "query($id:ID!){node(id:$id){... on PullRequest"
249
- "{number url reviewDecision state baseRefName}}}"
282
+ "{number url reviewDecision state baseRefName "
283
+ "commits(last:1){nodes{commit{statusCheckRollup{contexts(first:100){nodes{"
284
+ "__typename ... on CheckRun{name conclusion} "
285
+ "... on StatusContext{context state}"
286
+ "}}}}}}}}}"
287
+ )
288
+
289
+ # Reshape the envelope into the porcelain's shape: unwrap `.data.node`, hoist
290
+ # the last commit's rollup contexts to a top-level `statusCheckRollup` list,
291
+ # and drop the `commits` scaffolding that carried it.
292
+ # `has("commits")` rather than an unconditional default, and the distinction is
293
+ # the point: a node that CARRIES the scaffolding and no contexts is a PR with no
294
+ # checks, which is genuinely not failing and gets an empty list. A node without
295
+ # the scaffolding is a probe that never asked, and it must leave the key absent
296
+ # so the re-target path can tell the two apart instead of reading both as green.
297
+ NODE_JQ = (
298
+ "if .data.node == null then null else .data.node as $n "
299
+ "| if ($n | has(\"commits\")) then ($n | del(.commits)) "
300
+ "+ {statusCheckRollup: "
301
+ "((($n.commits.nodes[0].commit.statusCheckRollup.contexts.nodes)) // [])} "
302
+ "else $n end end"
250
303
  )
251
304
 
252
305
  # What a probe spec asks for. `view` and `node` differ only in how the PR is
@@ -725,7 +778,7 @@ def probe_args(kind, subject, repo_args, fields):
725
778
  "gh", "api", "graphql",
726
779
  "-f", "query=" + NODE_QUERY,
727
780
  "-f", "id=" + subject,
728
- "--jq", ".data.node",
781
+ "--jq", NODE_JQ,
729
782
  ]
730
783
  args = ["gh", "pr", "view"]
731
784
  if subject is not None:
@@ -966,6 +1019,20 @@ Do one of these instead:
966
1019
  - leave the PR on its covered base and merge it there.
967
1020
  """
968
1021
 
1022
+ RETARGET_CHECKS_UNREADABLE = """Blocked: re-targeting %s onto "%s" cannot be judged, because this guard could
1023
+ not read the pull request's checks.
1024
+
1025
+ That ref has ZERO required status checks, so the one thing standing between the
1026
+ move and a permission-free gate bypass is whether the PR is currently failing —
1027
+ and the probe returned no `statusCheckRollup` at all. An absent rollup is not an
1028
+ empty one. Reporting the move as the sanctioned green-PR batching case here
1029
+ would be a verdict about a question that was never asked.
1030
+
1031
+ Re-target through `gh pr edit --base` instead, which reads the checks, or fix
1032
+ the probe. Do not report the PR as batched until something has actually looked.
1033
+ """
1034
+
1035
+
969
1036
  UNCOVERED_RETARGET_NOTICE = (
970
1037
  "block-blind-automerge: %s is being re-targeted onto \"%s\", a ref with ZERO "
971
1038
  "required status checks; its gates will run but cannot block a merge\n"
@@ -1036,6 +1103,18 @@ for act, kind, subject, repo_args, target_ref in acts:
1036
1103
  # nothing can block it", which holds whatever base it came from.
1037
1104
  if not base_is_uncovered(payload, repo_args, target_ref):
1038
1105
  continue
1106
+ # Fails CLOSED, and only here. Everywhere else in this file an
1107
+ # unanswerable question degrades and continues, because the guard being
1108
+ # unable to run must not become the reason a command is refused. This
1109
+ # branch is different: the base has already been confirmed to have zero
1110
+ # required checks, so an empty `failing` list is the whole basis for
1111
+ # allowing the move, and an ABSENT rollup produces the identical empty
1112
+ # list. Passing on it would be a measurement that could not fail.
1113
+ if not isinstance(payload.get("statusCheckRollup"), list):
1114
+ sys.stderr.write(
1115
+ RETARGET_CHECKS_UNREADABLE % (pr_name(payload), target_ref)
1116
+ )
1117
+ sys.exit(1)
1039
1118
  failing = failing_check_names(payload)
1040
1119
  if not failing:
1041
1120
  # A green PR moving onto a stack base is the sanctioned batching
@@ -8,19 +8,44 @@
8
8
  # block-direct-issue-create.sh beside it (same delegation pattern as
9
9
  # block-instruction-file-edits.agy.sh).
10
10
  #
11
- # SCOPE GAP, recorded rather than silently dropped (AGENTS.md). This used to
12
- # read "no scope gap here: the canonical guard is Bash-only by construction, and
13
- # `run_command` is exactly the surface it needs." That stopped being true in
14
- # CodySwannGT/lisa#3753: the canonical guard now covers a SECOND substrate
15
- # structured tool payloads, where a creation arrives as named fields rather than
16
- # as a command line — because the filing contract was enforced on the shell and
17
- # unenforced on every tool call beside it.
11
+ # THE SECOND SUBSTRATE (CodySwannGT/lisa#3785). CodySwannGT/lisa#3753 taught the
12
+ # canonical guard that a creation also arrives as NAMED FIELDS rather than as a
13
+ # command line. This adapter used to forward `run_command` and nothing else, and
14
+ # the registration matched `run_command` only, so on agy that substrate was
15
+ # unenforced refused entry twice over, exactly as it was on Claude before
16
+ # CodySwannGT/lisa#3753. Widening one without the other changes nothing.
18
17
  #
19
- # This adapter forwards `run_command` and nothing else, so on agy that second
20
- # substrate is still uncovered. Closing it needs agy's own tool-call envelope
21
- # (which tool names its creation surface, and where the arguments land), and
22
- # that is a different piece of work from translating one protocol. The shell
23
- # surface agy does expose receives the whole guard, exactly as before.
18
+ # agy's envelope was CAPTURED, not guessed a probe plugin registered with an
19
+ # empty matcher, driven through `agy --dangerously-skip-permissions -p`, on
20
+ # agy 1.1.3:
21
+ #
22
+ # {"toolCall":{"name":"call_mcp_tool","args":{
23
+ # "ServerName":"probe-tracker","ToolName":"create_issue",
24
+ # "Arguments":{"title":"envelope probe","body":"capture"},
25
+ # "toolAction":"...","toolSummary":"..."}}}
26
+ #
27
+ # Two things about it decide the translation below, and both would have been got
28
+ # wrong by a plausible guess:
29
+ #
30
+ # - EVERY MCP call arrives under the single tool name `call_mcp_tool`. The
31
+ # server and tool the model actually asked for live in `ServerName` /
32
+ # `ToolName`, so forwarding agy's outer name verbatim hands the canonical
33
+ # guard a name carrying no tracker noun, and its shape gate ALLOWS the lot.
34
+ # Measured before this change: forwarding `call_mcp_tool` raw ALLOWED an
35
+ # undeclared `create_issue`. So the adapter reassembles the name into the
36
+ # `mcp__<server>__<tool>` spelling the canonical guard already classifies on
37
+ # Claude — one vocabulary, one classifier.
38
+ # - The arguments land under `Arguments`, not inline beside the metadata, so
39
+ # `toolAction` / `toolSummary` — agy's own prose about the call — stay OUT
40
+ # of the payload the declaration is read from. Passing them would let a
41
+ # summary sentence mentioning the ready role answer for the filing.
42
+ #
43
+ # Every other tool is forwarded generically (`{tool_name, tool_input}`) rather
44
+ # than allowed here. The canonical guard owns the question of what counts as a
45
+ # creation; an adapter that pre-filtered would be a second copy of that policy,
46
+ # and the first native creation tool agy adds would arrive on the wrong side of
47
+ # it. The cost is one extra `bash` + `jq` per non-shell tool call, which is what
48
+ # the canonical guard's subprocess-free shape gate exists to keep cheap.
24
49
  #
25
50
  # Fail-open on missing runtimes: a missed refusal costs one under-declared
26
51
  # ticket, and `lisa-repair-intake` already sweeps for exactly that. Failing
@@ -47,15 +72,38 @@ input="$(cat 2>/dev/null || true)"
47
72
  command -v jq >/dev/null 2>&1 || allow
48
73
 
49
74
  tool_name="$(printf '%s' "$input" | jq -r '.toolCall.name // empty' 2>/dev/null || true)"
50
- [ "$tool_name" != "run_command" ] && allow
51
- command_str="$(printf '%s' "$input" | jq -r '.toolCall.args.CommandLine // empty' 2>/dev/null || true)"
52
- [ -z "$command_str" ] && allow
75
+ [ -z "$tool_name" ] && allow
76
+
77
+ canonical_input=""
78
+ if [ "$tool_name" = "run_command" ]; then
79
+ # The shell substrate, byte-identical to what it was before the second
80
+ # substrate arrived. Its verdicts are the control for this change.
81
+ command_str="$(printf '%s' "$input" | jq -r '.toolCall.args.CommandLine // empty' 2>/dev/null || true)"
82
+ [ -z "$command_str" ] && allow
83
+ canonical_input="$(jq -cn --arg command "$command_str" '{tool_name:"Bash",tool_input:{command:$command}}')"
84
+ elif [ "$tool_name" = "call_mcp_tool" ]; then
85
+ # A missing ServerName or ToolName is a payload this adapter cannot name, and
86
+ # naming is the whole of its job here. It hands the canonical guard the
87
+ # unspellable name rather than inventing a plausible one, so the guard's own
88
+ # fail-closed arm decides — never this adapter.
89
+ canonical_input="$(
90
+ printf '%s' "$input" |
91
+ jq -c '(.toolCall.args // {}) as $a
92
+ | {tool_name: ("mcp__" + ($a.ServerName // "?") + "__" + ($a.ToolName // "?")),
93
+ tool_input: ($a.Arguments // {})}' 2>/dev/null || true
94
+ )"
95
+ else
96
+ canonical_input="$(
97
+ printf '%s' "$input" |
98
+ jq -c '{tool_name: .toolCall.name, tool_input: (.toolCall.args // {})}' 2>/dev/null || true
99
+ )"
100
+ fi
101
+ [ -z "$canonical_input" ] && allow
53
102
 
54
103
  hook_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
55
104
  canonical_hook="$hook_dir/block-direct-issue-create.sh"
56
105
  [ -r "$canonical_hook" ] || allow
57
106
 
58
- canonical_input="$(jq -cn --arg command "$command_str" '{tool_name:"Bash",tool_input:{command:$command}}')"
59
107
  canonical_output=""
60
108
  canonical_status=0
61
109
  if canonical_output="$(printf '%s' "$canonical_input" | /bin/bash "$canonical_hook" 2>&1)"; then