@codyswann/lisa 4.54.13 → 4.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (578) hide show
  1. package/all/copy-contents/.gitattributes +8 -0
  2. package/all/copy-overwrite/scripts/check-orphaned-branches.mjs +78 -9
  3. package/all/copy-overwrite/scripts/check-third-party-action-pins.mjs +17 -1
  4. package/all/copy-overwrite/scripts/lib/process-tree-runner.mjs +194 -7
  5. package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +31 -0
  6. package/all/copy-overwrite/scripts/lisa-hooks/block-blind-automerge.sh +81 -2
  7. package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +293 -8
  8. package/all/copy-overwrite/scripts/lisa-hooks/block-instruction-file-edits.sh +21 -0
  9. package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +78 -15
  10. package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +21 -0
  11. package/all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh +21 -0
  12. package/all/copy-overwrite/scripts/lisa-hooks/guard-dedupe.bash +340 -0
  13. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +29 -1
  14. package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.mjs +183 -1
  15. package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh +21 -0
  16. package/all/copy-overwrite/scripts/lisa-postinstall.mjs +21 -1
  17. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +100 -5
  18. package/all/copy-overwrite/scripts/lisa-work-item.mjs +1085 -80
  19. package/all/create-only/.github/workflows/continuous-gates.yml +7 -0
  20. package/cdk/create-only/.github/workflows/ci.yml +7 -0
  21. package/cdk/create-only/.github/workflows/deploy.yml +21 -0
  22. package/dist/cli/apply.d.ts.map +1 -1
  23. package/dist/cli/apply.js +9 -1
  24. package/dist/cli/apply.js.map +1 -1
  25. package/dist/cli/doctor-apply-deletions.d.ts +61 -0
  26. package/dist/cli/doctor-apply-deletions.d.ts.map +1 -0
  27. package/dist/cli/doctor-apply-deletions.js +137 -0
  28. package/dist/cli/doctor-apply-deletions.js.map +1 -0
  29. package/dist/cli/doctor-cdk-preset-adoption.d.ts +15 -0
  30. package/dist/cli/doctor-cdk-preset-adoption.d.ts.map +1 -0
  31. package/dist/cli/doctor-cdk-preset-adoption.js +316 -0
  32. package/dist/cli/doctor-cdk-preset-adoption.js.map +1 -0
  33. package/dist/cli/doctor-config-shadowing.d.ts +22 -0
  34. package/dist/cli/doctor-config-shadowing.d.ts.map +1 -0
  35. package/dist/cli/doctor-config-shadowing.js +123 -0
  36. package/dist/cli/doctor-config-shadowing.js.map +1 -0
  37. package/dist/cli/doctor-rails-deploy-intent.d.ts +15 -0
  38. package/dist/cli/doctor-rails-deploy-intent.d.ts.map +1 -0
  39. package/dist/cli/doctor-rails-deploy-intent.js +197 -0
  40. package/dist/cli/doctor-rails-deploy-intent.js.map +1 -0
  41. package/dist/cli/doctor-seeded-artifacts.d.ts +12 -0
  42. package/dist/cli/doctor-seeded-artifacts.d.ts.map +1 -0
  43. package/dist/cli/doctor-seeded-artifacts.js +54 -0
  44. package/dist/cli/doctor-seeded-artifacts.js.map +1 -0
  45. package/dist/cli/doctor-stale-banner-scan.d.ts +44 -0
  46. package/dist/cli/doctor-stale-banner-scan.d.ts.map +1 -0
  47. package/dist/cli/doctor-stale-banner-scan.js +152 -0
  48. package/dist/cli/doctor-stale-banner-scan.js.map +1 -0
  49. package/dist/cli/doctor-stale-managed-banner.d.ts +19 -0
  50. package/dist/cli/doctor-stale-managed-banner.d.ts.map +1 -0
  51. package/dist/cli/doctor-stale-managed-banner.js +198 -0
  52. package/dist/cli/doctor-stale-managed-banner.js.map +1 -0
  53. package/dist/cli/doctor.d.ts.map +1 -1
  54. package/dist/cli/doctor.js +16 -0
  55. package/dist/cli/doctor.js.map +1 -1
  56. package/dist/cli/ui-detected-stacks.d.ts.map +1 -1
  57. package/dist/cli/ui-detected-stacks.js +3 -2
  58. package/dist/cli/ui-detected-stacks.js.map +1 -1
  59. package/dist/cli/update-check.d.ts.map +1 -1
  60. package/dist/cli/update-check.js +14 -0
  61. package/dist/cli/update-check.js.map +1 -1
  62. package/dist/cli/worktree-liveness.d.ts +5 -0
  63. package/dist/cli/worktree-liveness.d.ts.map +1 -1
  64. package/dist/cli/worktree-liveness.js +7 -6
  65. package/dist/cli/worktree-liveness.js.map +1 -1
  66. package/dist/cli/worktree-ownership.d.ts +13 -0
  67. package/dist/cli/worktree-ownership.d.ts.map +1 -1
  68. package/dist/cli/worktree-ownership.js +14 -0
  69. package/dist/cli/worktree-ownership.js.map +1 -1
  70. package/dist/configs/eslint/base.d.ts +34 -0
  71. package/dist/configs/eslint/base.d.ts.map +1 -1
  72. package/dist/configs/eslint/base.js +34 -0
  73. package/dist/configs/eslint/base.js.map +1 -1
  74. package/dist/core/apply-receipt.d.ts +65 -0
  75. package/dist/core/apply-receipt.d.ts.map +1 -1
  76. package/dist/core/apply-receipt.js +62 -2
  77. package/dist/core/apply-receipt.js.map +1 -1
  78. package/dist/core/cdk-preset-adoption.d.ts +136 -0
  79. package/dist/core/cdk-preset-adoption.d.ts.map +1 -0
  80. package/dist/core/cdk-preset-adoption.js +135 -0
  81. package/dist/core/cdk-preset-adoption.js.map +1 -0
  82. package/dist/core/config-shadowing.d.ts +36 -0
  83. package/dist/core/config-shadowing.d.ts.map +1 -1
  84. package/dist/core/config-shadowing.js +38 -0
  85. package/dist/core/config-shadowing.js.map +1 -1
  86. package/dist/core/config.d.ts +11 -0
  87. package/dist/core/config.d.ts.map +1 -1
  88. package/dist/core/config.js.map +1 -1
  89. package/dist/core/learnings-merge-driver.d.ts +10 -0
  90. package/dist/core/learnings-merge-driver.d.ts.map +1 -1
  91. package/dist/core/learnings-merge-driver.js +18 -0
  92. package/dist/core/learnings-merge-driver.js.map +1 -1
  93. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  94. package/dist/core/lisa-owned-hash-ledger.js +136 -0
  95. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  96. package/dist/core/lisa.d.ts.map +1 -1
  97. package/dist/core/lisa.js +9 -1
  98. package/dist/core/lisa.js.map +1 -1
  99. package/dist/core/nightly-e2e-guard-behavior-certificate.d.ts +5 -5
  100. package/dist/core/nightly-e2e-guard-behavior-certificate.js +7 -7
  101. package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
  102. package/dist/core/ownership-header.d.ts +74 -0
  103. package/dist/core/ownership-header.d.ts.map +1 -0
  104. package/dist/core/ownership-header.js +76 -0
  105. package/dist/core/ownership-header.js.map +1 -0
  106. package/dist/core/rails-deploy-production-intent.d.ts +36 -0
  107. package/dist/core/rails-deploy-production-intent.d.ts.map +1 -0
  108. package/dist/core/rails-deploy-production-intent.js +79 -0
  109. package/dist/core/rails-deploy-production-intent.js.map +1 -0
  110. package/dist/core/stale-managed-banner.d.ts +78 -0
  111. package/dist/core/stale-managed-banner.d.ts.map +1 -0
  112. package/dist/core/stale-managed-banner.js +118 -0
  113. package/dist/core/stale-managed-banner.js.map +1 -0
  114. package/dist/core/two-channel-delivery-scan.d.ts +33 -1
  115. package/dist/core/two-channel-delivery-scan.d.ts.map +1 -1
  116. package/dist/core/two-channel-delivery-scan.js +133 -6
  117. package/dist/core/two-channel-delivery-scan.js.map +1 -1
  118. package/dist/core/two-channel-delivery.d.ts +101 -4
  119. package/dist/core/two-channel-delivery.d.ts.map +1 -1
  120. package/dist/core/two-channel-delivery.js +121 -13
  121. package/dist/core/two-channel-delivery.js.map +1 -1
  122. package/dist/core/two-channel-staleness.d.ts +137 -0
  123. package/dist/core/two-channel-staleness.d.ts.map +1 -0
  124. package/dist/core/two-channel-staleness.js +268 -0
  125. package/dist/core/two-channel-staleness.js.map +1 -0
  126. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  127. package/dist/core/upstream-evidence-manifest.js +265 -121
  128. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  129. package/dist/core/workflow-deletion-ownership.d.ts +6 -24
  130. package/dist/core/workflow-deletion-ownership.d.ts.map +1 -1
  131. package/dist/core/workflow-deletion-ownership.js +22 -42
  132. package/dist/core/workflow-deletion-ownership.js.map +1 -1
  133. package/dist/detection/detectors/cdk.d.ts.map +1 -1
  134. package/dist/detection/detectors/cdk.js +2 -1
  135. package/dist/detection/detectors/cdk.js.map +1 -1
  136. package/dist/health/template-inspection.d.ts.map +1 -1
  137. package/dist/health/template-inspection.js +2 -1
  138. package/dist/health/template-inspection.js.map +1 -1
  139. package/dist/migrations/ensure-lisa-postinstall.d.ts +16 -0
  140. package/dist/migrations/ensure-lisa-postinstall.d.ts.map +1 -1
  141. package/dist/migrations/ensure-lisa-postinstall.js +16 -0
  142. package/dist/migrations/ensure-lisa-postinstall.js.map +1 -1
  143. package/dist/migrations/ensure-pinned-reusable-workflow-refs.d.ts +2 -2
  144. package/dist/migrations/ensure-pinned-reusable-workflow-refs.d.ts.map +1 -1
  145. package/dist/migrations/ensure-pinned-reusable-workflow-refs.js +98 -34
  146. package/dist/migrations/ensure-pinned-reusable-workflow-refs.js.map +1 -1
  147. package/dist/migrations/ensure-playwright-dedicated-caller.d.ts.map +1 -1
  148. package/dist/migrations/ensure-playwright-dedicated-caller.js +1 -0
  149. package/dist/migrations/ensure-playwright-dedicated-caller.js.map +1 -1
  150. package/dist/opencode/hooks-installer.d.ts.map +1 -1
  151. package/dist/opencode/hooks-installer.js +1 -0
  152. package/dist/opencode/hooks-installer.js.map +1 -1
  153. package/dist/opencode/plugin-templates/block-managed-file-edits.sh +78 -15
  154. package/dist/opencode/plugin-templates/block-no-verify.sh +21 -0
  155. package/dist/opencode/plugin-templates/guard-dedupe.bash +337 -0
  156. package/dist/opencode/plugin-templates/lisa-block-direct-issue-create.ts +242 -55
  157. package/dist/opencode/plugin-templates/parity-safety-net.sh +29 -1
  158. package/dist/strategies/package-lisa.d.ts.map +1 -1
  159. package/dist/strategies/package-lisa.js +2 -1
  160. package/dist/strategies/package-lisa.js.map +1 -1
  161. package/dist/utils/path-utils.d.ts +29 -0
  162. package/dist/utils/path-utils.d.ts.map +1 -1
  163. package/dist/utils/path-utils.js +41 -0
  164. package/dist/utils/path-utils.js.map +1 -1
  165. package/expo/create-only/.github/workflows/ci.yml +21 -0
  166. package/expo/create-only/.github/workflows/deploy.yml +28 -0
  167. package/expo/create-only/.github/workflows/maestro-e2e.yml +7 -0
  168. package/expo/create-only/.github/workflows/nightly-e2e-bypass-reaper.yml +124 -13
  169. package/expo/create-only/.github/workflows/nightly-e2e-health.yml +7 -0
  170. package/expo/create-only/.github/workflows/nightly-e2e-report.yml +7 -0
  171. package/expo/create-only/.github/workflows/nightly-e2e-tracking.yml +8 -0
  172. package/expo/create-only/.github/workflows/playwright-e2e.yml +7 -0
  173. package/harper-fabric/copy-overwrite/.github/workflows/ci.yml +7 -0
  174. package/harper-fabric/create-only/.github/workflows/deploy.yml +14 -0
  175. package/nestjs/create-only/.github/workflows/ci.yml +14 -0
  176. package/nestjs/create-only/.github/workflows/deploy.yml +28 -0
  177. package/package.json +10 -5
  178. package/phaser/copy-overwrite/.github/workflows/ci.yml +7 -0
  179. package/plugins/lisa/.claude-plugin/plugin.json +28 -1
  180. package/plugins/lisa/.codex-plugin/hooks.json +27 -0
  181. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  182. package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  183. package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +27 -4
  184. package/plugins/lisa/.codex-plugin/skills/lisa-github-prd-intake/SKILL.md +1 -1
  185. package/plugins/lisa/.codex-plugin/skills/lisa-github-validate-issue/SKILL.md +22 -0
  186. package/plugins/lisa/.codex-plugin/skills/lisa-github-verify/SKILL.md +14 -0
  187. package/plugins/lisa/.codex-plugin/skills/lisa-github-write-issue/SKILL.md +51 -0
  188. package/plugins/lisa/.codex-plugin/skills/lisa-intake/SKILL.md +1 -1
  189. package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +27 -4
  190. package/plugins/lisa/.codex-plugin/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  191. package/plugins/lisa/.codex-plugin/skills/lisa-jira-verify/SKILL.md +14 -0
  192. package/plugins/lisa/.codex-plugin/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  193. package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +55 -2
  194. package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +27 -4
  195. package/plugins/lisa/.codex-plugin/skills/lisa-linear-prd-intake/SKILL.md +47 -30
  196. package/plugins/lisa/.codex-plugin/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  197. package/plugins/lisa/.codex-plugin/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  198. package/plugins/lisa/.codex-plugin/skills/lisa-linear-verify/SKILL.md +14 -0
  199. package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +54 -3
  200. package/plugins/lisa/.codex-plugin/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  201. package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/SKILL.md +19 -7
  202. package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +28 -3
  203. package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/SKILL.md +28 -3
  204. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +94 -24
  205. package/plugins/lisa/.codex-plugin/skills/lisa-rework-triage/SKILL.md +32 -2
  206. package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +4 -4
  207. package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +1 -1
  208. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  209. package/plugins/lisa/agents/linear-prd-intake.md +8 -8
  210. package/plugins/lisa/hooks/block-blind-automerge.sh +81 -2
  211. package/plugins/lisa/hooks/block-direct-issue-create.agy.sh +64 -16
  212. package/plugins/lisa/hooks/block-direct-issue-create.sh +293 -8
  213. package/plugins/lisa/hooks/block-instruction-file-edits.sh +21 -0
  214. package/plugins/lisa/hooks/block-managed-file-edits.sh +78 -15
  215. package/plugins/lisa/hooks/block-no-verify.sh +21 -0
  216. package/plugins/lisa/hooks/block-shell-json-parsing.sh +21 -0
  217. package/plugins/lisa/hooks/failure-signature-index.mjs +240 -5
  218. package/plugins/lisa/hooks/guard-dedupe.bash +337 -0
  219. package/plugins/lisa/hooks/inject-rules.sh +13 -5
  220. package/plugins/lisa/hooks/operational-hazards.mjs +736 -0
  221. package/plugins/lisa/hooks/operational-hazards.sh +28 -0
  222. package/plugins/lisa/hooks/parity-safety-net.sh +29 -1
  223. package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +102 -21
  224. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +130 -2
  225. package/plugins/lisa/hooks/threshold-ratchet.mjs +63 -13
  226. package/plugins/lisa/hooks/worktree-binding-guard.mjs +183 -1
  227. package/plugins/lisa/hooks/worktree-binding-guard.sh +21 -0
  228. package/plugins/lisa/rules/eager/00-rule-index.md +1 -0
  229. package/plugins/lisa/rules/eager/operational-hazards.md +50 -0
  230. package/plugins/lisa/rules/eager/tracked-work.md +1 -1
  231. package/plugins/lisa/rules/reference/config-resolution.md +1 -1
  232. package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +1 -1
  233. package/plugins/lisa/rules/reference/operational-hazards.md +115 -0
  234. package/plugins/lisa/rules/reference/work-item-trailer-definition.md +129 -0
  235. package/plugins/lisa/scripts/intake-blocker-reprobe.mjs +407 -26
  236. package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +507 -0
  237. package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  238. package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +27 -4
  239. package/plugins/lisa/skills/lisa-github-prd-intake/SKILL.md +1 -1
  240. package/plugins/lisa/skills/lisa-github-validate-issue/SKILL.md +22 -0
  241. package/plugins/lisa/skills/lisa-github-verify/SKILL.md +14 -0
  242. package/plugins/lisa/skills/lisa-github-write-issue/SKILL.md +51 -0
  243. package/plugins/lisa/skills/lisa-intake/SKILL.md +1 -1
  244. package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +27 -4
  245. package/plugins/lisa/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  246. package/plugins/lisa/skills/lisa-jira-verify/SKILL.md +14 -0
  247. package/plugins/lisa/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  248. package/plugins/lisa/skills/lisa-linear-access/SKILL.md +55 -2
  249. package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +27 -4
  250. package/plugins/lisa/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  251. package/plugins/lisa/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  252. package/plugins/lisa/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  253. package/plugins/lisa/skills/lisa-linear-verify/SKILL.md +14 -0
  254. package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +54 -3
  255. package/plugins/lisa/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  256. package/plugins/lisa/skills/lisa-qa-clear/SKILL.md +19 -7
  257. package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +28 -3
  258. package/plugins/lisa/skills/lisa-qa-queue/SKILL.md +28 -3
  259. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +94 -24
  260. package/plugins/lisa/skills/lisa-rework-triage/SKILL.md +32 -2
  261. package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +5 -5
  262. package/plugins/lisa/skills/lisa-track/SKILL.md +1 -1
  263. package/plugins/lisa/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  264. package/plugins/lisa-agy/agents/linear-prd-intake.md +8 -8
  265. package/plugins/lisa-agy/hooks/block-blind-automerge.sh +81 -2
  266. package/plugins/lisa-agy/hooks/block-direct-issue-create.agy.sh +64 -16
  267. package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +293 -8
  268. package/plugins/lisa-agy/hooks/block-instruction-file-edits.sh +21 -0
  269. package/plugins/lisa-agy/hooks/block-managed-file-edits.sh +78 -15
  270. package/plugins/lisa-agy/hooks/block-shell-json-parsing.sh +21 -0
  271. package/plugins/lisa-agy/hooks/guard-dedupe.bash +337 -0
  272. package/plugins/lisa-agy/hooks/parity-safety-net.sh +29 -1
  273. package/plugins/lisa-agy/hooks.json +1 -1
  274. package/plugins/lisa-agy/plugin.json +1 -1
  275. package/plugins/lisa-agy/scripts/intake-blocker-reprobe.mjs +407 -26
  276. package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +507 -0
  277. package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  278. package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +27 -4
  279. package/plugins/lisa-agy/skills/lisa-github-prd-intake/SKILL.md +1 -1
  280. package/plugins/lisa-agy/skills/lisa-github-validate-issue/SKILL.md +22 -0
  281. package/plugins/lisa-agy/skills/lisa-github-verify/SKILL.md +14 -0
  282. package/plugins/lisa-agy/skills/lisa-github-write-issue/SKILL.md +51 -0
  283. package/plugins/lisa-agy/skills/lisa-intake/SKILL.md +1 -1
  284. package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +27 -4
  285. package/plugins/lisa-agy/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  286. package/plugins/lisa-agy/skills/lisa-jira-verify/SKILL.md +14 -0
  287. package/plugins/lisa-agy/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  288. package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +55 -2
  289. package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +27 -4
  290. package/plugins/lisa-agy/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  291. package/plugins/lisa-agy/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  292. package/plugins/lisa-agy/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  293. package/plugins/lisa-agy/skills/lisa-linear-verify/SKILL.md +14 -0
  294. package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +54 -3
  295. package/plugins/lisa-agy/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  296. package/plugins/lisa-agy/skills/lisa-qa-clear/SKILL.md +19 -7
  297. package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +28 -3
  298. package/plugins/lisa-agy/skills/lisa-qa-queue/SKILL.md +28 -3
  299. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +94 -24
  300. package/plugins/lisa-agy/skills/lisa-rework-triage/SKILL.md +32 -2
  301. package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +5 -5
  302. package/plugins/lisa-agy/skills/lisa-track/SKILL.md +1 -1
  303. package/plugins/lisa-agy/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  304. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  305. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  306. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  307. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  308. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  309. package/plugins/lisa-copilot/.claude-plugin/plugin.json +19 -1
  310. package/plugins/lisa-copilot/agents/linear-prd-intake.agent.md +8 -8
  311. package/plugins/lisa-copilot/hooks/block-blind-automerge.sh +81 -2
  312. package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +293 -8
  313. package/plugins/lisa-copilot/hooks/block-instruction-file-edits.sh +21 -0
  314. package/plugins/lisa-copilot/hooks/block-managed-file-edits.sh +78 -15
  315. package/plugins/lisa-copilot/hooks/block-no-verify.sh +21 -0
  316. package/plugins/lisa-copilot/hooks/block-shell-json-parsing.sh +21 -0
  317. package/plugins/lisa-copilot/hooks/failure-signature-index.mjs +240 -5
  318. package/plugins/lisa-copilot/hooks/guard-dedupe.bash +337 -0
  319. package/plugins/lisa-copilot/hooks/inject-rules.sh +13 -5
  320. package/plugins/lisa-copilot/hooks/operational-hazards.mjs +736 -0
  321. package/plugins/lisa-copilot/hooks/operational-hazards.sh +28 -0
  322. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +29 -1
  323. package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +102 -21
  324. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +130 -2
  325. package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +63 -13
  326. package/plugins/lisa-copilot/hooks/worktree-binding-guard.mjs +183 -1
  327. package/plugins/lisa-copilot/hooks/worktree-binding-guard.sh +21 -0
  328. package/plugins/lisa-copilot/rules/eager/00-rule-index.md +1 -0
  329. package/plugins/lisa-copilot/rules/eager/operational-hazards.md +50 -0
  330. package/plugins/lisa-copilot/rules/eager/tracked-work.md +1 -1
  331. package/plugins/lisa-copilot/rules/reference/config-resolution.md +1 -1
  332. package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +1 -1
  333. package/plugins/lisa-copilot/rules/reference/operational-hazards.md +115 -0
  334. package/plugins/lisa-copilot/rules/reference/work-item-trailer-definition.md +129 -0
  335. package/plugins/lisa-copilot/scripts/intake-blocker-reprobe.mjs +407 -26
  336. package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +507 -0
  337. package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  338. package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +27 -4
  339. package/plugins/lisa-copilot/skills/lisa-github-prd-intake/SKILL.md +1 -1
  340. package/plugins/lisa-copilot/skills/lisa-github-validate-issue/SKILL.md +22 -0
  341. package/plugins/lisa-copilot/skills/lisa-github-verify/SKILL.md +14 -0
  342. package/plugins/lisa-copilot/skills/lisa-github-write-issue/SKILL.md +51 -0
  343. package/plugins/lisa-copilot/skills/lisa-intake/SKILL.md +1 -1
  344. package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +27 -4
  345. package/plugins/lisa-copilot/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  346. package/plugins/lisa-copilot/skills/lisa-jira-verify/SKILL.md +14 -0
  347. package/plugins/lisa-copilot/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  348. package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +55 -2
  349. package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +27 -4
  350. package/plugins/lisa-copilot/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  351. package/plugins/lisa-copilot/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  352. package/plugins/lisa-copilot/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  353. package/plugins/lisa-copilot/skills/lisa-linear-verify/SKILL.md +14 -0
  354. package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +54 -3
  355. package/plugins/lisa-copilot/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  356. package/plugins/lisa-copilot/skills/lisa-qa-clear/SKILL.md +19 -7
  357. package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +28 -3
  358. package/plugins/lisa-copilot/skills/lisa-qa-queue/SKILL.md +28 -3
  359. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +94 -24
  360. package/plugins/lisa-copilot/skills/lisa-rework-triage/SKILL.md +32 -2
  361. package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +5 -5
  362. package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +1 -1
  363. package/plugins/lisa-copilot/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  364. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  365. package/plugins/lisa-cursor/agents/linear-prd-intake.md +8 -8
  366. package/plugins/lisa-cursor/hooks/block-blind-automerge.sh +81 -2
  367. package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +293 -8
  368. package/plugins/lisa-cursor/hooks/block-instruction-file-edits.sh +21 -0
  369. package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +78 -15
  370. package/plugins/lisa-cursor/hooks/block-no-verify.sh +21 -0
  371. package/plugins/lisa-cursor/hooks/block-shell-json-parsing.sh +21 -0
  372. package/plugins/lisa-cursor/hooks/failure-signature-index.mjs +240 -5
  373. package/plugins/lisa-cursor/hooks/guard-dedupe.bash +337 -0
  374. package/plugins/lisa-cursor/hooks/hooks.json +10 -0
  375. package/plugins/lisa-cursor/hooks/operational-hazards.mjs +736 -0
  376. package/plugins/lisa-cursor/hooks/operational-hazards.sh +28 -0
  377. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +29 -1
  378. package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +102 -21
  379. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +130 -2
  380. package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +63 -13
  381. package/plugins/lisa-cursor/hooks/worktree-binding-guard.mjs +183 -1
  382. package/plugins/lisa-cursor/hooks/worktree-binding-guard.sh +21 -0
  383. package/plugins/lisa-cursor/rules/00-rule-index.mdc +1 -0
  384. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +1 -1
  385. package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +1 -1
  386. package/plugins/lisa-cursor/rules/operational-hazards-reference.mdc +120 -0
  387. package/plugins/lisa-cursor/rules/operational-hazards.mdc +55 -0
  388. package/plugins/lisa-cursor/rules/tracked-work.mdc +1 -1
  389. package/plugins/lisa-cursor/rules/work-item-trailer-definition-reference.mdc +134 -0
  390. package/plugins/lisa-cursor/scripts/intake-blocker-reprobe.mjs +407 -26
  391. package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +507 -0
  392. package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  393. package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +27 -4
  394. package/plugins/lisa-cursor/skills/lisa-github-prd-intake/SKILL.md +1 -1
  395. package/plugins/lisa-cursor/skills/lisa-github-validate-issue/SKILL.md +22 -0
  396. package/plugins/lisa-cursor/skills/lisa-github-verify/SKILL.md +14 -0
  397. package/plugins/lisa-cursor/skills/lisa-github-write-issue/SKILL.md +51 -0
  398. package/plugins/lisa-cursor/skills/lisa-intake/SKILL.md +1 -1
  399. package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +27 -4
  400. package/plugins/lisa-cursor/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  401. package/plugins/lisa-cursor/skills/lisa-jira-verify/SKILL.md +14 -0
  402. package/plugins/lisa-cursor/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  403. package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +55 -2
  404. package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +27 -4
  405. package/plugins/lisa-cursor/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  406. package/plugins/lisa-cursor/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  407. package/plugins/lisa-cursor/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  408. package/plugins/lisa-cursor/skills/lisa-linear-verify/SKILL.md +14 -0
  409. package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +54 -3
  410. package/plugins/lisa-cursor/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  411. package/plugins/lisa-cursor/skills/lisa-qa-clear/SKILL.md +19 -7
  412. package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +28 -3
  413. package/plugins/lisa-cursor/skills/lisa-qa-queue/SKILL.md +28 -3
  414. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +94 -24
  415. package/plugins/lisa-cursor/skills/lisa-rework-triage/SKILL.md +32 -2
  416. package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +5 -5
  417. package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +1 -1
  418. package/plugins/lisa-cursor/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  419. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  420. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  421. package/plugins/lisa-expo-agy/plugin.json +1 -1
  422. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  423. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  424. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  425. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  426. package/plugins/lisa-harper-fabric/hooks/inject-rules.sh +14 -3
  427. package/plugins/lisa-harper-fabric/rules/eager/harper-fabric.md +31 -0
  428. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  429. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  430. package/plugins/lisa-harper-fabric-copilot/hooks/inject-rules.sh +14 -3
  431. package/plugins/lisa-harper-fabric-copilot/rules/eager/harper-fabric.md +31 -0
  432. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  433. package/plugins/lisa-harper-fabric-cursor/rules/harper-fabric-reference.mdc +57 -0
  434. package/plugins/lisa-harper-fabric-cursor/rules/harper-fabric.mdc +32 -53
  435. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  436. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  437. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  438. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  439. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  440. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  441. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  442. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  443. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  444. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  445. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  446. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  447. package/plugins/lisa-phaser/hooks/inject-rules.sh +14 -3
  448. package/plugins/lisa-phaser/rules/eager/phaser.md +44 -0
  449. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  450. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  451. package/plugins/lisa-phaser-copilot/hooks/inject-rules.sh +14 -3
  452. package/plugins/lisa-phaser-copilot/rules/eager/phaser.md +44 -0
  453. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  454. package/plugins/lisa-phaser-cursor/rules/phaser-reference.mdc +189 -0
  455. package/plugins/lisa-phaser-cursor/rules/phaser.mdc +45 -185
  456. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  457. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  458. package/plugins/lisa-rails/hooks/inject-rules.sh +14 -4
  459. package/plugins/lisa-rails/rules/eager/rails-conventions.md +23 -0
  460. package/plugins/lisa-rails-agy/plugin.json +1 -1
  461. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  462. package/plugins/lisa-rails-copilot/hooks/inject-rules.sh +14 -4
  463. package/plugins/lisa-rails-copilot/rules/eager/rails-conventions.md +23 -0
  464. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  465. package/plugins/lisa-rails-cursor/rules/rails-conventions-reference.mdc +181 -0
  466. package/plugins/lisa-rails-cursor/rules/rails-conventions.mdc +24 -177
  467. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  468. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  469. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  470. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  471. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  472. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  473. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  474. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  475. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  476. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  477. package/plugins/materialized-artifacts.json +1 -0
  478. package/plugins/src/base/.claude-plugin/plugin.json +27 -0
  479. package/plugins/src/base/agents/linear-prd-intake.md +8 -8
  480. package/plugins/src/base/hooks/block-blind-automerge.sh +81 -2
  481. package/plugins/src/base/hooks/block-direct-issue-create.agy.sh +64 -16
  482. package/plugins/src/base/hooks/block-direct-issue-create.sh +293 -8
  483. package/plugins/src/base/hooks/block-instruction-file-edits.sh +21 -0
  484. package/plugins/src/base/hooks/block-managed-file-edits.sh +78 -15
  485. package/plugins/src/base/hooks/block-no-verify.sh +21 -0
  486. package/plugins/src/base/hooks/block-shell-json-parsing.sh +21 -0
  487. package/plugins/src/base/hooks/failure-signature-index.mjs +240 -5
  488. package/plugins/src/base/hooks/guard-dedupe.bash +337 -0
  489. package/plugins/src/base/hooks/inject-rules.sh +13 -5
  490. package/plugins/src/base/hooks/operational-hazards.mjs +736 -0
  491. package/plugins/src/base/hooks/operational-hazards.sh +28 -0
  492. package/plugins/src/base/hooks/parity-safety-net.sh +29 -1
  493. package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +102 -21
  494. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +130 -2
  495. package/plugins/src/base/hooks/threshold-ratchet.mjs +63 -13
  496. package/plugins/src/base/hooks/worktree-binding-guard.mjs +183 -1
  497. package/plugins/src/base/hooks/worktree-binding-guard.sh +21 -0
  498. package/plugins/src/base/rules/eager/00-rule-index.md +1 -0
  499. package/plugins/src/base/rules/eager/operational-hazards.md +50 -0
  500. package/plugins/src/base/rules/eager/tracked-work.md +1 -1
  501. package/plugins/src/base/rules/reference/config-resolution.md +1 -1
  502. package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +1 -1
  503. package/plugins/src/base/rules/reference/operational-hazards.md +115 -0
  504. package/plugins/src/base/rules/reference/work-item-trailer-definition.md +129 -0
  505. package/plugins/src/base/scripts/intake-blocker-reprobe.mjs +407 -26
  506. package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +507 -0
  507. package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
  508. package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +27 -4
  509. package/plugins/src/base/skills/lisa-github-prd-intake/SKILL.md +1 -1
  510. package/plugins/src/base/skills/lisa-github-validate-issue/SKILL.md +22 -0
  511. package/plugins/src/base/skills/lisa-github-verify/SKILL.md +14 -0
  512. package/plugins/src/base/skills/lisa-github-write-issue/SKILL.md +51 -0
  513. package/plugins/src/base/skills/lisa-intake/SKILL.md +1 -1
  514. package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +27 -4
  515. package/plugins/src/base/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
  516. package/plugins/src/base/skills/lisa-jira-verify/SKILL.md +14 -0
  517. package/plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md +51 -0
  518. package/plugins/src/base/skills/lisa-linear-access/SKILL.md +55 -2
  519. package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +27 -4
  520. package/plugins/src/base/skills/lisa-linear-prd-intake/SKILL.md +48 -31
  521. package/plugins/src/base/skills/lisa-linear-to-tracker/SKILL.md +3 -3
  522. package/plugins/src/base/skills/lisa-linear-validate-issue/SKILL.md +22 -0
  523. package/plugins/src/base/skills/lisa-linear-verify/SKILL.md +14 -0
  524. package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +54 -3
  525. package/plugins/src/base/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  526. package/plugins/src/base/skills/lisa-qa-clear/SKILL.md +19 -7
  527. package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +28 -3
  528. package/plugins/src/base/skills/lisa-qa-queue/SKILL.md +28 -3
  529. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +94 -24
  530. package/plugins/src/base/skills/lisa-rework-triage/SKILL.md +32 -2
  531. package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +5 -5
  532. package/plugins/src/base/skills/lisa-track/SKILL.md +1 -1
  533. package/plugins/src/base/skills/lisa-tracker-build-intake/SKILL.md +9 -0
  534. package/plugins/src/harper-fabric/hooks/inject-rules.sh +14 -3
  535. package/plugins/src/harper-fabric/rules/eager/harper-fabric.md +31 -0
  536. package/plugins/src/phaser/hooks/inject-rules.sh +14 -3
  537. package/plugins/src/phaser/rules/eager/phaser.md +44 -0
  538. package/plugins/src/rails/hooks/inject-rules.sh +14 -4
  539. package/plugins/src/rails/rules/eager/rails-conventions.md +23 -0
  540. package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +63 -13
  541. package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +102 -21
  542. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +130 -2
  543. package/rails/create-only/.github/workflows/ci.yml +8 -0
  544. package/rails/create-only/.github/workflows/deploy.yml +22 -0
  545. package/scripts/build-plugins.sh +2 -1
  546. package/scripts/check-engine-floor.mjs +361 -0
  547. package/scripts/check-guard-parity-notes.mjs +709 -0
  548. package/scripts/check-template-workflow-refs.mjs +9 -0
  549. package/scripts/check-third-party-action-pins.mjs +17 -1
  550. package/scripts/check-workflow-contract-assertions.mjs +480 -0
  551. package/scripts/copy-opencode-plugin-templates.mjs +1 -0
  552. package/scripts/deployed-guard-advice.mjs +636 -0
  553. package/scripts/generate-agy-plugin-artifacts.mjs +35 -10
  554. package/scripts/generate-export-surface.mjs +105 -19
  555. package/scripts/generate-two-channel-couplings.ts +143 -212
  556. package/scripts/lisa-enforcement-fallback.sh +31 -0
  557. package/scripts/measure-scripts-profile-gap.mts +361 -0
  558. package/scripts/mutation-performance-measure.mjs +21 -5
  559. package/scripts/reconcile-release-tags.mjs +65 -84
  560. package/scripts/two-channel-couplings.json +302 -70
  561. package/scripts/workflow-contract-assertion.sh +47 -0
  562. package/typescript/copy-overwrite/.lintstagedrc.json +1 -0
  563. package/typescript/copy-overwrite/eslint.ignore.config.json +1 -0
  564. package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +527 -53
  565. package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +301 -13
  566. package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +63 -13
  567. package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +102 -21
  568. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +130 -2
  569. package/typescript/create-only/.github/workflows/ci.yml +7 -0
  570. /package/plugins/lisa-harper-fabric/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
  571. /package/plugins/lisa-harper-fabric-copilot/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
  572. /package/plugins/lisa-phaser/rules/{phaser.md → reference/phaser.md} +0 -0
  573. /package/plugins/lisa-phaser-copilot/rules/{phaser.md → reference/phaser.md} +0 -0
  574. /package/plugins/lisa-rails/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
  575. /package/plugins/lisa-rails-copilot/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
  576. /package/plugins/src/harper-fabric/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
  577. /package/plugins/src/phaser/rules/{phaser.md → reference/phaser.md} +0 -0
  578. /package/plugins/src/rails/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lisa-linear-prd-intake
