@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
@@ -188,6 +188,7 @@ In addition to the lifecycle roles above, the build lifecycle defines the **`hum
188
188
 
189
189
  - The blocks repair-intake **itself writes** are the auto-recoverable kind — it files a build-ready fix ticket and moves the item `blocked` *blocked by that ticket*, expecting the next cycle to self-heal. Those are **not** `human_needed`; if such an item arrives carrying a `human_needed` marker **this skill applied on an earlier cycle**, repair-intake **clears** it (the block is no longer waiting on a human).
190
190
  - **Never remove a `human_needed` marker this skill did not apply.** "Stale" is a judgment about the block's kind, not about who applied the marker or when — so without this rule an operator's deliberate hold, applied *after* correcting a wrong transition, is indistinguishable from a leftover the sweep is designed to clear, and gets swept. Establish provenance from the label event's actor (`rejection-detection` **Automation-reversal memory** reads the same surfaces); if provenance is not readable, **leave the marker in place**. Removing a human's hold is unrecoverable within the loop; leaving a stale one costs a cycle and is visible.
191
+ - **The one exception is a hold that has recorded its own discharge.** A `[lisa-human-gate-release]` comment naming the hold's `reason=` is not a guess about provenance — it is the hold's stated void condition, recorded on the item by the person who answered it. Clearing the marker there is not overriding a human's judgment; it is *enacting* it. That is the whole of the exception: no other reading of "this looks stale" reopens the question above, and an item whose release cannot be read stays held. See "Release the holds that have been answered" below (#3852).
191
192
  - The marker is consulted **before **any** repair transition**, not only before Class C. Class C's hard stop is the strictest reading of it, but a marker that is honoured on one classification path and ignored on the other three is not a guard — and Class A, dependency clearing, is exactly the path an operator reverting a wrongly-cleared blocker is trying to protect. Match it robustly (hyphen/underscore, case-insensitive, label set and note prose) wherever it is read.
192
193
  - The blocks the **vendor agent** writes when repair-intake re-dispatches it (its pre-flight gate) carry `human_needed` already — the agent owns that marker. repair-intake leaves it in place.
193
194
 
@@ -218,7 +219,7 @@ intakes use. Never call Atlassian MCP or `acli` directly — go through `lisa-at
218
219
  | Linear (build) | Linear MCP `list_issues` / `get_issue` / `list_comments` | Linear MCP `save_issue` (labels) / `save_comment` | `lisa-linear-agent` |
219
220
  | Notion (PRD) | `lisa-notion-access` (`query`, page comments) | `lisa-notion-access` `write-page` (status) / page comment | `lisa-notion-to-tracker` (dry-run) |
220
221
  | GitHub (PRD) | `gh issue list/view` (PRD labels) / GraphQL sub-issues / generated-work section | `gh issue edit` / `gh issue comment` / `gh issue close --reason completed` | `lisa-github-to-tracker` (dry-run) |
221
- | Linear (PRD) | Linear MCP `list_projects` / `get_project` (+ sentinel feedback issue) | Linear MCP `save_project` (labels) / `save_comment` | `lisa-linear-to-tracker` (dry-run) |
222
+ | Linear (PRD) | `lisa-linear-access` `list-projects` / `get-project` / `list-comments project_id` | `lisa-linear-access` `save-project` (labels) / `save-comment project_id` | `lisa-linear-to-tracker` (dry-run) |
222
223
  | Confluence (PRD) | `lisa-atlassian-access` CQL | `lisa-atlassian-access` page `parentId` update / comment | `lisa-confluence-to-tracker` (dry-run) |
223
224
 
224
225
  ## Staleness model
@@ -267,8 +268,9 @@ exposes, and compare it to `now - stale_after`:
267
268
  1. Provider-native status/label **transition** time into the in-progress role, when the provider
268
269
  exposes it cleanly (JIRA changelog transition to `claimed` / In Progress, GitHub label event,
269
270
  Linear state/label history, Notion/Confluence page move/status history).
270
- 2. Latest human lifecycle/progress **comment** or edit on the item (and, for Linear PRDs, the
271
- sentinel feedback issue). Exclude automation self-comments and Lisa audit markers such as
271
+ 2. Latest human lifecycle/progress **comment** or edit on the item (for Linear PRDs, the
272
+ project's own comments via `list-comments project_id`, plus any legacy sentinel feedback
273
+ issue for projects that predate project-level comments). Exclude automation self-comments and Lisa audit markers such as
272
274
  `[claude-build-intake]`, `[codex-build-intake]`, `[lisa-build-intake]`, and
