@codyswann/lisa 4.49.0 → 4.50.1

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 (409) hide show
  1. package/all/copy-overwrite/scripts/check-conflict-markers.mjs +4 -1
  2. package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +163 -0
  3. package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +178 -1
  4. package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +89 -10
  5. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +44 -0
  6. package/all/copy-overwrite/scripts/lisa-lint-staged-preflight.mjs +1 -1
  7. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +24 -24
  8. package/all/copy-overwrite/scripts/lisa-work-item.mjs +490 -81
  9. package/cdk/package-lisa/package.lisa.json +45 -15
  10. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  11. package/dist/core/lisa-owned-hash-ledger.js +76 -0
  12. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  13. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  14. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  15. package/dist/core/upstream-evidence-manifest.js +121 -227
  16. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  17. package/dist/opencode/plugin-templates/lisa-block-direct-issue-create.ts +45 -1
  18. package/dist/opencode/plugin-templates/parity-safety-net.sh +44 -0
  19. package/expo/package-lisa/package.lisa.json +110 -53
  20. package/harper-fabric/package-lisa/package.lisa.json +62 -32
  21. package/nestjs/package-lisa/package.lisa.json +57 -27
  22. package/npm-package/package-lisa/package.lisa.json +43 -7
  23. package/package.json +11 -7
  24. package/phaser/copy-overwrite/ast-grep/rules/no-day-truncating-file-age-predicate.yml +50 -0
  25. package/phaser/package-lisa/package.lisa.json +62 -32
  26. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  28. package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
  29. package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +4 -0
  30. package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +4 -0
  31. package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +4 -0
  32. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +4 -1
  33. package/plugins/lisa/hooks/block-direct-issue-create.sh +89 -10
  34. package/plugins/lisa/hooks/discharge-work-item-gates.sh +7 -1
  35. package/plugins/lisa/hooks/parity-safety-net.sh +44 -0
  36. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +12 -0
  37. package/plugins/lisa/rules/eager/00-rule-index.md +79 -0
  38. package/plugins/lisa/rules/eager/base-rules.md +10 -0
  39. package/plugins/lisa/rules/eager/config-resolution.md +1 -88
  40. package/plugins/lisa/rules/reference/automation-runbook-contract.md +97 -0
  41. package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +56 -0
  42. package/plugins/lisa/rules/reference/blocker-containment.md +58 -0
  43. package/plugins/lisa/rules/reference/claim-archaeology.md +42 -0
  44. package/plugins/lisa/rules/reference/claim-evidence-mapping.md +83 -0
  45. package/plugins/lisa/rules/reference/claim-time-guards.md +37 -0
  46. package/plugins/lisa/rules/reference/config-resolution.md +97 -0
  47. package/plugins/lisa/rules/reference/control-reachability.md +44 -0
  48. package/plugins/lisa/rules/reference/convergent-review.md +31 -0
  49. package/plugins/lisa/rules/reference/credential-substrate-precedence.md +57 -0
  50. package/plugins/lisa/rules/reference/dependency-decision-records.md +37 -0
  51. package/plugins/lisa/rules/reference/dependency-internalization-kit.md +47 -0
  52. package/plugins/lisa/rules/reference/dependency-trust-classes.md +48 -0
  53. package/plugins/lisa/rules/reference/deployed-state-readback.md +52 -0
  54. package/plugins/lisa/rules/reference/derived-branch-plan.md +52 -0
  55. package/plugins/lisa/rules/reference/design-source-of-truth.md +43 -0
  56. package/plugins/lisa/rules/reference/design-value-binding.md +103 -0
  57. package/plugins/lisa/rules/reference/documentation-source-paths.md +18 -0
  58. package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +75 -0
  59. package/plugins/lisa/rules/reference/observability-audit.md +20 -0
  60. package/plugins/lisa/rules/reference/prd-definition-of-ready.md +37 -0
  61. package/plugins/lisa/rules/reference/prd-lifecycle-rollup.md +36 -0
  62. package/plugins/lisa/rules/reference/pre-flight-autofill.md +88 -0
  63. package/plugins/lisa/rules/reference/promotion-contract.md +21 -0
  64. package/plugins/lisa/rules/reference/readiness-rubric.md +63 -0
  65. package/plugins/lisa/rules/reference/ready-role-filing.md +34 -0
  66. package/plugins/lisa/rules/reference/rejection-detection.md +69 -0
  67. package/plugins/lisa/rules/reference/repo-scope-split.md +48 -0
  68. package/plugins/lisa/rules/reference/reset-seed-coverage.md +55 -0
  69. package/plugins/lisa/rules/reference/usage-accounting.md +38 -0
  70. package/plugins/lisa/rules/reference/work-item-definition-of-ready.md +32 -0
  71. package/plugins/lisa/scripts/intake-blocker-reprobe.mjs +158 -1
  72. package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
  73. package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +4 -0
  74. package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +4 -0
  75. package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +4 -0
  76. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +4 -1
  77. package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +89 -10
  78. package/plugins/lisa-agy/hooks/parity-safety-net.sh +44 -0
  79. package/plugins/lisa-agy/plugin.json +1 -1
  80. package/plugins/lisa-agy/scripts/intake-blocker-reprobe.mjs +158 -1
  81. package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
  82. package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +4 -0
  83. package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +4 -0
  84. package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +4 -0
  85. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +4 -1
  86. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  88. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  89. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +89 -10
  93. package/plugins/lisa-copilot/hooks/discharge-work-item-gates.sh +7 -1
  94. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +44 -0
  95. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +12 -0
  96. package/plugins/lisa-copilot/rules/eager/00-rule-index.md +79 -0
  97. package/plugins/lisa-copilot/rules/eager/base-rules.md +10 -0
  98. package/plugins/lisa-copilot/rules/eager/config-resolution.md +1 -88
  99. package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +97 -0
  100. package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +56 -0
  101. package/plugins/lisa-copilot/rules/reference/blocker-containment.md +58 -0
  102. package/plugins/lisa-copilot/rules/reference/claim-archaeology.md +42 -0
  103. package/plugins/lisa-copilot/rules/reference/claim-evidence-mapping.md +83 -0
  104. package/plugins/lisa-copilot/rules/reference/claim-time-guards.md +37 -0
  105. package/plugins/lisa-copilot/rules/reference/config-resolution.md +97 -0
  106. package/plugins/lisa-copilot/rules/reference/control-reachability.md +44 -0
  107. package/plugins/lisa-copilot/rules/reference/convergent-review.md +31 -0
  108. package/plugins/lisa-copilot/rules/reference/credential-substrate-precedence.md +57 -0
  109. package/plugins/lisa-copilot/rules/reference/dependency-decision-records.md +37 -0
  110. package/plugins/lisa-copilot/rules/reference/dependency-internalization-kit.md +47 -0
  111. package/plugins/lisa-copilot/rules/reference/dependency-trust-classes.md +48 -0
  112. package/plugins/lisa-copilot/rules/reference/deployed-state-readback.md +52 -0
  113. package/plugins/lisa-copilot/rules/reference/derived-branch-plan.md +52 -0
  114. package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +43 -0
  115. package/plugins/lisa-copilot/rules/reference/design-value-binding.md +103 -0
  116. package/plugins/lisa-copilot/rules/reference/documentation-source-paths.md +18 -0
  117. package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +75 -0
  118. package/plugins/lisa-copilot/rules/reference/observability-audit.md +20 -0
  119. package/plugins/lisa-copilot/rules/reference/prd-definition-of-ready.md +37 -0
  120. package/plugins/lisa-copilot/rules/reference/prd-lifecycle-rollup.md +36 -0
  121. package/plugins/lisa-copilot/rules/reference/pre-flight-autofill.md +88 -0
  122. package/plugins/lisa-copilot/rules/reference/promotion-contract.md +21 -0
  123. package/plugins/lisa-copilot/rules/reference/readiness-rubric.md +63 -0
  124. package/plugins/lisa-copilot/rules/reference/ready-role-filing.md +34 -0
  125. package/plugins/lisa-copilot/rules/reference/rejection-detection.md +69 -0
  126. package/plugins/lisa-copilot/rules/reference/repo-scope-split.md +48 -0
  127. package/plugins/lisa-copilot/rules/reference/reset-seed-coverage.md +55 -0
  128. package/plugins/lisa-copilot/rules/reference/usage-accounting.md +38 -0
  129. package/plugins/lisa-copilot/rules/reference/work-item-definition-of-ready.md +32 -0
  130. package/plugins/lisa-copilot/scripts/intake-blocker-reprobe.mjs +158 -1
  131. package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
  132. package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +4 -0
  133. package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +4 -0
  134. package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +4 -0
  135. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +4 -1
  136. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  137. package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +89 -10
  138. package/plugins/lisa-cursor/hooks/discharge-work-item-gates.sh +7 -1
  139. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +44 -0
  140. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +12 -0
  141. package/plugins/lisa-cursor/rules/00-rule-index.mdc +84 -0
  142. package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +97 -0
  143. package/plugins/lisa-cursor/rules/base-rules.mdc +10 -0
  144. package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +56 -0
  145. package/plugins/lisa-cursor/rules/blocker-containment-reference.mdc +58 -0
  146. package/plugins/lisa-cursor/rules/claim-archaeology-reference.mdc +42 -0
  147. package/plugins/lisa-cursor/rules/claim-evidence-mapping-reference.mdc +83 -0
  148. package/plugins/lisa-cursor/rules/claim-time-guards-reference.mdc +37 -0
  149. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +97 -0
  150. package/plugins/lisa-cursor/rules/config-resolution.mdc +1 -88
  151. package/plugins/lisa-cursor/rules/control-reachability-reference.mdc +44 -0
  152. package/plugins/lisa-cursor/rules/convergent-review-reference.mdc +31 -0
  153. package/plugins/lisa-cursor/rules/credential-substrate-precedence-reference.mdc +57 -0
  154. package/plugins/lisa-cursor/rules/dependency-decision-records-reference.mdc +37 -0
  155. package/plugins/lisa-cursor/rules/dependency-internalization-kit-reference.mdc +47 -0
  156. package/plugins/lisa-cursor/rules/dependency-trust-classes-reference.mdc +48 -0
  157. package/plugins/lisa-cursor/rules/deployed-state-readback-reference.mdc +52 -0
  158. package/plugins/lisa-cursor/rules/derived-branch-plan-reference.mdc +52 -0
  159. package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +43 -0
  160. package/plugins/lisa-cursor/rules/design-value-binding-reference.mdc +103 -0
  161. package/plugins/lisa-cursor/rules/documentation-source-paths-reference.mdc +18 -0
  162. package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +75 -0
  163. package/plugins/lisa-cursor/rules/observability-audit-reference.mdc +20 -0
  164. package/plugins/lisa-cursor/rules/prd-definition-of-ready-reference.mdc +37 -0
  165. package/plugins/lisa-cursor/rules/prd-lifecycle-rollup-reference.mdc +36 -0
  166. package/plugins/lisa-cursor/rules/pre-flight-autofill-reference.mdc +88 -0
  167. package/plugins/lisa-cursor/rules/promotion-contract-reference.mdc +21 -0
  168. package/plugins/lisa-cursor/rules/readiness-rubric-reference.mdc +63 -0
  169. package/plugins/lisa-cursor/rules/ready-role-filing-reference.mdc +34 -0
  170. package/plugins/lisa-cursor/rules/rejection-detection-reference.mdc +69 -0
  171. package/plugins/lisa-cursor/rules/repo-scope-split-reference.mdc +48 -0
  172. package/plugins/lisa-cursor/rules/reset-seed-coverage-reference.mdc +55 -0
  173. package/plugins/lisa-cursor/rules/usage-accounting-reference.mdc +38 -0
  174. package/plugins/lisa-cursor/rules/work-item-definition-of-ready-reference.mdc +32 -0
  175. package/plugins/lisa-cursor/scripts/intake-blocker-reprobe.mjs +158 -1
  176. package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
  177. package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +4 -0
  178. package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +4 -0
  179. package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +4 -0
  180. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +4 -1
  181. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  182. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  183. package/plugins/lisa-expo-agy/plugin.json +1 -1
  184. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  185. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  186. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  187. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  188. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  189. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  190. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  191. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  192. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  193. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  194. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  195. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  196. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  197. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  198. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  199. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  200. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  201. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  202. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  203. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  204. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  205. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  206. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  207. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  208. package/plugins/lisa-rails-agy/plugin.json +1 -1
  209. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  210. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  211. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  212. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  213. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  214. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  215. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  216. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  217. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  218. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  219. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  220. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  221. package/plugins/src/base/hooks/block-direct-issue-create.sh +89 -10
  222. package/plugins/src/base/hooks/discharge-work-item-gates.sh +7 -1
  223. package/plugins/src/base/hooks/parity-safety-net.sh +44 -0
  224. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +12 -0
  225. package/plugins/src/base/rules/eager/00-rule-index.md +79 -0
  226. package/plugins/src/base/rules/eager/base-rules.md +10 -0
  227. package/plugins/src/base/rules/eager/config-resolution.md +1 -88
  228. package/plugins/src/base/rules/reference/automation-runbook-contract.md +97 -0
  229. package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +56 -0
  230. package/plugins/src/base/rules/reference/blocker-containment.md +58 -0
  231. package/plugins/src/base/rules/reference/claim-archaeology.md +42 -0
  232. package/plugins/src/base/rules/reference/claim-evidence-mapping.md +83 -0
  233. package/plugins/src/base/rules/reference/claim-time-guards.md +37 -0
  234. package/plugins/src/base/rules/reference/config-resolution.md +97 -0
  235. package/plugins/src/base/rules/reference/control-reachability.md +44 -0
  236. package/plugins/src/base/rules/reference/convergent-review.md +31 -0
  237. package/plugins/src/base/rules/reference/credential-substrate-precedence.md +57 -0
  238. package/plugins/src/base/rules/reference/dependency-decision-records.md +37 -0
  239. package/plugins/src/base/rules/reference/dependency-internalization-kit.md +47 -0
  240. package/plugins/src/base/rules/reference/dependency-trust-classes.md +48 -0
  241. package/plugins/src/base/rules/reference/deployed-state-readback.md +52 -0
  242. package/plugins/src/base/rules/reference/derived-branch-plan.md +52 -0
  243. package/plugins/src/base/rules/reference/design-source-of-truth.md +43 -0
  244. package/plugins/src/base/rules/reference/design-value-binding.md +103 -0
  245. package/plugins/src/base/rules/reference/documentation-source-paths.md +18 -0
  246. package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +75 -0
  247. package/plugins/src/base/rules/reference/observability-audit.md +20 -0
  248. package/plugins/src/base/rules/reference/prd-definition-of-ready.md +37 -0
  249. package/plugins/src/base/rules/reference/prd-lifecycle-rollup.md +36 -0
  250. package/plugins/src/base/rules/reference/pre-flight-autofill.md +88 -0
  251. package/plugins/src/base/rules/reference/promotion-contract.md +21 -0
  252. package/plugins/src/base/rules/reference/readiness-rubric.md +63 -0
  253. package/plugins/src/base/rules/reference/ready-role-filing.md +34 -0
  254. package/plugins/src/base/rules/reference/rejection-detection.md +69 -0
  255. package/plugins/src/base/rules/reference/repo-scope-split.md +48 -0
  256. package/plugins/src/base/rules/reference/reset-seed-coverage.md +55 -0
  257. package/plugins/src/base/rules/reference/usage-accounting.md +38 -0
  258. package/plugins/src/base/rules/reference/work-item-definition-of-ready.md +32 -0
  259. package/plugins/src/base/scripts/intake-blocker-reprobe.mjs +158 -1
  260. package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
  261. package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +4 -0
  262. package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +4 -0
  263. package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +4 -0
  264. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +4 -1
  265. package/rails/copy-overwrite/ast-grep/rules/no-day-truncating-file-age-predicate.yml +50 -0
  266. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +12 -0
  267. package/scripts/check-eager-rule-budget.mjs +176 -0
  268. package/scripts/check-generated-artifact-merge-coverage.mjs +7 -0
  269. package/scripts/check-rules-pairing.sh +45 -14
  270. package/scripts/check-shipped-surface-removals.mjs +851 -0
  271. package/scripts/generate-export-surface.mjs +318 -0
  272. package/scripts/lib/shipped-surface.mjs +212 -0
  273. package/scripts/lisa-enforcement-fallback.sh +178 -1
  274. package/scripts/remedy-conformance.mjs +435 -0
  275. package/scripts/two-channel-couplings.json +2 -2
  276. package/typescript/copy-contents/.husky/pre-push +147 -2
  277. package/typescript/copy-overwrite/ast-grep/rules/no-day-truncating-file-age-predicate.yml +50 -0
  278. package/typescript/copy-overwrite/audit.ignore.config.json +0 -10
  279. package/typescript/copy-overwrite/scripts/lisa-mutation.mjs +180 -29
  280. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +12 -0
  281. package/typescript/package-lisa/package.lisa.json +72 -42
  282. package/plugins/lisa/rules/eager/automation-runbook-contract.md +0 -92
  283. package/plugins/lisa/rules/eager/bdd-e2e-coverage.md +0 -51
  284. package/plugins/lisa/rules/eager/blocker-containment.md +0 -53
  285. package/plugins/lisa/rules/eager/claim-archaeology.md +0 -37
  286. package/plugins/lisa/rules/eager/claim-evidence-mapping.md +0 -78
  287. package/plugins/lisa/rules/eager/claim-time-guards.md +0 -32
  288. package/plugins/lisa/rules/eager/control-reachability.md +0 -39
  289. package/plugins/lisa/rules/eager/convergent-review.md +0 -24
  290. package/plugins/lisa/rules/eager/credential-substrate-precedence.md +0 -54
  291. package/plugins/lisa/rules/eager/dependency-decision-records.md +0 -32
  292. package/plugins/lisa/rules/eager/dependency-internalization-kit.md +0 -42
  293. package/plugins/lisa/rules/eager/dependency-trust-classes.md +0 -43
  294. package/plugins/lisa/rules/eager/deployed-state-readback.md +0 -47
  295. package/plugins/lisa/rules/eager/derived-branch-plan.md +0 -47
  296. package/plugins/lisa/rules/eager/design-source-of-truth.md +0 -38
  297. package/plugins/lisa/rules/eager/design-value-binding.md +0 -98
  298. package/plugins/lisa/rules/eager/documentation-source-paths.md +0 -13
  299. package/plugins/lisa/rules/eager/factory-model.md +0 -41
  300. package/plugins/lisa/rules/eager/leaf-only-lifecycle.md +0 -70
  301. package/plugins/lisa/rules/eager/observability-audit.md +0 -15
  302. package/plugins/lisa/rules/eager/prd-definition-of-ready.md +0 -32
  303. package/plugins/lisa/rules/eager/prd-lifecycle-rollup.md +0 -31
  304. package/plugins/lisa/rules/eager/pre-flight-autofill.md +0 -84
  305. package/plugins/lisa/rules/eager/project-learnings.md +0 -22
  306. package/plugins/lisa/rules/eager/promotion-contract.md +0 -18
  307. package/plugins/lisa/rules/eager/readiness-rubric.md +0 -58
  308. package/plugins/lisa/rules/eager/ready-role-filing.md +0 -29
  309. package/plugins/lisa/rules/eager/rejection-detection.md +0 -64
  310. package/plugins/lisa/rules/eager/repo-scope-split.md +0 -43
  311. package/plugins/lisa/rules/eager/reset-seed-coverage.md +0 -50
  312. package/plugins/lisa/rules/eager/usage-accounting.md +0 -33
  313. package/plugins/lisa/rules/eager/work-item-definition-of-ready.md +0 -27
  314. package/plugins/lisa-copilot/rules/eager/automation-runbook-contract.md +0 -92
  315. package/plugins/lisa-copilot/rules/eager/bdd-e2e-coverage.md +0 -51
  316. package/plugins/lisa-copilot/rules/eager/blocker-containment.md +0 -53
  317. package/plugins/lisa-copilot/rules/eager/claim-archaeology.md +0 -37
  318. package/plugins/lisa-copilot/rules/eager/claim-evidence-mapping.md +0 -78
  319. package/plugins/lisa-copilot/rules/eager/claim-time-guards.md +0 -32
  320. package/plugins/lisa-copilot/rules/eager/control-reachability.md +0 -39
  321. package/plugins/lisa-copilot/rules/eager/convergent-review.md +0 -24
  322. package/plugins/lisa-copilot/rules/eager/credential-substrate-precedence.md +0 -54
  323. package/plugins/lisa-copilot/rules/eager/dependency-decision-records.md +0 -32
  324. package/plugins/lisa-copilot/rules/eager/dependency-internalization-kit.md +0 -42
  325. package/plugins/lisa-copilot/rules/eager/dependency-trust-classes.md +0 -43
  326. package/plugins/lisa-copilot/rules/eager/deployed-state-readback.md +0 -47
  327. package/plugins/lisa-copilot/rules/eager/derived-branch-plan.md +0 -47
  328. package/plugins/lisa-copilot/rules/eager/design-source-of-truth.md +0 -38
  329. package/plugins/lisa-copilot/rules/eager/design-value-binding.md +0 -98
  330. package/plugins/lisa-copilot/rules/eager/documentation-source-paths.md +0 -13
  331. package/plugins/lisa-copilot/rules/eager/factory-model.md +0 -41
  332. package/plugins/lisa-copilot/rules/eager/leaf-only-lifecycle.md +0 -70
  333. package/plugins/lisa-copilot/rules/eager/observability-audit.md +0 -15
  334. package/plugins/lisa-copilot/rules/eager/prd-definition-of-ready.md +0 -32
  335. package/plugins/lisa-copilot/rules/eager/prd-lifecycle-rollup.md +0 -31
  336. package/plugins/lisa-copilot/rules/eager/pre-flight-autofill.md +0 -84
  337. package/plugins/lisa-copilot/rules/eager/project-learnings.md +0 -22
  338. package/plugins/lisa-copilot/rules/eager/promotion-contract.md +0 -18
  339. package/plugins/lisa-copilot/rules/eager/readiness-rubric.md +0 -58
  340. package/plugins/lisa-copilot/rules/eager/ready-role-filing.md +0 -29
  341. package/plugins/lisa-copilot/rules/eager/rejection-detection.md +0 -64
  342. package/plugins/lisa-copilot/rules/eager/repo-scope-split.md +0 -43
  343. package/plugins/lisa-copilot/rules/eager/reset-seed-coverage.md +0 -50
  344. package/plugins/lisa-copilot/rules/eager/usage-accounting.md +0 -33
  345. package/plugins/lisa-copilot/rules/eager/work-item-definition-of-ready.md +0 -27
  346. package/plugins/lisa-cursor/rules/automation-runbook-contract.mdc +0 -97
  347. package/plugins/lisa-cursor/rules/bdd-e2e-coverage.mdc +0 -56
  348. package/plugins/lisa-cursor/rules/blocker-containment.mdc +0 -58
  349. package/plugins/lisa-cursor/rules/claim-archaeology.mdc +0 -42
  350. package/plugins/lisa-cursor/rules/claim-evidence-mapping.mdc +0 -83
  351. package/plugins/lisa-cursor/rules/claim-time-guards.mdc +0 -37
  352. package/plugins/lisa-cursor/rules/control-reachability.mdc +0 -44
  353. package/plugins/lisa-cursor/rules/convergent-review.mdc +0 -29
  354. package/plugins/lisa-cursor/rules/credential-substrate-precedence.mdc +0 -59
  355. package/plugins/lisa-cursor/rules/dependency-decision-records.mdc +0 -37
  356. package/plugins/lisa-cursor/rules/dependency-internalization-kit.mdc +0 -47
  357. package/plugins/lisa-cursor/rules/dependency-trust-classes.mdc +0 -48
  358. package/plugins/lisa-cursor/rules/deployed-state-readback.mdc +0 -52
  359. package/plugins/lisa-cursor/rules/derived-branch-plan.mdc +0 -52
  360. package/plugins/lisa-cursor/rules/design-source-of-truth.mdc +0 -43
  361. package/plugins/lisa-cursor/rules/design-value-binding.mdc +0 -103
  362. package/plugins/lisa-cursor/rules/documentation-source-paths.mdc +0 -18
  363. package/plugins/lisa-cursor/rules/factory-model.mdc +0 -46
  364. package/plugins/lisa-cursor/rules/leaf-only-lifecycle.mdc +0 -75
  365. package/plugins/lisa-cursor/rules/observability-audit.mdc +0 -20
  366. package/plugins/lisa-cursor/rules/prd-definition-of-ready.mdc +0 -37
  367. package/plugins/lisa-cursor/rules/prd-lifecycle-rollup.mdc +0 -36
  368. package/plugins/lisa-cursor/rules/pre-flight-autofill.mdc +0 -89
  369. package/plugins/lisa-cursor/rules/project-learnings.mdc +0 -27
  370. package/plugins/lisa-cursor/rules/promotion-contract.mdc +0 -23
  371. package/plugins/lisa-cursor/rules/readiness-rubric.mdc +0 -63
  372. package/plugins/lisa-cursor/rules/ready-role-filing.mdc +0 -34
  373. package/plugins/lisa-cursor/rules/rejection-detection.mdc +0 -69
  374. package/plugins/lisa-cursor/rules/repo-scope-split.mdc +0 -48
  375. package/plugins/lisa-cursor/rules/reset-seed-coverage.mdc +0 -55
  376. package/plugins/lisa-cursor/rules/usage-accounting.mdc +0 -38
  377. package/plugins/lisa-cursor/rules/work-item-definition-of-ready.mdc +0 -32
  378. package/plugins/src/base/rules/eager/automation-runbook-contract.md +0 -92
  379. package/plugins/src/base/rules/eager/bdd-e2e-coverage.md +0 -51
  380. package/plugins/src/base/rules/eager/blocker-containment.md +0 -53
  381. package/plugins/src/base/rules/eager/claim-archaeology.md +0 -37
  382. package/plugins/src/base/rules/eager/claim-evidence-mapping.md +0 -78
  383. package/plugins/src/base/rules/eager/claim-time-guards.md +0 -32
  384. package/plugins/src/base/rules/eager/control-reachability.md +0 -39
  385. package/plugins/src/base/rules/eager/convergent-review.md +0 -24
  386. package/plugins/src/base/rules/eager/credential-substrate-precedence.md +0 -54
  387. package/plugins/src/base/rules/eager/dependency-decision-records.md +0 -32
  388. package/plugins/src/base/rules/eager/dependency-internalization-kit.md +0 -42
  389. package/plugins/src/base/rules/eager/dependency-trust-classes.md +0 -43
  390. package/plugins/src/base/rules/eager/deployed-state-readback.md +0 -47
  391. package/plugins/src/base/rules/eager/derived-branch-plan.md +0 -47
  392. package/plugins/src/base/rules/eager/design-source-of-truth.md +0 -38
  393. package/plugins/src/base/rules/eager/design-value-binding.md +0 -98
  394. package/plugins/src/base/rules/eager/documentation-source-paths.md +0 -13
  395. package/plugins/src/base/rules/eager/factory-model.md +0 -41
  396. package/plugins/src/base/rules/eager/leaf-only-lifecycle.md +0 -70
  397. package/plugins/src/base/rules/eager/observability-audit.md +0 -15
  398. package/plugins/src/base/rules/eager/prd-definition-of-ready.md +0 -32
  399. package/plugins/src/base/rules/eager/prd-lifecycle-rollup.md +0 -31
  400. package/plugins/src/base/rules/eager/pre-flight-autofill.md +0 -84
  401. package/plugins/src/base/rules/eager/project-learnings.md +0 -22
  402. package/plugins/src/base/rules/eager/promotion-contract.md +0 -18
  403. package/plugins/src/base/rules/eager/readiness-rubric.md +0 -58
  404. package/plugins/src/base/rules/eager/ready-role-filing.md +0 -29
  405. package/plugins/src/base/rules/eager/rejection-detection.md +0 -64
  406. package/plugins/src/base/rules/eager/repo-scope-split.md +0 -43
  407. package/plugins/src/base/rules/eager/reset-seed-coverage.md +0 -50
  408. package/plugins/src/base/rules/eager/usage-accounting.md +0 -33
  409. package/plugins/src/base/rules/eager/work-item-definition-of-ready.md +0 -27
