@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.55.1",
3
+ "version": "4.55.3",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.55.1",
3
+ "version": "4.55.3",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.55.1",
3
+ "version": "4.55.3",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.55.1",
3
+ "version": "4.55.3",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.55.1",
3
+ "version": "4.55.3",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -16,6 +16,17 @@
16
16
  "all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh",
17
17
  "expo/copy-overwrite/scripts/lib/bounded-spawn.mjs",
18
18
  "expo/copy-overwrite/scripts/lib/invoked-as-script.mjs",
19
+ "plugins/lisa/hooks/block-blind-automerge.sh",
20
+ "plugins/lisa/hooks/block-direct-issue-create.sh",
21
+ "plugins/lisa/hooks/block-instruction-file-edits.sh",
22
+ "plugins/lisa/hooks/block-managed-file-edits.sh",
23
+ "plugins/lisa/hooks/block-no-verify.sh",
24
+ "plugins/lisa/hooks/block-shell-json-parsing.sh",
25
+ "plugins/lisa/hooks/guard-dedupe.bash",
26
+ "plugins/lisa/hooks/parity-safety-net-heredoc.py",
27
+ "plugins/lisa/hooks/parity-safety-net.sh",
28
+ "plugins/lisa/hooks/worktree-binding-guard.mjs",
29
+ "plugins/lisa/hooks/worktree-binding-guard.sh",
19
30
  "rails/copy-overwrite/scripts/check-threshold-ratchet.mjs",
20
31
  "rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs",
21
32
  "rails/copy-overwrite/scripts/threshold-ratchet-families.mjs",
