@codyswann/lisa 4.32.3 → 4.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +94 -6
  2. package/all/copy-overwrite/scripts/lisa-gates.mjs +259 -5
  3. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +20 -39
  4. package/all/merge/.claude/settings.json +1 -3
  5. package/cdk/merge/.claude/settings.json +1 -1
  6. package/dist/cli/doctor-declared-contexts.d.ts +1 -1
  7. package/dist/cli/doctor-declared-contexts.d.ts.map +1 -1
  8. package/dist/cli/doctor-declared-contexts.js +48 -7
  9. package/dist/cli/doctor-declared-contexts.js.map +1 -1
  10. package/dist/cli/gate-report-drift-section.d.ts.map +1 -1
  11. package/dist/cli/gate-report-drift-section.js +2 -0
  12. package/dist/cli/gate-report-drift-section.js.map +1 -1
  13. package/dist/configs/vitest/base.d.ts +81 -0
  14. package/dist/configs/vitest/base.d.ts.map +1 -1
  15. package/dist/configs/vitest/base.js +106 -0
  16. package/dist/configs/vitest/base.js.map +1 -1
  17. package/dist/configs/vitest/cdk.d.ts +2 -2
  18. package/dist/configs/vitest/cdk.d.ts.map +1 -1
  19. package/dist/configs/vitest/cdk.js +4 -2
  20. package/dist/configs/vitest/cdk.js.map +1 -1
  21. package/dist/configs/vitest/harper-fabric.d.ts +2 -2
  22. package/dist/configs/vitest/harper-fabric.d.ts.map +1 -1
  23. package/dist/configs/vitest/harper-fabric.js +4 -2
  24. package/dist/configs/vitest/harper-fabric.js.map +1 -1
  25. package/dist/configs/vitest/nestjs.d.ts +2 -2
  26. package/dist/configs/vitest/nestjs.d.ts.map +1 -1
  27. package/dist/configs/vitest/nestjs.js +4 -2
  28. package/dist/configs/vitest/nestjs.js.map +1 -1
  29. package/dist/configs/vitest/phaser.d.ts +2 -2
  30. package/dist/configs/vitest/phaser.d.ts.map +1 -1
  31. package/dist/configs/vitest/phaser.js +4 -2
  32. package/dist/configs/vitest/phaser.js.map +1 -1
  33. package/dist/configs/vitest/typescript.d.ts +2 -2
  34. package/dist/configs/vitest/typescript.d.ts.map +1 -1
  35. package/dist/configs/vitest/typescript.js +4 -2
  36. package/dist/configs/vitest/typescript.js.map +1 -1
  37. package/dist/core/gate-context-owners.d.ts +18 -0
  38. package/dist/core/gate-context-owners.d.ts.map +1 -1
  39. package/dist/core/gate-context-owners.js +7 -0
  40. package/dist/core/gate-context-owners.js.map +1 -1
  41. package/dist/core/gate-declaration-drift.d.ts +37 -0
  42. package/dist/core/gate-declaration-drift.d.ts.map +1 -1
  43. package/dist/core/gate-declaration-drift.js +100 -26
  44. package/dist/core/gate-declaration-drift.js.map +1 -1
  45. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  46. package/dist/core/lisa-owned-hash-ledger.js +6 -0
  47. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  48. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  49. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  50. package/dist/core/upstream-evidence-manifest.js +47 -29
  51. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  52. package/dist/health/declared-checks-inspection.d.ts.map +1 -1
  53. package/dist/health/declared-checks-inspection.js +23 -7
  54. package/dist/health/declared-checks-inspection.js.map +1 -1
  55. package/dist/migrations/index.d.ts +1 -0
  56. package/dist/migrations/index.d.ts.map +1 -1
  57. package/dist/migrations/index.js +3 -0
  58. package/dist/migrations/index.js.map +1 -1
  59. package/dist/migrations/prune-retired-claude-deny-rules.d.ts +39 -0
  60. package/dist/migrations/prune-retired-claude-deny-rules.d.ts.map +1 -0
  61. package/dist/migrations/prune-retired-claude-deny-rules.js +152 -0
  62. package/dist/migrations/prune-retired-claude-deny-rules.js.map +1 -0
  63. package/expo/merge/.claude/settings.json +1 -1
  64. package/harper-fabric/merge/.claude/settings.json +1 -1
  65. package/nestjs/merge/.claude/settings.json +1 -1
  66. package/package.json +4 -4
  67. package/phaser/merge/.claude/settings.json +1 -1
  68. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa/.codex-plugin/skills/lisa-github-add-journey/SKILL.md +1 -0
  71. package/plugins/lisa/.codex-plugin/skills/lisa-github-validate-issue/SKILL.md +28 -1
  72. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +1 -0
  73. package/plugins/lisa/.codex-plugin/skills/lisa-jira-add-journey/SKILL.md +1 -0
  74. package/plugins/lisa/.codex-plugin/skills/lisa-jira-validate-ticket/SKILL.md +28 -1
  75. package/plugins/lisa/.codex-plugin/skills/lisa-linear-add-journey/SKILL.md +1 -0
  76. package/plugins/lisa/.codex-plugin/skills/lisa-linear-validate-issue/SKILL.md +27 -0
  77. package/plugins/lisa/.codex-plugin/skills/lisa-reproduce-bug/SKILL.md +8 -0
  78. package/plugins/lisa/.codex-plugin/skills/lisa-tdd-implementation/SKILL.md +1 -0
  79. package/plugins/lisa/.codex-plugin/skills/lisa-ticket-triage/SKILL.md +8 -0
  80. package/plugins/lisa/hooks/inject-resolved-config.mjs +12 -4
  81. package/plugins/lisa/hooks/inject-resolved-config.sh +39 -8
  82. package/plugins/lisa/rules/eager/control-reachability.md +39 -0
  83. package/plugins/lisa/rules/eager/falsifiable-checks.md +2 -0
  84. package/plugins/lisa/rules/eager/work-item-definition-of-ready.md +1 -1
  85. package/plugins/lisa/rules/reference/control-reachability.md +122 -0
  86. package/plugins/lisa/rules/reference/falsifiable-checks.md +2 -0
  87. package/plugins/lisa/skills/lisa-github-add-journey/SKILL.md +1 -0
  88. package/plugins/lisa/skills/lisa-github-validate-issue/SKILL.md +28 -1
  89. package/plugins/lisa/skills/lisa-implement/SKILL.md +1 -0
  90. package/plugins/lisa/skills/lisa-jira-add-journey/SKILL.md +1 -0
  91. package/plugins/lisa/skills/lisa-jira-validate-ticket/SKILL.md +28 -1
  92. package/plugins/lisa/skills/lisa-linear-add-journey/SKILL.md +1 -0
  93. package/plugins/lisa/skills/lisa-linear-validate-issue/SKILL.md +27 -0
  94. package/plugins/lisa/skills/lisa-reproduce-bug/SKILL.md +8 -0
  95. package/plugins/lisa/skills/lisa-tdd-implementation/SKILL.md +1 -0
  96. package/plugins/lisa/skills/lisa-ticket-triage/SKILL.md +8 -0
  97. package/plugins/lisa-agy/plugin.json +1 -1
  98. package/plugins/lisa-agy/skills/lisa-github-add-journey/SKILL.md +1 -0
  99. package/plugins/lisa-agy/skills/lisa-github-validate-issue/SKILL.md +28 -1
  100. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +1 -0
  101. package/plugins/lisa-agy/skills/lisa-jira-add-journey/SKILL.md +1 -0
  102. package/plugins/lisa-agy/skills/lisa-jira-validate-ticket/SKILL.md +28 -1
  103. package/plugins/lisa-agy/skills/lisa-linear-add-journey/SKILL.md +1 -0
  104. package/plugins/lisa-agy/skills/lisa-linear-validate-issue/SKILL.md +27 -0
  105. package/plugins/lisa-agy/skills/lisa-reproduce-bug/SKILL.md +8 -0
  106. package/plugins/lisa-agy/skills/lisa-tdd-implementation/SKILL.md +1 -0
  107. package/plugins/lisa-agy/skills/lisa-ticket-triage/SKILL.md +8 -0
  108. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  109. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  110. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  111. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  113. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  114. package/plugins/lisa-copilot/hooks/inject-resolved-config.mjs +12 -4
  115. package/plugins/lisa-copilot/hooks/inject-resolved-config.sh +39 -8
  116. package/plugins/lisa-copilot/rules/eager/control-reachability.md +39 -0
  117. package/plugins/lisa-copilot/rules/eager/falsifiable-checks.md +2 -0
  118. package/plugins/lisa-copilot/rules/eager/work-item-definition-of-ready.md +1 -1
  119. package/plugins/lisa-copilot/rules/reference/control-reachability.md +122 -0
  120. package/plugins/lisa-copilot/rules/reference/falsifiable-checks.md +2 -0
  121. package/plugins/lisa-copilot/skills/lisa-github-add-journey/SKILL.md +1 -0
  122. package/plugins/lisa-copilot/skills/lisa-github-validate-issue/SKILL.md +28 -1
  123. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +1 -0
  124. package/plugins/lisa-copilot/skills/lisa-jira-add-journey/SKILL.md +1 -0
  125. package/plugins/lisa-copilot/skills/lisa-jira-validate-ticket/SKILL.md +28 -1
  126. package/plugins/lisa-copilot/skills/lisa-linear-add-journey/SKILL.md +1 -0
  127. package/plugins/lisa-copilot/skills/lisa-linear-validate-issue/SKILL.md +27 -0
  128. package/plugins/lisa-copilot/skills/lisa-reproduce-bug/SKILL.md +8 -0
  129. package/plugins/lisa-copilot/skills/lisa-tdd-implementation/SKILL.md +1 -0
  130. package/plugins/lisa-copilot/skills/lisa-ticket-triage/SKILL.md +8 -0
  131. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  132. package/plugins/lisa-cursor/hooks/inject-resolved-config.mjs +12 -4
  133. package/plugins/lisa-cursor/hooks/inject-resolved-config.sh +39 -8
  134. package/plugins/lisa-cursor/rules/control-reachability-reference.mdc +127 -0
  135. package/plugins/lisa-cursor/rules/control-reachability.mdc +44 -0
  136. package/plugins/lisa-cursor/rules/falsifiable-checks-reference.mdc +2 -0
  137. package/plugins/lisa-cursor/rules/falsifiable-checks.mdc +2 -0
  138. package/plugins/lisa-cursor/rules/work-item-definition-of-ready.mdc +1 -1
  139. package/plugins/lisa-cursor/skills/lisa-github-add-journey/SKILL.md +1 -0
  140. package/plugins/lisa-cursor/skills/lisa-github-validate-issue/SKILL.md +28 -1
  141. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +1 -0
  142. package/plugins/lisa-cursor/skills/lisa-jira-add-journey/SKILL.md +1 -0
  143. package/plugins/lisa-cursor/skills/lisa-jira-validate-ticket/SKILL.md +28 -1
  144. package/plugins/lisa-cursor/skills/lisa-linear-add-journey/SKILL.md +1 -0
  145. package/plugins/lisa-cursor/skills/lisa-linear-validate-issue/SKILL.md +27 -0
  146. package/plugins/lisa-cursor/skills/lisa-reproduce-bug/SKILL.md +8 -0
  147. package/plugins/lisa-cursor/skills/lisa-tdd-implementation/SKILL.md +1 -0
  148. package/plugins/lisa-cursor/skills/lisa-ticket-triage/SKILL.md +8 -0
  149. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  150. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  151. package/plugins/lisa-expo-agy/plugin.json +1 -1
  152. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  153. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  154. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  155. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  156. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  157. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  158. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  159. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  160. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  161. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  162. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  163. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  164. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  165. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  166. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  167. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  168. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  169. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  170. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  171. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  172. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  173. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  174. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  175. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  176. package/plugins/lisa-rails-agy/plugin.json +1 -1
  177. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  178. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  179. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  180. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  181. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  182. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  183. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  184. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  185. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  186. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  187. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  188. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  189. package/plugins/src/base/hooks/inject-resolved-config.mjs +12 -4
  190. package/plugins/src/base/hooks/inject-resolved-config.sh +39 -8
  191. package/plugins/src/base/rules/eager/control-reachability.md +39 -0
  192. package/plugins/src/base/rules/eager/falsifiable-checks.md +2 -0
  193. package/plugins/src/base/rules/eager/work-item-definition-of-ready.md +1 -1
  194. package/plugins/src/base/rules/reference/control-reachability.md +122 -0
  195. package/plugins/src/base/rules/reference/falsifiable-checks.md +2 -0
  196. package/plugins/src/base/skills/lisa-github-add-journey/SKILL.md +1 -0
  197. package/plugins/src/base/skills/lisa-github-validate-issue/SKILL.md +28 -1
  198. package/plugins/src/base/skills/lisa-implement/SKILL.md +1 -0
  199. package/plugins/src/base/skills/lisa-jira-add-journey/SKILL.md +1 -0
  200. package/plugins/src/base/skills/lisa-jira-validate-ticket/SKILL.md +28 -1
  201. package/plugins/src/base/skills/lisa-linear-add-journey/SKILL.md +1 -0
  202. package/plugins/src/base/skills/lisa-linear-validate-issue/SKILL.md +27 -0
  203. package/plugins/src/base/skills/lisa-reproduce-bug/SKILL.md +8 -0
  204. package/plugins/src/base/skills/lisa-tdd-implementation/SKILL.md +1 -0
  205. package/plugins/src/base/skills/lisa-ticket-triage/SKILL.md +8 -0
  206. package/rails/merge/.claude/settings.json +1 -1
  207. package/scripts/two-channel-couplings.json +1 -1
  208. package/typescript/merge/.claude/settings.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"declared-checks-inspection.d.ts","sourceRoot":"","sources":["../../src/health/declared-checks-inspection.ts"],"names":[],"mappings":"AA0CA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AAiCjC;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,sBAAsB,GAC7B,aAAa,CAqDf;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CAgExB"}