@@ -494,6 +494,82 @@ project_dir = os.environ.get("LISA_GUARD_PROJECT_DIR", "")
494
494
  OVERRIDE_NAME = "LISA_ALLOW_DIRECT_ISSUE_CREATE"
495
495
  HUMAN_GATE_MARKER = "[lisa-human-gate]"
496
496
 
497
+ # Decoration a hold declaration may sit behind, and nothing more: whitespace,
498
+ # blockquote arrows, list bullets or numbers, emphasis, an opening HTML
499
+ # comment. One character class plus two optional groups, deliberately not a
500
+ # nested quantifier — this runs over untrusted issue bodies.
501
+ HUMAN_GATE_DECORATION = re.compile(r"^[ \t>*_+#-]*(?:\d+[.)][ \t]*)?(?:<!--[ \t]*)?[ \t]*")
502
+ HUMAN_GATE_FENCE = re.compile(r"```.*?```", re.DOTALL)
503
+ HUMAN_GATE_CODE_SPAN = re.compile(r"`[^`\n]*`")
504
+
505
+
506
+ def declares_human_gate(text):
507
+ """Whether a text DECLARES a hold rather than mentioning one.
508
+
509
+ The comment this replaces said the marker is matched anywhere because it
510
+ "has no other meaning, so its presence in the title or body IS the
511
+ declaration". That was true when written and is false now: the marker
512
+ acquired a second meaning -- being discussed -- the moment the feature
513
+ became something people file tickets about, and a ticket about the marker
514
+ then declares a hold on itself (CodySwannGT/lisa#3815).
515
+
516
+ A declaration is POSITIONAL: the marker leads its line, behind at most the
517
+ decoration above, with fenced blocks and inline code spans removed first
518
+ because that is how the marker is written ABOUT. The same rule the intake
519
+ matcher applies, so the two surfaces cannot disagree about one body.
520
+
521
+ NOTE the direction here differs from the intake matcher's. There a match
522
+ HOLDS an item, so a false positive parks work. Here a match ADMITS a
523
+ filing, so a false positive is a hole -- which makes this the tightening
524
+ direction on both sides at once.
525
+
526
+ Args:
527
+ text: Any candidate text -- one argv value, a body file, a payload.
528
+
529
+ Returns:
530
+ True when some line of the text declares a hold.
531
+ """
532
+ if not text:
533
+ return False
534
+ body = HUMAN_GATE_CODE_SPAN.sub("", HUMAN_GATE_FENCE.sub("", str(text)))
535
+ for line in body.split("\n"):
536
+ if HUMAN_GATE_DECORATION.sub("", line, count=1).startswith(
537
+ HUMAN_GATE_MARKER
538
+ ):
539
+ return True
540
+ if _comment_carries_marker(line):
541
+ return True
542
+ return False
543
+
544
+
545
+ def _comment_carries_marker(line):
546
+ """Whether an HTML comment on this line carries the marker.
547
+
548
+ The second accepted form, and the one this guard needs most: its inputs
549
+ are not markdown documents. A `--body` value is a single line, and a shell
550
+ script writes its declaration as `# <!-- ... -->`, so a purely
551
+ line-leading rule would refuse two declarations people have already
552
+ written -- both of which are in this repository's own test corpus.
553
+
554
+ It is not a loosening. An HTML comment is invisible when rendered, so
555
+ nobody wraps one around the marker in order to TALK about it; a quotation
556
+ has to be visible to be a quotation. Measured over this repository's 42
557
+ matching issue bodies, adding this branch changes not one verdict.
558
+
559
+ Args:
560
+ line: One line of text.
561
+
562
+ Returns:
563
+ True when some comment on the line contains the marker.
564
+ """
565
+ segments = line.split("<!--")
566
+ for segment in segments[1:]:
567
+ close = segment.find("-->")
568
+ inside = segment if close == -1 else segment[:close]
569
+ if HUMAN_GATE_MARKER in inside:
570
+ return True
571
+ return False
572
+
497
573
  # ---------------------------------------------------------------------------
