@codyswann/lisa 4.64.1 → 4.64.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  2. package/dist/core/lisa-owned-hash-ledger.js +24 -0
  3. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  4. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  5. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  6. package/dist/core/upstream-evidence-manifest.js +19 -17
  7. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  8. package/expo/create-only/stryker.conf.json +1 -0
  9. package/package.json +5 -5
  10. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  12. package/plugins/lisa/.codex-plugin/skills/lisa-design-intake/SKILL.md +1 -1
  13. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +3 -1
  14. package/plugins/lisa/.codex-plugin/skills/lisa-quality-review/SKILL.md +2 -2
  15. package/plugins/lisa/.codex-plugin/skills/lisa-review-local/SKILL.md +9 -3
  16. package/plugins/lisa/.codex-plugin/skills/lisa-tdd-implementation/SKILL.md +2 -1
  17. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-source-artifacts/SKILL.md +3 -1
  18. package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +50 -8
  19. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +24 -0
  20. package/plugins/lisa/rules/reference/design-source-of-truth.md +32 -10
  21. package/plugins/lisa/scripts/design-source-gate.mjs +35 -13
  22. package/plugins/lisa/skills/lisa-design-intake/SKILL.md +1 -1
  23. package/plugins/lisa/skills/lisa-implement/SKILL.md +3 -1
  24. package/plugins/lisa/skills/lisa-quality-review/SKILL.md +2 -2
  25. package/plugins/lisa/skills/lisa-review-local/SKILL.md +9 -3
  26. package/plugins/lisa/skills/lisa-tdd-implementation/SKILL.md +2 -1
  27. package/plugins/lisa/skills/lisa-tracker-source-artifacts/SKILL.md +3 -1
  28. package/plugins/lisa-agy/plugin.json +1 -1
  29. package/plugins/lisa-agy/scripts/design-source-gate.mjs +35 -13
  30. package/plugins/lisa-agy/skills/lisa-design-intake/SKILL.md +1 -1
  31. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +3 -1
  32. package/plugins/lisa-agy/skills/lisa-quality-review/SKILL.md +2 -2
  33. package/plugins/lisa-agy/skills/lisa-review-local/SKILL.md +9 -3
  34. package/plugins/lisa-agy/skills/lisa-tdd-implementation/SKILL.md +2 -1
  35. package/plugins/lisa-agy/skills/lisa-tracker-source-artifacts/SKILL.md +3 -1
  36. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  38. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  39. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +50 -8
  43. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +24 -0
  44. package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +32 -10
  45. package/plugins/lisa-copilot/scripts/design-source-gate.mjs +35 -13
  46. package/plugins/lisa-copilot/skills/lisa-design-intake/SKILL.md +1 -1
  47. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +3 -1
  48. package/plugins/lisa-copilot/skills/lisa-quality-review/SKILL.md +2 -2
  49. package/plugins/lisa-copilot/skills/lisa-review-local/SKILL.md +9 -3
  50. package/plugins/lisa-copilot/skills/lisa-tdd-implementation/SKILL.md +2 -1
  51. package/plugins/lisa-copilot/skills/lisa-tracker-source-artifacts/SKILL.md +3 -1
  52. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +50 -8
  54. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +24 -0
  55. package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +32 -10
  56. package/plugins/lisa-cursor/scripts/design-source-gate.mjs +35 -13
  57. package/plugins/lisa-cursor/skills/lisa-design-intake/SKILL.md +1 -1
  58. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +3 -1
  59. package/plugins/lisa-cursor/skills/lisa-quality-review/SKILL.md +2 -2
  60. package/plugins/lisa-cursor/skills/lisa-review-local/SKILL.md +9 -3
  61. package/plugins/lisa-cursor/skills/lisa-tdd-implementation/SKILL.md +2 -1
  62. package/plugins/lisa-cursor/skills/lisa-tracker-source-artifacts/SKILL.md +3 -1
  63. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-expo-agy/plugin.json +1 -1
  66. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  71. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  75. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  76. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  80. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  81. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  86. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-rails-agy/plugin.json +1 -1
  91. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  95. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  96. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  99. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  100. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  101. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  103. package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +50 -8
  104. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +24 -0
  105. package/plugins/src/base/rules/reference/design-source-of-truth.md +32 -10
  106. package/plugins/src/base/scripts/design-source-gate.mjs +35 -13
  107. package/plugins/src/base/skills/lisa-design-intake/SKILL.md +1 -1
  108. package/plugins/src/base/skills/lisa-implement/SKILL.md +3 -1
  109. package/plugins/src/base/skills/lisa-quality-review/SKILL.md +2 -2
  110. package/plugins/src/base/skills/lisa-review-local/SKILL.md +9 -3
  111. package/plugins/src/base/skills/lisa-tdd-implementation/SKILL.md +2 -1
  112. package/plugins/src/base/skills/lisa-tracker-source-artifacts/SKILL.md +3 -1
  113. package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +50 -8
  114. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +24 -0
  115. package/typescript/copy-overwrite/scripts/lisa-mutation.mjs +297 -25
  116. package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +50 -8
  117. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +24 -0
  118. package/typescript/create-only/stryker.conf.json +1 -0