3
- description: "Scans a Linear workspace (or a specific team) for projects carrying the configured `ready` PRD label and runs the first eligible one through the dry-run validation pipeline. A project that passes every gate gets tickets written and the label flipped to the configured `ticketed` label; a project that fails gets clarifying-question comments (on a sentinel feedback issue under the project) and the label flipped to the configured `blocked` label. Linear counterpart of `lisa-notion-prd-intake` and `lisa-confluence-prd-intake` — the workflow is identical; only the source-of-truth tools differ. Composes existing skills (linear-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough)."
3
+ description: "Scans a Linear workspace (or a specific team) for projects carrying the configured `ready` PRD label and runs the first eligible one through the dry-run validation pipeline. A project that passes every gate gets tickets written and the label flipped to the configured `ticketed` label; a project that fails gets clarifying-question comments (on the project itself, and on the relevant sub-issue where the failure anchors to one) and the label flipped to the configured `blocked` label. Linear counterpart of `lisa-notion-prd-intake` and `lisa-confluence-prd-intake` — the workflow is identical; only the source-of-truth tools differ. Composes existing skills (linear-to-tracker, tracker-validate, tracker-source-artifacts, product-walkthrough)."
4
4
  allowed-tools: ["Skill", "Bash"]
5
5
  ---