498
574
  # WHY THIS IS A TOKEN SCAN AND NOT A PROGRAM RESOLVER
499
575
  #
@@ -580,7 +656,7 @@ LABEL_FLAGS = {"--label", "--labels", "--add-label", "--status", "--state"}
580
656
  # None — container: state rolls up from children
581
657
  #
582
658
  # It is a marker with no other meaning, so it is matched wherever the payload
583
- # reaches — exactly the asymmetry `HUMAN_GATE_MARKER` gets, and for the same
659
+ # reaches — the asymmetry `HUMAN_GATE_MARKER` gets, and for the related
584
660
  # reason. Reading the declaration the writer already emits is also what keeps
585
661
  # the guard and the skill from drifting apart a second time: there is one
586
662
  # string, defined in one rule, and both read it.
@@ -1223,7 +1299,7 @@ def text_declares_readiness(text):
1223
1299
  Returns:
1224
1300
  True when the text declares build-ready or a human gate.
1225
1301
  """
1226
- if HUMAN_GATE_MARKER in text:
1302
+ if declares_human_gate(text):
1227
1303
  return True
1228
1304
  for role in (ready_role, upstream_ready_role, default_ready_role):
1229
1305
  if not role:
@@ -1267,7 +1343,7 @@ def scope_declaration(text, state_role_ok):
1267
1343
  Returns:
1268
1344
  True when the text carries a whole-scope declaration.
1269
1345
  """