1
+ {"version":3,"file":"declared-checks-inspection.d.ts","sourceRoot":"","sources":["../../src/health/declared-checks-inspection.ts"],"names":[],"mappings":"AA0CA,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AAiCjC;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,sBAAsB,GAC7B,aAAa,CAmDf;AAiBD;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CAgExB"}
@@ -40,7 +40,7 @@
40
40
  * @module health/declared-checks-inspection
41
41
  */
42
42
  import { contextOwners } from "../core/gate-context-owners.js";
43
- import { classifyDeclarationDrift, } from "../core/gate-declaration-drift.js";
43
+ import { classifyDeclarationDrift, isContradiction, isGap, } from "../core/gate-declaration-drift.js";
44
44
  import { loadGateRegistry } from "../cli/gate-report-registry.js";
45
45
  import { deterministicFinding, namedReason } from "./finding-utils.js";
46
46
  import { liveRequiredContexts, } from "./ruleset-inspection.js";
@@ -90,16 +90,32 @@ export function declaredChecksFinding(report) {
90
90
  if (retired.length > 0) {
91
91
  return deterministicFinding(CHECK, "fail", namedReason("Live branch protection requires contexts nothing will ever post — these are not failing, they can never report, and every pull request here waits on them forever", retired.map(entry => entry.detail)));
92
92
  }
93
- const contradictions = report.entries.filter(entry => entry.verdict === "declared-not-enforced" ||
94
- entry.verdict === "enforced-declared-off");
93
+ // Asked of the comparator rather than re-listed here. A hand-copied
94
+ // membership is how a verdict the comparator added reaches this report's
95
+ // JSON and never changes this finding's status — a new defect class
96
+ // detected, and silently scored as a pass.
97
+ const contradictions = report.entries.filter(entry => isContradiction(entry.verdict));
95
98
  if (contradictions.length > 0) {
96
- return deterministicFinding(CHECK, "fail", namedReason("Gates declarations contradict live branch protection", contradictions.map(entry => `${entry.context} (${entry.verdict})`)));
99
+ return deterministicFinding(CHECK, "fail", namedReason("Gates declarations contradict live branch protection", contradictions.map(namedEntry)));
97
100
  }
98
- const gaps = report.entries.filter(entry => entry.verdict === "enforced-undeclared" ||
99
- entry.verdict === "enforced-declared-optional");
101
+ const gaps = report.entries.filter(entry => isGap(entry.verdict));
100
102
  return gaps.length === 0
101
103
  ? deterministicFinding(CHECK, "pass", "Every context live branch protection requires is governed by a gates declaration.")
102
- : deterministicFinding(CHECK, "warn", namedReason("Live branch protection requires contexts no declaration governs", gaps.map(entry => `${entry.context} (${entry.verdict})`)));
104
+ : deterministicFinding(CHECK, "warn", namedReason("Live branch protection requires contexts no declaration governs", gaps.map(namedEntry)));
105
+ }
106
+ /**
107
+ * One entry, naming the gate as well as the context and the verdict.
108
+ *
109
+ * The gate id is what an operator edits. A line carrying only the context
110
+ * string makes them search the settings file for a name that does not appear
111
+ * in it — the derived context and the gate id are different strings, which is
112
+ * the whole reason this comparison exists.
113
+ * @param entry - One drift entry
114
+ * @returns The operator-readable phrase
115
+ */
116
+ function namedEntry(entry) {
117
+ const gate = entry.gateId === null ? "" : `, gate "${entry.gateId}"`;
118
+ return `${entry.context} (${entry.verdict}${gate})`;
103
119
  }