6
6
 
@@ -12,7 +12,7 @@ allowed-tools: ["Skill", "Bash"]
12
12
  - A Linear **team** URL or team key — scans every project on the team whose labels include the configured `ready` label. Example: `https://linear.app/acme/team/ENG/projects` or bare `ENG`.
13
13
  - The literal token `linear` — equivalent to "the default Linear workspace"; only valid if `linear.workspace` is configured in `.lisa.config.json`.
14
14
 
15
- Run one intake cycle against that scope. The first eligible project with the `ready` label is claimed, validated, routed to either the `blocked` label (with clarifying comments on a sentinel feedback issue) or the `ticketed` label (with destination tickets created), then the cycle exits. Remaining ready projects stay queued for later scheduler invocations.
15
+ Run one intake cycle against that scope. The first eligible project with the `ready` label is claimed, validated, routed to either the `blocked` label (with clarifying comments on the project) or the `ticketed` label (with destination tickets created), then the cycle exits. Remaining ready projects stay queued for later scheduler invocations.
16
16
 
17
17
  ## Workflow resolution
18
18
 
@@ -37,9 +37,15 @@ SHIPPED=$(read_role shipped "prd-shipped")
37
37
  SENTINEL=$(read_role sentinel "prd-intake-feedback")
38
38
  ```
39
39
 
40
+ `$SENTINEL` is **legacy-read-only**. This skill no longer creates a sentinel
41
+ feedback issue — unanchored comments go on the project. The role is still
42
+ resolved because projects intake ran against before this change already carry
43
+ one, and the rollup phase must recognise it to keep it out of the denominator
44
+ (see "Legacy sentinel feedback issues").
45
+
40
46
  In prose below, the role names refer to the resolved labels: e.g. "the `ready` label" means whatever `linear.labels.prd.ready` resolves to (default: `prd-ready`).
41
47
 
42
- This skill is the Linear counterpart of `lisa-notion-prd-intake` and `lisa-confluence-prd-intake`, and shares its PRD shipped rollup phase (3f) with `lisa-github-prd-intake`. The phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **project labels** instead of a status property, (2) the fetch / update tools are Linear MCP, and (3) clarifying-question comments land on a sentinel feedback Issue under the project (because Linear's MCP does not expose project-level comments). Keep all four intake skills behaviorally aligned: when changing intake logic — including the rollup phase — change them together.
48
+ This skill is the Linear counterpart of `lisa-notion-prd-intake` and `lisa-confluence-prd-intake`, and shares its PRD shipped rollup phase (3f) with `lisa-github-prd-intake`. The phases, gates, comment templates, and rules are identical — the only differences are (1) the lifecycle is encoded as **project labels** instead of a status property, and (2) the fetch / update surface is `lisa-linear-access`. Unanchored clarifying-question comments land on the **project itself**, exactly as they do on a Notion or Confluence page `lisa-linear-access operation: save-comment project_id:<ID>` maps to `commentCreate(input: { projectId, body })`, which Linear has always supported. Keep all four intake skills behaviorally aligned: when changing intake logic — including the rollup phase — change them together.
43
49
 
44
50
  The **PRD shipped rollup phase (3f)** transitions a `$TICKETED` PRD project to `$SHIPPED` once all its generated top-level work is terminal, per the `prd-lifecycle-rollup` rule. This is the Linear leg of the same vendor-neutral rollup that `lisa-github-prd-intake` implements for GitHub (LPC-1.3 #584); only the vendor surface (Linear workflow states + project labels) differs.
45
51
 
@@ -146,7 +152,7 @@ This call also indirectly invokes `lisa-tracker-source-artifacts` (artifact extr
146
152
 
147
153
  1. Re-invoke `lisa-linear-to-tracker` with `dry_run: false` to actually write the tickets. This re-runs Phases 1-5 and runs the preservation gate (Phase 5.5).
148
154
  2. Capture the created ticket keys from the skill's output.
149
- 3. Ensure the project has a sentinel feedback issue (see "Sentinel feedback issue" below for the helper). Post a comment on it via `lisa-linear-access operation: save-comment` listing the created tickets (epic, stories, sub-tasks) with their JIRA URLs. Lead with: `"Ticketed by Claude. Created N JIRA issues — see below. Add the $SHIPPED label to the Linear project after the work is delivered."`
155
+ 3. Post a comment on the project via `lisa-linear-access operation: save-comment project_id:<id>` listing the created tickets (epic, stories, sub-tasks) with their JIRA URLs. Lead with: `"Ticketed by Claude. Created N JIRA issues — see below. Add the $SHIPPED label to the Linear project after the work is delivered."`
150
156
  4. Transition labels: remove `$IN_REVIEW`, add `$TICKETED` via `save_project`.
151
157
  5. **Run Phase 3e (coverage audit)** before considering this PRD done.
152
158
 
@@ -157,13 +163,13 @@ The audience for these comments is the **product team**, not engineers. They are
157
163
  ##### 3c.1 Partition failures
158
164
 
159
165
  1. Drop every failure where `product_relevant = false`. Those are internal data-quality problems — the agent should fix its own spec rather than ask product to clarify a missing core field. Record the dropped failures under `Errors` in the cycle summary so engineers can see them; never surface them on the PRD.
160
- 2. Group the remaining product-relevant failures by `prd_anchor` (which, for Linear, is a sub-issue identifier when the failure traces to a specific issue, or `null` otherwise). Failures that share an anchor become one comment thread on that issue. Failures with `prd_anchor: null` are batched into one comment on the sentinel feedback issue, since they have no source sub-issue to attach to.
166
+ 2. Group the remaining product-relevant failures by `prd_anchor` (which, for Linear, is a sub-issue identifier when the failure traces to a specific issue, or `null` otherwise). Failures that share an anchor become one comment thread on that issue. Failures with `prd_anchor: null` are batched into one comment on the **project itself**, since they have no source sub-issue to attach to.
161
167
 
162
168
  ##### 3c.2 Render each comment
163
169
 
164
- Ensure the project has a sentinel feedback issue (see helper below). For each anchored group (`prd_anchor` is a sub-issue identifier), post a comment on THAT sub-issue via `lisa-linear-access operation: save-comment({issueId: <prd_anchor>, body: <template>})`. For the unanchored group, post a single comment on the sentinel feedback issue using the same template, prefixed with `Issues without a specific sub-issue anchor:` and one block per failure.
170
+ For each anchored group (`prd_anchor` is a sub-issue identifier), post a comment on THAT sub-issue via `lisa-linear-access operation: save-comment issue_id:<prd_anchor> body:<template>`. For the unanchored group, post a single comment on the **project** via `lisa-linear-access operation: save-comment project_id:<id> body:<template>`, using the same template, prefixed with `Issues without a specific sub-issue anchor:` and one block per failure.
165
171
 
166
- If `save_comment` fails for a specific anchored sub-issue (the issue was deleted between fetch and post, or the agent lacks comment permission), fall back to the sentinel feedback issue for that group. Do not silently drop the failure.
172
+ If `save-comment` fails for a specific anchored sub-issue (the issue was deleted between fetch and post, or the agent lacks comment permission), fall back to the **project** comment for that group. Do not silently drop the failure, and do not create an issue to hold it.
167
173
 
168
174
  ##### 3c.3 Comment template
169
175
 
@@ -207,7 +213,7 @@ Use these exact badge labels — they are the validator's category values transl
207
213
 
208
214
  ##### 3c.6 Label transition
209
215
 
210
- After all comments are posted (anchored groups + the optional sentinel-issue summary), transition labels: remove `$IN_REVIEW`, add `$BLOCKED` via `save_project`. Do NOT write any destination tickets.
216
+ After all comments are posted (anchored groups + the optional project-level summary), transition labels: remove `$IN_REVIEW`, add `$BLOCKED` via `save_project`. Do NOT write any destination tickets.
211
217
 
212
218
  #### 3d. Stop
213
219
 
@@ -223,8 +229,8 @@ Per-ticket gates prove each ticket is well-formed; they do NOT prove the *set* o
223
229
  | Verdict | Action |
224
230
  |---------|--------|
225
231
  | `COMPLETE` | Done. Leave label as `$TICKETED`. End the cycle. |
226
- | `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory comment on the sentinel feedback issue naming the scope-creep tickets (so product can decide whether to close them as out-of-scope). Leave label as `$TICKETED`. |
227
- | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a comment using the same product-facing template as Phase 3c.3 — anchored on the relevant sub-issue when `prd_anchor` is non-null, on the sentinel feedback issue otherwise; category badge from the gap's `category` field; `What's unclear` and `Recommendation` from the audit report's `what` and `recommendation` fields. Apply the same forbidden-language rules from Phase 3c.5. (b) Post one summary comment on the sentinel feedback issue listing the tickets that *were* successfully created (so product knows what to keep vs. what to extend). (c) Transition labels from `$TICKETED` back to `$BLOCKED` via `save_project`. |
232
+ | `COMPLETE_WITH_SCOPE_CREEP` | Post an advisory comment on the project naming the scope-creep tickets (so product can decide whether to close them as out-of-scope). Leave label as `$TICKETED`. |
233
+ | `GAPS_FOUND` | The created ticket set is incomplete. (a) For each gap, post a comment using the same product-facing template as Phase 3c.3 — anchored on the relevant sub-issue when `prd_anchor` is non-null, on the project otherwise; category badge from the gap's `category` field; `What's unclear` and `Recommendation` from the audit report's `what` and `recommendation` fields. Apply the same forbidden-language rules from Phase 3c.5. (b) Post one summary comment on the project listing the tickets that *were* successfully created (so product knows what to keep vs. what to extend). (c) Transition labels from `$TICKETED` back to `$BLOCKED` via `save_project`. |
228
234
  | `NO_TICKETS_FOUND` | Should not happen if step 2 succeeded. If it does, log it as an Error in the cycle summary and leave label as `$TICKETED` with a comment flagging the audit failure for human review. |