1270
- if HUMAN_GATE_MARKER in text:
1346
+ if declares_human_gate(text):
1271
1347
  return True
1272
1348
  return bool(state_role_ok and LIFECYCLE_ROLE_READY.search(text))
1273
1349
 
@@ -1497,20 +1573,23 @@ def declares_readiness(raw_args, roles, extra="", state_role_ok=False):
1497
1573
  candidates = [part.strip().strip("'\"") for part in raw.split(",")]
1498
1574
  if role in candidates:
1499
1575
  return True
1500
- # The human-gate marker is matched anywhere, and that asymmetry is
1501
- # deliberate: it is a marker with no other meaning, so its presence in the
1502
- # title or body IS the declaration. The build-ready role is an ordinary
1503
- # string that appears in prose about the queue all the time.
1504
- if HUMAN_GATE_MARKER in " ".join(args):
1576
+ # Checked per ARGV VALUE rather than against `" ".join(args)`, and that is
1577
+ # what makes the positional rule mean anything here. Joining first destroys
1578
+ # position: after a join, no value's line start survives except the first
1579
+ # argument's, so "the marker leads its line" would be decided by argument
1580
+ # order. A `--title` value is its own single line, which is exactly the
1581
+ # unit the rule is about -- and titles must keep being read, since this
1582
+ # guard reads them and the intake matcher does not.
1583
+ if any(declares_human_gate(value) for value in args):
1505
1584
  return True
