@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
@@ -317,7 +317,12 @@ other gate's verdict — however conclusive — may promote an item a person par
317
317
  drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
318
318
  the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
319
319
  all and sit anywhere in the body, so a structured parse would miss them while appearing to work
320
- on every item that happens to have one.
320
+ on every item that happens to have one. **Pass the item's `comments` alongside its labels and
321
+ body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
322
+ see the discharge — it goes on holding an item whose question was answered weeks ago, which is
323
+ the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
324
+ fails closed, and that is exactly why it is easy to miss: nothing breaks, the item simply never
325
+ comes back.
321
326
  2. **On `claimable: false` with reason `human-gate`, do not claim and do not dispatch.**
322
327
  3. **Reconcile the lane; do not merely skip.** Skipping alone leaves the item in `$READY`, re-judged
323
328
  and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
@@ -329,14 +334,32 @@ other gate's verdict — however conclusive — may promote an item a person par
329
334
  already out of the lane and already marked yields no second mutation and no second comment. This
330
335
  is the same repair the leaf-only gate already performs for a ready item that must not be
331
336
  dispatched.
332
- 4. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
337
+ 4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
338
+ The hold left durable state behind: the item is out of the queue and flagged as needing a person,
339
+ and answering the question does not undo either. Call
340
+ `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
341
+ and apply exactly the actions it returns: remove the configured human-needed marker, add the
342
+ configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
343
+ of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
344
+ item never held plans nothing, so it can only ever un-do a hold and can never promote something on
345
+ its own. It is idempotent by state, so a second cycle over a released item yields no second
346
+ mutation and no second comment.
347
+
348
+ **Never edit the description to clear a hold.** The only body write available is a whole-body
349
+ replacement, so deleting one line means rewriting the whole record and hoping nothing was
350
+ dropped — the reason holds accumulated instead of being lifted. The hold note stays in the
351
+ description as history; the release is a comment beside it.
352
+ 5. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
333
353
  distinguishes "nothing was eligible" from "something eligible was held for a person". A lane
334
354
  mutation nobody can see afterwards is the same class of problem this gate exists to fix.
335
355
  Report alongside it what the precision rule SKIPPED, via `summarizeHumanGateMentions(n)`
336
356
  — the marker occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815).
337
357
  A rule that quietly declines to honour half the occurrences it sees reads exactly like a
338
- rule that saw none, so the count is printed even when it is zero.
339
- 5. **Continue to the next candidate.** A held item does not end the cycle.
358
+ rule that saw none, so the count is printed even when it is zero. Report what was RELEASED
359
+ beside it via `summarizeHumanGateReleases([...])`, printed even when it is zero: a release path
360
+ that has stopped working and a cycle with nothing to release read identically otherwise, which
361
+ is how a missing inverse stays missing.
362
+ 6. **Continue to the next candidate.** A held item does not end the cycle.
340
363
 
341
364
 
342
365
  #### 3a.0 Repo-scope gate (claim only current-repo issues)
@@ -29,7 +29,7 @@ SHIPPED=$(node "$ROLE_RESOLVER" --role prd.shipped --vendor github --intent writ
29
29
 
30
30
  In prose below, the role names refer to the resolved labels: e.g. "the `ready` label" means whatever `github.labels.prd.ready` resolves to (default: `prd-ready`).
31
31
 
32
- This skill is the GitHub counterpart of `lisa-notion-prd-intake`, `lisa-confluence-prd-intake`, and `lisa-linear-prd-intake`. Phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **issue labels** (mirroring Linear's project labels and Confluence's page labels), (2) the fetch / update tools are the `gh` CLI, and (3) clarifying-question comments land directly on the source PRD issue (because GitHub Issues *do* have native comments — no sentinel issue required, unlike Linear). Keep all four skills behaviorally aligned: when changing intake logic, change them together.
32
+ This skill is the GitHub counterpart of `lisa-notion-prd-intake`, `lisa-confluence-prd-intake`, and `lisa-linear-prd-intake`. Phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **issue labels** (mirroring Linear's project labels and Confluence's page labels), (2) the fetch / update tools are the `gh` CLI, and (3) clarifying-question comments land directly on the source PRD issue. Keep all four skills behaviorally aligned: when changing intake logic, change them together.
33
33
 
34
34
  The **PRD shipped rollup phase (3f)** transitions a `$TICKETED` PRD to `$SHIPPED` once all its generated top-level work is terminal, per the `prd-lifecycle-rollup` rule. This phase is GitHub-only here because its vendor surface (issue close + labels via `gh`) is GitHub-specific; the Linear / Confluence / Notion intake skills carry the **same** vendor-neutral rollup with their own surfaces (sibling sub-task #584, now landed). All four intake skills are behaviorally aligned across the rollup phase too — keep them in sync when changing rollup logic.
35
35
 
@@ -15,6 +15,28 @@ Run all organizational quality gates against an issue spec OR an existing issue.
15
15
  1. **An existing issue ref** (`org/repo#<number>` or `https://github.com/<org>/<repo>/issues/<number>`): fetch it and validate the live state. Use this for post-write checks.