104
120
  /**
105
121
  * Compare the gates declaration with the live ruleset.
@@ -1 +1 @@
1
- {"version":3,"file":"declared-checks-inspection.js","sourceRoot":"","sources":["../../src/health/declared-checks-inspection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"declared-checks-inspection.js","sourceRoot":"","sources":["../../src/health/declared-checks-inspection.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@ export { EnsureSonarExcludesLisaHarnessMigration } from "./ensure-sonar-excludes
16
16
  export { EnsureTsconfigLocalFilesFallbackMigration } from "./ensure-tsconfig-local-files-fallback.js";
17
17
  export { EnsureWikiSourceDeclaredMigration } from "./ensure-wiki-source-declared.js";
18
18
  export { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
19
+ export { PruneRetiredClaudeDenyRulesMigration } from "./prune-retired-claude-deny-rules.js";
19
20
  export { ReconcileClaudeStackPluginsMigration } from "./reconcile-claude-stack-plugins.js";
20
21
  export { UntrackCodexMarketplaceMigration } from "./untrack-codex-marketplace.js";
21
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,6CAA6C,EAAE,MAAM,gDAAgD,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,EAAE,uCAAuC,EAAE,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,qCAAqC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAElF;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD;;;OAGG;gBACS,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE;IAuB7C;;;OAGG;IACH,MAAM,IAAI,SAAS,SAAS,EAAE;IAI9B;;;;OAIG;IACG,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/D;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;CAazE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,6CAA6C,EAAE,MAAM,gDAAgD,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,EAAE,uCAAuC,EAAE,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,qCAAqC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,oCAAoC,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAElF;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD;;;OAGG;gBACS,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE;IAwB7C;;;OAGG;IACH,MAAM,IAAI,SAAS,SAAS,EAAE;IAI9B;;;;OAIG;IACG,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/D;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;CAazE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D"}
@@ -14,6 +14,7 @@ import { EnsureSonarExcludesLisaHarnessMigration } from "./ensure-sonar-excludes
14
14
  import { EnsureTsconfigLocalFilesFallbackMigration } from "./ensure-tsconfig-local-files-fallback.js";
15
15
  import { EnsureWikiSourceDeclaredMigration } from "./ensure-wiki-source-declared.js";
16
16
  import { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
17
+ import { PruneRetiredClaudeDenyRulesMigration } from "./prune-retired-claude-deny-rules.js";
17
18
  import { ReconcileClaudeStackPluginsMigration } from "./reconcile-claude-stack-plugins.js";
18
19
  import { UntrackCodexMarketplaceMigration } from "./untrack-codex-marketplace.js";
19
20
  export { EnsureAuditIgnoreLocalExclusionsMigration } from "./ensure-audit-ignore-local-exclusions.js";
@@ -32,6 +33,7 @@ export { EnsureSonarExcludesLisaHarnessMigration } from "./ensure-sonar-excludes
32
33
  export { EnsureTsconfigLocalFilesFallbackMigration } from "./ensure-tsconfig-local-files-fallback.js";
33
34
  export { EnsureWikiSourceDeclaredMigration } from "./ensure-wiki-source-declared.js";
34
35
  export { EnsureTsconfigLocalIncludesMigration } from "./ensure-tsconfig-local-includes.js";
36
+ export { PruneRetiredClaudeDenyRulesMigration } from "./prune-retired-claude-deny-rules.js";
35
37
  export { ReconcileClaudeStackPluginsMigration } from "./reconcile-claude-stack-plugins.js";
36
38
  export { UntrackCodexMarketplaceMigration } from "./untrack-codex-marketplace.js";
37
39
  /**
@@ -61,6 +63,7 @@ export class MigrationRegistry {
61
63
  new EnsureSeededGatesMigration(),
62
64
  new EnsureSonarExcludesLisaHarnessMigration(),
63
65
  new EnsureWikiSourceDeclaredMigration(),
66
+ new PruneRetiredClaudeDenyRulesMigration(),
64
67
  new ReconcileClaudeStackPluginsMigration(),
65
68
  new UntrackCodexMarketplaceMigration(),
66
69
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,6CAA6C,EAAE,MAAM,gDAAgD,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,EAAE,uCAAuC,EAAE,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,qCAAqC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,oCAAoC,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAalF,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,6CAA6C,EAAE,MAAM,gDAAgD,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,EAAE,uCAAuC,EAAE,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,qCAAqC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,wCAAwC,EAAE,MAAM,yCAAyC,CAAC;AACnG,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,EAAE,yCAAyC,EAAE,MAAM,2CAA2C,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,oCAAoC,EAAE,MAAM,sCAAsC,CAAC;AAC5F,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAElF;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACX,UAAU,CAAuB;IAElD;;;OAGG;IACH,YAAY,UAAiC;QAC3C,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI;YAC9B,IAAI,oCAAoC,EAAE;YAC1C,IAAI,yCAAyC,EAAE;YAC/C,IAAI,yCAAyC,EAAE;YAC/C,IAAI,6CAA6C,EAAE;YACnD,IAAI,qCAAqC,EAAE;YAC3C,IAAI,mCAAmC,EAAE;YACzC,IAAI,uCAAuC,EAAE;YAC7C,IAAI,qCAAqC,EAAE;YAC3C,IAAI,8BAA8B,EAAE;YACpC,IAAI,gCAAgC,EAAE;YACtC,IAAI,wCAAwC,EAAE;YAC9C,IAAI,8BAA8B,EAAE;YACpC,IAAI,kCAAkC,EAAE;YACxC,IAAI,0BAA0B,EAAE;YAChC,IAAI,uCAAuC,EAAE;YAC7C,IAAI,iCAAiC,EAAE;YACvC,IAAI,oCAAoC,EAAE;YAC1C,IAAI,oCAAoC,EAAE;YAC1C,IAAI,gCAAgC,EAAE;SACvC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB,CAAC,GAAqB;QAC7C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,IAAI,SAAS,CAAC,gBAAgB,EAAE,CAAC;gBAC/B,MAAM,SAAS,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,GAAqB;QAChC,MAAM,OAAO,GAAsB,EAAE,CAAC;QACtC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC1D,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,iBAAiB,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { Migration, MigrationContext, MigrationResult } from "./migration.interface.js";
2
+ /**
3
+ * Migration: prune retired Lisa deny rules from `.claude/settings.json`.
4
+ *
5
+ * Lisa seeds `permissions.deny` by deep-merging each detected stack's
6
+ * `merge/.claude/settings.json` template, and that merge unions arrays — it can
7
+ * only ever *add* entries (`src/utils/json-utils.ts`, `deepMergeWithArrayUnion`).
8
+ * So dropping a rule from the template stops fresh projects from receiving it
9
+ * and does nothing at all for the projects that already have it: every host
10
+ * seeded by an older Lisa keeps the entry in its own settings file forever.
11
+ * Removing it needs an explicit migration, exactly as pruning a stale stack
12
+ * plugin did (see `reconcile-claude-stack-plugins`).
13
+ *
14
+ * Runs after the merge strategies, so it removes the rule even in the window
15
+ * where a template still contributes it.
16
+ *
17
+ * Scope is deliberately narrow: only the exact strings in
18
+ * {@link RETIRED_DENY_RULES} are removed, and only from `permissions.deny`.
19
+ * Host-authored deny rules, `allow`, `ask`, and every other setting are never
20
+ * touched. A missing settings file is a silent no-op; an unparseable one is
21
+ * left byte-for-byte alone with a warning, never rewritten.
22
+ */
23
+ export declare class PruneRetiredClaudeDenyRulesMigration implements Migration {
24
+ readonly name = "prune-retired-claude-deny-rules";
25
+ readonly description = "Remove retired Lisa deny rules from .claude/settings.json that array-union merge cannot un-add";
26
+ /**
27
+ * Whether the project's settings carry any retired deny rule.
28
+ * @param ctx - Migration context
29
+ * @returns True when at least one retired rule is present
30
+ */
31
+ applies(ctx: MigrationContext): Promise<boolean>;
32
+ /**
33
+ * Remove the retired deny rules and write the result back.
34
+ * @param ctx - Migration context
35
+ * @returns Result naming the rules removed
36
+ */
37
+ apply(ctx: MigrationContext): Promise<MigrationResult>;
38
+ }
39
+ //# sourceMappingURL=prune-retired-claude-deny-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-retired-claude-deny-rules.d.ts","sourceRoot":"","sources":["../../src/migrations/prune-retired-claude-deny-rules.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAwGlC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,oCAAqC,YAAW,SAAS;IACpE,QAAQ,CAAC,IAAI,qCAAqC;IAClD,QAAQ,CAAC,WAAW,oGAC+E;IAEnG;;;;OAIG;IACG,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAatD;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;CAmC7D"}
@@ -0,0 +1,152 @@
1
+ import { existsSync } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { readJsonOrNull, writeJson } from "../utils/json-utils.js";
4
+ const SETTINGS_REL_PATH = path.join(".claude", "settings.json");
5
+ /**
6
+ * Deny rules Lisa's `merge/.claude/settings.json` templates once shipped and
7
+ * have since retired. Only these exact strings are pruned — every other entry
8
+ * in `permissions.deny`, and every entry in `allow` / `ask`, is host-owned and
9
+ * left untouched.
10
+ *
11
+ * `Read(./.entire/metadata/**)` is written with a *relative* path. A relative
12
+ * deny pattern cannot be statically matched against a Bash command shaped
13
+ * `cd <dir> && <read a relative path>`, so Claude Code cannot prove the command
14
+ * safe and escalates it to a human approval prompt. With agent fleets running,
15
+ * that fires constantly.
16
+ */
17
+ const RETIRED_DENY_RULES = new Set([
18
+ "Read(./.entire/metadata/**)",
19
+ ]);
20
+ /**
21
+ * Read the project's `.claude/settings.json`, returning null when absent or
22
+ * unparseable. The two cases are distinguished by the caller via
23
+ * {@link settingsFileExists} so a malformed file can warn instead of passing
24
+ * silently as "nothing to do".
25
+ * @param projectDir - Destination project directory
26
+ * @returns Parsed settings, or null when the file is missing or invalid JSON
27
+ */
28
+ async function readClaudeSettings(projectDir) {
29
+ return readJsonOrNull(path.join(projectDir, SETTINGS_REL_PATH));
30
+ }
31
+ /**
32
+ * Whether the project has a `.claude/settings.json` file on disk at all.
33
+ * @param projectDir - Destination project directory
34
+ * @returns True when the file exists, regardless of whether it parses
35
+ */
36
+ function settingsFileExists(projectDir) {
37
+ return existsSync(path.join(projectDir, SETTINGS_REL_PATH));
38
+ }
39
+ /**
40
+ * Extract the retired deny rules present in a settings object.
41
+ *
42
+ * Returns an empty list whenever `permissions.deny` is missing or is not an
43
+ * array — a host that shaped it differently is left entirely alone.
44
+ * @param settings - Parsed settings object
45
+ * @returns The retired rule strings actually present, in file order
46
+ */
47
+ function findRetiredDenyRules(settings) {
48
+ const deny = settings.permissions?.deny;
49
+ if (!Array.isArray(deny)) {
50
+ return [];
51
+ }
52
+ return deny.filter((entry) => typeof entry === "string" && RETIRED_DENY_RULES.has(entry));
53
+ }
54
+ /**
55
+ * Rebuild a settings object with the retired deny rules removed.
56
+ *
57
+ * Surgical by construction: every other key of `settings`, every other key of
58
+ * `permissions`, and every surviving `deny` entry keep their original value and
59
+ * relative order. `deny` is left in place as an empty array when the retired
60
+ * rules were its only members — dropping the key would be a structural change
61
+ * the host never asked for.
62
+ * @param settings - Parsed settings object
63
+ * @returns A new settings object without the retired deny rules
64
+ */
65
+ function withoutRetiredDenyRules(settings) {
66
+ const permissions = settings.permissions ?? {};
67
+ const deny = permissions.deny;
68
+ if (!Array.isArray(deny)) {
69
+ return settings;
70
+ }
71
+ return {
72
+ ...settings,
73
+ permissions: {
74
+ ...permissions,
75
+ deny: deny.filter(entry => !(typeof entry === "string" && RETIRED_DENY_RULES.has(entry))),
76
+ },
77
+ };
78
+ }
79
+ /**
80
+ * Migration: prune retired Lisa deny rules from `.claude/settings.json`.
81
+ *
82
+ * Lisa seeds `permissions.deny` by deep-merging each detected stack's
83
+ * `merge/.claude/settings.json` template, and that merge unions arrays — it can
84
+ * only ever *add* entries (`src/utils/json-utils.ts`, `deepMergeWithArrayUnion`).
85
+ * So dropping a rule from the template stops fresh projects from receiving it
86
+ * and does nothing at all for the projects that already have it: every host
87
+ * seeded by an older Lisa keeps the entry in its own settings file forever.
88
+ * Removing it needs an explicit migration, exactly as pruning a stale stack
89
+ * plugin did (see `reconcile-claude-stack-plugins`).
90
+ *
91
+ * Runs after the merge strategies, so it removes the rule even in the window
92
+ * where a template still contributes it.
93
+ *
94
+ * Scope is deliberately narrow: only the exact strings in
95
+ * {@link RETIRED_DENY_RULES} are removed, and only from `permissions.deny`.
96
+ * Host-authored deny rules, `allow`, `ask`, and every other setting are never
97
+ * touched. A missing settings file is a silent no-op; an unparseable one is
98
+ * left byte-for-byte alone with a warning, never rewritten.
99
+ */
100
+ export class PruneRetiredClaudeDenyRulesMigration {
101
+ name = "prune-retired-claude-deny-rules";
102
+ description = "Remove retired Lisa deny rules from .claude/settings.json that array-union merge cannot un-add";
103
+ /**
104
+ * Whether the project's settings carry any retired deny rule.
105
+ * @param ctx - Migration context
106
+ * @returns True when at least one retired rule is present
107
+ */
108
+ async applies(ctx) {
109
+ const settings = await readClaudeSettings(ctx.projectDir);
110
+ if (settings === null) {
111
+ if (settingsFileExists(ctx.projectDir)) {
112
+ ctx.logger.warn(`Could not parse ${SETTINGS_REL_PATH}; leaving it unchanged (${this.name})`);
113
+ }
114
+ return false;
115
+ }
116
+ return findRetiredDenyRules(settings).length > 0;
117
+ }
118
+ /**
119
+ * Remove the retired deny rules and write the result back.
120
+ * @param ctx - Migration context
121
+ * @returns Result naming the rules removed
122
+ */
123
+ async apply(ctx) {
124
+ const settings = await readClaudeSettings(ctx.projectDir);
125
+ if (settings === null) {
126
+ return { name: this.name, action: "noop" };
127
+ }
128
+ const retired = findRetiredDenyRules(settings);
129
+ if (retired.length === 0) {
130
+ return { name: this.name, action: "noop" };
131
+ }
132
+ const message = `Removed retired deny ${retired.length === 1 ? "rule" : "rules"} from ${SETTINGS_REL_PATH}: ${retired.join(", ")}`;
133
+ if (ctx.dryRun) {
134
+ ctx.logger.dry(`Would update ${SETTINGS_REL_PATH}: ${message}`);
135
+ return {
136
+ name: this.name,
137
+ action: "applied",
138
+ changedFiles: [SETTINGS_REL_PATH],
139
+ message,
140
+ };
141
+ }
142
+ await writeJson(path.join(ctx.projectDir, SETTINGS_REL_PATH), withoutRetiredDenyRules(settings));
143
+ ctx.logger.success(message);
144
+ return {
145
+ name: this.name,
146
+ action: "applied",
147
+ changedFiles: [SETTINGS_REL_PATH],
148
+ message,
149
+ };
150
+ }
151
+ }
152
+ //# sourceMappingURL=prune-retired-claude-deny-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-retired-claude-deny-rules.js","sourceRoot":"","sources":["../../src/migrations/prune-retired-claude-deny-rules.ts"],"names":[],"mappings":"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"}
@@ -36,7 +36,7 @@
36
36
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
37
37
  },