273
275
  `[lisa-repair-intake]`.
274
276
  3. For build items, latest **PR-side forward-progress activity** on the linked PR: newest commit,
@@ -466,25 +468,49 @@ branch — operate on it the same way.
466
468
 
467
469
  **4. Classify as a blocker.** Treat any of these as a real external blocker:
468
470
 
469
- - **True merge conflict** — `gh pr update-branch` (step 3) reported a conflict, or
470
- `git merge-tree --write-tree origin/<base> <head>` exits non-zero. A
471
- merely `BEHIND` branch is **not** here it was re-synced in step 3. Unlike the other classes below, a
472
- conflict is **resolvable by re-running the build**, so step 5 gives it one in-place re-dispatch before
473
- filing see its conflict-first rule.
474
-
475
- **`mergeable = CONFLICTING` and `mergeStateStatus = DIRTY` are hints that
476
- START this check, never the verdict that ends it.** Both are cached
477
- computations that go stale measured, GitHub reported `DIRTY` for two
478
- branches at the same moment while only one actually conflicted, and a single
479
- response has carried `MERGEABLE` and `DIRTY` together
480
- (CodySwannGT/lisa#3694). Confirm with `merge-tree` before classifying, and
481
- say in the run summary which answer you acted on.
482
-
483
- **This class matters more here than in `lisa-drive-pr-to-merge`.** There a
484
- spurious `DIRTY` costs a wasted resolve, which a human sees. Here it files a
485
- BLOCKER against a pull request with nothing wrong with it, unattended — so
486
- the wrong answer becomes durable tracker state that a later cycle reads as
487
- fact. Verify before filing, never after.
471
+ - **True merge conflict** — confirmed by a **merge trial**, never by a cached field.
472
+ `mergeable = CONFLICTING` and `mergeStateStatus = DIRTY` are hints that say *go look*: both are
473
+ computed asynchronously, and a stale one is served often enough that GitHub reported `DIRTY` for two
474
+ branches at the same moment while only one of them actually conflicted (#3694). Re-derive from
475
+ primary evidence at the moment of asking:
476
+
477
+ ```sh
478
+ base=$(gh pr view <pr> --json baseRefName --jq .baseRefName)
479
+ head=$(gh pr view <pr> --json headRefOid --jq .headRefOid)
480
+ git fetch --quiet origin "$base" "pull/<pr>/head" || readable=no
481
+ git rev-parse --verify --quiet "origin/$base^{commit}" >/dev/null || readable=no
482
+ git rev-parse --verify --quiet "$head^{commit}" >/dev/null || readable=no
483
+ out=$(git merge-tree --write-tree "origin/$base" "$head" 2>/dev/null); code=$?
484
+ ```
485
+
486
+ `merge-tree --write-tree` merges into the object store only no working tree, no index and no
487
+ branch is touched so it is safe inside an unattended scanner.
488
+
489
+ **Read the exit code together with stdout; the exit code alone cannot separate the three states.**
490
+ Measured on git 2.53.0: a trial naming a ref that does not exist exits `1`, the same code a genuine
491
+ conflict returns, printing nothing on stdout and `merge-tree: <ref> - not something we can merge`
492
+ on stderr. A trial that ran always prints the resulting tree OID on its first line; one that could
493
+ not run prints nothing. Three states, and the third is not optional:
494
+
495
+ - `code == 1` **and** `$out` non-empty → **CONFLICTED**. A real external blocker. Unlike the other
496
+ classes below, a conflict is **resolvable by re-running the build**, so step 5 gives it one
497
+ in-place re-dispatch before filing — see its conflict-first rule.
498
+ - `code == 0` → **CLEAN**. Not a blocker, whatever the API said. Write nothing, leave the item
499
+ `claimed`, and let a later cycle re-ask.
500
+ - `readable=no`, `$out` empty, or any other exit → **NOT DETERMINED**. The trial could not run — an
501
+ unresolvable ref, an unreachable remote, a git older than 2.38 — which is an absence of evidence,
502
+ not a verdict. Write nothing, file nothing, leave the item `claimed`, and record it as
503
+ `not_determined` in the run summary so a later cycle re-asks.
504
+
505
+ A `gh pr update-branch` (step 3) that reported a conflict it cannot apply also counts as
506
+ CONFLICTED — that is a merge actually attempted, not a cached answer. A merely `BEHIND` branch is
507
+ **not** here — it was re-synced in step 3.
508
+
509
+ **Filing on a cached field is the expensive direction here.** In a fix-mode loop a false
510
+ CONFLICTED wastes a resolve, which a human sees; in this scanner it files a
511
+ BLOCKER against a pull request that has nothing wrong with it, unattended — so the wrong answer
512
+ becomes durable tracker state that a later cycle reads as fact, and intake will keep doing that
513
+ without anyone noticing. Verify before filing, never after.
488
514
  - **Failing required checks** — `statusCheckRollup` has a `FAILURE`/`ERROR`/`TIMED_OUT` conclusion,
489
515
  or `mergeStateStatus = UNSTABLE`/`BLOCKED` due to checks.
490
516
  - **Change requests outstanding** — `reviewDecision = CHANGES_REQUESTED`, or unresolved CodeRabbit
@@ -905,8 +931,8 @@ intake runs per item**, targeted at this single PRD and **skipping the claim** (
905
931
  ### PRD `blocked` → re-validate if new answers exist
906
932
 
907
933
  1. Determine whether **new clarifying answers** exist: any comment/update on the PRD newer than
908
- the last `[lisa-repair-intake]` note or the original `blocked` note. For Linear include the
909
- sentinel feedback issue and anchored sub-issue comments; for Confluence include inline/footer
934
+ the last `[lisa-repair-intake]` note or the original `blocked` note. For Linear include the project's own
935
+ comments, anchored sub-issue comments, and any legacy sentinel feedback issue; for Confluence include inline/footer
910
936
  comments where the access layer exposes them; for Notion include page comments and
911
937
  `last_edited_time`.
912
938
  2. If new answers exist → run the `lisa:<source>-to-tracker` dry-run validate→route pipeline as
@@ -1023,6 +1049,50 @@ with labels like `build-ready`, or with no Lisa status label at all, that are in
1023
1049
  substring match whose precision is a separate open defect (#3815). Refusing and reporting is
1024
1050
  the safe failure direction without the latch. Count these under `held_for_person`, never under
1025
1051
  `normalized_ready`.
1052
+
1053
+ **Pass the item's `comments`.** The planner reads a recorded `[lisa-human-gate-release]` comment
1054
+ as the discharge of the hold naming the same `reason=`, and an item read without its comments is
1055
+ an item whose discharge cannot be seen. That fails closed — it stays held — which is the safe
1056
+ direction and precisely why the omission is invisible.
1057
+
1058
+ 2b. **Release the holds that have been answered.** This is step 2a's inverse and it is the reason
1059
+ this sweep is where it lives: applying a hold had a path and lifting one had none, so a person
1060
+ could supply exactly what a held item asked for, record the decision on the item, and the item
1061
+ stayed held forever (CodySwannGT/lisa#3852). The expensive part — getting a person's attention,
1062
+ framing the question, obtaining a judgment — was already paid for, and the system discarded the
1063
+ answer.
1064
+
1065
+ Enumerate items carrying the configured `human_needed` marker **or** a `[lisa-human-gate]` marker
1066
+ in the body, and for each call
1067
+ `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
1068
+ from `scripts/intake-blocker-reprobe.mjs`. Apply exactly the actions it returns: remove the
1069
+ human-needed marker, add the configured build `ready` label back, and post
1070
+ `formatHumanGateReleaseNote()` once. Do **not** re-implement the discharge test, and do **not**
1071
+ decide it from labels alone — the hold and its release are body and comment surfaces.
1072
+
1073
+ Three refusals make this safe to run on every cycle, and each one is in the planner rather than
1074
+ in this prose so it cannot drift:
1075
+
1076
+ - **Still held plans nothing.** Every outstanding reason holds the whole item; an item whose
1077
+ second question is unanswered is not half-released.
1078
+ - **Never held plans nothing.** Without that this would be a path that adds the build-ready role
1079
+ to arbitrary items — a promotion mechanism wearing a release mechanism's name.
1080
+ - **An item that has moved on is not dragged back.** The ready role is restored only when the
1081
+ item carries no other configured lifecycle label.
1082
+
1083
+ This is a genuine exception to "never remove a `human_needed` marker this skill did not apply",
1084
+ and the exception is narrow enough to state exactly: provenance is the wrong question when the
1085
+ *hold itself* names the condition that voids it and that condition is recorded. The general rule
1086
+ stands because "stale" is otherwise a judgment about the block's kind; here nothing is being
1087
+ judged — a release naming the hold's own reason is on the item, or it is not.
1088
+
1089
+ **Never edit a description to clear a hold**, here or anywhere. The only body write this plugin
1090
+ has is a whole-body replacement, so deleting one line means rewriting the record and hoping
1091
+ nothing was dropped. That is why holds accumulated: each individual release was a small gamble
1092
+ with a large downside. The hold note stays in the body as history; the release is a comment
1093
+ beside it. Count these under `released_to_queue`, and name them in the cycle summary via
1094
+ `summarizeHumanGateReleases([...])` — printed even when it is zero, because a release path that
1095
+ has stopped working and a cycle with nothing to release read identically otherwise.
1026
1096
  3. Classify the issue:
1027
1097
  - **PRD** if it has PRD labels/markers (`prd`, `type:PRD`, `kind:prd`), PRD structure
1028
1098
  (`## Problem`, `## Goals`, `## Validation Journey`, generated-work/backlink sections), or
@@ -41,8 +41,34 @@ first-attempt work.
41
41
  comment posted by `lisa-tracker-evidence` (`[lisa-evidence]` / the vendor evidence
42
42
  header). Only markers proving a prior *implementation* attempt qualify —
43
43
  `[lisa-rework-triage]` comments and other unrelated `[lisa-*]` annotations never do.
44
- 4. **Explicit rework marker.** A `rework`, `qa-fail`, or `regression` label applied by QA or
45
- the verify lifecycle.
44
+ 4. **Explicit rework marker.** A `rework` or `regression` label applied by QA or the verify
45
+ lifecycle, or a **live** QA-failure signal.
46
+
47
+ The QA-failure signal is transient, so its bare presence is not the signal — its
48
+ liveness is. Ask the resolver, never the label list:
49
+
50
+ ```bash
51
+ RESOLVER="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-plugins/lisa}}/scripts/qa-signal-lifecycle.mjs"
52
+ node "$RESOLVER" --vendor "<jira|linear|github>" --item bundle.json
53
+ # bundle.json: { "labels": [...], "comments": [<bodies, oldest first>], "role": "<current>" }
54
+ ```
55
+
56
+ Branch on `action`, never on the label being there:
57
+
58
+ | `outcome` | Meaning | What triage does |
59
+ |---|---|---|
60
+ | `live` | the failure is unresolved | signal 4 fires — this is rework |
61
+ | `stale` | a later QA pass, or the certified/terminal role, voided it | signal 4 does **not** fire; **remove the label** (same tracker surface that applied it) and note the repair in the triage comment. Keep evaluating signals 1–3 |
62
+ | `absent` | no signal | signal 4 does not fire |
63
+ | `unchecked` | a declared void condition has no predicate | treat as `live` and surface it — a control nothing can evaluate is a defect to report, not an exemption |
64
+
65
+ Clearing a stale signal here is the repair path for items labelled before the signal had
66
+ an inverse; without it that backlog never drains. The `[lisa-qa-fail]` comments are the
67
+ history and are never touched — a stale signal removed still leaves the failure fully
68
+ readable, and signal 3 still reads those comments.
69
+
70
+ `rework` and `regression` are matched on presence as before. Whether they have the same
71
+ shape is **unverified** and not claimed here.
46
72
 
47
73
  Record which signal fired — it is part of the evidence trail.
48
74
 
@@ -170,3 +196,7 @@ which blocks per the normal triage rules.
170
196
  bypass the quality gates this loop exists to strengthen.
171
197
  - Noise discipline: one triage comment per bounce (fingerprinted), no upstream issue without
172
198
  the dedupe search, and upstream issues describe failure *classes*, not single incidents.
199
+ - Never key on a durable mark whose inverse you have not checked. A signal with no expiry
200
+ degrades toward meaning "this item has been around a while"
201
+ (`state-changes-without-inverses`), and a deterministic input that degrades is
202
+ deterministically wrong.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lisa-setup-linear
3
- description: "Configure Linear as the destination tracker and/or the PRD source for this project. Verifies Linear access (MCP OAuth or a personal API key in OS keychain), resolves the workspace slug and team key, scaffolds the build-queue **workflow states** (`linear.workflow`) when Linear is the tracker and/or the PRD-lifecycle project-label namespace (`prd-*` + issue-level sentinel) when Linear is the PRD source, writes the `linear` section into `.lisa.config.json`, and offers to set top-level `tracker: \"linear\"` and/or `source: \"linear\"`. Idempotent — re-running updates the existing section and reuses existing labels. No /lisa:setup:atlassian prerequisite."
3
+ description: "Configure Linear as the destination tracker and/or the PRD source for this project. Verifies Linear access (MCP OAuth or a personal API key in OS keychain), resolves the workspace slug and team key, scaffolds the build-queue **workflow states** (`linear.workflow`) when Linear is the tracker and/or the PRD-lifecycle project-label namespace (`prd-*`) when Linear is the PRD source, writes the `linear` section into `.lisa.config.json`, and offers to set top-level `tracker: \"linear\"` and/or `source: \"linear\"`. Idempotent — re-running updates the existing section and reuses existing labels. No /lisa:setup:atlassian prerequisite."
4
4
  allowed-tools: ["Bash", "Read", "Write", "Edit", "Skill", "AskUserQuestion", "mcp__linear-server__authenticate", "mcp__linear-server__complete_authentication"]
5
5
  ---
6
6
 
@@ -13,7 +13,7 @@ The two lifecycles run on different primitives, and conflating them is the most
13
13
  - **Build queue → native workflow STATES**, read from `linear.workflow.*`. Not labels. See "Why Linear uses states, not labels" in `config-resolution`, and Step 3a below. `lisa-linear-build-intake` reads only these.
14
14
  - **PRD lifecycle → PROJECT labels** (`prd-*`), because a PRD is a Linear Project.
15
15
 
16
- Project labels and issue labels are distinct namespaces in Linear and are NOT interchangeable — creating an issue label named `prd-ready` will not work for the PRD flow. The one issue label this skill creates is the sentinel feedback marker, which belongs to the PRD flow despite being an issue label (Linear's MCP has no project-level comments see `linear-prd-intake`).
16
+ Project labels and issue labels are distinct namespaces in Linear and are NOT interchangeable — creating an issue label named `prd-ready` will not work for the PRD flow. Every PRD-lifecycle label this skill creates is a **project** label; the PRD flow needs no issue label at all, because clarifying-question comments go on the project itself (see `linear-prd-intake`).
17
17
 
18
18
  **A `status:*` issue-label namespace is no longer scaffolded or read.** It was the pre-state-model build lane; see "Migrating a project that predates the state model" below for what to do with a config that still carries it.
19
19
 
@@ -280,7 +280,7 @@ Probe with `lisa-linear-access operation: list-project-labels`. Create missing o
280
280
  | `ticketed` | `prd-ticketed` | project label |
281
281
  | `shipped` | `prd-shipped` | project label |
282
282
  | `verified` | `prd-verified` | project label |
283
- | `sentinel` | `prd-intake-feedback` | **issue** label (marks the sentinel feedback issue create via `create_issue_label`) |
283
+ | `sentinel` | `prd-intake-feedback` | **Legacy, not created.** An issue label that marked the fabricated feedback issues earlier versions used before project-level comments were wired up. Configured only so the rollup can recognise and exclude an existing one; a fresh workspace never needs it |
284
284
 
285
285
  #### 3c. Handle name collisions / renames
286
286
 
@@ -357,7 +357,7 @@ jq -e '.linear.workspace' .lisa.config.json >/dev/null
357
357
  [ "$(jq -r '.tracker // empty' .lisa.config.json)" = "linear" ] && jq -e '.linear.teamKey' .lisa.config.json >/dev/null
358
358
  ```
359
359
 
360
- Confirm what was scaffolded is present: `list-workflow-states` for every build role when Linear is the tracker, `list_project_labels` for `prd-*` (including the terminal `prd-verified`) and `list_issue_labels` for the sentinel when Linear is the PRD source. Do NOT expect a `status:*` namespace — it is not part of this model. Report success with the resolved workspace, team key (if any), which namespaces were scaffolded (created vs. already existed), any non-default overrides, and whether `tracker` / `source` were set. Direct the user to `/lisa:intake` to test.
360
+ Confirm what was scaffolded is present: `list-workflow-states` for every build role when Linear is the tracker, `list_project_labels` for `prd-*` (including the terminal `prd-verified`) when Linear is the PRD source. Do NOT expect a `status:*` namespace — it is not part of this model. Report success with the resolved workspace, team key (if any), which namespaces were scaffolded (created vs. already existed), any non-default overrides, and whether `tracker` / `source` were set. Direct the user to `/lisa:intake` to test.
361
361
 
362
362
  ## Idempotency
363
363
 
@@ -369,7 +369,7 @@ Confirm what was scaffolded is present: `list-workflow-states` for every build r
369
369
 
370
370
  - Never write the API key to `.lisa.config.json`. It stays in keychain or `LINEAR_API_KEY`.
371
371
  - Never accept the API key via this skill's stdin/chat — always the platform clipboard-pipe pattern, so the value never enters the LLM context.
372
- - Never conflate the two label kinds: build labels are **issue** labels, PRD labels are **project** labels. The sentinel is an issue label. Creating the wrong kind silently breaks the corresponding intake flow.
372
+ - Never conflate the two label kinds: build labels are **issue** labels, PRD labels are **project** labels. Creating the wrong kind silently breaks the corresponding intake flow.
373
373
  - Never create a duplicate label for a role that already has a (differently-named) label — map and record an override instead.
374
374
  - Never set `tracker` / `source` without explicit confirmation — they're project-wide switches.
375
375
  - Never invent a workspace slug or team key. Derive from the validated identity / team list and confirm; if resolution fails, ask the user.
@@ -78,5 +78,5 @@ Otherwise:
78
78
  - Branch setup may call `node scripts/lisa-work-item.mjs attach-branch` after the feature branch exists.
79
79
  - Keep the binding across ordinary interruptions and blocked outcomes so resumed work remains attributable.
80
80
  - Clear it only after true terminal completion — merged, deployed/verified where required, tracker evidence/backlink complete, and the work item terminal — by running `node scripts/lisa-work-item.mjs clear` and verifying no current binding remains.
81
- - A held filing writes no binding at all, so there is nothing to clear. The gate is released by a human, not by this skill: a human removes the `[lisa-human-gate]` marker and flips the leaf into the build-ready role, and a later invocation then resolves it on the ordinary path.
81
+ - A held filing writes no binding at all, so there is nothing to clear. The gate is released by a human decision, but not by a human edit: the person records the decision as a comment on the leaf beginning `[lisa-human-gate-release]` and repeating the hold's `reason=` verbatim, and the next intake sweep takes the human-needed marker off and puts the leaf back in the build-ready role on its own (`planHumanGateRelease` in `scripts/intake-blocker-reprobe.mjs`). A later invocation then resolves it on the ordinary path. **Do not tell anyone to delete the marker from the description, and do not delete it here.** The only description write available is a whole-body replacement, so clearing one line means rewriting the entire record — which is why, before this, the rational move was always to leave a hold in place and answered holds only accumulated (CodySwannGT/lisa#3852). The hold stays in the body as history; the release is recorded beside it.
82
82
  - A tracker outage, invalid item, failed claim, or failed binding blocks durable work. Never continue untracked and never ask a Git hook to create the item.
@@ -62,6 +62,15 @@ Shared helpers own both, so the vocabulary cannot drift per vendor:
62
62
  blocker re-probe carries an absolute human gate: an item carrying the configured human-needed label
63
63
  or a `[lisa-human-gate]` marker is never auto-selected, whatever a probe returns.
64
64
 
65
+ That gate has an inverse, and it is forwarded identically: a hold ends when a
66
+ `[lisa-human-gate-release]` comment naming the same `reason=` is recorded on the item. Every vendor
67
+ scanner passes the item's `comments` into the gate helpers so the discharge is visible, and calls
68
+ `planHumanGateRelease(...)` to take the marker off and put the item back in the queue. **No vendor
69
+ scanner clears a hold by editing the description** — the only body write any of them has is a
70
+ whole-body replacement, so a release that went through the description would risk destroying the
71
+ record it was releasing, which is why holds accumulated with no way out (CodySwannGT/lisa#3852).
72
+ The hold note stays in the description as history and the release sits beside it as a comment.
73
+
65
74
  Measured: sweeping one team by lane name saw 39 of 343 open rows; by category it sees 100. The
66
75
  61-row gap produced 31 consecutive false "dry lane" cycles, every record honest and every
67
76
  conclusion wrong (#2657).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.54.13",
3
+ "version": "4.55.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -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