229
235
 
230
236
  3. The created tickets remain in the destination tracker regardless of the verdict — they are valid in their own right. The audit only tells us whether *more* are needed.
@@ -251,6 +257,8 @@ Read the PRD's **generated top-level work** — its created Epics and any top-le
251
257
 
252
258
  2. **Documented `## Tickets` section (fallback).** When the native relationship is unavailable (the destination tracker is a *different* system — e.g. Linear PRD → JIRA tracker — so the children were never linked as Linear issues), parse the machine-readable generated-work section `lisa-prd-backlink` writes to the PRD (`## Tickets`, alias `## Generated Work`; see #582). Top-level children are the `### <Epic key>: <title>` group headers' first line (`- [<ref>](<url>) — Epic`) plus any top-level Story listed directly under `### Unparented items`. Lines nested deeper (` - ... — Story:` under an Epic, ` - ... — Sub-task:`) are descendants, NOT top-level children — skip them.
253
259
 
260
+ **Exclude any Issue carrying the `$SENTINEL` label from the child set entirely — before the dedupe, before the predicate.** A legacy sentinel is an artifact of this skill, not generated work, and it can never be terminal: closing it was forbidden precisely so its comment history stayed intact. Counting it kept the PRD out of `$SHIPPED` forever — a project whose real children were all terminal still sat at `$TICKETED` because the one non-terminal child was the reporting mechanism itself. It is excluded regardless of its state, so projects that already have a sentinel unjam without anyone touching the sentinel. Record it in the cycle summary as `excluded: legacy sentinel <ref>` so the exclusion is visible rather than silent.
261
+
254
262
  Dedupe the resulting child set by **child-ref identity** (the Linear issue/project identifier, e.g. `TEAM-123` or its UUID) so a child that appears both as a native relationship and in the documented section is counted once (`prd-lifecycle-rollup` idempotency dedupe key). If neither source yields any child (the PRD generated nothing, or the relationship was never recorded), record `no generated top-level children — rollup skipped` and leave the PRD as `$TICKETED`; do not ship an empty PRD.
255
263
 
256
264
  ##### 3f.3 Apply the terminal-state predicate
@@ -261,7 +269,7 @@ For each top-level child, fetch its workflow state and classify per the `prd-lif
261
269
  - **Terminal-but-dropped.** The child is in a **canceled** workflow state (the `canceled`-category state). Like a not-planned leaf, it does not hold the PRD open and is excluded from the shipped set.
262
270
  - **Incomplete / blocked.** Anything else: any backlog / unstarted / started / triage workflow state. Holds the PRD open.
263
271
 
264
- The set of **required** children for the all-terminal check is the top-level children minus the canceled (terminal-but-dropped) ones.
272
+ The set of **required** children for the all-terminal check is the top-level children minus the canceled (terminal-but-dropped) ones. Legacy `$SENTINEL`-labelled Issues never reach this predicate at all — 3f.2 drops them from the child set, so they are absent from both the numerator and the denominator.
265
273
 
266
274
  ##### 3f.4 Branch on the rollup verdict
267
275
 
@@ -269,12 +277,12 @@ The set of **required** children for the all-terminal check is the top-level chi
269
277
 
270
278
  1. Transition labels: remove `$TICKETED`, add `$SHIPPED` via `lisa-linear-access operation: save-project({id, labels})`. Verify exactly one lifecycle label remains (the single-label invariant).
271
279
  2. Leave the PRD active for `/lisa:verify-prd`; do not archive at the shipped hop.
272
- 3. Post a short rollup comment on the sentinel feedback issue naming the terminal child set and (when dropped children exist) the dropped set, so the audit trail records *why* the PRD shipped. Lead with `"Shipped by Claude — all generated top-level work is complete."`
280
+ 3. Post a short rollup comment on the project naming the terminal child set and (when dropped children exist) the dropped set, so the audit trail records *why* the PRD shipped. Lead with `"Shipped by Claude — all generated top-level work is complete."`
273
281
 
274
282
  **Any required child incomplete / blocked**:
275
283
 
276
284
  1. Leave the PRD label as `$TICKETED` and leave the project **active**. Do NOT add `$SHIPPED`. Do NOT archive.
277
- 2. Report the incomplete child set — both in the cycle summary and, when at least one cycle has previously ticketed this PRD, as a single advisory comment on the sentinel feedback issue listing the still-open children (`- <ref> "<title>" — <state>`), so product can see what's blocking the rollup. Keep it idempotent: regenerate the advisory rather than appending a fresh one each cycle.
285
+ 2. Report the incomplete child set — both in the cycle summary and, when at least one cycle has previously ticketed this PRD, as a single advisory comment on the project listing the still-open children (`- <ref> "<title>" — <state>`), so product can see what's blocking the rollup. Keep it idempotent: regenerate the advisory rather than appending a fresh one each cycle.
278
286
 
279
287
  ##### 3f.5 Rollup cites the rule
280
288
 
@@ -315,28 +323,37 @@ Coverage audit summary: <n> COMPLETE / <n> COMPLETE_WITH_SCOPE_CREEP / <n> GAPS_
315
323
 
316
324
  Print to the agent's output. Do not write this summary to Linear or the destination tracker — it's an operational record for the human.
317
325
 
318
- ## Sentinel feedback issue
319
-
320
- Linear's MCP does not expose project-level comments. To preserve the comment-based feedback channel that Notion and Confluence intake have natively, this skill maintains a single sentinel **feedback Issue** under each project. All clarifying-question comments that don't anchor to a specific sub-issue land here.
326
+ ## Legacy sentinel feedback issues
321
327
 
322
- The sentinel issue is identified by:
328
+ Earlier versions of this skill find-or-created one Issue per project — titled
329
+ `"PRD intake: clarifying questions"`, labelled `$SENTINEL` — to hold the
330
+ unanchored clarifying-question comments, on the belief that Linear had no
331
+ project-level comment channel. It does: `commentCreate(input: { projectId, body })`
332
+ and `Project.comments` are first-class operations, now exposed by
333
+ `lisa-linear-access` as the `project_id` forms of `save-comment` and
334
+ `list-comments`. The constraint was this wrapper, never the substrate.
323
335
 
324
- - A stable title: `"PRD intake: clarifying questions"`
325
- - A stable label: `$SENTINEL` (issue-level label, distinct from the project-level PRD lifecycle labels)
326
- - Membership in the project being processed
336
+ **This skill no longer creates a sentinel.** There is no find-or-create step;
337
+ unanchored comments go on the project. New projects never get one.
327
338
 
328
- Helper behavior call this **before** posting any clarifying-question comment in Phase 3c or 3e:
339
+ Projects processed before this change still carry theirs, so:
329
340
 
330
- 1. Search for an existing feedback issue: `list_issues({project: <id>, label: "$SENTINEL"})`. If multiple match (shouldn't happen, but defensive), use the oldest by `createdAt`.
331
- 2. If none exists: ensure the `$SENTINEL` label exists on the project's team via `list_issue_labels` then `create_issue_label` if needed; then create the sentinel via `save_issue({team: <team-id>, project: <id>, title: "PRD intake: clarifying questions", description: "Auto-created by lisa-linear-prd-intake. This issue collects clarifying-question comments that don't anchor to a specific sub-issue. Do not close manually — it is reused across intake cycles.", labels: ["$SENTINEL"]})`. Capture the new issue identifier.
332
- 3. Return the issue identifier to the caller for use in `save_comment({issueId: <id>, body: ...})`.
341
+ - **Do not close, archive, delete, or repurpose an existing sentinel.** Its
342
+ comment history is a real audit trail, and it has nowhere else to live yet.
343
+ Retiring them is deliberately out of scope here.
344
+ - **Do not post to it either.** New unanchored comments go on the project, so the
345
+ two channels do not interleave.
346
+ - **The rollup ignores it** (Phase 3f.2). That is what stops an existing sentinel
347
+ from holding its project out of `$SHIPPED` forever.
333
348
 
334
- Idempotency: the helper finds-or-creates. Re-runs of the cycle reuse the same sentinel issue. Comments accumulate; product reads top-down to see the latest cycle's findings. Do not delete or repurpose old comments history is the audit trail.
349
+ `$SENTINEL` therefore survives in config as a **read-only recognizer** — the
350
+ label name the rollup matches on to exclude these issues. It is no longer a
351
+ label this skill writes.
335
352
 
336
353
  ## Idempotency & safety
337
354
 
338
355
  - **One item per cycle**: this skill processes the first eligible ready project from Phase 2, then exits. New or remaining `$READY` projects are picked up by later scheduler invocations.
339
- - **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa-linear-to-tracker` (which delegates to `lisa-tracker-write`), only ever changes Linear project labels among `$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, and `$SHIPPED` (the last via the rollup phase 3f only), only ever creates/comments on the sentinel feedback issue (never any other Linear issue). It never edits project descriptions, never edits Linear documents, never touches the `draft` label, never archives projects at the shipped hop, and never deletes projects.
356
+ - **No writes outside the lifecycle**: this skill only ever writes to the destination tracker via `lisa-linear-to-tracker` (which delegates to `lisa-tracker-write`), only ever changes Linear project labels among `$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, and `$SHIPPED` (the last via the rollup phase 3f only), only ever comments on the PRD project itself and on the sub-issues a failure anchors to (never on any other Linear issue, and it creates no Linear issue of its own). It never edits project descriptions, never edits Linear documents, never touches the `draft` label, never archives projects at the shipped hop, and never deletes projects.
340
357
  - **Claim-first ordering**: the label flip to `$IN_REVIEW` happens BEFORE validation runs, so a re-entrant call won't double-process.
341
358
  - **Failure handling**: an exception processing the selected project is caught and recorded under "Errors" in the summary, then the cycle exits. The project that errored is left labelled `$IN_REVIEW` — the human investigates from there.
342
359
  - **Single-label invariant**: after every transition, verify exactly one lifecycle label is present on the project. If two are present (rare race), surface as an Error and skip — do NOT auto-resolve, the human decides.
@@ -358,18 +375,18 @@ Destination tracker config (jira / github / linear) is consumed by `lisa-tracker
358
375
  | `.lisa.config.json` `linear.labels.prd.blocked` | `prd-blocked` | Project label set on validation failure |
359
376
  | `.lisa.config.json` `linear.labels.prd.ticketed` | `prd-ticketed` | Project label set on success |
360
377
  | `.lisa.config.json` `linear.labels.prd.shipped` | `prd-shipped` | Project label set by the rollup phase (3f) when all generated top-level work is terminal; product may also set it by hand |
361
- | `.lisa.config.json` `linear.labels.prd.sentinel` | `prd-intake-feedback` | Issue-level label marking the sentinel feedback issue |
378
+ | `.lisa.config.json` `linear.labels.prd.sentinel` | `prd-intake-feedback` | Issue-level label marking a **legacy** sentinel feedback issue. Read-only: matched so the rollup can exclude it (Phase 3f.2); never written by this skill |
362
379
 
363
380
  ## Rules
364
381
 
365
382
  - Never write to the destination tracker outside of `lisa-linear-to-tracker` → `lisa-tracker-write`. The validator's verdict gates progress; bypassing it produces broken tickets.
366
- - Never add or remove a label this skill doesn't own (`$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, and `$SHIPPED` via the rollup phase only). Product owns the `draft` and `ready` labels; product and the rollup phase (3f) both set `shipped`. The issue-level `$SENTINEL` label is owned by this skill but is not a lifecycle label.
383
+ - Never add or remove a label this skill doesn't own (`$IN_REVIEW`, `$BLOCKED`, `$TICKETED`, and `$SHIPPED` via the rollup phase only). Product owns the `draft` and `ready` labels; product and the rollup phase (3f) both set `shipped`. The issue-level `$SENTINEL` label is read-only here matched to recognise legacy sentinel issues, never applied.
367
384
  - Set `$SHIPPED` only from the rollup phase, and only when all generated top-level children are terminal per the `prd-lifecycle-rollup` rule. Never ship on partial completion and never archive at shipped.