16
16
  2. **A proposed issue spec** (YAML block, see schema below): validate as-is without touching GitHub. Use this for pre-write and dry-run checks.
17
17
 
18
+ ### Standalone entry point — validating an item written by another path
19
+
20
+ Input form 1 is a **supported entry point in its own right**, not only an internal step of a
21
+ caller flow. Point this skill at any existing item — however it was written, including by a
22
+ bespoke script, a direct API or GraphQL call, or the vendor's own web UI — and it fetches the
23
+ live state and runs the full gate set against it.
24
+
25
+ Copy-pasteable, via the Skill tool:
26
+
27
+ ```text
28
+ Skill(skill: "lisa-github-validate-issue", args: "CodySwannGT/lisa#3663")
29
+ ```
30
+
31
+ where the argument is an issue ref such as `CodySwannGT/lisa#3663`, or the full issue URL. The report it returns is the same structured PASS/FAIL
32
+ report the write path consumes, so a bespoke write path can discharge both the pre-write
33
+ validate and the post-write verify obligation with it (see the bespoke-path section of
34
+ `lisa-github-write-issue`).
35
+
36
+ This skill is plugin-resident. It is invoked through the Skill tool and is **not** expected to
37
+ appear in any repository's `scripts/` directory; not finding a shell script by this name is
38
+ not evidence that the capability is absent.
39
+
18
40
  ### Spec schema
19
41
 
20
42
  Specs are passed as a fenced YAML block. Required keys depend on `issue_type`.