1506
1585
  for path in body_file_paths(args):
1507
1586
  try:
1508
1587
  with open(path, encoding="utf-8", errors="replace") as handle:
1509
- if HUMAN_GATE_MARKER in handle.read():
1588
+ if declares_human_gate(handle.read()):
1510
1589
  return True
1511
1590
  except OSError:
1512
1591
  continue
1513
- if extra and HUMAN_GATE_MARKER in extra:
1592
+ if declares_human_gate(extra):
1514
1593
  return True
1515
1594
  # The state-based path. Scoped by `state_role_ok` rather than checked
1516
1595
  # unconditionally, so this adds a compliant command where none existed and
@@ -26,6 +26,11 @@
26
26
  # divergence: upstream blocks unconditionally; Lisa allows clean-tree resets.
27
27
  # Residual risk (documented, accepted): the dirty check runs in the hook's
28
28
  # cwd at hook time, so a `cd elsewhere && git reset --hard` evades it.
29
+ # - `git read-tree` with an update flag AND `--reset` while the working tree
30
+ # is dirty (issue #3978): the plumbing spelling of the same discard, on the
31
+ # same condition, printing the same remedy. Index-only `read-tree`, and
32
+ # `read-tree -m -u` without `--reset` (which git itself refuses rather than
33
+ # clobber a modified file), stay allowed. Lisa-only guard.
29
34
  # - `git rebase --abort`/`--quit` while the in-progress rebase holds