@@ -18,14 +18,20 @@ One deterministic gate runs ahead of the judgement-based review and is exempt
18
18
  from the confidence filtering below, because it is decided by a script rather
19
19
  than by an agent's opinion.
20
20
 
21
- **Design-source gate (`design-source-of-truth` rule).** Run it against the
22
- branch diff before step 1:
21
+ **Design-source gate (`design-source-of-truth` rule).** First read
22
+ `designSource.enabled` in `.lisa.config.json`. Only boolean `false` opts out:
23
+ omit the design-source review step; do not request DESIGN-SOURCE markers, Figma
24
+ nodes, or Figma access for this obligation. Record `SKIPPED: designSource.enabled=false`
25
+ in the review. Absent, true, or invalid values keep enforcement enabled.
26
+ The separate design-value binding review below still applies.
27
+
28
+ When enabled, run the gate against the branch diff before step 1:
23
29
 
24
30
  ```bash
25
31
  node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/design-source-gate.mjs" --base=main --head=HEAD
26
32
  ```
27
33
 
28
- Exit 0 = PASS, exit 1 = FAIL. A FAIL is a **blocking** review finding and is
34
+ Exit 0 = PASS or explicit SKIPPED, exit 1 = FAIL. A FAIL is a **blocking** review finding and is
29
35
  reported verbatim at the top of the review — it is never scored, never filtered
30
36
  by confidence, and never demoted to a nitpick. It qualifies under
31
37
  `convergent-review` because it names a concrete failure scenario: the design
@@ -72,7 +72,8 @@ TDD Cycle:
72
72
 
73
73
  - Write the minimum production code to make the test pass
74
74
  - Do not optimize, do not add features beyond what the test requires
75
- - For any UI surface the implementation adds or changes, the `design-source-of-truth` rule requires its design-source declaration to land in the same commit as the surface it describes — `DESIGN-SOURCE: <figma-url>` when the surface is backed by a Figma node (sync it back first if Figma access exists), or the exception marker `DESIGN-SOURCE: none — not in Figma` when it genuinely is not captured at the source. `scripts/design-source-gate.mjs` fails closed on an undeclared surface. Cite the rule; do not restate its marker grammar here.
75
+ - Read `designSource.enabled` in `.lisa.config.json` before preparing design-source instructions. Only boolean `false` opts out: omit the design-source step and do not request DESIGN-SOURCE markers, Figma nodes, or Figma access for this obligation. Absent, true, or invalid values keep enforcement enabled.
76
+ - When enabled, for any UI surface the implementation adds or changes, the `design-source-of-truth` rule requires its design-source declaration to land in the same commit as the surface it describes — `DESIGN-SOURCE: <figma-url>` when the surface is backed by a Figma node (sync it back first if Figma access exists), or the exception marker `DESIGN-SOURCE: none — not in Figma` when it genuinely is not captured at the source. `scripts/design-source-gate.mjs` fails closed on an undeclared surface. Cite the rule; do not restate its marker grammar here.
76
77
  - Separately, the `design-value-binding` rule governs where each *value* on that surface came from: in an axis with a published variable collection, bind the variable and use a screenshot only to verify; in an axis with none, measure and record what you derived. A literal in a typed axis is a block, not a TODO. Cite the rule; do not restate its conditions here.
77
78
  - The goal is the simplest code that makes the test green
78
79
 
@@ -93,7 +93,9 @@ Mocks define visual *intent*, not implementation shortcut. Every UI-touching tic
93
93
 
94
94
  If no existing component fits, building a new one is an explicit decision that must be recorded in the ticket (with rationale) before implementation. Lovable-generated components are never the reuse target — always use the project's own components.
95
95
 
96
- The divergence note above covers the **ticket** side of this event. The **code** side is governed by the `design-source-of-truth` rule: a UI surface built with no Figma source behind it is either synced back to Figma and annotated `DESIGN-SOURCE: <figma-url>`, or explicitly marked `DESIGN-SOURCE: none — not in Figma`, and review fails closed if neither happened. Cite the rule for the code obligation rather than restating it here — a ticket comment closes with the ticket, the annotation stays with the surface.
96
+ Before adding the code-side obligation to ticket or teammate instructions, read `designSource.enabled` in `.lisa.config.json`. Only boolean `false` opts out: omit the design-source step; do not request DESIGN-SOURCE markers, Figma nodes, or Figma access for this obligation. Absent, true, or invalid values keep enforcement enabled. Preserve supplied artifacts and component-reuse requirements regardless; `design-value-binding` remains independent.
97
+
98
+ When enabled, the divergence note above covers the **ticket** side of this event. The **code** side is governed by the `design-source-of-truth` rule: a UI surface built with no Figma source behind it is either synced back to Figma and annotated `DESIGN-SOURCE: <figma-url>`, or explicitly marked `DESIGN-SOURCE: none — not in Figma`, and review fails closed if neither happened. Cite the rule for the code obligation rather than restating it here — a ticket comment closes with the ticket, the annotation stays with the surface.
97
99
 