@@ -22,6 +22,20 @@ This indirection exists so the gate definitions live in exactly one place (`lisa
22
22
 
23
23
  Pass through `lisa-github-validate-issue`'s structured output unchanged. Do not summarize or paraphrase — downstream callers (e.g. `lisa-github-agent`'s pre-flight gate) parse the gate lines.
24
24
 
25
+ ## Comparison semantics — semantic, never byte-exact
26
+
27
+ Verification here re-runs `lisa-github-validate-issue` against the live issue. It does **not** compare the
28
+ stored body against the sent body byte for byte, and it must never drift to doing so.
29
+
30
+ GitHub normalizes markdown on write. Observed normalizations include rewriting `-` bullets
31
+ as `*`, wrapping a bare URL as an explicit link, and re-segmenting bold emphasis around
32
+ inline code spans — all lossless, all rendering-identical. **A byte-exact comparator cannot
33
+ distinguish vendor markdown normalization from corruption**, so it reports failure on
34
+ perfectly healthy writes and trains its reader to ignore it (CodySwannGT/lisa#3663).
35
+
36
+ Any comparison of tracker-normalized rich text is therefore semantic, or
37
+ normalize-then-compare. Byte-exact comparison of such text is forbidden.
38
+
25
39
  ## Notes
26
40
 
27
41
  - This skill is read-only. It never edits the issue, posts comments, or changes labels.
@@ -322,6 +322,17 @@ person scanning a board and to any path that has not yet been routed through the
322
322
  If the label does not exist in the tracker, create it, or record that it could not be applied and
323
323
  proceed — the marker still holds. Never file the label *instead of* the marker.
324
324
 
325
+ **Write a `reason=` the release can name.** The hold's reason is not decoration: a hold ends when a
326
+ `[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item, and the
327
+ next intake sweep then takes the marker label off and puts the item back in the build-ready role on
328
+ its own. Matching is per-reason so that a hold declared *after* an earlier release is not born
329
+ discharged. A keyless hold is legal and is discharged by a keyless release; a hold whose reason is a
330
+ paragraph is legal and nobody will reproduce it. Prefer a short slug the person answering it can
331
+ retype. Do **not** instruct anyone to delete the marker from the description to lift the hold — the
332
+ only body write available is a whole-body replacement, so that asks them to rewrite the whole record
333
+ to clear one line, which is why answered holds accumulated instead of being lifted
334
+ (CodySwannGT/lisa#3852). The marker stays as history; the release is recorded beside it.
335
+
325
336
  If a leaf arrives with `build_ready` omitted or `false` **and** no `human_gate`, do not create it: report the incomplete handoff and name both ways to resolve it (`build_ready: true`, or a `human_gate` reason). Containers are exempt — their state rolls up from children, so they need neither.
326
337
 
327
338
  **The container exemption is executable, not prose.** It used to live only in the sentence above,
@@ -445,6 +456,46 @@ The mapping below is the single source of truth for how JIRA concepts translate
445
456
  | Worklog | Comments (no native time tracking) |
446
457
  | Triage marker | Label `claude-triaged-<repo>` |
447
458
 
459
+ ## Writing by a bespoke path (your own script, direct API or GraphQL)
460
+
461
+ Nothing here stops a consumer from writing to GitHub through `gh issue create` directly, the GitHub REST or GraphQL API, or your own script, and nothing should
462
+ try to — a script that owns the credential plumbing is often the only practical transport.
463
+ **The transport is not the gate.** A bespoke write path still owes both halves of the quality
464
+ gate this skill runs, and owes them explicitly, because no phase of this flow will ever run
465
+ for it.
466
+
467
+ A bespoke script's own read-back does not discharge either obligation. Re-reading the issue
468
+ and confirming GitHub stored what was sent **proves transport, not quality**: it shows the
469
+ fields round-tripped and says nothing about whether what was sent clears a single gate. An
470
+ agent that reads `VERIFIED` out of such a script has been told the issue was checked when it
471
+ was not. Measured once, on one issue, on 2026-09-03 (CodySwannGT/lisa#3663): a local
472
+ script's read-back was clean on every field, and the issue then failed gates S5, S9 and S18
473
+ when the validator was run against it by hand.
474
+
475
+ What a bespoke write path still owes — the same two checks, invoked by hand:
476
+
477
+ 1. **Pre-write validate**, the obligation Phase 5.5 discharges here. Invoke `lisa-github-validate-issue` via
478
+ the Skill tool with the proposed spec as a YAML block **before** writing. Never write on a
479
+ `FAIL` verdict.
480
+ 2. **Post-write verify**, the obligation Phase 7 discharges here. Invoke `lisa-github-verify` via the
481
+ Skill tool with the identifier of the issue you just wrote — or `lisa-github-validate-issue` directly in
482
+ identifier mode, which fetches and validates the live state. Never report success on a
483
+ `FAIL` verdict.
484
+
485
+ Both run standalone against an existing live issue; `lisa-github-validate-issue` documents the copy-pasteable
486
+ invocation under its standalone entry point.
487
+
488
+ **Three outcomes, never two.** `PASS`, `FAIL` and *could not validate* are distinct results.
489
+ If the validator did not run to a verdict — the skill was unavailable, a credential was
490
+ missing, the issue could not be fetched — that is **not** a pass. Report it as unvalidated and
491
+ say why. Collapsing "could not validate" into "validated" is the same misreading as trusting
492
+ a read-back.
493
+
494
+ **These are skills, not scripts.** `lisa-github-validate-issue` and `lisa-github-verify` are plugin-resident and invoked
495
+ through the Skill tool. They are **not** expected to appear in any repository's `scripts/`
496
+ directory, and their absence from one is not evidence that the capability is missing —
497
+ searching the repository you happen to be standing in is the wrong search.
498
+
448
499
  ## Rules
449
500
 
450
501
  - Never create a non-bug issue without a parent Epic / Story (sub-issue link).
@@ -107,7 +107,7 @@ The single-item skills (`lisa-plan`, `lisa-implement`) and the per-vendor batch
107
107
  4. **Process the first eligible Ready item only** (claim-first ordering for idempotency):
108
108
  - Notion PRDs → `lisa-notion-prd-intake` handles per-item: claim (Status=In Review), dry-run validate, branch to Blocked or Ticketed, coverage audit
109
109
  - Confluence PRDs → `lisa-confluence-prd-intake` handles per-item: claim (relabel to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed`, coverage audit
110
- - Linear PRDs → `lisa-linear-prd-intake` handles per-item: claim (relabel project to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed` (with a sentinel feedback issue under each project hosting clarifying-question comments), coverage audit
110
+ - Linear PRDs → `lisa-linear-prd-intake` handles per-item: claim (relabel project to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed` (clarifying-question comments posted on the project itself), coverage audit
111
111
  - GitHub PRDs → `lisa-github-prd-intake` handles per-item: claim (relabel issue to `prd-in-review`), dry-run validate, branch to `prd-blocked` or `prd-ticketed` (with clarifying-question comments posted directly on the PRD issue), coverage audit
112
112
  - JIRA tickets → `lisa-jira-build-intake` handles per-item: claim, dispatch to `lisa-jira-agent`, transition to On Dev on success
113
113
  - GitHub build issues (when `tracker = github`) → `lisa-tracker-build-intake` → `lisa-github-build-intake` handles per-item: optional ready-queue assignee filtering, claim (relabel to `status:in-progress`), dispatch to `lisa-github-agent`, relabel to `status:on-dev` on success
@@ -222,7 +222,12 @@ other gate's verdict — however conclusive — may promote an item a person par
222
222
  drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
223
223
  the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
224
224
  all and sit anywhere in the body, so a structured parse would miss them while appearing to work
225
- on every item that happens to have one.
225
+ on every item that happens to have one. **Pass the item's `comments` alongside its labels and
226
+ body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
227
+ see the discharge — it goes on holding an item whose question was answered weeks ago, which is
228
+ the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
229
+ fails closed, and that is exactly why it is easy to miss: nothing breaks, the item simply never
230
+ comes back.
226
231
  2. **On `claimable: false` with reason `human-gate`, do not claim and do not dispatch.**
227
232
  3. **Reconcile the lane; do not merely skip.** Skipping alone leaves the item in `$READY`, re-judged
228
233
  and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
@@ -234,14 +239,32 @@ other gate's verdict — however conclusive — may promote an item a person par
234
239
  already out of the lane and already marked yields no second mutation and no second comment. This
235
240
  is the same repair the leaf-only gate already performs for a ready item that must not be
236
241
  dispatched.
237
- 4. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
242
+ 4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
243
+ The hold left durable state behind: the item is out of the queue and flagged as needing a person,
244
+ and answering the question does not undo either. Call
245
+ `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
246
+ and apply exactly the actions it returns: remove the configured human-needed marker, add the
247
+ configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
248
+ of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
249
+ item never held plans nothing, so it can only ever un-do a hold and can never promote something on
250
+ its own. It is idempotent by state, so a second cycle over a released item yields no second
251
+ mutation and no second comment.
252
+
253
+ **Never edit the description to clear a hold.** The only body write available is a whole-body
254
+ replacement, so deleting one line means rewriting the whole record and hoping nothing was
255
+ dropped — the reason holds accumulated instead of being lifted. The hold note stays in the
256
+ description as history; the release is a comment beside it.
257
+ 5. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
238
258
  distinguishes "nothing was eligible" from "something eligible was held for a person". A lane
239
259
  mutation nobody can see afterwards is the same class of problem this gate exists to fix.
240
260
  Report alongside it what the precision rule SKIPPED, via `summarizeHumanGateMentions(n)`
241
261
  — the marker occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815).
242
262
  A rule that quietly declines to honour half the occurrences it sees reads exactly like a
243
- rule that saw none, so the count is printed even when it is zero.
244
- 5. **Continue to the next candidate.** A held item does not end the cycle.
263
+ rule that saw none, so the count is printed even when it is zero. Report what was RELEASED
264
+ beside it via `summarizeHumanGateReleases([...])`, printed even when it is zero: a release path
265
+ that has stopped working and a cycle with nothing to release read identically otherwise, which
266
+ is how a missing inverse stays missing.
267
+ 6. **Continue to the next candidate.** A held item does not end the cycle.
245
268
 
246
269
 
247
270
  #### 3a.0 Repo-scope gate (claim only current-repo tickets)
@@ -17,6 +17,28 @@ Run all organizational quality gates against a ticket spec OR an existing ticket
17
17
  1. **An existing ticket key** (e.g. `PROJ-1234`): fetch it and validate the live state. Use this for post-write checks.
18
18
  2. **A proposed ticket spec** (YAML block, see schema below): validate as-is without touching JIRA. Use this for pre-write and dry-run checks.
19
19
 
20
+ ### Standalone entry point — validating an item written by another path
21
+
22
+ Input form 1 is a **supported entry point in its own right**, not only an internal step of a
23
+ caller flow. Point this skill at any existing item — however it was written, including by a
24
+ bespoke script, a direct API or GraphQL call, or the vendor's own web UI — and it fetches the
25
+ live state and runs the full gate set against it.
26
+
27
+ Copy-pasteable, via the Skill tool:
28
+
29
+ ```text
30
+ Skill(skill: "lisa-jira-validate-ticket", args: "PROJ-1234")
31
+ ```
32
+
33
+ where the argument is a ticket key such as `PROJ-1234`. The report it returns is the same structured PASS/FAIL
34
+ report the write path consumes, so a bespoke write path can discharge both the pre-write
35
+ validate and the post-write verify obligation with it (see the bespoke-path section of
36
+ `lisa-jira-write-ticket`).
37
+
38
+ This skill is plugin-resident. It is invoked through the Skill tool and is **not** expected to
39
+ appear in any repository's `scripts/` directory; not finding a shell script by this name is
40
+ not evidence that the capability is absent.
41
+
20
42
  ### Spec schema
21
43
 
22
44
  Specs are passed as a fenced YAML block. Required keys depend on `issue_type`.
@@ -23,6 +23,20 @@ This indirection exists so the gate definitions live in exactly one place (`lisa
23
23
 
24
24
  Pass through `lisa-jira-validate-ticket`'s structured output unchanged. Do not summarize or paraphrase — downstream callers (e.g. `lisa-jira-agent`'s pre-flight gate) parse the gate lines.
25
25
 
26
+ ## Comparison semantics — semantic, never byte-exact
27
+
28
+ Verification here re-runs `lisa-jira-validate-ticket` against the live ticket. It does **not** compare the
29
+ stored body against the sent body byte for byte, and it must never drift to doing so.
30
+
31
+ JIRA normalizes markdown on write. Observed normalizations include rewriting `-` bullets
32
+ as `*`, wrapping a bare URL as an explicit link, and re-segmenting bold emphasis around
33
+ inline code spans — all lossless, all rendering-identical. **A byte-exact comparator cannot
34
+ distinguish vendor markdown normalization from corruption**, so it reports failure on
35
+ perfectly healthy writes and trains its reader to ignore it (CodySwannGT/lisa#3663).
36
+
37
+ Any comparison of tracker-normalized rich text is therefore semantic, or
38
+ normalize-then-compare. Byte-exact comparison of such text is forbidden.
39
+
26
40
  ## Notes
27
41
 
28
42
  - This skill is read-only. It never edits the ticket, posts comments, or changes status.
@@ -307,6 +307,17 @@ person scanning a board and to any path that has not yet been routed through the
307
307
  If the label does not exist in the tracker, create it, or record that it could not be applied and
308
308
  proceed — the marker still holds. Never file the label *instead of* the marker.
309
309
 
310
+ **Write a `reason=` the release can name.** The hold's reason is not decoration: a hold ends when a
311
+ `[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item, and the
312
+ next intake sweep then takes the marker label off and puts the item back in the build-ready role on
313
+ its own. Matching is per-reason so that a hold declared *after* an earlier release is not born
314
+ discharged. A keyless hold is legal and is discharged by a keyless release; a hold whose reason is a
315
+ paragraph is legal and nobody will reproduce it. Prefer a short slug the person answering it can
316
+ retype. Do **not** instruct anyone to delete the marker from the description to lift the hold — the
317
+ only body write available is a whole-body replacement, so that asks them to rewrite the whole record
318
+ to clear one line, which is why answered holds accumulated instead of being lifted
319
+ (CodySwannGT/lisa#3852). The marker stays as history; the release is recorded beside it.
320
+
310
321
  If a leaf arrives with `build_ready` omitted or `false` **and** no `human_gate`, do not create it: report the incomplete handoff and name both ways to resolve it (`build_ready: true`, or a `human_gate` reason). Containers are exempt — their status rolls up from children, so they need neither.
311
322
 
312
323
  ## Phase 5.5 — Validate (Pre-write Gate)
@@ -355,6 +366,46 @@ Post a creation comment via `lisa-atlassian-access` `operation: comment key: <K>
355
366
 
356
367
  Skip this step only on UPDATE when no material change was made.
357
368
 
369
+ ## Writing by a bespoke path (your own script, direct API or GraphQL)
370
+
371
+ Nothing here stops a consumer from writing to JIRA through the JIRA REST API directly, `acli`, or your own script, and nothing should
372
+ try to — a script that owns the credential plumbing is often the only practical transport.
373
+ **The transport is not the gate.** A bespoke write path still owes both halves of the quality
374
+ gate this skill runs, and owes them explicitly, because no phase of this flow will ever run
375
+ for it.
376
+
377
+ A bespoke script's own read-back does not discharge either obligation. Re-reading the ticket
378
+ and confirming JIRA stored what was sent **proves transport, not quality**: it shows the
379
+ fields round-tripped and says nothing about whether what was sent clears a single gate. An
380
+ agent that reads `VERIFIED` out of such a script has been told the ticket was checked when it
381
+ was not. Measured once, on one ticket, on 2026-09-03 (CodySwannGT/lisa#3663): a local
382
+ script's read-back was clean on every field, and the ticket then failed gates S5, S9 and S18
383
+ when the validator was run against it by hand.
384
+
385
+ What a bespoke write path still owes — the same two checks, invoked by hand:
386
+
387
+ 1. **Pre-write validate**, the obligation Phase 5.5 discharges here. Invoke `lisa-jira-validate-ticket` via
388
+ the Skill tool with the proposed spec as a YAML block **before** writing. Never write on a
389
+ `FAIL` verdict.
390
+ 2. **Post-write verify**, the obligation Phase 7 discharges here. Invoke `lisa-jira-verify` via the
391
+ Skill tool with the identifier of the ticket you just wrote — or `lisa-jira-validate-ticket` directly in
392
+ identifier mode, which fetches and validates the live state. Never report success on a
393
+ `FAIL` verdict.
394
+
395
+ Both run standalone against an existing live ticket; `lisa-jira-validate-ticket` documents the copy-pasteable
396
+ invocation under its standalone entry point.
397
+
398
+ **Three outcomes, never two.** `PASS`, `FAIL` and *could not validate* are distinct results.
399
+ If the validator did not run to a verdict — the skill was unavailable, a credential was
400
+ missing, the ticket could not be fetched — that is **not** a pass. Report it as unvalidated and
401
+ say why. Collapsing "could not validate" into "validated" is the same misreading as trusting
402
+ a read-back.
403
+
404
+ **These are skills, not scripts.** `lisa-jira-validate-ticket` and `lisa-jira-verify` are plugin-resident and invoked
405
+ through the Skill tool. They are **not** expected to appear in any repository's `scripts/`
406
+ directory, and their absence from one is not evidence that the capability is missing —
407
+ searching the repository you happen to be standing in is the wrong search.
408
+
358
409
  ## Rules
359
410
 
360
411
  - Never create a non-bug ticket without an epic parent.
@@ -23,8 +23,8 @@ operation: get-issue id:<ID>
23
23
  operation: save-issue payload:{...} [lifecycle_role:<ROLE>] [env:<KEY>]
24
24
  operation: list-workflow-states team:<ID>
25
25
  operation: create-workflow-state payload:{...}
26
- operation: list-comments issue_id:<ID>
27
- operation: save-comment issue_id:<ID> body:"..."
26
+ operation: list-comments (issue_id:<ID> | project_id:<ID>)
27
+ operation: save-comment (issue_id:<ID> | project_id:<ID>) body:"..."
28
28
  operation: history id:<ID>
29
29
  operation: list-issue-labels [team:<ID>]
30
30
  operation: create-issue-label payload:{...}
@@ -294,6 +294,55 @@ Set `isTeamDefault` per node by comparing `node.id` against
294
294
  the team's default, resolve the default through the team record and join on `id`
295
295
  the same way.
296
296
 
297
+ ## `save-comment` / `list-comments` — an Issue **or** a Project
298
+
299
+ Both comment operations take **either** `issue_id:` or `project_id:`. Exactly one
300
+ is required; passing both, or neither, is refused naming the operation.
301
+
302
+ Linear treats a comment's target as one field on the same input type, so the
303
+ project form is not a second mechanism — it is the same mutation with a
304
+ different anchor. Direct introspection of `https://api.linear.app/graphql`:
305
+ `CommentCreateInput` accepts `issueId`, `projectId`, `projectUpdateId`,
306
+ `documentContentId`, and `parentId`, and the `Project` type exposes
307
+ `Project.comments`. Neither is beta and neither needs a special scope.
308
+
309
+ ```graphql
310
+ # save-comment — the anchor field is chosen by which id the caller passed.
311
+ mutation($input:CommentCreateInput!){
312
+ commentCreate(input:$input){ success comment{ id url createdAt } }
313
+ }
314
+ ```
315
+
316
+ Build `$input` as `{ issueId: <id>, body: <body> }` for the Issue form and
317
+ `{ projectId: <id>, body: <body> }` for the Project form. Nothing else differs —
318
+ same mutation, same result shape, same error handling.
319
+
320
+ ```graphql
321
+ # list-comments project_id:<ID> — page via pageInfo so a long-lived PRD's
322
+ # feedback history never silently truncates.
323
+ query($id:String!){
324
+ project(id:$id){
325
+ comments(first:100){
326
+ pageInfo{ hasNextPage endCursor }
327
+ nodes{ id body createdAt url user{ name } }
328
+ }
329
+ }
330
+ }
331
+ ```
332
+
333
+ The Issue form reads through `issue(id:$id){ comments{...} }` with the identical
334
+ node shape, so a caller consumes one result format for either anchor.
335
+
336
+ **Substrate.** The Linear MCP exposes comments on Issues only, so the
337
+ `project_id` form resolves solely through the tier-1 `LINEAR_API_KEY` + GraphQL
338
+ substrate — the same restriction `history` carries, and for the same reason.
339
+ That is not a gap in Linear: the precedence contract already puts GraphQL ahead
340
+ of the MCP, so the preferred substrate has always been able to do this. Only
341
+ this wrapper could not, which is what made callers fabricate an Issue to hold a
342
+ Project's comments. If tier 1 is unavailable, fail with the layer's standard
343
+ `Error:` result naming `save-comment project_id` — do **not** silently degrade
344
+ into creating an Issue to comment on.
345
+
297
346
  ## `history` — transition history (read-only)
298
347
 
299
348
  `history id:<ID>` returns an Issue's ordered past state changes — the raw
@@ -371,6 +420,10 @@ query($id:String!){
371
420
  - Missing token plus missing MCP is a hard failure naming `LINEAR_API_KEY`.
372
421
  - Mutations send only the fields being changed, matching existing Linear skill
373
422
  guidance that `save_*` style updates should not clobber unrelated fields.
423
+ - A comment anchors to exactly one target. `save-comment` and `list-comments`
424
+ take `issue_id` **or** `project_id`, never both and never neither. A caller
425
+ that wants to comment on a Project passes `project_id` — it never creates an
426
+ Issue to hold the comment, and this layer never creates one on its behalf.
374
427
  - Every workflow-state write is resolved by
375
428
  `scripts/linear-state-write-target.mjs` from a declared `lifecycle_role`,
376
429
  before either transport. The ID dispatched is the ID that script returned —
@@ -216,7 +216,12 @@ other gate's verdict — however conclusive — may promote an item a person par
216
216
  drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
217
217
  the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
218
218
  all and sit anywhere in the body, so a structured parse would miss them while appearing to work
219
- on every item that happens to have one.
219
+ on every item that happens to have one. **Pass the item's `comments` alongside its labels and
220
+ body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
221
+ see the discharge — it goes on holding an item whose question was answered weeks ago, which is
222
+ the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
223
+ fails closed, and that is exactly why it is easy to miss: nothing breaks, the item simply never
224
+ comes back.
220
225
  2. **On `claimable: false` with reason `human-gate`, do not claim and do not dispatch.**
221
226
  3. **Reconcile the lane; do not merely skip.** Skipping alone leaves the item in `$READY`, re-judged
222
227
  and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
@@ -228,14 +233,32 @@ other gate's verdict — however conclusive — may promote an item a person par
228
233
  already out of the lane and already marked yields no second mutation and no second comment. This
229
234
  is the same repair the leaf-only gate already performs for a ready item that must not be
230
235
  dispatched.
231
- 4. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
236
+ 4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
237
+ The hold left durable state behind: the item is out of the queue and flagged as needing a person,
238
+ and answering the question does not undo either. Call
239
+ `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
240
+ and apply exactly the actions it returns: remove the configured human-needed marker, add the
241
+ configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
242
+ of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
243
+ item never held plans nothing, so it can only ever un-do a hold and can never promote something on
244
+ its own. It is idempotent by state, so a second cycle over a released item yields no second
245
+ mutation and no second comment.
246
+
247
+ **Never edit the description to clear a hold.** The only body write available is a whole-body
248
+ replacement, so deleting one line means rewriting the whole record and hoping nothing was
249
+ dropped — the reason holds accumulated instead of being lifted. The hold note stays in the
250
+ description as history; the release is a comment beside it.
251
+ 5. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
232
252
  distinguishes "nothing was eligible" from "something eligible was held for a person". A lane
233
253
  mutation nobody can see afterwards is the same class of problem this gate exists to fix.
234
254
  Report alongside it what the precision rule SKIPPED, via `summarizeHumanGateMentions(n)`
235
255
  — the marker occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815).
236
256
  A rule that quietly declines to honour half the occurrences it sees reads exactly like a
237
- rule that saw none, so the count is printed even when it is zero.
238
- 5. **Continue to the next candidate.** A held item does not end the cycle.
257
+ rule that saw none, so the count is printed even when it is zero. Report what was RELEASED
258
+ beside it via `summarizeHumanGateReleases([...])`, printed even when it is zero: a release path
259
+ that has stopped working and a cycle with nothing to release read identically otherwise, which
260
+ is how a missing inverse stays missing.
261
+ 6. **Continue to the next candidate.** A held item does not end the cycle.
239
262
 
240
263
 
241
264
  #### 3a.0 Repo-scope gate (claim only current-repo Issues)