368
- - Never edit a project's description or any attached Linear document. Communication with product happens only through comments on sub-issues or on the sentinel feedback issue.
369
- - Never post a single dump of all gate failures on one comment. One comment per `prd_anchor` group on the relevant sub-issue (or one comment on the sentinel feedback issue for unanchored failures only). Comments must be sub-issue-anchored where possible, categorized, plain-language, and contain a concrete recommendation.
385
+ - Never edit a project's description or any attached Linear document. Communication with product happens only through comments on the project itself, or on the sub-issue a failure anchors to.
386
+ - Never post a single dump of all gate failures on one comment. One comment per `prd_anchor` group on the relevant sub-issue (or one comment on the project for unanchored failures only). Comments must be sub-issue-anchored where possible, categorized, plain-language, and contain a concrete recommendation.
370
387
  - Never include a gate ID, internal skill name, or engineering shorthand in a comment body.
371
388
  - Never run more than one intake cycle concurrently against the same scope. This skill assumes serial execution.
372
- - Never close, archive, or otherwise modify the sentinel feedback issue except to post comments on it. Its longevity is the audit trail.
389
+ - Never create a Linear issue to hold a comment. Unanchored feedback belongs on the project. Never close, archive, repurpose, or post to a legacy sentinel issue either its existing history is an audit trail, and retiring those issues is a separate, deliberate follow-up.
373
390
  - If `lisa-linear-to-tracker` returns errors, treat them as gate failures: comment + `$BLOCKED`. Don't silently fail.