38
38
  "permissions": {
39
- "deny": ["Read(./.entire/metadata/**)"]
39
+ "deny": []
40
40
  },
41
41
  "plansDirectory": "./plans"
42
42
  }
@@ -28,7 +28,7 @@
28
28
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
29
29
  },
30
30
  "permissions": {
31
- "deny": ["Read(./.entire/metadata/**)"]
31
+ "deny": []
32
32
  },
33
33
  "plansDirectory": "./plans"
34
34
  }
@@ -27,7 +27,7 @@
27
27
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
28
28
  },
29
29
  "permissions": {
30
- "deny": ["Read(./.entire/metadata/**)"]
30
+ "deny": []
31
31
  },
32
32
  "plansDirectory": "./plans"
33
33
  }
package/package.json CHANGED
@@ -165,7 +165,7 @@
165
165
  "zod-validation-error": "^4.0.0"
166
166
  },
167
167
  "name": "@codyswann/lisa",
168
- "version": "4.32.3",
168
+ "version": "4.33.0",
169
169
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
170
170
  "main": "dist/index.js",
171
171
  "exports": {
@@ -313,7 +313,7 @@
313
313
  "test": "tests"
314
314
  },
315
315
  "types": "./dist/index.d.ts",
316
- "lisaReleaseCommit": "7ef9df059e8ad72593b531abaec2adbcbf4f20ea",
317
- "gitHead": "7ef9df059e8ad72593b531abaec2adbcbf4f20ea",
318
- "lisaReleaseTag": "v4.32.3"
316
+ "lisaReleaseCommit": "fe589d747efc474cf9dc5e73c397b2df2ca129a8",
317
+ "gitHead": "fe589d747efc474cf9dc5e73c397b2df2ca129a8",
318
+ "lisaReleaseTag": "v4.33.0"
319
319
  }