98
100
  ## 8. Preservation gate (run after creating tickets)
99
101
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -18,6 +18,7 @@ import {
18
18
  extractStrykerConstraints,
19
19
  extractStrykerMutate,
20
20
  familyFor,
21
+ globRoot,
21
22
  parseJson,
22
23
  } from "./threshold-ratchet-families.mjs";
23
24
 
@@ -154,15 +155,56 @@ function compareStryker(relPath, base, current) {
154
155
  );
155
156
  const baseMutate = extractStrykerMutate(base);
156
157
  const currentMutate = extractStrykerMutate(current);
158
+ // Roots the gate already covered, and roots this change adds. An exclusion
159
+ // scoped to a newly added root narrows territory that was not being mutated
160
+ // a moment ago, so it cannot shrink the gate — the change is a net widening.
161
+ //
162
+ // Without this, repairing an INERT `mutate` list is unreachable without a
163
+ // human-approved ratchet exception: the repair necessarily adds source roots
164
+ // AND the test-file exclusions that belong with them, and every one of those
165
+ // exclusions read as a weakening. Measured on two repositories whose real
166
+ // effect was 0 -> 69 and 0 -> 75 files mutated (CodySwannGT/lisa#4243).
167
+ const baseRoots = [...baseMutate.positives].map(globRoot);
168
+ /**
169
+ * Whether an exclusion might touch any baseline positive.
170
+ *
171
+ * Both containment directions matter: excluding `src` removes a baseline
172
+ * rooted at `src/existing`, too. An empty prefix (wildcards, braces, classes
173
+ * or extglobs at the root) might cover everything. We grant an exemption
174
+ * only for provably disjoint territory, never from a guessed glob overlap.
175
+ * @param {string} root A rooted glob prefix
176
+ * @returns {boolean} True when overlap cannot be ruled out
177
+ */
178
+ const overlapsBase = root =>
179
+ baseRoots.some(
180
+ base =>
181
+ root === "" ||
182
+ base === "" ||
183
+ root === base ||
184
+ root.startsWith(`${base}/`) ||
185
+ base.startsWith(`${root}/`)
186
+ );
187
+ const addedRoots = [...currentMutate.positives]
188
+ .filter(positive => !baseMutate.positives.has(positive))
189
+ .map(globRoot)
190
+ .filter(root => root !== "");
191
+ /**
192
+ * Whether a root lies inside territory THIS change is adding.
193
+ * @param {string} root A rooted glob prefix
194
+ * @returns {boolean} True when an added root equals or contains it
195
+ */
196
+ const underAdded = root =>
197
+ addedRoots.some(added => root === added || root.startsWith(`${added}/`));
157
198
  for (const negation of currentMutate.negations) {
158
- if (!baseMutate.negations.has(negation)) {
159
- findings.push({
160
- file: relPath,
161
- key: `mutate ${negation}`,
162
- type: TYPE_EXEMPTION_ADDED,
163
- message: `${relPath}: new mutation-testing exclusion "${negation}" — excluding files from a gate is a weakening.`,
164
- });
165
- }
199
+ if (baseMutate.negations.has(negation)) continue;
200
+ const root = globRoot(negation);
201
+ if (!overlapsBase(root) && underAdded(root)) continue;
202
+ findings.push({
203
+ file: relPath,
204
+ key: `mutate ${negation}`,
205
+ type: TYPE_EXEMPTION_ADDED,
206
+ message: `${relPath}: new mutation-testing exclusion "${negation}" — excluding files from a gate is a weakening.`,
207
+ });
166
208
  }