30
35
  # human-made conflict resolutions (AUTO_MERGE discriminator; issue #1956).
31
36
  # Clean or untouched rebase state stays abortable; the apply backend and a
@@ -1819,6 +1824,45 @@ $DESTRUCTIVE_GUIDANCE"
1819
1824
  fi
1820
1825
  fi
1821
1826
 
1827
+ # 3a. `git read-tree` with BOTH an update flag and `--reset`, on the same dirty
1828
+ # tree — the plumbing spelling of guard 3 (issue #3978). It resets the index
1829
+ # and writes the result into the working tree, discarding tracked
1830
+ # modifications: the identical destruction, reached through a command that
1831
+ # carries no `--hard` and no `reset` subcommand, so every pattern in
1832
+ # guard 3 misses it. A guard an agent can walk around is a guard that stops
1833
+ # the honest caller and not the one looking for a way through, and this
1834
+ # spelling is strictly worse than the blocked one — it discards WITHOUT
1835
+ # preserving, which is exactly the property guard 3's remedy supplies. Both
1836
+ # refusals therefore print the same $PRESERVE_GUIDANCE, so what they teach
1837
+ # cannot drift apart.
1838
+ #
1839
+ # `--reset` is the discriminator, not `-u`, and the pairing is deliberate:
1840
+ #
1841
+ # - `read-tree` with no update flag touches the INDEX only and destroys
1842
+ # nothing in the working tree, so a blanket `read-tree` block would be
1843
+ # over-broad.
1844
+ # - `read-tree -m -u` (a merge without `--reset`) is safe by git's own
1845
+ # construction: it REFUSES rather than overwrite a locally modified file
1846
+ # ("entry would be overwritten by merge"). `--reset` is precisely the flag
1847
+ # that switches that refusal off.
1848
+ #
1849
+ # So the destructive combination is an update flag AND `--reset` together,
1850
+ # in either order. The update flag is matched in the checkout guard's idiom
1851
+ # so a bundled short option (`-iu`) cannot dodge the anchor, with leading
1852
+ # whitespace required so a `--index-output=/tmp/out-u` style value cannot
1853
+ # read as the flag. Same conditional dirty-tree shape and same accepted
1854
+ # residual risk as guard 3: the probe runs in the hook's cwd at hook time.
1855
+ readonly GIT_READ_TREE="${GIT_CMD}read-tree"
1856
+ if matches "${GIT_READ_TREE}"'[^;&|]*[[:space:]]--reset([[:space:]]|$)' \
1857
+ && matches "${GIT_READ_TREE}"'[^;&|]*[[:space:]](-[[:alnum:]]*u[[:alnum:]]*|--update)([[:space:]]|=|$)'; then
1858
+ if git rev-parse --is-inside-work-tree >/dev/null 2>&1 \
1859
+ && [ -n "$(git status --porcelain 2>/dev/null)" ]; then
1860
+ block "git read-tree -u --reset on a dirty working tree would discard uncommitted changes (commit first, or preserve as below)" "$PRESERVE_GUIDANCE
1861
+
1862
+ $DESTRUCTIVE_GUIDANCE"
1863
+ fi
1864
+ fi
1865
+
1822
1866
  # 3b. `git rebase --abort` / `--quit` ONLY while human/agent conflict
1823
1867
  # resolutions exist (issue #1956). `--abort` restores the pre-rebase branch
1824
1868
  # and discards every resolution; `--quit` deletes the rebase bookkeeping
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -37,6 +37,143 @@ function normalizeLabels(labels) {
37
37
  .filter(label => label.length > 0);
38
38
  }