@@ -29,7 +29,7 @@
29
29
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
30
30
  },
31
31
  "permissions": {
32
- "deny": ["Read(./.entire/metadata/**)"]
32
+ "deny": []
33
33
  },
34
34
  "disabledMcpjsonServers": ["phaser-editor"],
35
35
  "plansDirectory": "./plans"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.32.3",
3
+ "version": "4.33.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.32.3",
3
+ "version": "4.33.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -87,6 +87,7 @@ Compose the journey with typed `[EVIDENCE: <artifact-type>: <name>]` markers at
87
87
  6. **Cover happy path AND error path** — At minimum, one success and one failure marker.
88
88
  7. **On a leaf work unit, the markers are binding** — For a Bug / Task / Sub-task / Improvement, every typed `[EVIDENCE: <artifact-type>: <name>]` here is the issue's evidence manifest: validation gate S14 requires at least one, and the issue cannot be closed until each named artifact is captured **in its declared type** and attached (see the "Per-Work-Unit Evidence Contract" in the `verification` rule). Name only evidence you intend to capture — and name all of it.
89
89
  8. **Reference sibling evidence without claiming it** — Use only `[EVIDENCE-REF: <work-item-ref> | <artifact-type>: <kebab-case-name>]` when prose points to an artifact declared by another issue. Never paste, quote, or code-format the sibling's `[EVIDENCE: ...]` marker: that exact prefix creates a local obligation. `EVIDENCE-REF` never satisfies this issue's S14 minimum, uniqueness check, capture list, or completion gate; a runtime-changing leaf still needs at least one local `[EVIDENCE: ...]` marker.