@@ -280,7 +280,8 @@ NODE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_=-]+$")
280
280
  NODE_QUERY = (
281
281
  "query($id:ID!){node(id:$id){... on PullRequest"
282
282
  "{number url reviewDecision state baseRefName "
283
- "commits(last:1){nodes{commit{statusCheckRollup{contexts(first:100){nodes{"
283
+ "commits(last:1){nodes{commit{statusCheckRollup{contexts(first:100){"
284
+ "pageInfo{hasNextPage} nodes{"
284
285
  "__typename ... on CheckRun{name conclusion} "
285
286
  "... on StatusContext{context state}"
286
287
  "}}}}}}}}}"
@@ -294,9 +295,13 @@ NODE_QUERY = (
294
295
  # checks, which is genuinely not failing and gets an empty list. A node without
295
296
  # the scaffolding is a probe that never asked, and it must leave the key absent
296
297
  # so the re-target path can tell the two apart instead of reading both as green.
298
+ # A truncated page is equally unreadable: a failing check may be on the next
299
+ # page, so a green first page cannot authorize an uncovered-base re-target.
297
300
  NODE_JQ = (
298
301
  "if .data.node == null then null else .data.node as $n "
299
- "| if ($n | has(\"commits\")) then ($n | del(.commits)) "
302
+ "| if ($n.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.hasNextPage == true) "
303
+ "then ($n | del(.commits)) "
304
+ "elif ($n | has(\"commits\")) then ($n | del(.commits)) "
300
305
  "+ {statusCheckRollup: "
301
306
  "((($n.commits.nodes[0].commit.statusCheckRollup.contexts.nodes)) // [])} "
302
307
  "else $n end end"
@@ -1024,9 +1029,9 @@ not read the pull request's checks.
1024
1029
 
1025
1030
  That ref has ZERO required status checks, so the one thing standing between the
1026
1031
  move and a permission-free gate bypass is whether the PR is currently failing —
1027
- and the probe returned no `statusCheckRollup` at all. An absent rollup is not an
1028
- empty one. Reporting the move as the sanctioned green-PR batching case here
1029
- would be a verdict about a question that was never asked.
1032
+ and the probe returned no complete `statusCheckRollup`. An absent or truncated
1033
+ rollup is not an empty one. Reporting the move as the sanctioned green-PR
1034
+ batching case here would claim a result the probe did not establish.
1030
1035
 
1031
1036
  Re-target through `gh pr edit --base` instead, which reads the checks, or fix
1032
1037
  the probe. Do not report the PR as batched until something has actually looked.
@@ -2106,6 +2106,10 @@ def unparseable_reads_only(text):
2106
2106
  Returns:
2107
2107
  True when every segment's command word is a known reader.
2108
2108
  """
2109
+ # Unlexable operands cannot be certified as data when shell substitutions
2110
+ # may execute inside them. Preserve the plain apostrophe reader exemption.
2111
+ if any(operator in text for operator in ("$(", "`", "<(", ">(")):
2112
+ return False
2109
2113
  words = raw_command_words(text)
2110
2114
  return bool(words) and all(word in READ_ONLY_PROGRAMS for word in words)
2111
2115
 
@@ -566,6 +566,7 @@ EOF
566
566
  import os
567
567
  import re
568
568
  import shlex
569
+ import sys
569
570
 
570
571
  command = os.environ.get("MANAGED_EDIT_COMMAND", "")
571
572
  project = os.environ.get("MANAGED_EDIT_PROJECT", "") or os.getcwd()
@@ -576,6 +577,7 @@ project = os.environ.get("MANAGED_EDIT_PROJECT", "") or os.getcwd()
576
577
  FOLLOW_MAX_BYTES = 262144
577
578
  FOLLOW_MAX_FILES = 8
578
579
  FOLLOW_MAX_DEPTH = 3
580
+ ENV_SPLIT_UNRESOLVED = 42
579
581
 
580
582
  # Spelled with chr() rather than backslash escapes on purpose. This source is
581
583
  # embedded in a shell heredoc and copied verbatim through several generators
@@ -607,7 +609,7 @@ FOLLOW_WRAPPERS = {
607
609
  # positional count: the walk below re-enters its assignment skip on the
608
610
  # next iteration and steps over as many as are present.
609
611
  "env": (
610
- frozenset({"-C", "--chdir", "-P", "-S", "--split-string", "-u", "--unset"}),
612
+ frozenset({"-C", "--chdir", "-P", "-u", "--unset"}),
611
613
  0,
612
614
  ),
613
615
  "exec": (frozenset({"-a"}), 0),
@@ -741,6 +743,31 @@ def statements(tokens):
741
743
  return grouped
742
744
 
743
745
 
746
+ class UnresolvedEnvSplit(ValueError):
747
+ """Split-string syntax whose executed arguments cannot be proven here."""
748
+
749
+
750
+ def parse_env_split(split_string):
751
+ """Parse only the env -S subset shared with ordinary quoted arguments.
752
+
753
+ GNU env has its own escapes, comments and environment interpolation. Do
754
+ not pretend shlex implements those, or invent environment values in a
755
+ pre-execution guard. The operator can spell the resulting command directly.
756
+
757
+ Args:
758
+ split_string: The literal argument supplied to env's split option.
759
+
760
+ Returns:
761
+ Arguments for the supported subset; otherwise raises UnresolvedEnvSplit.
762
+ """
763
+ if any(marker in split_string for marker in (BACKSLASH, "#", "$", chr(96), chr(11), chr(12))):
764
+ raise UnresolvedEnvSplit("escapes, comments, shell substitution, variable expansion or control whitespace")
765
+ try:
766
+ return shlex.split(split_string, comments=False, posix=True)
767
+ except ValueError as error:
768
+ raise UnresolvedEnvSplit("unbalanced quoting") from error
769
+
770
+
744
771
  def command_word(statement):
745
772
  """The program a statement runs, and the tokens after it.
746
773
 
@@ -757,6 +784,7 @@ def command_word(statement):
757
784
  its command word is itself the executed script.
758
785
  """
759
786
  index = 0
787
+ split_expansions = 0
760
788
  while index < len(statement):
761
789
  token = statement[index]
762
790
  if "=" in token and not token.startswith(("=", "-")):
@@ -772,6 +800,36 @@ def command_word(statement):
772
800
  if option == "--":
773
801
  index += 1
774
802
  break
803
+ # env -S inserts the split string back into env's argument list;
804
+ # it is executable input, not an option value to discard. Keep
805
+ # shell -c's quoted operand intact while expanding the env layer.
806
+ # The known no-operand flags can be combined before S (-vS/-ivS).
807
+ # Stop at S: the rest belongs to its argument, not more flags.
808
+ short_split = re.match(r"^-[iv0]*S(.*)$", option)
809
+ if program == "env" and (
810
+ option == "--split-string"
811
+ or option.startswith("--split-string=")
812
+ or short_split is not None
813
+ ):
814
+ consumed = 1
815
+ if option == "--split-string" or (
816
+ short_split is not None and not short_split.group(1)
817
+ ):
818
+ if index + 1 >= len(statement):
819
+ raise UnresolvedEnvSplit("missing split-string operand")
820
+ split_string = statement[index + 1]
821
+ consumed = 2
822
+ elif option.startswith("--split-string="):
823
+ split_string = option.split("=", 1)[1]
824
+ else:
825
+ split_string = short_split.group(1)
826
+ if split_expansions >= 64:
827
+ raise UnresolvedEnvSplit("nested split-string limit")
828
+ expanded = parse_env_split(split_string)
829
+ statement = [token] + expanded + statement[index + consumed :]
830
+ split_expansions += 1
831
+ index = 0
832
+ break
775
833
  index += 2 if option in separate else 1
776
834
  index += positional
777
835
  return (None, None, [])
@@ -985,7 +1043,11 @@ def collect(text, depth, seen, out):
985
1043
 
986
1044
 
987
1045
  targets = []
988
- collect(command, 0, set(), targets)
1046
+ try:
1047
+ collect(command, 0, set(), targets)
1048
+ except UnresolvedEnvSplit as error:
1049
+ sys.stderr.write(str(error) + NEWLINE)
1050
+ sys.exit(ENV_SPLIT_UNRESOLVED)
989
1051
  for target in targets:
990
1052
  cleaned = target.strip().strip("'\"")
991
1053
  if cleaned:
@@ -1003,6 +1065,15 @@ PY
1003
1065
  else
1004
1066
  analyzer_status=$?
1005
1067
  fi
1068
+ if [ "$analyzer_status" -eq 42 ]; then
1069
+ printf 'Blocked: cannot resolve env --split-string for managed-file protection.\n' >&2
1070
+ printf 'Use an explicit command without split-string escapes, comments or variable expansion.\n' >&2
1071
+ while IFS= read -r analyzer_line; do
1072
+ [ -n "$analyzer_line" ] && printf ' %s\n' "$analyzer_line" >&2
1073
+ done <"$analyzer_stderr"
1074
+ rm -f "$analyzer_stderr"
1075
+ exit 2
1076
+ fi
1006
1077
  if [ "$analyzer_status" -ne 0 ]; then
1007
1078
  printf 'block-managed-file-edits: Bash analyzer failed (exit %s); Bash write protection is NOT active\n' "$analyzer_status" >&2
1008
1079
  while IFS= read -r analyzer_line; do
@@ -51,12 +51,9 @@
51
51
  # refusal reaching the agent without the message that explains it. On a
52
52
  # refusal every channel evaluates and speaks exactly as it does today.
53
53
  #
54
- # COST ON THE PATH THAT GETS NO BENEFIT. A host with one channel must not pay
55
- # for a mechanism it cannot use. The channel check is builtins only — one small
56
- # file read, no subshell, no fork — and returns before the digest is computed
57
- # unless a second channel has actually been seen. The digest, and the one `stat`
58
- # that feeds it the per-call discriminator, are reached only where a second
59
- # channel is live, which is exactly where they are repaid.
54
+ # State ownership, modes and ancestry are verified before channel discovery.
55
+ # After that validation the channel check uses only builtins, and returns
56
+ # before digesting code or sizing the transcript unless another channel is live.
60
57
 
61
58
  # Key this guard would memoise under, once computed. Empty means "record
62
59
  # nothing on exit".
@@ -74,14 +71,25 @@ lisa_guard_memo_ready=0
74
71
  # Digest tool for the memo key, resolved once. Empty disables the memo.
75
72
  lisa_guard_memo_digest_tool=""
76
73
 
77
- # Whether a directory is a real directory this user owns, and not a symlink —
78
- # builtins only, so this costs no process.
79
- #
80
- # `-O` is the load-bearing test: a memo planted by another user would suppress a
81
- # refusal, so a directory this user does not own is never used. The dispatcher
82
- # validates the whole parent chain before exporting `LISA_GUARD_MEMO_DIR`; this
83
- # re-checks the leaf rather than trusting the environment variable, because an
84
- # exported path is an input like any other.
74
+ # Read ownership and all permission bits without accepting output from a
75
+ # failed platform-specific stat invocation.
76
+ # $1 - directory; sets lisa_guard_memo_owner and lisa_guard_memo_mode
77
+ lisa_guard_memo_stat() {
78
+ local facts=""
79
+ facts="$(stat -c '%u %a' "$1" 2>/dev/null)" ||
80
+ facts="$(stat -f '%u %p' "$1" 2>/dev/null)" || return 1
81
+ lisa_guard_memo_owner="${facts%% *}"
82
+ lisa_guard_memo_mode="${facts#* }"
83
+ case "$lisa_guard_memo_owner:$lisa_guard_memo_mode" in
84
+ *[!0-9:]* | :* | *:) return 1 ;;
85
+ esac
86
+ case "$lisa_guard_memo_mode" in *[!0-7]*) return 1 ;; esac
87
+ lisa_guard_memo_mode=$((8#$lisa_guard_memo_mode & 8#7777))
88
+ }
89
+
90
+ # Memo leaves must be private even when a sticky shared temp ancestor is safe.
91
+ # Ownership alone allows another local account to plant a session/allow file
92
+ # in an owned but group- or world-writable directory.
85
93
  #
86
94
  # $1 - candidate directory
87
95
  lisa_guard_memo_dir_usable() {
@@ -89,23 +97,42 @@ lisa_guard_memo_dir_usable() {
89
97
  [ -d "$1" ] || return 1
90
98
  [ ! -L "$1" ] || return 1
91
99
  [ -O "$1" ] || return 1
100
+ lisa_guard_memo_stat "$1" || return 1
101
+ [ $((lisa_guard_memo_mode & 8#0022)) -eq 0 ]
102
+ }
103
+
104
+ # Resolve parents physically and verify every ancestor. Plugin hooks do not
105
+ # inherit the dispatcher's trust walk, and exported paths are still inputs.
106
+ # $1 - candidate memo base; sets lisa_guard_memo_base only on success
107
+ lisa_guard_memo_trust_base() {
108
+ lisa_guard_memo_dir_usable "$1" || return 1
109
+ local physical=""
110
+ physical="$(cd "$1" 2>/dev/null && pwd -P)" || return 1
111
+ local current="$physical"
112
+ while :; do
113
+ lisa_guard_memo_stat "$current" || return 1
114
+ [ "$lisa_guard_memo_owner" = 0 ] || [ -O "$current" ] || return 1
115
+ if [ $((lisa_guard_memo_mode & 8#0022)) -ne 0 ] &&
116
+ [ $((lisa_guard_memo_mode & 8#1000)) -eq 0 ]; then
117
+ return 1
118
+ fi
119
+ [ "$current" != / ] || break
120
+ current="${current%/*}"
121
+ [ -n "$current" ] || current=/
122
+ done
123
+ lisa_guard_memo_base="$physical"
92
124
  }
93
125
 
94
126
  # Establish the memo base directory.
95
127
  #
96
- # Preferred source is `LISA_GUARD_MEMO_DIR`, exported by the dispatcher, which
97
- # has already resolved `TMPDIR` physically and walked every parent for ownership
98
- # and mode. Guards it spawns therefore pay nothing for that walk. A guard
99
- # reached by the plugin channel has no such parent, so it creates the directory
100
- # itself under `TMPDIR` — private by umask, and used only when this user owns
101
- # it. If neither works the memo is unavailable and every guard evaluates, which
102
- # is today's behaviour.
128
+ # Preferred source is `LISA_GUARD_MEMO_DIR`, exported by the dispatcher. Both
129
+ # this input and the plugin channel's TMPDIR fallback receive the same trust
130
+ # checks. Missing state is created privately; untrusted state disables memo use.
103
131
  lisa_guard_memo_resolve_base() {
104
132
  [ -z "$lisa_guard_memo_base" ] || return 0
105
133
 
106
134
  local candidate="${LISA_GUARD_MEMO_DIR:-}"
107
- if lisa_guard_memo_dir_usable "$candidate"; then
108
- lisa_guard_memo_base="$candidate"
135
+ if lisa_guard_memo_trust_base "$candidate"; then
109
136
  return 0
110
137
  fi
111
138
 
@@ -118,8 +145,7 @@ lisa_guard_memo_resolve_base() {
118
145
  if [ ! -e "$candidate" ] && [ ! -L "$candidate" ]; then
119
146
  (umask 077 && mkdir -p "$candidate") 2>/dev/null || true
120
147
  fi
121
- if lisa_guard_memo_dir_usable "$candidate"; then
122
- lisa_guard_memo_base="$candidate"
148
+ if lisa_guard_memo_trust_base "$candidate"; then
123
149
  return 0
124
150
  fi
125
151
  return 1
@@ -165,6 +191,7 @@ lisa_guard_memo_sweep() {
165
191
  #
166
192
  # $1 - guard name, used only to name the memo file
167
193
  # $2 - the raw tool payload this guard was handed on stdin
194
+ # Remaining arguments - files containing delegated verdict code
168
195
  lisa_guard_dedupe() {
169
196
  local guard_name="${1:-}"
170
197
  local payload="${2:-}"
@@ -194,8 +221,7 @@ lisa_guard_dedupe() {
194
221
  fresh_session=1
195
222
  fi
196
223
  fi
197
- [ -d "$session_dir" ] || return 0
198
- [ ! -L "$session_dir" ] || return 0
224
+ lisa_guard_memo_dir_usable "$session_dir" || return 0
199
225
 
200
226
  # Swept once, by the process that created the session directory, so a
201
227
  # long-lived machine does not accumulate memo state. Off the hot path by
@@ -278,11 +304,18 @@ lisa_guard_dedupe() {
278
304
  case "$transcript_size" in "" | *[!0-9]*) return 0 ;; esac
279
305
 
280
306
  # One command substitution, covering everything the verdict depends on: the
281
- # guard's own bytes, this library's bytes, the payload, and which call it is.
307
+ # guard's own bytes, this library, delegated code, payload, and call identity.
308
+ # Keep literal bytes (including trailing newlines), and propagate every read
309
+ # failure. A successful digest of a partial stream is not proof of identity.
282
310
  local key=""
283
311
  key="$(
312
+ set -o pipefail
284
313
  {
285
- cat "$self_script" "${BASH_SOURCE[0]}" 2>/dev/null
314
+ local source_file=""
315
+ for source_file in "$self_script" "${BASH_SOURCE[0]}" "${@:3}"; do
316
+ cat "$source_file" 2>/dev/null || exit 1
317
+ printf '\0'
318
+ done
286
319
  printf '\n%s\n' "$payload"
287
320
  printf '%s\n' "$transcript_size"
288
321
  } | if [ "$lisa_guard_memo_digest_tool" = "shasum" ]; then
@@ -293,6 +326,7 @@ lisa_guard_dedupe() {
293
326
  )" || key=""
294
327
  key="${key%% *}"
295
328
  case "$key" in "" | *[!0-9a-f]*) return 0 ;; esac
329
+ [ "${#key}" -eq 64 ] || return 0
296
330
 
297
331
  # One memo file per guard per session, rewritten as the call moves on, so the
298
332
  # state directory stays a fixed size however long a session runs. A saturated
@@ -136,7 +136,8 @@ if [ -r "$lisa_guard_dedupe_lib" ]; then
136
136
  # shellcheck source=guard-dedupe.bash
137
137
  . "$lisa_guard_dedupe_lib"
138
138
  trap 'lisa_guard_dedupe_record $?' EXIT
139
- lisa_guard_dedupe parity-safety-net "$input"
139
+ lisa_guard_dedupe parity-safety-net "$input" \
140
+ "$lisa_guard_hook_dir/parity-safety-net-heredoc.py"
140
141
  fi
141
142
 
142
143
  tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
@@ -54,7 +54,8 @@ if [ -r "$lisa_guard_dedupe_lib" ]; then
54
54
  # shellcheck source=guard-dedupe.bash
55
55
  . "$lisa_guard_dedupe_lib"
56
56
  trap 'lisa_guard_dedupe_record $?' EXIT
57
- lisa_guard_dedupe worktree-binding-guard "$input"
57
+ lisa_guard_dedupe worktree-binding-guard "$input" \
58
+ "$lisa_guard_hook_dir/worktree-binding-guard.mjs"
58
59
  fi
59
60
 
60
61
  if ! command -v node >/dev/null 2>&1; then
@@ -68,6 +68,7 @@ Paths are relative to this file.
68
68
 
69
69
  | Slug | Read it when | Body |
70
70
  |---|---|---|
71
+ | `operational-hazards` | looking up or publishing an active operational hazard that other sessions must see | [../reference/operational-hazards.md](../reference/operational-hazards.md) |
71
72
  | `automation-runbook-contract` | registering a loop, or ending any flow with its run outcome | [../reference/automation-runbook-contract.md](../reference/automation-runbook-contract.md) |
72
73
  | `convergent-review` | reviewing a PR or resolving review findings | [../reference/convergent-review.md](../reference/convergent-review.md) |
73
74
  | `credential-substrate-precedence` | writing or editing an `*-access` skill | [../reference/credential-substrate-precedence.md](../reference/credential-substrate-precedence.md) |
@@ -7,7 +7,7 @@ These are mandatory disciplines that apply to every session. Full prose, JIRA de
7
7
  You are factory machinery, not a chat assistant. Three consequences bind every session:
8
8
 
9
9
  - **Do not pause mid-flow to ask a human whether to proceed.** Handoff happens at the gates — the ready-role flips and intake's adversarial validation — never in the middle of a flow.
10
- - **Every flow must work headless**: no interactive prompts, idempotent re-runs, clean exits on empty queues. Flows run under native schedulers as often as under a human.
10
+ - **Every admitted flow must work headless**: no interactive prompts after admission, idempotent re-runs, clean exits on empty queues. Resolve required input before admission: interactive requests may need clarification; unattended requests with missing input return `recovery-required` without guessing or applying side effects. Flows run under native schedulers as often as under a human.
11
11
  - **Never weaken a gate to get work through it — fix the work.**
12
12
 
13
13
  The model these follow from (the four factories, the gate, the loops, the brownfield on-ramp) is [reference/factory-model.md](../reference/factory-model.md); read it when you need the shape rather than the obligations.
@@ -16,6 +16,8 @@ The model these follow from (the four factories, the gate, the loops, the brownf
16
16
 
17
17
  Treat every request as potentially underspecified. Before starting any work:
18
18
 
19
+ **Unattended: override stop-and-ask below.** Missing input means `recovery-required`: no guessing, prompts or side effects. Ask only before interactive admission.
20
+
19
21
  1. Identify ambiguities that would prevent completion. If any exist, stop and ask.
20
22
  2. Identify open questions whose answers would change your approach. If any exist, stop and ask.
21
23
  3. Define how you will empirically verify the work is complete by USING the resulting software, not just running tests. If you cannot define this, stop and ask.
@@ -25,14 +25,25 @@ The result is one-directional propagation. **New guidance travels; corrections d
25
25
  - **Record every withdrawal in the ledger, with one command.** Retracting a claim you circulated,
26
26
  wrote down, or published is not done until this has run:
27
27
 
28
+ ```sh
29
+ node "$CLAUDE_PLUGIN_ROOT/hooks/withdrawn-rulings.mjs" --withdraw "<id>" \
30
+ --claim "<the withdrawn claim, verbatim>" \
31
+ --because "<what disproved it>" \
32
+ --derived "<an artifact you left standing on it>"
28
33
  ```
29
- node "$CLAUDE_PLUGIN_ROOT/hooks/withdrawn-rulings.mjs" --withdraw <id> \
34
+
35
+ If the audit found no surviving derived artifact, use this alternative:
36
+
37
+ ```sh
38
+ node "$CLAUDE_PLUGIN_ROOT/hooks/withdrawn-rulings.mjs" --withdraw "<id>" \
30
39
  --claim "<the withdrawn claim, verbatim>" \
31
40
  --because "<what disproved it>" \
32
- --derived "<an artifact you left standing on it>" ... | --derived none \
33
- [--superseded-by <id>] [--reached <channel> ...]
41
+ --derived none
34
42
  ```
35
43
 
44
+ Repeat `--derived "<artifact>"` for additional artifacts. Either form may also
45
+ include `--superseded-by "<id>"` and repeated `--reached "<channel>"` arguments.
46
+
36
47
  The verbatim claim is required and the command refuses without it: **a tombstone the holder of the
37
48
  claim cannot recognise reaches them without reaching them.**
38
49
 
@@ -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
  ## Automation Runbook 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
  ## BDD Behavior Contract & E2E Coverage (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
  ## Blocker Containment (load-bearing)
8
8
 
@@ -39,7 +39,7 @@ A false negative (left blocked) costs a cycle and is visible. A false positive (
39
39
 
40
40
  ## The one carve-out: a blocker with no code
41
41
 
42
- A dependency need not deliver code. A blocker **closed as completed** that positively declares no code deliverable — `Target Backend Environment: None — no runtime behavior change` (doc-only / config-only / type-only), no linked PR, no merge commit — is **cleared**, because there is no artifact whose location could matter.
42
+ A dependency need not deliver code. A blocker **closed as completed** that positively declares no code deliverable — `## Target Backend Environment` reading `None — no runtime behavior change: <kind>` (`doc-only` / `config-only` / `type-only`), no linked PR, no merge commit — is **cleared**, because there is no artifact whose location could matter.
43
43
 
44
44
  This requires a **positive determination**, never an absence. "I could not find a PR" is fail-closed under the rule above; "the item declares it ships no code" is this carve-out. Collapsing the two turns the carve-out into a universal bypass.
45
45
 
@@ -131,7 +131,7 @@ A blocker is cleared under this carve-out when **all** of the following hold:
131
131
 
132
132
  1. it is **closed as completed** (not `not planned` — see `rejection-detection`, where *not planned* is a durable decline);
133
133
  2. it **positively declares no code deliverable** — `## Target Backend Environment` reading `None — no runtime behavior change: doc-only` (or `config-only` / `type-only`), per the grammar `derived-branch-plan` already defines;
134
- 3. it has **no linked merged PR**. If it has one, the normal containment test applies regardless of what the section declares — the code is the authority over the prose.
134
+ 3. it has **no linked PR and no merge commit**. Any linked PR requires the normal containment test regardless of what the section declares; an open or unmerged PR remains blocking — the code is the authority over the prose.
135
135
 
136
136
  This is a **positive determination, never an absence.** "I could not find a PR" is `no-pr` in the fail-closed table above. "The item declares that it ships no code" is this carve-out. Collapsing the two converts a narrow carve-out into a universal bypass, and it is the single most likely way for this rule to be implemented wrongly.
137
137
 
@@ -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
  ## Claim-Time Archaeology (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
  ## Claim → Evidence Mapping 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
  ## Claim-Time Guards (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
  ## Control Reachability — A Prescribed Control Must Reach the Changed Path (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
  ## Convergent Review
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
  ## Credential-Substrate Precedence (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
  ## Dependency Decisions (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
  ## Dependency Internalization Kit (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
  ## Dependency Trust Classes (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
  ## Deployed-State Readback (load-bearing)
8
8