39
39
 
40
+ /**
41
+ * Decoration a declaration may sit behind, and nothing more.
42
+ *
43
+ * Whitespace, blockquote arrows, list bullets or numbers, emphasis, a comment
44
+ * hash, and an opening HTML comment. `#` is there on EVIDENCE rather than
45
+ * taste: a shell script declares a hold as `# <marker> reason=…` — a bare
46
+ * marker behind a SHELL comment, with no HTML comment anywhere — and that form
47
+ * is in this repository's own guard fixtures. A single character class plus two
48
+ * optional groups —
49
+ * deliberately not a nested-quantifier pattern, because this runs over
50
+ * untrusted work-item bodies and `sonarjs/slow-regex` is right about that
51
+ * shape.
52
+ */
53
+ const LEADING_DECORATION =
54
+ /^[ \t>*_+#-]*(?:\d+[.)][ \t]*)?(?:<!--[ \t]*)?[ \t]*/u;
55
+
56
+ /**
57
+ * The body with fenced blocks and inline code spans removed.
58
+ *
59
+ * Documentation of a declaration is not a declaration, and a fenced example is
60
+ * how the declaration form gets written ABOUT. The same move
61
+ * `pr-arming-sweep.mjs` makes for the auto-merge-off marker
62
+ * (CodySwannGT/lisa#3986), and the same one `block-direct-issue-create.sh`
63
+ * makes when it strips heredoc bodies before tokenising argv.
64
+ * @param {unknown} body - The raw item body
65
+ * @returns {string} The body with quoted and code regions blanked out
66
+ */
67
+ function declarativeText(body) {
68
+ return String(body ?? "")
69
+ .replace(/```[\s\S]*?```/gu, "")
70
+ .replace(/`[^`\n]*`/gu, "");
71
+ }
72
+
73
+ /**
74
+ * Whether an HTML comment on this line carries the marker.
75
+ *
76
+ * The second declaration form, and it is not a concession: an HTML comment is
77
+ * invisible when the body is rendered, so nobody writes one to TALK about the
78
+ * marker — a quotation has to be visible to be a quotation. Prose about the
79
+ * marker is written in sentences, code spans and fenced examples, all of which
80
+ * this rule already excludes.
81
+ *
82
+ * Scanned rather than pattern-matched. A regular expression with two lazy
83
+ * `[^\n]*?` runs around a literal is the ambiguous shape this module avoids
84
+ * elsewhere, and an indexOf walk is both linear and easier to be sure about.
85
+ * @param {string} line - One line of the body
86
+ * @returns {boolean} True when a comment on this line contains the marker
87
+ */
88
+ function commentCarriesMarker(line) {
89
+ const segments = line.split("<!--");
90
+ for (let index = 1; index < segments.length; index += 1) {
91
+ const close = segments[index].indexOf("-->");
92
+ const inside =
93
+ close === -1 ? segments[index] : segments[index].slice(0, close);
94
+ if (inside.includes(HUMAN_GATE_MARKER)) return true;
95
+ }
96
+ return false;
97
+ }
98
+
99
+ /**
100
+ * Whether one line DECLARES a hold rather than mentioning one.
101
+ *
102
+ * Two accepted forms, and the corpus says they cost nothing to combine:
103
+ * measured over this repository's 42 matching bodies, line-leading alone and
104
+ * line-leading-or-comment hold the SAME 29. The comment branch exists because
105
+ * the filing guard reads inputs that are not markdown documents — a one-line
106
+ * `--body` string and a shell script — where a declaration legitimately sits
107
+ * after other text on its line.
108
+ * @param {string} line - One line of the body
109
+ * @returns {boolean} True when the line declares a hold
110
+ */
111
+ function declaresOnLine(line) {
112
+ if (line.replace(LEADING_DECORATION, "").startsWith(HUMAN_GATE_MARKER)) {
113
+ return true;
114
+ }
115
+ return commentCarriesMarker(line);
116
+ }
117
+
118
+ /**
119
+ * Count what a body says about the hold marker, split by what it MEANS.
120
+ *
121
+ * ## Why the substring test had to go
122
+ *
123
+ * `isHumanGated` asked one question — does the body contain the marker
124
+ * anywhere — and that form was deliberate, documented, and correct when it was
125
+ * written: *"it is a marker with no other meaning, so its presence IS the
126
+ * declaration."* The premise expired. The marker acquired a second meaning —
127
+ * **being discussed** — the moment the feature became something people file
128
+ * tickets about, so a sentence quoting it, a Gherkin line naming it, and a
129
+ * ticket about it all read as declared holds (CodySwannGT/lisa#3815).
130
+ *
131
+ * The consequence is not one skipped cycle. `planHumanGateReconciliation`
132
+ * removes the ready role and applies the human-needed label, so a false
133
+ * positive rewrites the item's own metadata and every later sweep agrees with
134
+ * the first. And the affected population GROWS with the documentation: 38
135
+ * matching bodies measured 2026-09-04, 42 on 2026-09-05.
136
+ *
137
+ * ## The rule
138
+ *
139
+ * A declaration is POSITIONAL — the marker leads its line, behind at most
140
+ * blockquote, list, emphasis or opening-comment decoration — evaluated after
141
+ * code regions are removed. Measured over this repository's 42 matching bodies:
142
+ * this holds 29 of them and correctly releases the two live ready-lane items
143
+ * that only discussed the marker.
144
+ *
145
+ * The stricter HTML-comment-only rule was measured and REJECTED: it holds only
146
+ * 18, dropping declarations that carry `human-needed` today. Losing a real hold
147
+ * is the unsafe direction and would need a retrofit of the tracker.
148
+ *
149
+ * ## Why it counts rather than answering yes or no
150
+ *
151
+ * A heuristic that silently drops candidates is indistinguishable from one that
152
+ * found none. Every occurrence this rule declines to honour is counted and
153
+ * reported, so "the rule demoted 33 mentions" is a fact an operator can read
154
+ * rather than an absence they must infer.
155
+ * @param {unknown} body - The item body
156
+ * @returns {{ total: number, declared: number, demoted: number }} Occurrences,
157
+ * those that declare a hold, and those demoted to mentions
158
+ */
159
+ export function humanGateMentions(body) {
160
+ const raw = String(body ?? "");
161
+ const total = raw.split(HUMAN_GATE_MARKER).length - 1;
162
+ const declared = declarativeText(raw)
163
+ .split("\n")
164
+ .filter(line => declaresOnLine(line)).length;
165
+ return { total, declared, demoted: total - declared };
166
+ }
167
+
168
+ /**
169
+ * Whether a body declares a hold, as opposed to discussing one.
170
+ * @param {unknown} body - The item body
171
+ * @returns {boolean} True when at least one line declares a hold
172
+ */
173
+ export function bodyDeclaresHold(body) {
174
+ return humanGateMentions(body).declared > 0;
175
+ }
176
+
40
177
  /**
41
178
  * Whether an item is held for a person, on either surface.
42
179
  *
@@ -64,7 +201,7 @@ export function isHumanGated(input) {
64
201
  return true;
65
202
  }
66
203
 
67
- return String(input.body ?? "").includes(HUMAN_GATE_MARKER);
204
+ return bodyDeclaresHold(input.body);
68
205
  }
69
206
 
70
207
  /**
@@ -432,6 +569,26 @@ export function formatHumanGateNote() {
432
569
  * @param {readonly unknown[]} held - Item references held this cycle
433
570
  * @returns {string} One summary line
434
571
  */
572
+ /**
573
+ * Render the cycle-summary line naming what the precision rule DEMOTED.
574
+ *
575
+ * The counterpart of {@link summarizeHumanGateHolds}, and it exists for the
576
+ * same reason: a mutation nobody can see afterwards is the problem this whole
577
+ * area keeps having. A rule that quietly declines to honour half the marker
578
+ * occurrences it sees reads exactly like a rule that saw none, so the count is
579
+ * printed even when it is zero — measured across this repository's matching
580
+ * bodies, 33 of 62 occurrences are mentions rather than declarations.
581
+ * @param {unknown} demoted - How many occurrences were mentions, not declarations
582
+ * @returns {string} One summary line
583
+ */
584
+ export function summarizeHumanGateMentions(demoted = 0) {
585
+ const count = Number.isFinite(Number(demoted))
586
+ ? Math.trunc(Number(demoted))
587
+ : 0;
588
+ const shown = count > 0 ? String(count) : "none";
589
+ return `Marker mentions demoted (not declarations): ${shown}.`;
590
+ }
591
+
435
592
  export function summarizeHumanGateHolds(held = []) {
436
593
  const names = (Array.isArray(held) ? held : [])
437
594
  .map(item => trimmedString(item))
@@ -1136,10 +1136,26 @@ not there, and a lifecycle step performed by hand is one nothing can verify
1136
1136
  happened.
1137
1137
 
1138
1138
  **The backstop, for the ones that still slip:** `lisa-work-item.mjs sweep`
1139
- reports every claimed item that already has a merged pull request, and
1139
+ reports every open item — in the **ready** lane as well as the **claimed** one —
1140
+ that a commit on a deploy branch DECLARES via its `Work-Item:` trailer, and
1140
1141
  `--apply` completes them. Reporting is the default deliberately — a sweep that
1141
1142
  closes things as a side effect of being run is not one anyone runs twice.
1142
1143
 
1144
+ You do not need to run it. The `🧹 Lifecycle Drift Sweep` workflow runs it
1145
+ daily and files a deduplicated issue when drift exists, because a report with
1146
+ no consumer and no report are the same thing with different amounts of code.
1147
+
1148
+ Two properties worth knowing, because both were once the other way round:
1149
+
1150
+ - **Credit requires a declaration, never a mention.** Evidence is a commit
1151
+ reachable from a deploy branch whose own trailer names the item. It used to
1152
+ be a timeline cross-reference, which any pull request that so much as *named*
1153
+ `#N` created — so one merged land-stack pull request made every sibling in
1154
+ its batch look shipped. Measured: 8 of 53 reported items had no commit
1155
+ declaring them, and every one of the 8 had live work open against it.
1156
+ - **A clean result names the lanes it examined.** "No drift" over a subject
1157
+ list that excluded the ready lane was true and unusable.
1158
+
1143
1159
  ## 4. Terminal states
1144
1160
 
1145
1161
  Loop until one of:
@@ -332,6 +332,10 @@ other gate's verdict — however conclusive — may promote an item a person par
332
332
  4. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
333
333
  distinguishes "nothing was eligible" from "something eligible was held for a person". A lane
334
334
  mutation nobody can see afterwards is the same class of problem this gate exists to fix.
335
+ Report alongside it what the precision rule SKIPPED, via `summarizeHumanGateMentions(n)`
336
+ — the marker occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815).
337
+ A rule that quietly declines to honour half the occurrences it sees reads exactly like a
338
+ rule that saw none, so the count is printed even when it is zero.
335
339
  5. **Continue to the next candidate.** A held item does not end the cycle.
336
340
 
337
341
 
@@ -237,6 +237,10 @@ other gate's verdict — however conclusive — may promote an item a person par
237
237
  4. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
238
238
  distinguishes "nothing was eligible" from "something eligible was held for a person". A lane
239
239
  mutation nobody can see afterwards is the same class of problem this gate exists to fix.
240
+ Report alongside it what the precision rule SKIPPED, via `summarizeHumanGateMentions(n)`
241
+ — the marker occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815).
242
+ A rule that quietly declines to honour half the occurrences it sees reads exactly like a
243
+ rule that saw none, so the count is printed even when it is zero.
240
244
  5. **Continue to the next candidate.** A held item does not end the cycle.