90
+ 9. **A named existing test is a control, and a control declares its reachability** — When the journey pins an *existing* test as a red-before-green control ("must go red", "fails before the fix and passes after"), the `control-reachability` rule requires the issue to say what makes that test reach the changed code: `[CONTROL: <test-identifier> | reaches: <input-or-field>]`, one per named control, validated by gate S20. Name the fixture key, field, argument, or state that carries execution into the change — not the code itself. A test whose fixture never reaches the changed path stays green for a reason unrelated to the change, and the stopping rule then reads as "revert a correct fix". Introducing a **new** test instead carries no such obligation; S20 is `N/A` and no marker is written.
90
91
 
91
92
  ### Step 6: Present to User for Approval
92
93
 
@@ -100,6 +100,7 @@ Per-type content requirements are defined once in the vendor-neutral `work-item-
100
100
  | S17 Improvement measurability | `acceptance-criteria` | true |
101
101
  | S18 Stateless-pickup dry-run | `product-clarity` | true |
102
102
  | S19 Branch Plan derivation | `technical` | false |
103
+ | S20 Named-control reachability | `acceptance-criteria` | true |
103
104
  | F1 Issue type label exists in repo | `structural` | false |
104
105
  | F2 Parent sub-issue exists and is the right type | `structural` | false |
105
106
  | F3 Linked issues exist | `structural` | false |
@@ -326,6 +327,31 @@ Failing a proposed spec is free; failing every existing issue would turn a legac
326
327
 
327
328
  FAIL names both plans (rendered and recomputed) and points the remediation at **the environment, never the branch** — e.g. `"Branch Plan conflicts with the environment mapping. Rendered 'Branch from: release/staging'; recomputed from Target Backend Environment 'production' via deploy.branches → 'main'. Correct the environment, not the branch — the branches are derived. Then re-render."` Never silently choose between the two plans.
328
329
 
330
+ #### S20 — Named-control reachability
331
+
332
+ Enforces the vendor-neutral `control-reachability` rule: **a work item that names an existing test as a red-before-green control must say what makes that test reach the code the change touches.** A control whose reachability cannot be stated is not a control — its green tells the implementer nothing, and the issue's own stopping rule then instructs a revert of a correct fix.
333
+
334
+ **When the gate applies.** Run S20 when the body — `Acceptance Criteria`, `Technical Approach`, or `Validation Journey` — names an **existing** test AND predicts a state change for it when the work lands. Signals: "must go red", "currently passes and must fail", "fails before the fix and passes after", "if it still passes the fix did nothing", or any equivalent stopping rule.
335
+
336
+ **When it must stay silent.** `N/A` otherwise. A issue that introduces a **new** test rather than pinning an existing one carries no reachability obligation and must never be reported as incomplete on this basis. This half is load-bearing: a gate that fires on every work item is one callers learn to route around.
337
+
338
+ **What must be present.** One marker per named control, inside `## Validation Journey`:
339
+
340
+ ```text
341
+ [CONTROL: <test-identifier> | reaches: <input-or-field>]
342
+ ```
343
+
344
+ Parse by the exact `[CONTROL:` prefix and split on the single `|`.
345
+
346
+ - `<test-identifier>` — non-empty; the test file path, the test name, or both. It must be enough to run the test.
347
+ - `reaches:` — the literal key, then a non-empty description of the **input, field, fixture key, argument, or state** that carries execution into the changed code.
348
+
349
+ FAIL when a named existing-test control has no marker, when a marker is malformed (missing the `|`, an empty identifier, a missing or empty `reaches:` half), or when the `reaches:` half restates the assertion instead of naming an input (`reaches: the fix`, `reaches: the changed code path`). Naming the code is not enough; the marker answers "what in this fixture gets execution there".
350
+
351
+ Remediation: `"Name the input or field that makes <test> reach the code this work changes, as [CONTROL: <test> | reaches: <field>]. If the fixture does not reach it, the test cannot observe this change — extend the fixture or specify a new test instead."`
352
+
353
+ `product_relevant: true` — an unfalsifiable stopping rule is a specification defect, and whoever wrote the issue is who can repair it. `lisa-github-write-issue` renders the marker; `control-reachability` carries the implementer-side counterpart, which forbids acting on the stopping rule before the cause of an unmoved control is established.
354
+
329
355
  ### Feasibility Gates (require GitHub lookups; skip in `--spec-only`)