374
391
 
375
392
  ## Adoption (one-time per project)
@@ -32,7 +32,7 @@ This skill supports two modes, controlled by a `dry_run` flag in `$ARGUMENTS`:
32
32
  - **`dry_run: false`** (default — full mode): run all phases, write tickets via `lisa-tracker-write`, run the preservation gate, report.
33
33
  - **`dry_run: true`** (planning + validation only — no writes): run Phases 1, 1.5, 1.6, 2, 3, 4 to plan the hierarchy and draft each ticket spec, then call `lisa-tracker-validate` (with `--spec-only`) on every drafted ticket. Aggregate the per-ticket validator reports into a single dry-run report. **Skip Phase 5 (sub-task creation), Phase 5.5 (preservation gate), and Phase 6 (results report)** — none of those make sense without writes. Return the dry-run report so the caller (e.g. `lisa-linear-prd-intake`) can decide whether to proceed.
34
34
 
35
- Dry-run output format is identical to `lisa-notion-to-tracker`'s and `lisa-confluence-to-tracker`'s. Reuse the same fields, including `prd_anchor` and `prd_section`, the `### Requirement register` section, and the per-node `requirements:` lists. The only difference: Linear has no inline-comment selection-anchor primitive at the project level — `prd_anchor` is the anchor a downstream caller would use to *post a comment on the related sub-issue* (typically the issue identifier, e.g. `LIN-123`, scoped to a section heading). When the failure does not map to any single sub-issue, set `prd_anchor: null` and the caller falls back to its sentinel feedback channel.
35
+ Dry-run output format is identical to `lisa-notion-to-tracker`'s and `lisa-confluence-to-tracker`'s. Reuse the same fields, including `prd_anchor` and `prd_section`, the `### Requirement register` section, and the per-node `requirements:` lists. The only difference: Linear has no inline-comment selection-anchor primitive at the project level — `prd_anchor` is the anchor a downstream caller would use to *post a comment on the related sub-issue* (typically the issue identifier, e.g. `LIN-123`, scoped to a section heading). When the failure does not map to any single sub-issue, set `prd_anchor: null` and the caller posts it on the project itself.
36
36
 
37
37
  ```text
38
38
  ## linear-to-tracker dry-run: <PRD title>
@@ -275,7 +275,7 @@ Skip the *walkthrough* only when the work has no user-visible surface, or affect
275
275
  **Git ancestry, a merge check and `cdk synth` are never deployment evidence** — a discarded pipeline execution leaves a commit merged and unshipped, and all three still report "present". **An unanswerable probe is not a "no"**: when the state cannot be read back, record that the check could not be performed rather than defaulting to absent.
276
276
 
277
277
 
278
- Walkthrough findings are surfaced back to product via the orchestrating intake skill (`lisa-linear-prd-intake`), which posts them on the project's sentinel feedback issue. This skill itself does NOT post to Linear — it only reads. The walkthrough section is also inherited onto the resulting epic / stories under a `## Current Product` subsection in the JIRA description.
278
+ Walkthrough findings are surfaced back to product via the orchestrating intake skill (`lisa-linear-prd-intake`), which posts them on the project itself. This skill itself does NOT post to Linear — it only reads. The walkthrough section is also inherited onto the resulting epic / stories under a `## Current Product` subsection in the JIRA description.
279
279
 
280
280
  ### Phase 3: Create Epics
281
281
 
@@ -450,5 +450,5 @@ Track tickets that are shared across PRDs to avoid duplication. When a sub-task
450
450
  - **Project description format**: Linear project descriptions are markdown. Treat headings (`#`, `##`, `###`) as section markers for `prd_section`.
451
451
  - **Document parents**: Linear documents are attached to either a Project or an Issue (exactly one). For PRD intake, only documents attached to the project being processed are in scope. Documents attached to a child Issue are picked up via that issue's content surface.
452
452
  - **Comment threading**: Linear comments are threaded via a `parentId` field on each comment. When fetching comments via `list_comments`, capture the full reply tree — replies often hold the actual decision while the root comment was the question.
453
- - **No project-level comments via MCP**: clarifying-question comments cannot land directly on the project itself. The orchestrating skill (`lisa-linear-prd-intake`) handles this by maintaining a sentinel feedback issue under the project. This skill does not write to Linear at all it only reads.
453
+ - **No inline selection anchors on a project**: Linear has no equivalent of a Notion selection snippet or a Confluence inline comment, so an unanchored failure has no in-text location to attach to. It still lands on the project `lisa-linear-access operation: save-comment project_id:<ID>` posts a project-level comment — just as a whole-page comment rather than an inline one. This skill does not write to Linear at all; it only reads.
454
454
  - **Issue identifiers** (`LIN-123`, `ENG-456`, etc.) are the closest analog to a Confluence inline-comment anchor. When dry-run output sets `prd_anchor` to an issue identifier, the caller knows it can post a clarifying-question comment on that specific issue if it wants block-level anchoring.
