@codyswann/lisa 4.55.1 → 4.55.3

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 (434) hide show
  1. package/all/copy-overwrite/scripts/check-orphaned-branches.mjs +49 -13
  2. package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +9 -1
  3. package/all/copy-overwrite/scripts/lisa-hooks/block-blind-automerge.sh +10 -5
  4. package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +4 -0
  5. package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +73 -2
  6. package/all/copy-overwrite/scripts/lisa-hooks/guard-dedupe.bash +63 -29
  7. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +2 -1
  8. package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh +2 -1
  9. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +7 -2
  10. package/all/copy-overwrite/scripts/lisa-work-item.mjs +50 -14
  11. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  12. package/dist/core/lisa-owned-hash-ledger.js +36 -0
  13. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  14. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  15. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  16. package/dist/core/upstream-evidence-manifest.js +89 -139
  17. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  18. package/dist/opencode/plugin-templates/block-managed-file-edits.sh +76 -2
  19. package/dist/opencode/plugin-templates/block-no-verify.sh +3 -0
  20. package/dist/opencode/plugin-templates/guard-dedupe.bash +66 -29
  21. package/dist/opencode/plugin-templates/parity-safety-net-heredoc.py +3 -0
  22. package/dist/opencode/plugin-templates/parity-safety-net.sh +5 -1
  23. package/dist/opencode/support-file-resolver.d.ts.map +1 -1
  24. package/dist/opencode/support-file-resolver.js +3 -1
  25. package/dist/opencode/support-file-resolver.js.map +1 -1
  26. package/expo/copy-overwrite/plugins/withAndroidSplashNoClientExit.js +23 -21
  27. package/expo/create-only/.github/required-checks.json +1 -1
  28. package/nestjs/create-only/.github/required-checks.json +1 -1
  29. package/package.json +4 -4
  30. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +18 -10
  33. package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +18 -9
  34. package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +45 -7
  35. package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +18 -7
  36. package/plugins/lisa/.codex-plugin/skills/lisa-linear-prd-intake/SKILL.md +12 -2
  37. package/plugins/lisa/.codex-plugin/skills/lisa-linear-validate-issue/SKILL.md +1 -18
  38. package/plugins/lisa/.codex-plugin/skills/lisa-linear-verify/SKILL.md +0 -17
  39. package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +3 -34
  40. package/plugins/lisa/.codex-plugin/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  41. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +46 -6
  42. package/plugins/lisa/.codex-plugin/skills/lisa-rework-triage/SKILL.md +2 -1
  43. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
  44. package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +1 -1
  45. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
  46. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
  47. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
  48. package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +18 -4
  49. package/plugins/lisa/hooks/block-blind-automerge.sh +13 -5
  50. package/plugins/lisa/hooks/block-direct-issue-create.sh +7 -0
  51. package/plugins/lisa/hooks/block-instruction-file-edits.sh +3 -0
  52. package/plugins/lisa/hooks/block-managed-file-edits.sh +76 -2
  53. package/plugins/lisa/hooks/block-no-verify.sh +3 -0
  54. package/plugins/lisa/hooks/block-shell-json-parsing.sh +3 -0
  55. package/plugins/lisa/hooks/guard-dedupe.bash +66 -29
  56. package/plugins/lisa/hooks/parity-safety-net-heredoc.py +3 -0
  57. package/plugins/lisa/hooks/parity-safety-net.sh +5 -1
  58. package/plugins/lisa/hooks/worktree-binding-guard.mjs +3 -0
  59. package/plugins/lisa/hooks/worktree-binding-guard.sh +5 -1
  60. package/plugins/lisa/rules/eager/00-rule-index.md +1 -0
  61. package/plugins/lisa/rules/eager/base-rules.md +3 -1
  62. package/plugins/lisa/rules/eager/withdrawn-rulings.md +14 -3
  63. package/plugins/lisa/rules/reference/automation-runbook-contract.md +1 -1
  64. package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +1 -1
  65. package/plugins/lisa/rules/reference/blocker-containment.md +3 -3
  66. package/plugins/lisa/rules/reference/claim-archaeology.md +1 -1
  67. package/plugins/lisa/rules/reference/claim-evidence-mapping.md +1 -1
  68. package/plugins/lisa/rules/reference/claim-time-guards.md +1 -1
  69. package/plugins/lisa/rules/reference/control-reachability.md +1 -1
  70. package/plugins/lisa/rules/reference/convergent-review.md +1 -1
  71. package/plugins/lisa/rules/reference/credential-substrate-precedence.md +1 -1
  72. package/plugins/lisa/rules/reference/dependency-decision-records.md +1 -1
  73. package/plugins/lisa/rules/reference/dependency-internalization-kit.md +1 -1
  74. package/plugins/lisa/rules/reference/dependency-trust-classes.md +1 -1
  75. package/plugins/lisa/rules/reference/deployed-state-readback.md +1 -1
  76. package/plugins/lisa/rules/reference/derived-branch-plan.md +1 -1
  77. package/plugins/lisa/rules/reference/design-source-of-truth.md +1 -1
  78. package/plugins/lisa/rules/reference/design-value-binding.md +1 -1
  79. package/plugins/lisa/rules/reference/documentation-source-paths.md +1 -1
  80. package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +1 -1
  81. package/plugins/lisa/rules/reference/observability-audit.md +1 -1
  82. package/plugins/lisa/rules/reference/prd-definition-of-ready.md +1 -1
  83. package/plugins/lisa/rules/reference/prd-lifecycle-rollup.md +1 -1
  84. package/plugins/lisa/rules/reference/pre-flight-autofill.md +1 -1
  85. package/plugins/lisa/rules/reference/promotion-contract.md +1 -1
  86. package/plugins/lisa/rules/reference/readiness-rubric.md +1 -1
  87. package/plugins/lisa/rules/reference/ready-role-filing.md +1 -1
  88. package/plugins/lisa/rules/reference/rejection-detection.md +1 -1
  89. package/plugins/lisa/rules/reference/repo-scope-split.md +9 -10
  90. package/plugins/lisa/rules/reference/reset-seed-coverage.md +1 -1
  91. package/plugins/lisa/rules/reference/usage-accounting.md +1 -1
  92. package/plugins/lisa/rules/reference/work-item-definition-of-ready.md +1 -1
  93. package/plugins/lisa/scripts/linear-state-write-target.mjs +2 -2
  94. package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +24 -11
  95. package/plugins/lisa/scripts/resolve-lifecycle-role.mjs +2 -7
  96. package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +18 -10
  97. package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +18 -9
  98. package/plugins/lisa/skills/lisa-linear-access/SKILL.md +45 -7
  99. package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +18 -7
  100. package/plugins/lisa/skills/lisa-linear-prd-intake/SKILL.md +12 -2
  101. package/plugins/lisa/skills/lisa-linear-validate-issue/SKILL.md +1 -18
  102. package/plugins/lisa/skills/lisa-linear-verify/SKILL.md +0 -17
  103. package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +3 -34
  104. package/plugins/lisa/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  105. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +46 -6
  106. package/plugins/lisa/skills/lisa-rework-triage/SKILL.md +2 -1
  107. package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
  108. package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +1 -1
  109. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
  110. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
  111. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
  112. package/plugins/lisa/skills/lisa-track/SKILL.md +18 -4
  113. package/plugins/lisa-agy/hooks/block-blind-automerge.sh +13 -5
  114. package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +7 -0
  115. package/plugins/lisa-agy/hooks/block-instruction-file-edits.sh +3 -0
  116. package/plugins/lisa-agy/hooks/block-managed-file-edits.sh +76 -2
  117. package/plugins/lisa-agy/hooks/block-shell-json-parsing.sh +3 -0
  118. package/plugins/lisa-agy/hooks/guard-dedupe.bash +66 -29
  119. package/plugins/lisa-agy/hooks/parity-safety-net-heredoc.py +3 -0
  120. package/plugins/lisa-agy/hooks/parity-safety-net.sh +5 -1
  121. package/plugins/lisa-agy/plugin.json +1 -1
  122. package/plugins/lisa-agy/scripts/linear-state-write-target.mjs +2 -2
  123. package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +24 -11
  124. package/plugins/lisa-agy/scripts/resolve-lifecycle-role.mjs +2 -7
  125. package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +18 -10
  126. package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +18 -9
  127. package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +45 -7
  128. package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +18 -7
  129. package/plugins/lisa-agy/skills/lisa-linear-prd-intake/SKILL.md +12 -2
  130. package/plugins/lisa-agy/skills/lisa-linear-validate-issue/SKILL.md +1 -18
  131. package/plugins/lisa-agy/skills/lisa-linear-verify/SKILL.md +0 -17
  132. package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +3 -34
  133. package/plugins/lisa-agy/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  134. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +46 -6
  135. package/plugins/lisa-agy/skills/lisa-rework-triage/SKILL.md +2 -1
  136. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
  137. package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +1 -1
  138. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
  139. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
  140. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
  141. package/plugins/lisa-agy/skills/lisa-track/SKILL.md +18 -4
  142. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  143. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  144. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  145. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  146. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  147. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  148. package/plugins/lisa-copilot/hooks/block-blind-automerge.sh +13 -5
  149. package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +7 -0
  150. package/plugins/lisa-copilot/hooks/block-instruction-file-edits.sh +3 -0
  151. package/plugins/lisa-copilot/hooks/block-managed-file-edits.sh +76 -2
  152. package/plugins/lisa-copilot/hooks/block-no-verify.sh +3 -0
  153. package/plugins/lisa-copilot/hooks/block-shell-json-parsing.sh +3 -0
  154. package/plugins/lisa-copilot/hooks/guard-dedupe.bash +66 -29
  155. package/plugins/lisa-copilot/hooks/parity-safety-net-heredoc.py +3 -0
  156. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +5 -1
  157. package/plugins/lisa-copilot/hooks/worktree-binding-guard.mjs +3 -0
  158. package/plugins/lisa-copilot/hooks/worktree-binding-guard.sh +5 -1
  159. package/plugins/lisa-copilot/rules/eager/00-rule-index.md +1 -0
  160. package/plugins/lisa-copilot/rules/eager/base-rules.md +3 -1
  161. package/plugins/lisa-copilot/rules/eager/withdrawn-rulings.md +14 -3
  162. package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +1 -1
  163. package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +1 -1
  164. package/plugins/lisa-copilot/rules/reference/blocker-containment.md +3 -3
  165. package/plugins/lisa-copilot/rules/reference/claim-archaeology.md +1 -1
  166. package/plugins/lisa-copilot/rules/reference/claim-evidence-mapping.md +1 -1
  167. package/plugins/lisa-copilot/rules/reference/claim-time-guards.md +1 -1
  168. package/plugins/lisa-copilot/rules/reference/control-reachability.md +1 -1
  169. package/plugins/lisa-copilot/rules/reference/convergent-review.md +1 -1
  170. package/plugins/lisa-copilot/rules/reference/credential-substrate-precedence.md +1 -1
  171. package/plugins/lisa-copilot/rules/reference/dependency-decision-records.md +1 -1
  172. package/plugins/lisa-copilot/rules/reference/dependency-internalization-kit.md +1 -1
  173. package/plugins/lisa-copilot/rules/reference/dependency-trust-classes.md +1 -1
  174. package/plugins/lisa-copilot/rules/reference/deployed-state-readback.md +1 -1
  175. package/plugins/lisa-copilot/rules/reference/derived-branch-plan.md +1 -1
  176. package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +1 -1
  177. package/plugins/lisa-copilot/rules/reference/design-value-binding.md +1 -1
  178. package/plugins/lisa-copilot/rules/reference/documentation-source-paths.md +1 -1
  179. package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +1 -1
  180. package/plugins/lisa-copilot/rules/reference/observability-audit.md +1 -1
  181. package/plugins/lisa-copilot/rules/reference/prd-definition-of-ready.md +1 -1
  182. package/plugins/lisa-copilot/rules/reference/prd-lifecycle-rollup.md +1 -1
  183. package/plugins/lisa-copilot/rules/reference/pre-flight-autofill.md +1 -1
  184. package/plugins/lisa-copilot/rules/reference/promotion-contract.md +1 -1
  185. package/plugins/lisa-copilot/rules/reference/readiness-rubric.md +1 -1
  186. package/plugins/lisa-copilot/rules/reference/ready-role-filing.md +1 -1
  187. package/plugins/lisa-copilot/rules/reference/rejection-detection.md +1 -1
  188. package/plugins/lisa-copilot/rules/reference/repo-scope-split.md +9 -10
  189. package/plugins/lisa-copilot/rules/reference/reset-seed-coverage.md +1 -1
  190. package/plugins/lisa-copilot/rules/reference/usage-accounting.md +1 -1
  191. package/plugins/lisa-copilot/rules/reference/work-item-definition-of-ready.md +1 -1
  192. package/plugins/lisa-copilot/scripts/linear-state-write-target.mjs +2 -2
  193. package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +24 -11
  194. package/plugins/lisa-copilot/scripts/resolve-lifecycle-role.mjs +2 -7
  195. package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +18 -10
  196. package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +18 -9
  197. package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +45 -7
  198. package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +18 -7
  199. package/plugins/lisa-copilot/skills/lisa-linear-prd-intake/SKILL.md +12 -2
  200. package/plugins/lisa-copilot/skills/lisa-linear-validate-issue/SKILL.md +1 -18
  201. package/plugins/lisa-copilot/skills/lisa-linear-verify/SKILL.md +0 -17
  202. package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +3 -34
  203. package/plugins/lisa-copilot/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  204. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +46 -6
  205. package/plugins/lisa-copilot/skills/lisa-rework-triage/SKILL.md +2 -1
  206. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
  207. package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +1 -1
  208. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
  209. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
  210. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
  211. package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +18 -4
  212. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  213. package/plugins/lisa-cursor/hooks/block-blind-automerge.sh +13 -5
  214. package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +7 -0
  215. package/plugins/lisa-cursor/hooks/block-instruction-file-edits.sh +3 -0
  216. package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +76 -2
  217. package/plugins/lisa-cursor/hooks/block-no-verify.sh +3 -0
  218. package/plugins/lisa-cursor/hooks/block-shell-json-parsing.sh +3 -0
  219. package/plugins/lisa-cursor/hooks/guard-dedupe.bash +66 -29
  220. package/plugins/lisa-cursor/hooks/parity-safety-net-heredoc.py +3 -0
  221. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +5 -1
  222. package/plugins/lisa-cursor/hooks/worktree-binding-guard.mjs +3 -0
  223. package/plugins/lisa-cursor/hooks/worktree-binding-guard.sh +5 -1
  224. package/plugins/lisa-cursor/rules/00-rule-index.mdc +1 -0
  225. package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +1 -1
  226. package/plugins/lisa-cursor/rules/base-rules.mdc +3 -1
  227. package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +1 -1
  228. package/plugins/lisa-cursor/rules/blocker-containment-reference.mdc +3 -3
  229. package/plugins/lisa-cursor/rules/claim-archaeology-reference.mdc +1 -1
  230. package/plugins/lisa-cursor/rules/claim-evidence-mapping-reference.mdc +1 -1
  231. package/plugins/lisa-cursor/rules/claim-time-guards-reference.mdc +1 -1
  232. package/plugins/lisa-cursor/rules/control-reachability-reference.mdc +1 -1
  233. package/plugins/lisa-cursor/rules/convergent-review-reference.mdc +1 -1
  234. package/plugins/lisa-cursor/rules/credential-substrate-precedence-reference.mdc +1 -1
  235. package/plugins/lisa-cursor/rules/dependency-decision-records-reference.mdc +1 -1
  236. package/plugins/lisa-cursor/rules/dependency-internalization-kit-reference.mdc +1 -1
  237. package/plugins/lisa-cursor/rules/dependency-trust-classes-reference.mdc +1 -1
  238. package/plugins/lisa-cursor/rules/deployed-state-readback-reference.mdc +1 -1
  239. package/plugins/lisa-cursor/rules/derived-branch-plan-reference.mdc +1 -1
  240. package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +1 -1
  241. package/plugins/lisa-cursor/rules/design-value-binding-reference.mdc +1 -1
  242. package/plugins/lisa-cursor/rules/documentation-source-paths-reference.mdc +1 -1
  243. package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +1 -1
  244. package/plugins/lisa-cursor/rules/observability-audit-reference.mdc +1 -1
  245. package/plugins/lisa-cursor/rules/prd-definition-of-ready-reference.mdc +1 -1
  246. package/plugins/lisa-cursor/rules/prd-lifecycle-rollup-reference.mdc +1 -1
  247. package/plugins/lisa-cursor/rules/pre-flight-autofill-reference.mdc +1 -1
  248. package/plugins/lisa-cursor/rules/promotion-contract-reference.mdc +1 -1
  249. package/plugins/lisa-cursor/rules/readiness-rubric-reference.mdc +1 -1
  250. package/plugins/lisa-cursor/rules/ready-role-filing-reference.mdc +1 -1
  251. package/plugins/lisa-cursor/rules/rejection-detection-reference.mdc +1 -1
  252. package/plugins/lisa-cursor/rules/repo-scope-split-reference.mdc +9 -10
  253. package/plugins/lisa-cursor/rules/reset-seed-coverage-reference.mdc +1 -1
  254. package/plugins/lisa-cursor/rules/usage-accounting-reference.mdc +1 -1
  255. package/plugins/lisa-cursor/rules/withdrawn-rulings.mdc +14 -3
  256. package/plugins/lisa-cursor/rules/work-item-definition-of-ready-reference.mdc +1 -1
  257. package/plugins/lisa-cursor/scripts/linear-state-write-target.mjs +2 -2
  258. package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +24 -11
  259. package/plugins/lisa-cursor/scripts/resolve-lifecycle-role.mjs +2 -7
  260. package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +18 -10
  261. package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +18 -9
  262. package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +45 -7
  263. package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +18 -7
  264. package/plugins/lisa-cursor/skills/lisa-linear-prd-intake/SKILL.md +12 -2
  265. package/plugins/lisa-cursor/skills/lisa-linear-validate-issue/SKILL.md +1 -18
  266. package/plugins/lisa-cursor/skills/lisa-linear-verify/SKILL.md +0 -17
  267. package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +3 -34
  268. package/plugins/lisa-cursor/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  269. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +46 -6
  270. package/plugins/lisa-cursor/skills/lisa-rework-triage/SKILL.md +2 -1
  271. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
  272. package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +1 -1
  273. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
  274. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
  275. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
  276. package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +18 -4
  277. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  278. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  279. package/plugins/lisa-expo-agy/plugin.json +1 -1
  280. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  281. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  282. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  283. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  284. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  285. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  286. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  287. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  288. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  289. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  290. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  291. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  292. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  293. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  294. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  295. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  296. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  297. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  298. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  299. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  300. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  301. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  302. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  303. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  304. package/plugins/lisa-rails-agy/plugin.json +1 -1
  305. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  306. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  307. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  308. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  309. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  310. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  311. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  312. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  313. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  314. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  315. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  316. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  317. package/plugins/materialized-artifacts.json +11 -0
  318. package/plugins/src/base/hooks/block-blind-automerge.sh +10 -5
  319. package/plugins/src/base/hooks/block-direct-issue-create.sh +4 -0
  320. package/plugins/src/base/hooks/block-managed-file-edits.sh +73 -2
  321. package/plugins/src/base/hooks/guard-dedupe.bash +63 -29
  322. package/plugins/src/base/hooks/parity-safety-net.sh +2 -1
  323. package/plugins/src/base/hooks/worktree-binding-guard.sh +2 -1
  324. package/plugins/src/base/rules/eager/00-rule-index.md +1 -0
  325. package/plugins/src/base/rules/eager/base-rules.md +3 -1
  326. package/plugins/src/base/rules/eager/withdrawn-rulings.md +14 -3
  327. package/plugins/src/base/rules/reference/automation-runbook-contract.md +1 -1
  328. package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +1 -1
  329. package/plugins/src/base/rules/reference/blocker-containment.md +3 -3
  330. package/plugins/src/base/rules/reference/claim-archaeology.md +1 -1
  331. package/plugins/src/base/rules/reference/claim-evidence-mapping.md +1 -1
  332. package/plugins/src/base/rules/reference/claim-time-guards.md +1 -1
  333. package/plugins/src/base/rules/reference/control-reachability.md +1 -1
  334. package/plugins/src/base/rules/reference/convergent-review.md +1 -1
  335. package/plugins/src/base/rules/reference/credential-substrate-precedence.md +1 -1
  336. package/plugins/src/base/rules/reference/dependency-decision-records.md +1 -1
  337. package/plugins/src/base/rules/reference/dependency-internalization-kit.md +1 -1
  338. package/plugins/src/base/rules/reference/dependency-trust-classes.md +1 -1
  339. package/plugins/src/base/rules/reference/deployed-state-readback.md +1 -1
  340. package/plugins/src/base/rules/reference/derived-branch-plan.md +1 -1
  341. package/plugins/src/base/rules/reference/design-source-of-truth.md +1 -1
  342. package/plugins/src/base/rules/reference/design-value-binding.md +1 -1
  343. package/plugins/src/base/rules/reference/documentation-source-paths.md +1 -1
  344. package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +1 -1
  345. package/plugins/src/base/rules/reference/observability-audit.md +1 -1
  346. package/plugins/src/base/rules/reference/prd-definition-of-ready.md +1 -1
  347. package/plugins/src/base/rules/reference/prd-lifecycle-rollup.md +1 -1
  348. package/plugins/src/base/rules/reference/pre-flight-autofill.md +1 -1
  349. package/plugins/src/base/rules/reference/promotion-contract.md +1 -1
  350. package/plugins/src/base/rules/reference/readiness-rubric.md +1 -1
  351. package/plugins/src/base/rules/reference/ready-role-filing.md +1 -1
  352. package/plugins/src/base/rules/reference/rejection-detection.md +1 -1
  353. package/plugins/src/base/rules/reference/repo-scope-split.md +9 -10
  354. package/plugins/src/base/rules/reference/reset-seed-coverage.md +1 -1
  355. package/plugins/src/base/rules/reference/usage-accounting.md +1 -1
  356. package/plugins/src/base/rules/reference/work-item-definition-of-ready.md +1 -1
  357. package/plugins/src/base/scripts/linear-state-write-target.mjs +2 -2
  358. package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +24 -11
  359. package/plugins/src/base/scripts/resolve-lifecycle-role.mjs +2 -7
  360. package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +18 -10
  361. package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +18 -9
  362. package/plugins/src/base/skills/lisa-linear-access/SKILL.md +45 -7
  363. package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +18 -7
  364. package/plugins/src/base/skills/lisa-linear-prd-intake/SKILL.md +12 -2
  365. package/plugins/src/base/skills/lisa-linear-validate-issue/SKILL.md +1 -18
  366. package/plugins/src/base/skills/lisa-linear-verify/SKILL.md +0 -17
  367. package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +3 -34
  368. package/plugins/src/base/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
  369. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +46 -6
  370. package/plugins/src/base/skills/lisa-rework-triage/SKILL.md +2 -1
  371. package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
  372. package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +1 -1
  373. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
  374. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
  375. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
  376. package/plugins/src/base/skills/lisa-track/SKILL.md +18 -4
  377. package/scripts/build-plugins.sh +4 -0
  378. package/scripts/copy-opencode-plugin-templates.mjs +5 -1
  379. package/scripts/lisa-enforcement-fallback.sh +9 -1
  380. package/scripts/two-channel-couplings.json +5 -33
  381. package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +551 -13
  382. package/typescript/create-only/.github/required-checks.json +1 -1
  383. package/plugins/lisa/.codex-plugin/skills/lisa-qa-checklist/SKILL.md +0 -70
  384. package/plugins/lisa/.codex-plugin/skills/lisa-qa-checklist/agents/openai.yaml +0 -4
  385. package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/SKILL.md +0 -86
  386. package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/agents/openai.yaml +0 -4
  387. package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +0 -119
  388. package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/agents/openai.yaml +0 -4
  389. package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/SKILL.md +0 -94
  390. package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/agents/openai.yaml +0 -4
  391. package/plugins/lisa/commands/qa-checklist.md +0 -6
  392. package/plugins/lisa/commands/qa-clear.md +0 -6
  393. package/plugins/lisa/commands/qa-fail.md +0 -6
  394. package/plugins/lisa/commands/qa-queue.md +0 -6
  395. package/plugins/lisa/skills/lisa-qa-checklist/SKILL.md +0 -70
  396. package/plugins/lisa/skills/lisa-qa-checklist/agents/openai.yaml +0 -4
  397. package/plugins/lisa/skills/lisa-qa-clear/SKILL.md +0 -86
  398. package/plugins/lisa/skills/lisa-qa-clear/agents/openai.yaml +0 -4
  399. package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +0 -119
  400. package/plugins/lisa/skills/lisa-qa-fail/agents/openai.yaml +0 -4
  401. package/plugins/lisa/skills/lisa-qa-queue/SKILL.md +0 -94
  402. package/plugins/lisa/skills/lisa-qa-queue/agents/openai.yaml +0 -4
  403. package/plugins/lisa-agy/commands/lisa/qa-checklist.md +0 -6
  404. package/plugins/lisa-agy/commands/lisa/qa-clear.md +0 -6
  405. package/plugins/lisa-agy/commands/lisa/qa-fail.md +0 -6
  406. package/plugins/lisa-agy/commands/lisa/qa-queue.md +0 -6
  407. package/plugins/lisa-agy/skills/lisa-qa-checklist/SKILL.md +0 -70
  408. package/plugins/lisa-agy/skills/lisa-qa-clear/SKILL.md +0 -86
  409. package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +0 -119
  410. package/plugins/lisa-agy/skills/lisa-qa-queue/SKILL.md +0 -94
  411. package/plugins/lisa-copilot/commands/lisa/qa-checklist.md +0 -6
  412. package/plugins/lisa-copilot/commands/lisa/qa-clear.md +0 -6
  413. package/plugins/lisa-copilot/commands/lisa/qa-fail.md +0 -6
  414. package/plugins/lisa-copilot/commands/lisa/qa-queue.md +0 -6
  415. package/plugins/lisa-copilot/skills/lisa-qa-checklist/SKILL.md +0 -70
  416. package/plugins/lisa-copilot/skills/lisa-qa-clear/SKILL.md +0 -86
  417. package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +0 -119
  418. package/plugins/lisa-copilot/skills/lisa-qa-queue/SKILL.md +0 -94
  419. package/plugins/lisa-cursor/commands/lisa/qa-checklist.md +0 -6
  420. package/plugins/lisa-cursor/commands/lisa/qa-clear.md +0 -6
  421. package/plugins/lisa-cursor/commands/lisa/qa-fail.md +0 -6
  422. package/plugins/lisa-cursor/commands/lisa/qa-queue.md +0 -6
  423. package/plugins/lisa-cursor/skills/lisa-qa-checklist/SKILL.md +0 -70
  424. package/plugins/lisa-cursor/skills/lisa-qa-clear/SKILL.md +0 -86
  425. package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +0 -119
  426. package/plugins/lisa-cursor/skills/lisa-qa-queue/SKILL.md +0 -94
  427. package/plugins/src/base/commands/qa-checklist.md +0 -6
  428. package/plugins/src/base/commands/qa-clear.md +0 -6
  429. package/plugins/src/base/commands/qa-fail.md +0 -6
  430. package/plugins/src/base/commands/qa-queue.md +0 -6
  431. package/plugins/src/base/skills/lisa-qa-checklist/SKILL.md +0 -70
  432. package/plugins/src/base/skills/lisa-qa-clear/SKILL.md +0 -86
  433. package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +0 -119
  434. package/plugins/src/base/skills/lisa-qa-queue/SKILL.md +0 -94
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Derived Branch Plan (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Design Source of Truth (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Design Value Binding (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Documentation Source Paths (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Leaf-Only Build-Ready Invariant (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Observability Audit (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## PRD Definition of Ready (requirement atoms)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## PRD Lifecycle Rollup & Generated-Top-Level-Work Contract (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Pre-Flight Spec Autofill — Draft-Then-Block (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Promotion Contract (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Repository Readiness Rubric (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Ready-Role Filing (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Rejection Detection at Claim Time (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Repo Scope & Work-Time Splitting (load-bearing)
8
8
 
@@ -42,9 +42,10 @@ A tracker can oversee multiple repos. Build-intake claims only current-repo tick
42
42
 
43
43
  Then, for each ready candidate:
44
44
 
45
- 1. **Read `repo:<name>` label.** Wrong repo → skip. Current repo → leaf-only gate + claim. Unlabeled → determine + stamp + re-apply.
46
- 2. **Multi-repo leaf → split, never claim.** Each split sibling is created build-ready and stamped with its own `repo:<name>`.
47
- 3. **Wrong-repo single-repo leaf → skip** (label keeps it cheap next cycle).
45
+ 1. **Count distinct repository markers first** — all `repo:<name>` labels plus recognized JIRA repository components, deduplicated by repository. Containers go to the leaf-only gate; do not split them.
46
+ 2. **Multi-repo leaf → split, never claim.** More than one repository uses the work-time split; each sibling is build-ready and stamped with its own `repo:<name>`.
47
+ 3. **Exactly one repository:** current repo → leaf-only gate + claim; wrong repo → skip.
48
+ 4. **No repository marker:** determine from content and code, stamp the resolved markers, then re-apply this decision from the count.
48
49
 
49
50
  ---
50
51
 
@@ -86,12 +87,10 @@ A ticketing system can oversee multiple repos (one JIRA project / Linear team fo
86
87
 
87
88
  Resolve the current repo per the `config-resolution` "Repo scoping" section (config `repo` → `github.repo` → git remote basename; stop with a clear error if unresolvable). Then walk the ready candidates in priority order and apply the **repo-scope decision** to each before claiming:
88
89
 
89
- 1. **Read the candidate's repo marker** — the `repo:<name>` label (JIRA: also a component equal to a repo name).
90
- - **Labeled for another repo** → **skip** cheaply (do not claim, do not re-determine); it stays `ready` for that repo's own intake. Move to the next candidate.
91
- - **Labeled for the current repo** → proceed to the leaf-only gate + claim (the cheap, common path once labels exist).
92
- - **Unlabeled** → **determine** the target repo(s) from the ticket (description, acceptance criteria, technical approach) confirmed against the actual code surfaces the change requires — the same detection as step 1 of the work-time split. Then **stamp** the resolved `repo:<name>` label(s) so future cycles filter cheaply, and re-apply this decision with the now-known repo.
93
- 2. **Multi-repo leaf → split, never claim.** If determination finds the leaf touches more than one repo, run the **work-time split procedure** below to break it into single-repo siblings — each created **build-ready** (`build_ready: true`, so the build queue auto-claims it) and stamped with its own `repo:<name>`. After the split, the current repo's sibling (if any) becomes a normal current-repo candidate; the others are separate single-repo `ready` leaves for their repos. A multi-repo leaf is never claimed as-is.
94
- 3. **Wrong repo → skip.** A single-repo leaf whose `repo:<name>` ≠ the current repo is left `ready` (and labeled) and skipped; intake moves on until it finds a claimable current-repo leaf, then stops (one item per cycle).
90
+ 1. **Count distinct repository markers first** — all `repo:<name>` labels and JIRA components equal to recognized repository names, deduplicated by repository. Containers go to the leaf-only gate and are never split or claimed here.
91
+ 2. **Multi-repo leaf → split, never claim.** More than one distinct repository takes the work-time split procedure before any wrong-repository skip. Each sibling is created **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`. The current repo's sibling, if any, becomes a normal candidate.
92
+ 3. **Exactly one repository:** a single-repo leaf for the current repo proceeds to the leaf-only gate + claim; a leaf for another repo is skipped and left ready for its own intake.
93
+ 4. **No repository marker:** determine the target repo(s) from description, acceptance criteria, technical approach and actual code surfaces. Stamp the resolved `repo:<name>` labels and re-apply from step 1. Continue until one current-repo leaf is claimed or the candidates are exhausted.
95
94
 
96
95
  **Query-time pre-filter (the cheapest arm — apply before the per-candidate walk).** When the queue is queryable, scope the candidate **query itself** to the current repo so sibling-repo tickets never even enter the set — instead of pulling the whole project's ready tickets and skipping the wrong ones one-by-one (a full wasted scan when none belong to the current repo, e.g. a JIRA project shared across `frontend`/`backend`/`infrastructure`). On JIRA, append to the JQL:
97
96
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Reset/Seed Coverage & State Classification (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Usage Accounting (load-bearing)
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
4
4
  > section below is the former eager head, preserved verbatim; the full
5
- > contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
5
+ > contract follows it. Reachable on demand via [the rule index](../eager/00-rule-index.md).
6
6
 
7
7
  ## Work-Item Definition of Ready (type-keyed)
8
8
 
@@ -174,8 +174,8 @@ export const resolveStateWriteTarget = ({
174
174
  return refuse(
175
175
  REFUSALS.MISSING_ROLE,
176
176
  "no lifecycle role was declared. Every `stateId` write must name the role " +
177
- "it is applying (ready | claimed | blocked | review | done | qa.queue | " +
178
- "qa.certified) so the configured target can be resolved instead of trusted."
177
+ "it is applying (ready | claimed | blocked | review | done) so the " +
178
+ "configured target can be resolved instead of trusted."
179
179
  );
180
180
 
181
181
  // The environment key belongs to exactly one shape: an env-indexed `done`.
@@ -71,10 +71,13 @@ import {
71
71
  parseArgs,
72
72
  parseConfig,
73
73
  readPath,
74
- resolveRole,
75
74
  } from "./resolve-lifecycle-role.mjs";
76
75
 
77
- /** The QA-failure signal: applied by `lisa-qa-fail`, read by rework triage. */
76
+ /**
77
+ * The QA-failure signal. Historically applied by the retired `lisa-qa-fail`
78
+ * skill; now applied by a human or by whatever a project uses for QA, and read
79
+ * by rework triage.
80
+ */
78
81
  export const QA_FAILURE_SIGNAL = "qa-failure";
79
82
 
80
83
  /** The human-gate signal: applied at filing, read by every intake sweep. */
@@ -190,8 +193,13 @@ const verdictOf = body => {
190
193
  };
191
194
 
192
195
  /**
193
- * Role names whose occupancy proves the QA failure was resolved: the certified
194
- * role, and every environment rung of the terminal `done` map.
196
+ * Role names whose occupancy proves the QA failure was resolved: every
197
+ * environment rung of the terminal `done` map.
198
+ *
199
+ * Previously this also resolved a `qa.certified` role. That role was retired
200
+ * along with the QA acceptance skills that were its only writers, so reaching a
201
+ * `done` rung is now the whole proof. A project that wants a distinct
202
+ * post-QA state expresses it as a `done` rung.
195
203
  *
196
204
  * @param {object} options inputs
197
205
  * @param {string} options.vendor `jira` | `linear` | `github`
@@ -199,16 +207,21 @@ const verdictOf = body => {
199
207
  * @returns {string[]} configured role names, empty when none are bound
200
208
  */
201
209
  export const voidingRoles = ({ vendor, config }) => {
202
- const certified = resolveRole({
203
- role: "qa.certified",
204
- vendor,
205
- global: config,
206
- });
207
210
  const root = VENDOR_ROOTS[vendor];
208
211
  const doneMap = root ? readPath(config, `${root}.done`) : undefined;
212
+ // `done` has two sanctioned shapes: an env-indexed map, and a single scalar
213
+ // state for a project with one terminal rung. Every other reader handles
214
+ // both — linear-state-write-target.mjs:147, lifecycle-label-trust.mjs:213,
215
+ // queue-status-build-readers.mjs:315 — and this one must too. Missing the
216
+ // scalar here returns NO voiding roles at all, which holds a QA failure live
217
+ // forever on exactly the projects with the simplest config.
209
218
  const done =
210
- doneMap && typeof doneMap === "object" ? Object.values(doneMap) : [];
211
- return [certified.value, ...done].filter(
219
+ typeof doneMap === "string"
220
+ ? [doneMap]
221
+ : doneMap && typeof doneMap === "object"
222
+ ? Object.values(doneMap)
223
+ : [];
224
+ return done.filter(
212
225
  name => typeof name === "string" && name.trim().length > 0
213
226
  );
214
227
  };
@@ -80,12 +80,7 @@ export const REQUIRED_ROLES = Object.freeze([
80
80
  * Roles a project MAY bind. Omitting one means the lifecycle skips that
81
81
  * transition. These have NO built-in default — that is the whole point of R1.
82
82
  */
83
- export const OPTIONAL_ROLES = Object.freeze([
84
- "review",
85
- "qa.queue",
86
- "qa.certified",
87
- "human_needed",
88
- ]);
83
+ export const OPTIONAL_ROLES = Object.freeze(["review", "human_needed"]);
89
84
 
90
85
  /** Where each vendor keeps its build lifecycle role map. */
91
86
  export const VENDOR_ROOTS = Object.freeze({
@@ -155,7 +150,7 @@ export const parseConfig = file => {
155
150
  * built-in default tier: see R1 in the module docblock.
156
151
  *
157
152
  * @param {object} options resolution inputs
158
- * @param {string} options.role role name (`ready`, `review`, `qa.queue`, …)
153
+ * @param {string} options.role role name (`ready`, `review`, `human_needed`, …)
159
154
  * @param {string} options.vendor one of `jira` | `linear` | `github`
160
155
  * @param {"read" | "write"} [options.intent] what the caller will do with it
161
156
  * @param {string} [options.env] env key when resolving the env-keyed `done` map
@@ -215,9 +215,15 @@ nothing survives, exit on the denominator-stated summary from `summarizeDryLane`
215
215
  A blocker is a **claim with a timestamp, not a fact** — it goes stale the moment its condition comes
216
216
  true, and nothing re-read one before this phase. For each `$BLOCKED` candidate:
217
217
 
218
- 1. **Human gate first, and it is absolute.** An issue carrying the configured human-needed label
219
- (`github.labels.build.human_needed`, default `human-needed`) or a `[lisa-human-gate]` marker in
220
- its body is **never** auto-selected, whatever any probe says.
218
+ 1. **Read release comments before applying the human gate.** Pass all item comments, labels,
219
+ body and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
220
+ call `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
221
+ and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
222
+ until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
223
+ A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
224
+ comment history cannot discharge a hold. A release removes only the human hold: continue the
225
+ remaining blocker checks below before selecting the item.
226
+
221
227
  2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
222
228
  version on trunk, a published package, a CI run history, an advisory's patched status — rot
223
229
  fastest and are cheapest to check. A human decision is not machine-testable; leave it.
@@ -335,8 +341,9 @@ other gate's verdict — however conclusive — may promote an item a person par
335
341
  is the same repair the leaf-only gate already performs for a ready item that must not be
336
342
  dispatched.
337
343
  4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
338
- The hold left durable state behind: the item is out of the queue and flagged as needing a person,
339
- and answering the question does not undo either. Call
344
+ This ready-lane candidate can retain a historical body marker and a human-needed label.
345
+ This step reconciles only candidates still in the ready lane; released holds outside it are
346
+ recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
340
347
  `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
341
348
  and apply exactly the actions it returns: remove the configured human-needed marker, add the
342
349
  configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
@@ -369,11 +376,12 @@ GitHub Issues live in one repo by definition, so the scanned repo's issues are u
369
376
  1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report.
370
377
  2. **Cheap path first.** Prefer candidates already carrying the `repo:<current>` label. Keep the Phase 2 scan broad so unlabeled issues are still seen, determined, and stamped.
371
378
  3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
372
- - Carries `repo:<other>` → **skip** (leave it `ready` for that repo's own intake); next candidate.
373
- - **Unlabeled** → determine the target repo(s) from the issue + code surfaces, then **stamp** `repo:<name>` via `gh issue edit <n> --add-label "repo:<name>"` (create the label lazily) so later cycles filter cheaply; re-apply with the now-known repo. (An issue whose work is entirely in the scanned repo is simply labeled `repo:<current>`.)
374
- - **Container visibility is allowed.** A multi-repo Epic / Story / Spike may legitimately carry multiple `repo:<name>` labels for operator visibility. Do not split or claim it here; leave the repo markers intact and fall through to the leaf-only gate, which repairs the stale build-ready label instead of dispatching the container.
375
- - **Multi-repo leaf → split, never claim.** Run the `repo-scope-split` work-time procedure into single-repo siblings, each created **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
376
- - **Single-repo leaf for the current repo** → fall through to 3a (leaf-only gate) and 3b (claim).
379
+ - **Count distinct repository markers first**: collect all `repo:<name>` labels and, on JIRA, recognized repository components; deduplicate by repository. A container may carry multiple `repo:<name>` labels. Do not split or claim it here; send it to the leaf-only gate.
380
+ - **Multi-repo leaf → split, never claim.** More than one repository takes the work-time split before any wrong-repository skip. Each sibling is **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
381
+ - **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
382
+ - **No repository marker** → determine target repo(s) from the ticket and code, stamp `repo:<name>` through the vendor access layer, and re-apply from the count.
383
+ - **Single-repo leaf for the current repo** → fall through to 3a and 3b.
384
+
377
385
  4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the candidate set is exhausted — exit cleanly on the denominator-stated summary, naming the current repo alongside the swept lanes.
378
386
 
379
387
  #### 3a. Leaf-only claim gate (repair containers)
@@ -189,9 +189,15 @@ swept (see `automation-runbook-contract`).
189
189
  A blocker is a **claim with a timestamp, not a fact** — it goes stale the moment its condition comes
190
190
  true, and nothing re-read one before this phase. For each pre-work candidate outside `$READY`:
191
191
 
192
- 1. **Human gate first, and it is absolute.** A ticket carrying the configured human-needed label
193
- (`jira.labels.human_needed`, default `Human Needed`) or a `[lisa-human-gate]` marker in its
194
- description is **never** auto-selected, whatever any probe says.
192
+ 1. **Read release comments before applying the human gate.** Pass all item comments, labels,
193
+ body and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
194
+ call `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
195
+ and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
196
+ until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
197
+ A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
198
+ comment history cannot discharge a hold. A release removes only the human hold: continue the
199
+ remaining blocker checks below before selecting the item.
200
+
195
201
  2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
196
202
  version on trunk, a published package, a CI run history, an advisory's patched status — rot
197
203
  fastest and are cheapest to check. A human decision is not machine-testable; leave it.
@@ -240,8 +246,9 @@ other gate's verdict — however conclusive — may promote an item a person par
240
246
  is the same repair the leaf-only gate already performs for a ready item that must not be
241
247
  dispatched.
242
248
  4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
243
- The hold left durable state behind: the item is out of the queue and flagged as needing a person,
244
- and answering the question does not undo either. Call
249
+ This ready-lane candidate can retain a historical body marker and a human-needed label.
250
+ This step reconciles only candidates still in the ready lane; released holds outside it are
251
+ recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
245
252
  `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
246
253
  and apply exactly the actions it returns: remove the configured human-needed marker, add the
247
254
  configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
@@ -274,10 +281,12 @@ A JIRA project can oversee multiple repos (`frontend` / `backend` / `infrastruct
274
281
  1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report — do not claim tickets you cannot scope.
275
282
  2. **Cheap path first.** Phase 1's query-time pre-filter has already dropped tickets explicitly stamped for a sibling repo, so the Phase 2 result set is current-repo-labeled + unlabeled tickets. Prefer candidates already carrying `repo:<current>` — a JIRA **label**, or a **component** equal to the repo name (accepted as an alias); the pre-filter is label-only, so a ticket scoped solely by a sibling-repo **component** can still appear and is skipped here. The result set still includes unlabeled tickets so they can be determined and stamped; this gate orders/filters what remains.
276
283
  3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
277
- - Carries `repo:<other>` (label or component) → **skip** (leave it `ready` for that repo's own intake); next candidate.
278
- - **Unlabeled** → determine the target repo(s) from the ticket (description, AC, technical approach) confirmed against the code surfaces, then **stamp** `repo:<name>` via `lisa-atlassian-access` `operation: write-ticket` (add the label / set the component) so later cycles filter cheaply; re-apply with the now-known repo.
279
- - **Multi-repo leaf → split, never claim.** Run the `repo-scope-split` work-time procedure to break it into single-repo siblings, each created **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
280
- - **Single-repo leaf for the current repo** → fall through to 3a (leaf-only gate) and 3b (claim).
284
+ - **Count distinct repository markers first**: collect all `repo:<name>` labels and, on JIRA, recognized repository components; deduplicate by repository. A container may carry multiple `repo:<name>` labels. Do not split or claim it here; send it to the leaf-only gate.
285
+ - **Multi-repo leaf → split, never claim.** More than one repository takes the work-time split before any wrong-repository skip. Each sibling is **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
286
+ - **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
287
+ - **No repository marker** → determine target repo(s) from the ticket and code, stamp `repo:<name>` through the vendor access layer, and re-apply from the count.
288
+ - **Single-repo leaf for the current repo** → fall through to 3a and 3b.
289
+
281
290
  4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the candidate set is exhausted — exit cleanly on the denominator-stated summary, naming the current repo alongside the swept lanes.
282
291
 
283
292
  #### 3a. Leaf-only claim gate (skip / safe-block containers)
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
188
188
 
189
189
  **This layer does not accept a state to write. It resolves one.** A `save-issue`
190
190
  that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
191
- role it is applying (`ready`, `claimed`, `blocked`, `review`, `done`,
192
- `qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
191
+ role it is applying (for example, `ready`, `claimed`, `blocked`, `review`, `done`; the configured role contract is authoritative) — plus `env:<KEY>` when the role is the env-indexed
193
192
  `done`. This layer then resolves that role against config and the team's own
194
193
  catalog, and sends the ID **it** resolved.
195
194
 
@@ -320,9 +319,9 @@ same mutation, same result shape, same error handling.
320
319
  ```graphql
321
320
  # list-comments project_id:<ID> — page via pageInfo so a long-lived PRD's
322
321
  # feedback history never silently truncates.
323
- query($id:String!){
322
+ query($id:String!,$after:String){
324
323
  project(id:$id){
325
- comments(first:100){
324
+ comments(first:100,after:$after){
326
325
  pageInfo{ hasNextPage endCursor }
327
326
  nodes{ id body createdAt url user{ name } }
328
327
  }
@@ -330,8 +329,47 @@ query($id:String!){
330
329
  }
331
330
  ```
332
331
 
333
- The Issue form reads through `issue(id:$id){ comments{...} }` with the identical
334
- node shape, so a caller consumes one result format for either anchor.
332
+ The Issue form uses `issue(id:$id)` with the same `first:100,after:$after`
333
+ arguments and node shape. For **both** anchors, use this access-layer adapter with
334
+ `linear_graphql` above; it accumulates every page and prints no partial history.
335
+ A read succeeds only after `hasNextPage` is false. Errors, malformed pages, and
336
+ missing or repeated continuation cursors fail the whole read.
337
+
338
+ ```bash
339
+ linear_list_comment_pages() { # issue|project id -> complete JSON node array
340
+ local anchor="$1" id="$2" after=null nodes='[]' seen='[]'
341
+ local query variables response connection cursor
342
+ case "$anchor" in issue|project) ;; *) echo "Error: invalid comment anchor" >&2; return 1 ;; esac
343
+ query='query($id:String!,$after:String){'"$anchor"'(id:$id){comments(first:100,after:$after){pageInfo{hasNextPage endCursor} nodes{id body createdAt url user{name}}}}}'
344
+ while :; do
345
+ variables=$(jq -cn --arg id "$id" --argjson after "$after" '{id:$id,after:$after}') || return 1
346
+ response=$(linear_graphql "$query" "$variables") || return 1
347
+ connection=$(printf '%s' "$response" | jq -ce --arg anchor "$anchor" '
348
+ if (.errors != null and .errors != []) then error("GraphQL comments read failed")
349
+ else .data[$anchor].comments end |
350
+ if (.nodes | type) != "array" or (.pageInfo.hasNextPage | type) != "boolean"
351
+ then error("Incomplete comments page") else . end') || return 1
352
+ nodes=$(jq -cn --argjson prior "$nodes" --argjson page "$connection" '$prior + $page.nodes') || return 1
353
+ if [ "$(printf '%s' "$connection" | jq -r '.pageInfo.hasNextPage')" = false ]; then
354
+ printf '%s\n' "$nodes"
355
+ return 0
356
+ fi
357
+ cursor=$(printf '%s' "$connection" | jq -ce '.pageInfo.endCursor | select(type == "string" and length > 0)') || {
358
+ echo "Error: incomplete comments history; missing cursor" >&2; return 1;
359
+ }
360
+ if jq -en --argjson seen "$seen" --argjson cursor "$cursor" '$seen | index($cursor) != null' >/dev/null; then
361
+ echo "Error: incomplete comments history; repeated cursor" >&2
362
+ return 1
363
+ fi
364
+ seen=$(jq -cn --argjson seen "$seen" --argjson cursor "$cursor" '$seen + [$cursor]') || return 1
365
+ after="$cursor"
366
+ done
367
+ }
368
+ ```
369
+
370
+ Call `linear_list_comment_pages project "$PROJECT_ID"` for `project_id`, or
371
+ `linear_list_comment_pages issue "$ISSUE_ID"` for `issue_id`. The caller receives
372
+ one complete node array; it must not interpret a failed command as zero comments.
335
373
 
336
374
  **Substrate.** The Linear MCP exposes comments on Issues only, so the
337
375
  `project_id` form resolves solely through the tier-1 `LINEAR_API_KEY` + GraphQL
@@ -340,7 +378,7 @@ That is not a gap in Linear: the precedence contract already puts GraphQL ahead
340
378
  of the MCP, so the preferred substrate has always been able to do this. Only
341
379
  this wrapper could not, which is what made callers fabricate an Issue to hold a
342
380
  Project's comments. If tier 1 is unavailable, fail with the layer's standard
343
- `Error:` result naming `save-comment project_id` — do **not** silently degrade
381
+ `Error:` result naming the requested `save-comment project_id` or `list-comments project_id` operation — do **not** silently degrade
344
382
  into creating an Issue to comment on.
345
383
 
346
384
  ## `history` — transition history (read-only)
@@ -182,7 +182,15 @@ A blocker is a **claim with a timestamp, not a fact**. It is written once and go
182
182
 
183
183
  For each pre-work candidate that is **not** in `$READY`:
184
184
 
185
- 1. **Human gate first, and it is absolute.** An Issue carrying the configured human-needed label (`linear.labels.build.human_needed`, default `human-needed`) or a `[lisa-human-gate]` marker in its description is **never** auto-selected, whatever any probe says. Skip it and move on.
185
+ 1. **Read release comments before applying the human gate.** Pass all item comments, labels,
186
+ body and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
187
+ call `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
188
+ and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
189
+ until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
190
+ A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
191
+ comment history cannot discharge a hold. A release removes only the human hold: continue the
192
+ remaining blocker checks below before selecting the item.
193
+
186
194
  2. **Extract the stated discharge condition** from the description or the most recent blocking comment — the sentence naming what has to become true.
187
195
  3. **Probe it.** Machine-testable conditions are the ones that rot fastest and are cheapest to check: a version on trunk (`git show origin/<trunk>:<manifest>`), a published package, a run history (`gh run list`), an advisory's patched status. A condition that is a human decision is not machine-testable — leave it and move on.
188
196
  4. **Classify with the shared helper** so the ordering and the evidence requirement cannot drift per vendor:
@@ -234,8 +242,9 @@ other gate's verdict — however conclusive — may promote an item a person par
234
242
  is the same repair the leaf-only gate already performs for a ready item that must not be
235
243
  dispatched.
236
244
  4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
237
- The hold left durable state behind: the item is out of the queue and flagged as needing a person,
238
- and answering the question does not undo either. Call
245
+ This ready-lane candidate can retain a historical body marker and a human-needed label.
246
+ This step reconciles only candidates still in the ready lane; released holds outside it are
247
+ recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
239
248
  `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
240
249
  and apply exactly the actions it returns: remove the configured human-needed marker, add the
241
250
  configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
@@ -268,10 +277,12 @@ A Linear team can oversee multiple repos (`frontend` / `backend` / `infrastructu
268
277
  1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report.
269
278
  2. **Cheap path first.** Prefer candidates already carrying the `repo:<current>` label. Keep the Phase 2 scan broad so unlabeled Issues are still seen, determined, and stamped.
270
279
  3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
271
- - Carries `repo:<other>` → **skip** (leave it `ready` for that repo's own intake); next candidate.
272
- - **Unlabeled** → determine the target repo(s) from the Issue + code surfaces, then **stamp** `repo:<name>` via `lisa-linear-access operation: save-issue` (resolve/create the label via `list_issue_labels`/`create_issue_label`) so later cycles filter cheaply; re-apply with the now-known repo.
273
- - **Multi-repo leaf → split, never claim.** Run the `repo-scope-split` work-time procedure into single-repo siblings, each created **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
274
- - **Single-repo leaf for the current repo** → fall through to 3a (leaf-only gate) and 3b (claim).
280
+ - **Count distinct repository markers first**: collect all `repo:<name>` labels and, on JIRA, recognized repository components; deduplicate by repository. A container may carry multiple `repo:<name>` labels. Do not split or claim it here; send it to the leaf-only gate.
281
+ - **Multi-repo leaf → split, never claim.** More than one repository takes the work-time split before any wrong-repository skip. Each sibling is **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
282
+ - **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
283
+ - **No repository marker** → determine target repo(s) from the ticket and code, stamp `repo:<name>` through the vendor access layer, and re-apply from the count.
284
+ - **Single-repo leaf for the current repo** → fall through to 3a and 3b.
285
+
275
286
  4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the candidate set is exhausted — exit cleanly on the denominator-stated summary, naming the current repo alongside the swept lanes.
276
287
 
277
288
  #### 3a. Leaf-only claim gate (skip / safe-block containers)
@@ -130,6 +130,16 @@ Select the first ready project returned by Phase 2 and process only that project
130
130
 
131
131
  #### 3a. Claim
132
132
 
133
+ **Preflight project comments before any claim or destination-ticket creation.** Through
134
+ `lisa-linear-access`, resolve an identity-matched tier-1 GraphQL credential and the
135
+ `save-comment project_id` adapter, then read the candidate's complete project comment
136
+ history with `list-comments project_id:<id>`. The issue-only MCP is insufficient for
137
+ this flow. If the required credential, adapter or read is unavailable, return the
138
+ layer's `Error:` naming the project-comment operation and leave the project ready;
139
+ create no tickets and no substitute comment-holder Issue. This is a read-only
140
+ capability preflight, not a test comment. It establishes the available transport;
141
+ later permission changes or write failures still follow the normal error handler.
142
+
133
143
  Transition labels via `lisa-linear-access operation: save-project({id, labels})`: pass the full new label set with `$READY` removed and `$IN_REVIEW` added. This is the idempotency lock — a re-entrant cycle running concurrently won't see this project because its query filters on `label: "$READY"`.
134
144
 
135
145
  If the update fails (permission error, race condition), log it and skip this project. Do not proceed to validation on a project you didn't successfully claim.
@@ -152,7 +162,7 @@ This call also indirectly invokes `lisa-tracker-source-artifacts` (artifact extr
152
162
 
153
163
  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).
154
164
  2. Capture the created ticket keys from the skill's output.
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."`
165
+ 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 the URLs returned by the configured destination tracker. Lead with: `"Ticketed by Claude. Created N tickets — see below. Add the $SHIPPED label to the Linear project after the work is delivered."`
156
166
  4. Transition labels: remove `$IN_REVIEW`, add `$TICKETED` via `save_project`.
157
167
  5. **Run Phase 3e (coverage audit)** before considering this PRD done.
158
168
 
@@ -396,6 +406,6 @@ Before this skill can run against a Linear workspace or team, the team must adop
396
406
  1. Apply the `ready` label (default: `prd-ready`) to projects that are ready for ticketing (replaces the Notion `Status = Ready` flip and the Confluence `prd-ready` page label).
397
407
  2. Reserve `in_review`, `blocked`, `ticketed` (defaults: `prd-in-review`, `prd-blocked`, `prd-ticketed`) for this skill — humans should not set them manually except to recover from an error.
398
408
  3. (Optional but recommended) Add the `draft` and `shipped` labels (defaults: `prd-draft`, `prd-shipped`) for in-progress PRDs and delivered work respectively, so the full lifecycle is visible at a glance.
399
- 4. The labels must exist as **project labels** in Linear (`list_project_labels` should return them). Issue-level labels with the same names won't work; Linear keeps the two label kinds separate.
409
+ 4. The labels must exist as **project labels** in Linear (`list-project-labels` should return them). Issue-level labels with the same names won't work; Linear keeps the two label kinds separate.
400
410
 
401
411
  If the workspace hasn't adopted these labels, the first run exits with a label-convention error (not the idle empty-set message) — this distinguishes a setup issue from a genuinely empty queue so operators know to apply the convention rather than assuming there is no work. See Phase 2 for how the skill detects this case.