330
356
 
331
357
  #### F1 — Issue type label exists in repo
@@ -487,6 +513,7 @@ Output is a single fenced text block. Callers parse it; do not add free-form pro
487
513
  - [PASS|FAIL|N/A] S17 Improvement measurability — <one-line reason>
488
514
  - [PASS|FAIL|N/A] S18 Stateless-pickup dry-run — <one-line reason>
489
515
  - [PASS|FAIL|N/A] S19 Branch Plan derivation — <one-line reason>
516
+ - [PASS|FAIL|N/A] S20 Named-control reachability — <one-line reason>
490
517
 
491
518
  ### Feasibility Gates (omit this section when --spec-only)
492
519
  - [PASS|FAIL|N/A] F1 Issue type label exists in repo — <one-line reason>
@@ -513,7 +540,7 @@ The verdict is `PASS` if every applicable gate is `PASS`. Any `FAIL` makes the v
513
540
 
514
541
  Same shape and meaning as `lisa-jira-validate-ticket` so downstream PRD-intake skills (Notion, Confluence, Linear, GitHub) can format comments uniformly:
515
542
 
516
- - **gate**: the gate ID (`S1`–`S18`, `F1`–`F5`).
543
+ - **gate**: the gate ID (`S1`–`S20`, `F1`–`F5`).
517
544
  - **category**: the gate's fixed category from the table.
518
545
  - **product_relevant**: matches the gate's table entry. `false` means the failure is an internal data-quality problem the caller should fix without bothering product.
519
546
  - **what**: plain-language, product-readable.
@@ -100,6 +100,7 @@ When deciding the agents to use, consider:
100
100
  * Before any task is implemented, the agent team must explore the codebase for relevant research (documentation, code, git history, etc) and update each task's `metadata.relevant_documentation` with the findings.
101
101
  * Each task must be reviewed by the team to make sure their verification passes.
102
102
  * Each task must have their learnings captured to the ledger by the learner subagent.
103
+ * When the work item prescribes an **existing** test as a red-before-green control ("that test must go red once this lands"), the `control-reachability` rule binds the team. Read the item's `[CONTROL: <test-identifier> | reaches: <input-or-field>]` declaration (gate S20) and confirm the named input is in that test's fixture. If the control does not move when the change lands, **do not act on the stopping rule until the cause is established**: the change had no effect (revisit the change) or the fixture never reached the changed path (fix or extend the control — never revert). Prove reachability by execution — a temporary `throw` in the changed block under that one test, or coverage scoped to it — never by reading the fixture. A named control with no reachability declaration is an unvalidated control; treat it as a triage finding, not a pass.
103
104
 
104
105
  Using the general-purpose agent in Team Lead session, Determine the name of this plan
105
106
 
@@ -111,6 +111,7 @@ h3. Assertions
111
111
  6. **Cover happy path and error path** — At minimum, one success and one failure evidence marker
112
112
  7. **On a leaf work unit, the markers are binding** — For a Bug / Task / Sub-task / Improvement, every typed `[EVIDENCE: <artifact-type>: <name>]` here is the ticket's evidence manifest: validation gate S14 requires at least one, and the ticket cannot be closed until each named artifact is captured **in its declared type** and attached (see the "Per-Work-Unit Evidence Contract" in the `verification` rule). Name only evidence you intend to capture — and name all of it.
113
113
  8. **Reference sibling evidence without claiming it** — Use only `[EVIDENCE-REF: <work-item-ref> | <artifact-type>: <kebab-case-name>]` when prose points to an artifact declared by another ticket. Never paste, quote, or code-format the sibling's `[EVIDENCE: ...]` marker: that exact prefix creates a local obligation. `EVIDENCE-REF` never satisfies this ticket's S14 minimum, uniqueness check, capture list, or completion gate; a runtime-changing leaf still needs at least one local `[EVIDENCE: ...]` marker.
114
+ 9. **A named existing test is a control, and a control declares its reachability** — When the journey pins an *existing* test as a red-before-green control ("must go red", "fails before the fix and passes after"), the `control-reachability` rule requires the ticket to say what makes that test reach the changed code: `[CONTROL: <test-identifier> | reaches: <input-or-field>]`, one per named control, validated by gate S20. Name the fixture key, field, argument, or state that carries execution into the change — not the code itself. A test whose fixture never reaches the changed path stays green for a reason unrelated to the change, and the stopping rule then reads as "revert a correct fix". Introducing a **new** test instead carries no such obligation; S20 is `N/A` and no marker is written.
114
115
 
115
116
  ### Step 6: Present to User for Approval
116
117
 