@@ -19,6 +19,28 @@ Reads `linear.workspace`, `linear.teamKey` from `.lisa.config.json` (with `.loca
19
19
  1. **An existing Linear identifier** (e.g. `ENG-123` for an Issue, or `<workspace>/project/<slug>-<id>` for a Project): fetch and validate the live state.
20
20
  2. **A proposed item spec** (YAML block, see schema below): validate as-is without touching Linear.
21
21
 
22
+ ### Standalone entry point — validating an item written by another path
23
+
24
+ Input form 1 is a **supported entry point in its own right**, not only an internal step of a
25
+ caller flow. Point this skill at any existing item — however it was written, including by a
26
+ bespoke script, a direct API or GraphQL call, or the vendor's own web UI — and it fetches the
27
+ live state and runs the full gate set against it.
28
+
29
+ Copy-pasteable, via the Skill tool:
30
+
31
+ ```text
32
+ Skill(skill: "lisa-linear-validate-issue", args: "ENG-123")
33
+ ```
34
+
35
+ where the argument is an Issue identifier such as `ENG-123`, or a Project URL. The report it returns is the same structured PASS/FAIL
36
+ report the write path consumes, so a bespoke write path can discharge both the pre-write
37
+ validate and the post-write verify obligation with it (see the bespoke-path section of
38
+ `lisa-linear-write-issue`).
39
+
40
+ This skill is plugin-resident. It is invoked through the Skill tool and is **not** expected to
41
+ appear in any repository's `scripts/` directory; not finding a shell script by this name is
42
+ not evidence that the capability is absent.
43
+
22
44
  ### Spec schema
23
45
 
24
46
  ```yaml
@@ -44,6 +44,20 @@ Return the validator's report verbatim — same structured format as `lisa-linea
44
44
 
45
45
  If the verdict is `FAIL`, the caller should fix the item and re-run verify. Never declare success on a `FAIL` verdict.
46
46
 
47
+ ## Comparison semantics — semantic, never byte-exact
48
+
49
+ Verification here re-runs `lisa-linear-validate-issue` against the live work item. It does **not** compare the
50
+ stored body against the sent body byte for byte, and it must never drift to doing so.
51
+
52
+ Linear normalizes markdown on write. Observed normalizations include rewriting `-` bullets
53
+ as `*`, wrapping a bare URL as an explicit link, and re-segmenting bold emphasis around
54
+ inline code spans — all lossless, all rendering-identical. **A byte-exact comparator cannot
55
+ distinguish vendor markdown normalization from corruption**, so it reports failure on
56
+ perfectly healthy writes and trains its reader to ignore it (CodySwannGT/lisa#3663).
57
+
58
+ Any comparison of tracker-normalized rich text is therefore semantic, or
59
+ normalize-then-compare. Byte-exact comparison of such text is forbidden.
60
+
47
61
  ## Rules
48
62
 
49
63
  - Never write to Linear. Read-only.
@@ -299,7 +299,7 @@ If the item modifies an existing user-facing surface, a `lisa-product-walkthroug
299
299
  Before create/update, verify each field is populated where applicable:
300
300
 
301
301
  - **Workflow state**: set the resolved `ready` state (`linear.workflow.ready`, default `Ready`) on a new **leaf** work unit (Bug / Task / Sub-task / Improvement with no child work) per `leaf-only-lifecycle`, **only on explicit `build_ready: true`** (see the Build-ready control input below). A container (Epic Project / Story with sub-issues / Spike) is never put in the build-ready state.
302
- - **Labels**: taxonomy only — `type:<Kind>`, `repo:<name>`, `component:<name>`, and the `prd-intake-feedback` sentinel. Lifecycle is **not** a label on Linear; do not add `status:*` labels.
302
+ - **Labels**: taxonomy only — `type:<Kind>`, `repo:<name>`, `component:<name>`. Lifecycle is **not** a label on Linear; do not add `status:*` labels.
303
303
  - **Native priority field**: 0–4 per Linear's scale; explicit, not "unset".
304
304
  - **Native estimate**: per Linear's team-configured estimate scale (often 0–8 Fibonacci); skip for Epic / Spike.
305
305
  - **ProjectMilestone**: when the team uses dated milestones, set the milestone on the Project (Epic) or on the Issue (when an Issue belongs to a milestone).
@@ -334,6 +334,17 @@ person scanning a board and to any path that has not yet been routed through the
334
334
  If the label does not exist in the tracker, create it, or record that it could not be applied and
335
335
  proceed — the marker still holds. Never file the label *instead of* the marker.
336
336
 
337
+ **Write a `reason=` the release can name.** The hold's reason is not decoration: a hold ends when a
338
+ `[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item, and the
339
+ next intake sweep then takes the marker label off and puts the item back in the build-ready role on
340
+ its own. Matching is per-reason so that a hold declared *after* an earlier release is not born
341
+ discharged. A keyless hold is legal and is discharged by a keyless release; a hold whose reason is a
342
+ paragraph is legal and nobody will reproduce it. Prefer a short slug the person answering it can
343
+ retype. Do **not** instruct anyone to delete the marker from the description to lift the hold — the
344
+ only body write available is a whole-body replacement, so that asks them to rewrite the whole record
345
+ to clear one line, which is why answered holds accumulated instead of being lifted
346
+ (CodySwannGT/lisa#3852). The marker stays as history; the release is recorded beside it.
347
+
337
348
  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.
338
349
 
339
350
  ## Phase 5.5 — Validate (Pre-write Gate)
@@ -360,7 +371,7 @@ If the validator reports `PASS`, continue to Phase 6.
360
371
 
361
372
  ### CREATE — Story / Task / Bug / Spike / Improvement (Issue with projectId)
362
373
 
363
- 1. Resolve any required Issue labels (`type:<Kind>`, `repo:<name>`, `component:<name>`, `prd-intake-feedback` only if this is a sentinel issue) via `lisa-linear-access operation: list-issue-labels` (create via `lisa-linear-access operation: create-issue-label` if missing). Separately, place a **leaf** work unit in the `ready` lane by passing `lifecycle_role: ready` on the create call below — and only on **explicit `build_ready: true`**, per the Build-ready control input below. Omit the role for a container, and for a leaf whose `build_ready` is `false` or omitted, which then waits in the team's default backlog state for a human to promote it. Ready is an explicit claim, never an omission's default. Never resolve a state ID here and pass it as `stateId`: the access layer resolves the configured `ready` state itself and refuses anything else.
374
+ 1. Resolve any required Issue labels (`type:<Kind>`, `repo:<name>`, `component:<name>`) via `lisa-linear-access operation: list-issue-labels` (create via `lisa-linear-access operation: create-issue-label` if missing). Separately, place a **leaf** work unit in the `ready` lane by passing `lifecycle_role: ready` on the create call below — and only on **explicit `build_ready: true`**, per the Build-ready control input below. Omit the role for a container, and for a leaf whose `build_ready` is `false` or omitted, which then waits in the team's default backlog state for a human to promote it. Ready is an explicit claim, never an omission's default. Never resolve a state ID here and pass it as `stateId`: the access layer resolves the configured `ready` state itself and refuses anything else.
364
375
  2. Call `lisa-linear-access operation: save-issue` with: `team` (teamId), `title` (summary), `description` (markdown), `projectId` (the Epic Project), `priority` (0–4), `estimate`, `labelIds`, `assignee` if known.
365
376
  3. Capture the returned identifier (e.g. `ENG-123`) — Phase 4 sub-tasks need it as `parentId`.
366
377
  4. Add relationships from Phase 4b via `save_issue` (relations field) or paired relation calls.
@@ -384,7 +395,7 @@ Call the `lisa-linear-verify` skill on the resulting item. `lisa-linear-verify`
384
395
 
385
396
  ## Phase 8 — Announce
386
397
 
387
- Post a creation comment via `lisa-linear-access operation: save-comment` (on the Issue, or on a sentinel issue under the Project for Epic-level announcements) with:
398
+ Post a creation comment via `lisa-linear-access operation: save-comment` `issue_id:<ID>` for an Issue, `project_id:<ID>` for an Epic-level announcement, which goes on the Project itself. Never create an Issue to carry a Project's announcement. The comment contains:
388
399
 
389
400
  - `[<repo>]` prefix if the item is repo-scoped
390
401
  - Who the item is assigned to (if known)
@@ -393,6 +404,46 @@ Post a creation comment via `lisa-linear-access operation: save-comment` (on the
393
404
 
394
405
  Skip this step only on UPDATE when no material change was made.
395
406
 
407
+ ## Writing by a bespoke path (your own script, direct API or GraphQL)
408
+
409
+ Nothing here stops a consumer from writing to Linear through the Linear GraphQL API directly, a direct API call, or your own script, and nothing should
410
+ try to — a script that owns the credential plumbing is often the only practical transport.
411
+ **The transport is not the gate.** A bespoke write path still owes both halves of the quality
412
+ gate this skill runs, and owes them explicitly, because no phase of this flow will ever run
413
+ for it.
414
+
415
+ A bespoke script's own read-back does not discharge either obligation. Re-reading the work item
416
+ and confirming Linear stored what was sent **proves transport, not quality**: it shows the
417
+ fields round-tripped and says nothing about whether what was sent clears a single gate. An
418
+ agent that reads `VERIFIED` out of such a script has been told the work item was checked when it
419
+ was not. Measured once, on one work item, on 2026-09-03 (CodySwannGT/lisa#3663): a local
420
+ script's read-back was clean on every field, and the work item then failed gates S5, S9 and S18
421
+ when the validator was run against it by hand.
422
+
423
+ What a bespoke write path still owes — the same two checks, invoked by hand:
424
+
425
+ 1. **Pre-write validate**, the obligation Phase 5.5 discharges here. Invoke `lisa-linear-validate-issue` via
426
+ the Skill tool with the proposed spec as a YAML block **before** writing. Never write on a
427
+ `FAIL` verdict.
428
+ 2. **Post-write verify**, the obligation Phase 7 discharges here. Invoke `lisa-linear-verify` via the
429
+ Skill tool with the identifier of the work item you just wrote — or `lisa-linear-validate-issue` directly in
430
+ identifier mode, which fetches and validates the live state. Never report success on a
431
+ `FAIL` verdict.
432
+
433
+ Both run standalone against an existing live work item; `lisa-linear-validate-issue` documents the copy-pasteable
434
+ invocation under its standalone entry point.
435
+
436
+ **Three outcomes, never two.** `PASS`, `FAIL` and *could not validate* are distinct results.
437
+ If the validator did not run to a verdict — the skill was unavailable, a credential was
438
+ missing, the work item could not be fetched — that is **not** a pass. Report it as unvalidated and
439
+ say why. Collapsing "could not validate" into "validated" is the same misreading as trusting
440
+ a read-back.
441
+
442
+ **These are skills, not scripts.** `lisa-linear-validate-issue` and `lisa-linear-verify` are plugin-resident and invoked
443
+ through the Skill tool. They are **not** expected to appear in any repository's `scripts/`
444
+ directory, and their absence from one is not evidence that the capability is missing —
445
+ searching the repository you happen to be standing in is the wrong search.
446
+
396
447
  ## Rules
397
448
 
398
449
  - Never create a non-Epic, non-top-level item without a parent context (Project for Stories, parentId for Sub-tasks).
@@ -50,7 +50,7 @@ Per-ticket gates (`lisa-jira-validate-ticket`) prove each created ticket is well
50
50
  - **GitHub**: enumerate native sub-issues via `gh api graphql` (`subIssues` field), then `gh issue view <child-num> --json body,comments` per child. Recurse to depth 3.
51
51
  The audit walks the full PRD tree.
52
52
  4. If `tickets=[...]` not provided, locate the destination Epic by:
53
- - Looking for a destination URL in the PRD body, comments, or the PRD's most recent "Ticketed by Claude" comment posted by `lisa-notion-prd-intake` / `lisa-confluence-prd-intake` / `lisa-linear-prd-intake` / `lisa-github-prd-intake` (for Linear, this comment lives on the project's sentinel feedback issue; for the others, it lives on the PRD page / issue itself).
53
+ - Looking for a destination URL in the PRD body, comments, or the PRD's most recent "Ticketed by Claude" comment posted by `lisa-notion-prd-intake` / `lisa-confluence-prd-intake` / `lisa-linear-prd-intake` / `lisa-github-prd-intake` (for every vendor, this comment lives on the PRD page / project / issue itself).
54
54
  - Searching the destination tracker via `lisa-tracker-read` (or directly via `searchJiraIssuesUsingJql` / `gh issue list --search`) for an epic whose summary or description references the PRD title or project ID.
55
55
  - If no epic found, return verdict `NO_TICKETS_FOUND` with a clear remediation — coverage cannot be assessed without the ticket set.
56
56
  5. Once the epic is known, fetch all child stories and sub-tasks:
@@ -174,7 +174,7 @@ Atomic PRD items extracted: <n>
174
174
  ### Scope-creep count: <n>
175
175
  ```
176
176
 
177
- `prd_anchor` and `prd_section` are built the same way as in `lisa-notion-to-tracker` / `lisa-confluence-to-tracker` / `lisa-linear-to-tracker` / `lisa-github-to-tracker`. For Notion, `prd_anchor` is the `selection_with_ellipsis` start/end snippet; for Confluence, it's the inline-comment selection text accepted by `createConfluenceInlineComment`; for Linear, it's a sub-issue identifier (e.g. `LIN-123`) when the gap maps to a specific issue, otherwise `null` (the caller posts unanchored Linear gaps on the project's sentinel feedback issue); for GitHub, it's the section heading from the PRD issue body when the gap traces to a specific section, otherwise `null` (the caller approximates inline anchoring by quoting a body excerpt at the top of the comment). The downstream caller knows which vendor it's writing to and uses the right API; this skill just emits the anchor that vendor expects.
177
+ `prd_anchor` and `prd_section` are built the same way as in `lisa-notion-to-tracker` / `lisa-confluence-to-tracker` / `lisa-linear-to-tracker` / `lisa-github-to-tracker`. For Notion, `prd_anchor` is the `selection_with_ellipsis` start/end snippet; for Confluence, it's the inline-comment selection text accepted by `createConfluenceInlineComment`; for Linear, it's a sub-issue identifier (e.g. `LIN-123`) when the gap maps to a specific issue, otherwise `null` (the caller posts unanchored Linear gaps as a project-level comment); for GitHub, it's the section heading from the PRD issue body when the gap traces to a specific section, otherwise `null` (the caller approximates inline anchoring by quoting a body excerpt at the top of the comment). The downstream caller knows which vendor it's writing to and uses the right API; this skill just emits the anchor that vendor expects.
178
178
 
179
179
  `category` is drawn from the same fixed taxonomy used by `lisa-jira-validate-ticket` so downstream callers can apply one consistent comment-formatting policy. Most coverage gaps map to `scope` (item not represented in any ticket) or `product-clarity` (item too vague to map). Use `acceptance-criteria` for missing pass/fail conditions and `design-ux` for missing visuals.
180
180
 
@@ -46,9 +46,20 @@ Read `.lisa.config.json`:
46
46
  `[lisa-qa-clear] Certified without human QA: scope is <repo(s)>, not observable
47
47
  with end-user access. Verified by the automated lifecycle pre-promotion.`
48
48
  2. Then transition to the certified status.
49
- 3. Verify both halves landed before counting the ticket as moved. A comment without
50
- the transition, or a transition without the comment, is a **partial** — report it
51
- as such, never as completed.
49
+ 3. Then clear the QA-failure **signal**, because certifying is one of its two void
50
+ conditions and this is the second path that reaches it:
51
+
52
+ ```bash
53
+ RESOLVER="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-plugins/lisa}}/scripts/qa-signal-lifecycle.mjs"
54
+ SIGNAL=$(node "$RESOLVER" --vendor "<jira|linear|github>" --print-label)
55
+ ```
56
+
57
+ Remove `$SIGNAL` through the same tracker surface that applied it. Removing a label
58
+ the ticket does not carry is a no-op, so this runs unconditionally. The
59
+ `[lisa-qa-fail]` comments are never touched — the history stays, the signal goes.
60
+ 4. Verify all three landed before counting the ticket as moved. A comment without
61
+ the transition, a transition without the comment, or a certified ticket still
62
+ wearing the signal is a **partial** — report it as such, never as completed.
52
63
  5. Report the batch:
53
64
 
54
65
  ```text
@@ -68,7 +79,8 @@ marks exactly what was auto-cleared.
68
79
  - Never bulk-move on an inferred repo list without explicit operator confirmation.
69
80
  - Every cleared ticket carries the audit comment; a transition without the comment is a
70
81
  bug in this procedure.
71
- - Idempotent by repair, not by skip: a ticket is complete only when it has BOTH the
72
- `[lisa-qa-clear]` comment AND the certified status. Re-runs finish partials — comment
73
- present but not certified → transition it; certified but no comment → post the
74
- comment. Only fully-complete tickets are skipped silently.
82
+ - Idempotent by repair, not by skip: a ticket is complete only when it has the
83
+ `[lisa-qa-clear]` comment, the certified status, AND no QA-failure signal. Re-runs
84
+ finish partials — comment present but not certified → transition it; certified but no
85
+ comment post the comment; certified but still signalled → clear the signal. Only
86
+ fully-complete tickets are skipped silently.
@@ -71,10 +71,32 @@ not smoothed over.
71
71
  For `not-covered-by-ac`, do NOT transition the ticket — the spec question goes to the
72
72
  human product gate. Flag it in the response and stop after posting.
73
73
 
74
- ## Phase 4 — Label and transition
74
+ ## Phase 4 — Signal and transition
75
75
 
76
- 1. Apply the `qa-fail` label this is the deterministic rework signal `lisa-rework-triage`
77
- keys on at next claim, and the gap classification above becomes its primary evidence.
76
+ 1. Apply the QA-failure **signal** label. Resolve its name never hardcode one:
77
+
78
+ ```bash
79
+ SIGNAL=$(node "${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-plugins/lisa}}/scripts/qa-signal-lifecycle.mjs" \
80
+ --vendor "<jira|linear|github>" --print-label) # `qa.labels.fail`, default `qa-fail`
81
+ ```
82
+
83
+ This is the deterministic rework signal `lisa-rework-triage` keys on at next claim, and
84
+ the gap classification above becomes its primary evidence.
85
+
86
+ The signal is **transient, and it says so.** Two void conditions lift it, both with an
87
+ executable predicate in `scripts/qa-signal-lifecycle.mjs`: a later QA pass verdict
88
+ (`qa-pass-recorded`), or the item reaching the certified or a terminal role
89
+ (`certified-role-reached`). `lisa-qa-queue` clears it on the pass path and `lisa-qa-clear`
90
+ clears it when it certifies without a human, so the clear path is as reachable as this
91
+ one. Record that in the comment so nobody has to infer it:
92
+
93
+ ```text
94
+ Signal: <label> — voided by a later QA pass, or by reaching the certified/terminal role.
95
+ ```
96
+
97
+ What is durable is the **history**: this `[lisa-qa-fail]` comment is never rewritten or
98
+ removed, so "failed QA twice before shipping" stays readable after the label is gone.
99
+ The label is the machine-read signal; the comment is the record.
78
100
  2. Transition the ticket to the build-ready status (`jira.workflow.ready`, or the
79
101
  configured tracker's equivalent ready label/state when `tracker` is GitHub or
80
102
  Linear). The rework loop takes it from here: intake claims it, `lisa-ticket-triage` Phase 2.5 runs
@@ -92,3 +114,6 @@ human product gate. Flag it in the response and stop after posting.
92
114
  - The expectation gap must cite a specific evidence artifact or say `no-evidence-found` —
93
115
  a gap classification without a citation is a guess, and guesses are worse than
94
116
  `no-evidence-found`.
117
+ - Never apply a signal whose clear path you cannot name. A durable mark with no inverse is
118
+ a defect class of its own (`state-changes-without-inverses`): it stays correct at the
119
+ moment it fires and becomes wrong by outliving what it described.
@@ -45,9 +45,32 @@ Read `.lisa.config.json`:
45
45
 
46
46
  ## Recording the verdict
47
47
 
48
- - **Pass** — transition the ticket to the certified status via the tracker access layer,
49
- post a brief `[lisa-qa-queue] QA pass` comment naming who verified and when, and offer
50
- the next item.
48
+ - **Pass** — three writes, in this order, and the pairing must be failure-safe exactly as
49
+ `lisa-qa-clear`'s is:
50
+ 1. Post a brief `[lisa-qa-queue] QA pass` comment naming who verified and when. The
51
+ literal marker matters: it is the `qa-pass-recorded` void condition's evidence.
52
+ 2. Transition the ticket to the certified status via the tracker access layer.
53
+ 3. **Clear the QA-failure signal.** A pass is the inverse of a fail, and until this runs
54
+ an item that failed once reads as failing forever to `lisa-rework-triage`:
55
+
56
+ ```bash
57
+ RESOLVER="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-plugins/lisa}}/scripts/qa-signal-lifecycle.mjs"
58
+ SIGNAL=$(node "$RESOLVER" --vendor "<jira|linear|github>" --print-label)
59
+ ```
60
+
61
+ Remove `$SIGNAL` from the item through the same tracker surface that applied it —
62
+ `gh issue edit <n> --remove-label "$SIGNAL"` on GitHub, the label-update mutation on
63
+ Linear, the `update.labels[].remove` field on JIRA. Removing a label the item does not
64
+ carry is a no-op on every tracker, so this is safe to run unconditionally.
65
+
66
+ Verify all three landed before reporting the pass. A transition without the signal
67
+ cleared is a **partial** — report it as such and finish it, never count it as complete.
68
+
69
+ The failure **history** is untouched: the `[lisa-qa-fail]` comments stay exactly as
70
+ written. Only the machine-read signal is voided, so "this failed QA twice before
71
+ shipping" remains readable while "this is failing QA" stops being asserted.
72
+
73
+ Then offer the next item.
51
74
  - **Fail** — invoke `lisa-qa-fail` with the ticket key and the tester's own words
52
75
  (verbatim — do not paraphrase away detail; attach any screenshots they provided). That
53
76
  skill owns the failure report, the expectation-gap diagnosis, the `qa-fail` label, and
@@ -63,6 +86,8 @@ Read `.lisa.config.json`:
63
86
  - One ticket at a time — never dump the queue on the tester.
64
87
  - The tester's verbatim description is evidence; preserve it exactly in whatever is posted.
65
88
  - Never transition to certified without an explicit "pass" from the tester.
89
+ - Never certify without clearing the QA-failure signal. The clear path must stay as
90
+ reachable as the path that applied it (`state-changes-without-inverses`).
66
91
  - All tracker writes go through the access layer / `lisa-qa-fail` — this skill never
67
92
  hand-crafts tracker mutations beyond the pass transition and its comment.
68
93
  - Session summary on request ("how did we do?"): counts of passed / failed / blocked /