241
245
 
242
246
 
@@ -231,6 +231,10 @@ other gate's verdict — however conclusive — may promote an item a person par
231
231
  4. **Name it in the cycle summary** via `summarizeHumanGateHolds([...])`, so the record
232
232
  distinguishes "nothing was eligible" from "something eligible was held for a person". A lane
233
233
  mutation nobody can see afterwards is the same class of problem this gate exists to fix.
234
+ Report alongside it what the precision rule SKIPPED, via `summarizeHumanGateMentions(n)`
235
+ — the marker occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815).
236
+ A rule that quietly declines to honour half the occurrences it sees reads exactly like a
237
+ rule that saw none, so the count is printed even when it is zero.
234
238
  5. **Continue to the next candidate.** A held item does not end the cycle.
235
239
 
236
240
 
@@ -994,7 +994,10 @@ with labels like `build-ready`, or with no Lisa status label at all, that are in
994
994
  instead — it says that nothing was changed and how a person resumes the item, which is the
995
995
  opposite of what the reconciliation note says and must not be substituted for it. A promotion
996
996
  declined silently is invisible, which is the quieter version of the failure this step exists to
997
- prevent, so name every held item in the cycle summary via `summarizeHumanGateHolds([...])`.
997
+ prevent, so name every held item in the cycle summary via `summarizeHumanGateHolds([...])`. Report what the
998
+ precision rule skipped beside it via `summarizeHumanGateMentions(n)`: the marker
999
+ occurrences that were mentions rather than declarations (CodySwannGT/lisa#3815),
1000
+ because a rule that silently drops candidates reads like one that found none.
998
1001
 
999
1002
  ### Ungated non-ready filing → surface as an incomplete handoff (read-only)
1000
1003
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.49.0",
3
+ "version": "4.50.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"