@@ -97,6 +97,7 @@ Per-type content requirements are defined once in the vendor-neutral `work-item-
97
97
  | S17 Improvement measurability | `acceptance-criteria` | true |
98
98
  | S18 Stateless-pickup dry-run | `product-clarity` | true |
99
99
  | S19 Branch Plan derivation | `technical` | false |
100
+ | S20 Named-control reachability | `acceptance-criteria` | true |
100
101
  | F1 Issue type valid in project | `structural` | false |
101
102
  | F2 Epic parent exists and is an Epic | `structural` | false |
102
103
  | F3 Linked tickets exist | `structural` | false |
@@ -328,6 +329,31 @@ Failing a proposed spec is free; failing every existing ticket would turn a lega
328
329
 
329
330
  FAIL names both plans (rendered and recomputed) and points the remediation at **the environment, never the branch** — e.g. `"Branch Plan conflicts with the environment mapping. Rendered 'Branch from: release/staging'; recomputed from Target Backend Environment 'production' via deploy.branches → 'main'. Correct the environment, not the branch — the branches are derived. Then re-render."` Never silently choose between the two plans.
330
331
 
332
+ #### S20 — Named-control reachability
333
+
334
+ Enforces the vendor-neutral `control-reachability` rule: **a work item that names an existing test as a red-before-green control must say what makes that test reach the code the change touches.** A control whose reachability cannot be stated is not a control — its green tells the implementer nothing, and the ticket's own stopping rule then instructs a revert of a correct fix.
335
+
336
+ **When the gate applies.** Run S20 when the body — `Acceptance Criteria`, `Technical Approach`, or `Validation Journey` — names an **existing** test AND predicts a state change for it when the work lands. Signals: "must go red", "currently passes and must fail", "fails before the fix and passes after", "if it still passes the fix did nothing", or any equivalent stopping rule.
337
+
338
+ **When it must stay silent.** `N/A` otherwise. A ticket that introduces a **new** test rather than pinning an existing one carries no reachability obligation and must never be reported as incomplete on this basis. This half is load-bearing: a gate that fires on every work item is one callers learn to route around.
339
+
340
+ **What must be present.** One marker per named control, inside `h2. Validation Journey`:
341
+
342
+ ```text
343
+ [CONTROL: <test-identifier> | reaches: <input-or-field>]
344
+ ```
345
+
346
+ Parse by the exact `[CONTROL:` prefix and split on the single `|`.
347
+
348
+ - `<test-identifier>` — non-empty; the test file path, the test name, or both. It must be enough to run the test.
349
+ - `reaches:` — the literal key, then a non-empty description of the **input, field, fixture key, argument, or state** that carries execution into the changed code.
350
+
351
+ FAIL when a named existing-test control has no marker, when a marker is malformed (missing the `|`, an empty identifier, a missing or empty `reaches:` half), or when the `reaches:` half restates the assertion instead of naming an input (`reaches: the fix`, `reaches: the changed code path`). Naming the code is not enough; the marker answers "what in this fixture gets execution there".
352
+
353
+ Remediation: `"Name the input or field that makes <test> reach the code this work changes, as [CONTROL: <test> | reaches: <field>]. If the fixture does not reach it, the test cannot observe this change — extend the fixture or specify a new test instead."`
354
+
355
+ `product_relevant: true` — an unfalsifiable stopping rule is a specification defect, and whoever wrote the ticket is who can repair it. `lisa-jira-write-ticket` renders the marker; `control-reachability` carries the implementer-side counterpart, which forbids acting on the stopping rule before the cause of an unmoved control is established.
356
+
331
357
  ### Feasibility Gates (require JIRA lookups; skip in dry-run if requested)
332
358
 
333
359
  #### F1 — Issue type valid in project
@@ -416,6 +442,7 @@ Output is a single fenced text block. Callers parse it; do not add free-form pro
416
442
  - [PASS|FAIL|N/A] S17 Improvement measurability — <one-line reason>
417
443
  - [PASS|FAIL|N/A] S18 Stateless-pickup dry-run — <one-line reason>
418
444
  - [PASS|FAIL|N/A] S19 Branch Plan derivation — <one-line reason>
445
+ - [PASS|FAIL|N/A] S20 Named-control reachability — <one-line reason>
419
446
 
420
447
  ### Feasibility Gates (omit this section when --spec-only)
421
448
  - [PASS|FAIL|N/A] F1 Issue type valid in project — <one-line reason>
@@ -441,7 +468,7 @@ The verdict is `PASS` if and only if every applicable gate is `PASS`. Any `FAIL`
441
468
 
442
469
  ### Failure-detail fields
443
470
 
444
- - **gate**: the gate ID (`S1`–`S18`, `F1`–`F5`).
471
+ - **gate**: the gate ID (`S1`–`S20`, `F1`–`F5`).
445
472
  - **category**: the gate's fixed category from the table above. Callers use this to label or filter comments — `product-clarity`, `acceptance-criteria`, `design-ux`, `scope`, `dependency`, `data`, `technical`, or `structural`.
446
473
  - **product_relevant**: matches the gate's table entry. `false` means the failure is an internal data-quality problem (e.g., the agent built a malformed spec, an issue type is invalid in the project) and the caller should fix it without bothering the product team. `true` means the PRD needs product input to resolve.
447
474
  - **what**: plain-language description of the issue. No gate IDs, no JIRA jargon, no engineering shorthand. A product owner reading this on a Notion comment should understand what is unclear and why.
@@ -87,6 +87,7 @@ Compose the journey with typed `[EVIDENCE: <artifact-type>: <name>]` markers at
87
87
  6. **Cover happy path and error path** — At minimum, one success and one failure evidence marker.
88
88
  7. **On a leaf work unit, the markers are binding** — For a Bug / Task / Sub-task / Improvement, every typed `[EVIDENCE: <artifact-type>: <name>]` here is the item's evidence manifest: validation gate S14 requires at least one, and the item cannot be closed until each named artifact is captured **in its declared type** and attached (see the "Per-Work-Unit Evidence Contract" in the `verification` rule). Name only evidence you intend to capture — and name all of it.
89
89
  8. **Reference sibling evidence without claiming it** — Use only `[EVIDENCE-REF: <work-item-ref> | <artifact-type>: <kebab-case-name>]` when prose points to an artifact declared by another item. Never paste, quote, or code-format the sibling's `[EVIDENCE: ...]` marker: that exact prefix creates a local obligation. `EVIDENCE-REF` never satisfies this item's S14 minimum, uniqueness check, capture list, or completion gate; a runtime-changing leaf still needs at least one local `[EVIDENCE: ...]` marker.
90
+ 9. **A named existing test is a control, and a control declares its reachability** — When the journey pins an *existing* test as a red-before-green control ("must go red", "fails before the fix and passes after"), the `control-reachability` rule requires the item to say what makes that test reach the changed code: `[CONTROL: <test-identifier> | reaches: <input-or-field>]`, one per named control, validated by gate S20. Name the fixture key, field, argument, or state that carries execution into the change — not the code itself. A test whose fixture never reaches the changed path stays green for a reason unrelated to the change, and the stopping rule then reads as "revert a correct fix". Introducing a **new** test instead carries no such obligation; S20 is `N/A` and no marker is written.
90
91
 
91
92
  ### Step 6: Present to User for Approval
92
93