167
209
  for (const positive of baseMutate.positives) {
168
210
  if (!currentMutate.positives.has(positive)) {
@@ -308,6 +308,30 @@ export function extractStrykerMutate(conf) {
308
308
  return { positives, negations };
309
309
  }
310
310
 
311
+ /**
312
+ * The literal directory prefix a glob is rooted at, before any wildcard.
313
+ *
314
+ * `lib/**\/*.spec.ts` and `!lib/**\/*.d.ts` are both rooted at `lib`. This is
315
+ * what lets the ratchet tell territory a change ADDED from territory it
316
+ * already covered: an exclusion inside a newly added root cannot shrink a
317
+ * gate, because nothing there was being mutated a moment ago.
318
+ * @param {string} glob A stryker mutate entry, with or without a leading `!`
319
+ * @returns {string} The rooted prefix, or "" when the glob starts with a wildcard
320
+ */
321
+ export function globRoot(glob) {
322
+ const bare = glob.startsWith("!") ? glob.slice(1) : glob;
323
+ // Backslash escapes and parent traversal make textual containment unsafe.
324
+ // An unknown prefix overlaps everything rather than granting an exemption.
325
+ if (bare.includes("\\") || bare.split("/").includes("..")) return "";
326
+ const rooted = [];
327
+ for (const segment of bare.split("/")) {
328
+ if (segment === "." || segment === "") continue;
329
+ if (["*", "?", "{", "[", "("].some(meta => segment.includes(meta))) break;
330
+ rooted.push(segment);
331
+ }
332
+ return rooted.join("/");
333
+ }
334
+
311
335
  /**
312
336
  * Parse one k6 threshold expression (`p(95)<1000`, `rate>=0.99`, …) into a
313
337
  * ratchet constraint. Upper bounds (`<`, `<=`) may only decrease; lower
@@ -6,18 +6,41 @@ alwaysApply: false
6
6
  # Design Source of Truth
7
7
 
8
8
  > Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
9
- > section below is the former eager head, preserved verbatim; the full
9
+ > section below is the former eager head, maintained with the full
10
10
  > contract follows it. Reachable on demand via [the rule index](00-rule-index.mdc).
11
11
 
12
12
  ## Design Source of Truth (load-bearing)
13
13
 
14
- **Figma is the design source of truth, and every UI surface a change touches declares where its design came from.** A changed UI surface that neither cites a Figma node nor carries the designated marker is a contract violation — and so is a surface whose declaration the gate cannot resolve.
14
+ **When enabled, Figma is the design source of truth, and every UI surface a change touches declares where its design came from.** A changed UI surface that neither cites a Figma node nor carries the designated marker is a contract violation — and so is a surface whose declaration the gate cannot resolve.
15
15
 
16
16
  **One vendor-neutral contract, cited by** `lisa-implement`, `lisa-tdd-implementation`, `lisa-review-local`, `lisa-quality-review`, and `lisa-tracker-source-artifacts` (the `leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug, never divergent per-skill prose).
17
17
 
18
+ ## Explicit project opt-out
19
+
20
+ A project with **no design source at all** may set this in `.lisa.config.json`:
21
+
22
+ ```json
23
+ { "designSource": { "enabled": false } }
24
+ ```
25
+
26
+ Only `designSource.enabled` set to boolean `false` opts out. Absent, true, and
27
+ invalid values retain the default enforcement. The explicit configuration is
28
+ the auditable record; it replaces per-file exception markers for this project.
29
+ The gate exits 0 with `SKIPPED: designSource.enabled=false` before resolving the
30
+ diff. JSON output reports `verdict: "SKIPPED"`, the config key in `reasons`, and
31
+ zero judged surfaces. A skip does not claim that surfaces passed inspection.
32
+
33
+ When opted out, the five consuming skills omit the design-source step from
34
+ plans, tickets, teammate instructions, and review; they do not ask for markers,
35
+ Figma nodes, or Figma access for this obligation. All declaration, sync-back,
36
+ and fail-closed requirements below apply only when enabled. Host design-system
37
+ rules, `design-value-binding`, and `bdd-e2e-coverage` remain independent and
38
+ unchanged. A project that has Figma must still not use `exclude` to hide its UI
39
+ tree from this contract.
40
+
18
41
  ## Membership
19
42
 
20
- Membership is **surface, not repo name or file extension**: a file is in scope the moment a change makes it render something user-observable — a screen, component, layout, style token, visual state, or markup a user reads. Barrels, pure-logic modules, tests, stories, generated output, and vendored code are out. Projects narrow or widen the default detection through `designSource.include` / `designSource.exclude` in `.lisa.config.json`; they never turn the obligation off.
43
+ Membership is **surface, not repo name or file extension**: a file is in scope the moment a change makes it render something user-observable — a screen, component, layout, style token, visual state, or markup a user reads. Barrels, pure-logic modules, tests, stories, generated output, and vendored code are out. Projects narrow or widen the default detection through `designSource.include` / `designSource.exclude` in `.lisa.config.json`; those filters never turn the obligation off. Only the explicit project opt-out above does.
21
44
 
22
45
  ## The two declarations
23
46
 
@@ -44,7 +67,7 @@ Projects that carry their own design-system rules (`figma-design-system`, `desig
44
67
 
45
68
  ## Bootstrap and degradation
46
69
 
47
- Adoption never demands a retroactive backfill: the gate judges **only the surfaces this change touched**. Pre-existing unannotated UI is burndown, recorded and worked down, not this work item's blocker. If a project has no Figma at all, that is not an exemption — every changed surface carries the marker, and the resulting exception list is the honest record of how much of the product lives outside its design source. Behavior obligations for the same surfaces are unchanged and still governed by `bdd-e2e-coverage`.
70
+ Adoption never demands a retroactive backfill: the gate judges **only the surfaces this change touched**. Pre-existing unannotated UI is burndown, recorded and worked down, not this work item's blocker. A project with no design source may use the explicit project opt-out above; otherwise every changed surface still needs a declaration. Behavior obligations for the same surfaces are unchanged and still governed by `bdd-e2e-coverage`.
48
71
 
49
72
  ---
50
73
 
@@ -193,7 +216,7 @@ Two consequences worth stating plainly:
193
216
  node design-source-gate.mjs --base=origin/main [--head=HEAD] [--figma-access] [--json]
194
217
  ```
195
218
 
196
- Exit `0` = PASS, `1` = FAIL, `2` = usage error. It classifies every changed file into one status:
219
+ Exit `0` = PASS or explicit SKIPPED, `1` = FAIL, `2` = usage error. When enabled, it classifies every changed file into one status:
197
220
 
198
221
  | Status | Verdict | Meaning |
199
222
  |---|---|---|
@@ -236,8 +259,7 @@ so a repository with hundreds of unannotated legacy components can adopt the con
236
259
  and be green on Tuesday. Pre-existing unannotated UI is **burndown**: recorded, worked down
237
260
  opportunistically as files are touched, never treated as the current work item's blocker.
238
261
 
239
- A project with no Figma at all is not exempt. Every changed surface carries the marker, and the
240
- resulting exception list is the honest, mounting record of how much of the product lives outside its
241
- design source — which is far more useful than an exemption flag that makes the question disappear.
242
- Deleting or excluding a surface to make the gate green is a violation of the same kind as deleting a
243
- BDD scenario to improve coverage: mark it, do not drop it.
262
+ A project with no design source may opt out explicitly using `designSource.enabled: false`.
263
+ Without that explicit opt-out, every changed surface still declares its source. In an enabled
264
+ project, deleting or excluding a surface to make the gate green is a violation of the same kind as
265
+ deleting a BDD scenario to improve coverage: mark it, do not drop it.
@@ -19,7 +19,11 @@
19
19
  * at the source; it is the exception, not the default, and the gate reports
20
20
  * every one of them so review can challenge it.
21
21
  *
22
- * **The gate fails closed.** Anything it cannot resolve into one of those two
22
+ * Projects with no design source may explicitly set `designSource.enabled`
23
+ * to boolean false. The gate reports SKIPPED before resolving the diff; all
24
+ * other values retain the default enforcement.
25
+ *
26
+ * **When enabled, the gate fails closed.** Anything it cannot resolve into one of those two
23
27
  * declarations is a violation: no annotation, a malformed one, a file that both
24
28
  * cites Figma and denies having a source, a changed file it could not read, or
25
29
  * a diff it could not compute. A gate that returns PASS when it could not look
@@ -32,7 +36,7 @@
32
36
  * to all of it — it asks only whether the design source is declared.
33
37
  *
34
38
  * Run it: `node design-source-gate.mjs --base=origin/main [--head=HEAD] [--json]`
35
- * Exit 0 = PASS, 1 = FAIL (any violation, or anything unresolvable), 2 = usage.
39
+ * Exit 0 = PASS or SKIPPED, 1 = FAIL (any violation, or anything unresolvable), 2 = usage.
36
40
  */
37
41
  import { execFileSync } from "node:child_process";
38
42
  import { readFileSync, realpathSync } from "node:fs";
@@ -338,10 +342,10 @@ export const VIOLATION_STATUSES = new Set([
338
342
  * files?: readonly { path: string, changeType?: string, content?: string | null }[] | null,
339
343
  * diffError?: string | null,
340
344
  * figmaAccess?: boolean,
341
- * config?: { include?: readonly string[], exclude?: readonly string[] }
345
+ * config?: { enabled?: unknown, include?: readonly string[], exclude?: readonly string[] }
342
346
  * }} input Change under evaluation.
343
347
  * @returns {{
344
- * verdict: "PASS" | "FAIL",
348
+ * verdict: "PASS" | "FAIL" | "SKIPPED",
345
349
  * reasons: string[],
346
350
  * violations: object[],
347
351
  * exceptions: object[],
@@ -352,6 +356,21 @@ export const VIOLATION_STATUSES = new Set([
352
356
  * }} The gate result.
353
357
  */
354
358
  export function evaluateDesignSource(input = {}) {
359
+ // Only the explicit boolean opts out: a missing or mistyped setting must
360
+ // never silently remove enforcement from an existing adopter.
361
+ if (input.config?.enabled === false) {
362
+ return {
363
+ verdict: "SKIPPED",
364
+ reasons: ["designSource.enabled=false"],
365
+ violations: [],
366
+ exceptions: [],
367
+ syncBackPreferred: [],
368
+ sealed: [],
369
+ notApplicable: [],
370
+ summary: { judged: 0, sealed: 0, exceptions: 0, violations: 0 },
371
+ };
372
+ }
373
+
355
374
  const reasons = [];
356
375
  const files = Array.isArray(input.files) ? input.files : null;
357
376
 
@@ -452,7 +471,7 @@ export function collectChangedFiles(base, head) {
452
471
  /**
453
472
  * Read the optional `designSource` block from `.lisa.config.json`.
454
473
  *
455
- * @returns {{ include?: string[], exclude?: string[] }} Project overrides, or {}.
474
+ * @returns {{ enabled?: unknown, include?: string[], exclude?: string[] }} Project overrides, or {}.
456
475
  */
457
476
  function readProjectConfig() {
458
477
  try {
@@ -471,6 +490,9 @@ function readProjectConfig() {
471
490
  * @returns {string} Report text.
472
491
  */
473
492
  export function renderReport(result) {
493
+ if (result.verdict === "SKIPPED") {
494
+ return "design-source gate: SKIPPED: designSource.enabled=false";
495
+ }
474
496
  const lines = [`design-source gate: ${result.verdict}`];
475
497
 
476
498
  if (result.verdict === "PASS") {
@@ -534,15 +556,15 @@ export function runCli(argv) {
534
556
  return 2;
535
557
  }
536
558
 
537
- const { files, diffError } = collectChangedFiles(
538
- base,
539
- args.get("head") ?? "HEAD"
540
- );
559
+ const config = readProjectConfig();
560
+ const change =
561
+ config.enabled === false
562
+ ? {}
563
+ : collectChangedFiles(base, args.get("head") ?? "HEAD");
541
564
  const result = evaluateDesignSource({
542
- files,
543
- diffError,
565
+ ...change,
544
566
  figmaAccess: args.get("figma-access") === "true",
545
- config: readProjectConfig(),
567
+ config,
546
568
  });
547
569
 
548
570
  process.stdout.write(
@@ -550,7 +572,7 @@ export function runCli(argv) {
550
572
  ? `${JSON.stringify(result, null, 2)}\n`
551
573
  : `${renderReport(result)}\n`
552
574
  );
553
- return result.verdict === "PASS" ? 0 : 1;
575
+ return result.verdict === "FAIL" ? 1 : 0;
554
576
  }
555
577
 
556
578
  /**
@@ -14,7 +14,7 @@ This skill carries the **judgment**. It does not carry the **policy** — that i
14
14
 
15
15
  ## What this is not
16
16
 
17
- `design-source-of-truth` and `scripts/design-source-gate.mjs` already ask whether a changed surface **declares where its design came from**. This asks the orthogonal question: are the **values on it bound**. Both apply. A surface can cite a perfectly valid design node and still paint a literal that no variable backs — that is the case this skill exists for, and it is invisible to the other gate.
17
+ `design-source-of-truth` and `scripts/design-source-gate.mjs` already ask whether a changed surface **declares where its design came from**. This asks the orthogonal question: are the **values on it bound**. Design-source declarations apply unless the project explicitly sets `designSource.enabled` to boolean `false`; that opt-out does not disable this skill or `design-value-binding`. A surface can cite a perfectly valid design node and still paint a literal that no variable backs — that is the case this skill exists for, and it is invisible to the other gate.
18
18
 
19
19
  ## Why this gate is executable and not advisory
20
20
 
@@ -160,7 +160,9 @@ IF it is a Fix (bug), execute the Reproduce sub-flow FIRST:
160
160
 
161
161
  For any Fix flow, and for any Build flow that changes user-visible behavior, regression coverage is a required deliverable at the highest practical observation level for the reported surface. If the project has a browser, device, or end-to-end harness for that platform (for example Playwright, Maestro, Detox, Cypress, or an equivalent runtime), the task plan and definition of done MUST include a deterministic regression spec against the reported surface, using mocked or seeded data where needed. This is alongside unit or integration coverage, not a substitute for it. For **frontend work** the deliverable is defined by the `bdd-e2e-coverage` rule and has two halves, both landing in this PR: the Gherkin scenario (stable ID, required platforms) added or updated in the project's behavior contract, and aligned automation in the project's configured runner for **every** platform that scenario requires — no runner substitutes for another, because they guard different platforms of the same behavior. The coverage gate must pass and the matrix and burndown be regenerated before the item is done. Cite the rule; do not restate its scenario, waiver, or bootstrap mechanics here.
162
162
 
163
- For work that adds or changes a **UI surface**, the `design-source-of-truth` rule adds a second non-demotable deliverable landing in this same PR: every UI surface the change touches declares where its design came from. Figma is the source of truth, so **prefer sync-back** — if the surface is not in Figma yet and the tool-access preflight proved Figma access, reflect it there and cite the node with `DESIGN-SOURCE: <figma-url>`. Only when the surface genuinely does not belong in the design source (debug affordance, dev-only playground, internal tooling) does it carry the exception marker `DESIGN-SOURCE: none — not in Figma`, ideally with a trailing reason. `scripts/design-source-gate.mjs` decides this deterministically and fails closed on anything it cannot resolve; a FAIL blocks the item exactly as a failing coverage gate does. Host design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or the project's equivalent) stay authoritative about *what* to build — this obligation is only about declaring the source. Cite the rule; do not restate its marker grammar, host-precedence, or bootstrap mechanics here.
163
+ Before preparing any design-source tasks or teammate instructions, read `designSource.enabled` in `.lisa.config.json`. Only boolean `false` opts out: omit the design-source step from the plan and all teammate prompts; do not request DESIGN-SOURCE markers, Figma nodes, or Figma access for this obligation. Absent, true, or invalid values keep enforcement enabled. The separate `design-value-binding` obligation and host design-system rules remain in force.
164
+
165
+ When enabled, for work that adds or changes a **UI surface**, the `design-source-of-truth` rule adds a second non-demotable deliverable landing in this same PR: every UI surface the change touches declares where its design came from. Figma is the source of truth, so **prefer sync-back** — if the surface is not in Figma yet and the tool-access preflight proved Figma access, reflect it there and cite the node with `DESIGN-SOURCE: <figma-url>`. Only when the surface genuinely does not belong in the design source (debug affordance, dev-only playground, internal tooling) does it carry the exception marker `DESIGN-SOURCE: none — not in Figma`, ideally with a trailing reason. `scripts/design-source-gate.mjs` decides this deterministically and fails closed on anything it cannot resolve; a FAIL blocks the item exactly as a failing coverage gate does. Host design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or the project's equivalent) stay authoritative about *what* to build — this obligation is only about declaring the source. Cite the rule; do not restate its marker grammar, host-precedence, or bootstrap mechanics here.
164
166
 
165
167
  The `design-value-binding` rule adds a second, orthogonal obligation on the same surfaces: **values come from design variables where a variable system exists.** That contract asks whether the values are *bound*, not whether the source is *declared* — a surface can cite a valid design node and still paint a literal no variable backs. Resolve the regime per axis, block only on the five objectively checkable conditions, and record every value derived in an untyped axis on the work item. `/lisa:design:intake` runs it. Cite the rule; do not restate its conditions, config schema, or comment grammar here.
166
168
 
@@ -16,7 +16,7 @@ For each changed file, evaluate:
16
16
  3. **Test coverage** -- Tests present? Testing behavior, not implementation details? Edge cases covered?
17
17
  4. **Documentation** -- JSDoc on new functions explaining "why"? Preambles on new files?
18
18
  5. **Code clarity** -- Readable variable names? Unnecessary complexity? Could a new team member understand this?
19
- 6. **Design source** -- For UI surfaces, does each changed file say where its design came from? Run the deterministic gate rather than judging by eye:
19
+ 6. **Design source** -- Read `designSource.enabled` in `.lisa.config.json` first. Only boolean `false` opts out: omit the design-source review step; do not request DESIGN-SOURCE markers, Figma nodes, or Figma access for this obligation. Record `SKIPPED: designSource.enabled=false` in the review. Absent, true, or invalid values keep enforcement enabled. When enabled, for UI surfaces, does each changed file say where its design came from? Run the deterministic gate rather than judging by eye:
20
20
 
21
21
  ```bash
22
22
  node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/design-source-gate.mjs" --base=main --head=HEAD
@@ -24,7 +24,7 @@ For each changed file, evaluate:
24
24
 
25
25
  Exit 1 is a **Critical** finding under the `design-source-of-truth` rule -- the change is blocked until every UI surface either cites a Figma node (`DESIGN-SOURCE: <figma-url>`, the preferred fix -- sync it back) or carries the exception marker `DESIGN-SOURCE: none — not in Figma`. The gate fails closed: an unreadable file or an uncomputable diff is a FAIL, not a pass. Host design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or the project's equivalent) stay authoritative about what to build; this checks only that the source is declared. If the gate script is absent, say so in the review rather than skipping silently.
26
26
 
27
- Review the same surfaces against the `design-value-binding` rule as well — it asks the orthogonal question of whether each value is *bound* to what the design system publishes, not whether the source is declared. A literal in an axis the project publishes variables for is a **Critical** finding; the identical literal in an axis with no variable collection is correct and must not be flagged. Aesthetic disagreement is never a finding under this rule. Cite the rule; do not restate its conditions here.
27
+ 7. **Design-value binding** -- Independently of the design-source opt-out, review the same surfaces against the `design-value-binding` rule — it asks the orthogonal question of whether each value is *bound* to what the design system publishes, not whether the source is declared. A literal in an axis the project publishes variables for is a **Critical** finding; the identical literal in an axis with no variable collection is correct and must not be flagged. Aesthetic disagreement is never a finding under this rule. Cite the rule; do not restate its conditions here.
28
28
 
29
29
  ## Output Format
30
30
 
@@ -18,14 +18,20 @@ One deterministic gate runs ahead of the judgement-based review and is exempt
18
18
  from the confidence filtering below, because it is decided by a script rather
19
19
  than by an agent's opinion.
20
20
 
21
- **Design-source gate (`design-source-of-truth` rule).** Run it against the
22
- branch diff before step 1:
21
+ **Design-source gate (`design-source-of-truth` rule).** First read
22
+ `designSource.enabled` in `.lisa.config.json`. Only boolean `false` opts out:
23
+ omit the design-source review step; do not request DESIGN-SOURCE markers, Figma
24
+ nodes, or Figma access for this obligation. Record `SKIPPED: designSource.enabled=false`
25
+ in the review. Absent, true, or invalid values keep enforcement enabled.
26
+ The separate design-value binding review below still applies.
27
+
28
+ When enabled, run the gate against the branch diff before step 1:
23
29
 
24
30
  ```bash
25
31
  node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/design-source-gate.mjs" --base=main --head=HEAD
26
32
  ```
27
33
 
28
- Exit 0 = PASS, exit 1 = FAIL. A FAIL is a **blocking** review finding and is
34
+ Exit 0 = PASS or explicit SKIPPED, exit 1 = FAIL. A FAIL is a **blocking** review finding and is
29
35
  reported verbatim at the top of the review — it is never scored, never filtered
30
36
  by confidence, and never demoted to a nitpick. It qualifies under
31
37
  `convergent-review` because it names a concrete failure scenario: the design
@@ -72,7 +72,8 @@ TDD Cycle:
72
72
 
73
73
  - Write the minimum production code to make the test pass
74
74
  - Do not optimize, do not add features beyond what the test requires
75
- - For any UI surface the implementation adds or changes, the `design-source-of-truth` rule requires its design-source declaration to land in the same commit as the surface it describes — `DESIGN-SOURCE: <figma-url>` when the surface is backed by a Figma node (sync it back first if Figma access exists), or the exception marker `DESIGN-SOURCE: none — not in Figma` when it genuinely is not captured at the source. `scripts/design-source-gate.mjs` fails closed on an undeclared surface. Cite the rule; do not restate its marker grammar here.
75
+ - Read `designSource.enabled` in `.lisa.config.json` before preparing design-source instructions. Only boolean `false` opts out: omit the design-source step and do not request DESIGN-SOURCE markers, Figma nodes, or Figma access for this obligation. Absent, true, or invalid values keep enforcement enabled.
76
+ - When enabled, for any UI surface the implementation adds or changes, the `design-source-of-truth` rule requires its design-source declaration to land in the same commit as the surface it describes — `DESIGN-SOURCE: <figma-url>` when the surface is backed by a Figma node (sync it back first if Figma access exists), or the exception marker `DESIGN-SOURCE: none — not in Figma` when it genuinely is not captured at the source. `scripts/design-source-gate.mjs` fails closed on an undeclared surface. Cite the rule; do not restate its marker grammar here.
76
77
  - Separately, the `design-value-binding` rule governs where each *value* on that surface came from: in an axis with a published variable collection, bind the variable and use a screenshot only to verify; in an axis with none, measure and record what you derived. A literal in a typed axis is a block, not a TODO. Cite the rule; do not restate its conditions here.
77
78
  - The goal is the simplest code that makes the test green
78
79
 
@@ -93,7 +93,9 @@ Mocks define visual *intent*, not implementation shortcut. Every UI-touching tic
93
93
 
94
94
  If no existing component fits, building a new one is an explicit decision that must be recorded in the ticket (with rationale) before implementation. Lovable-generated components are never the reuse target — always use the project's own components.
95
95
 
96
- The divergence note above covers the **ticket** side of this event. The **code** side is governed by the `design-source-of-truth` rule: a UI surface built with no Figma source behind it is either synced back to Figma and annotated `DESIGN-SOURCE: <figma-url>`, or explicitly marked `DESIGN-SOURCE: none — not in Figma`, and review fails closed if neither happened. Cite the rule for the code obligation rather than restating it here — a ticket comment closes with the ticket, the annotation stays with the surface.
96
+ Before adding the code-side obligation to ticket or teammate instructions, read `designSource.enabled` in `.lisa.config.json`. Only boolean `false` opts out: omit the design-source step; do not request DESIGN-SOURCE markers, Figma nodes, or Figma access for this obligation. Absent, true, or invalid values keep enforcement enabled. Preserve supplied artifacts and component-reuse requirements regardless; `design-value-binding` remains independent.
97
+
98
+ When enabled, the divergence note above covers the **ticket** side of this event. The **code** side is governed by the `design-source-of-truth` rule: a UI surface built with no Figma source behind it is either synced back to Figma and annotated `DESIGN-SOURCE: <figma-url>`, or explicitly marked `DESIGN-SOURCE: none — not in Figma`, and review fails closed if neither happened. Cite the rule for the code obligation rather than restating it here — a ticket comment closes with the ticket, the annotation stays with the surface.
97
99
 
98
100
  ## 8. Preservation gate (run after creating tickets)
99
101
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "4.64.1",
3
+ "version": "4.64.3",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"