@codyswann/lisa 2.342.3 → 2.342.5

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 (53) hide show
  1. package/all/copy-overwrite/scripts/lisa-work-item.mjs +164 -42
  2. package/dist/core/upstream-evidence-manifest.js +1 -1
  3. package/package.json +1 -1
  4. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  5. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  6. package/plugins/lisa-agy/plugin.json +1 -1
  7. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  8. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  9. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  10. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo-agy/plugin.json +1 -1
  17. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  21. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  22. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  27. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  32. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  37. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-rails-agy/plugin.json +1 -1
  42. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  47. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  52. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
@@ -21,6 +21,36 @@ const RELEASE_SUBJECT =
21
21
  /^chore\(release\): \d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)? \[skip ci\]$/;
22
22
  const ZERO_OID = /^0+$/;
23
23
  const MARKER = "[lisa-pr-link]";
24
+ /**
25
+ * The prefix only — an anchored, fixed-length literal with no quantifier, so
26
+ * it cannot backtrack. The ReDoS was never here; it was in the `\s*(.+?)\s*$`
27
+ * tail, which is now string work.
28
+ *
29
+ * Deliberately still a regex rather than `line.toLowerCase().startsWith(…)`.
30
+ * `toLowerCase()` applies FULL Unicode case mapping, so U+212A KELVIN SIGN
31
+ * folds to "k" and `WorK-Item:` written with it would be accepted — a format
32
+ * this has never accepted, because `/i` on a non-unicode pattern canonicalizes
33
+ * ASCII only.
34
+ */
35
+ const WORK_ITEM_PREFIX = /^work-item:/i;
36
+
37
+ /**
38
+ * The value of a `Work-Item:` line, or null if this is not one.
39
+ *
40
+ * Replaces `/^Work-Item:\s*(.+?)\s*$/i`, which put a lazy quantifier between
41
+ * two `\s*` groups and backtracked super-linearly on a line that is mostly
42
+ * whitespace — over commit messages and PR bodies, which are not this
43
+ * script's to trust. Acceptance is unchanged: ASCII-case-insensitive prefix at
44
+ * the start of the line, non-empty value, surrounding whitespace ignored.
45
+ * @param {string} line One line of a commit message or PR body.
46
+ * @returns {string | null} The trimmed value, or null.
47
+ */
48
+ function workItemLineValue(line) {
49
+ const match = WORK_ITEM_PREFIX.exec(line);
50
+ if (!match) return null;
51
+ const value = line.slice(match[0].length).trim();
52
+ return value === "" ? null : value;
53
+ }
24
54
  const GUIDANCE = [
25
55
  "Mention the ticket this work relates to, or ask Lisa to create one:",
26
56
  " Work-Item: <configured-project-ticket>",
@@ -29,21 +59,9 @@ const GUIDANCE = [
29
59
  class TrackingError extends Error {}
30
60
 
31
61
  /**
32
- * Say which of three different failures a `gh` invocation actually hit.
33
- *
34
- * The three are indistinguishable from an exit status alone, and they send the
35
- * reader to three different places: a missing binary is an environment to
36
- * provision, a refused credential is an access grant to obtain, and only the
37
- * third is anything to do with the ticket.
38
- *
39
- * Collapsing them cost a real round trip. On Claude Code web, where `gh` is not
40
- * pre-installed, every commit was refused with "issue #2202 does not exist or
41
- * is inaccessible" — about an issue that was open and correct. The message
42
- * accused the ticket, so that is where the reader went.
43
- * @param {{status: number|null, error?: Error, stderr?: string}} result Spawn result.
44
- * @param {string} ref Work item reference, for the message.
45
- * @param {string} noun What the reference names.
46
- * @returns {string} A message naming the actual fault.
62
+ * The tracker could not be ASKED a missing binary, a refused credential, a
63
+ * call that never completed. Distinct from a TrackingError, which carries the
64
+ * tracker's own "no". Only this kind may be degraded.
47
65
  */
48
66
  export class TrackerUnreachableError extends TrackingError {}
49
67
 
@@ -61,13 +79,35 @@ export class TrackerUnreachableError extends TrackingError {}
61
79
  */
62
80
  export function githubFailure(result, ref) {
63
81
  const reason = githubFailureReason(result, ref, "GitHub issue");
82
+ // ANY spawn-level error means the tracker could not be asked — the binary is
83
+ // missing (ENOENT), the call was killed at its deadline (ETIMEDOUT), the
84
+ // system could not fork (EAGAIN). Singling out ENOENT made a timed-out `gh`
85
+ // a non-degradable TrackingError, i.e. "this work item is invalid" because
86
+ // the network was slow.
64
87
  const unreachable =
65
- result.error?.code === "ENOENT" || /cannot authenticate/.test(reason);
88
+ result.error !== undefined || /cannot authenticate/.test(reason);
66
89
  return unreachable
67
90
  ? new TrackerUnreachableError(reason)
68
91
  : new TrackingError(reason);
69
92
  }
70
93
 
94
+ /**
95
+ * Say which of three different failures a `gh` invocation actually hit.
96
+ *
97
+ * The three are indistinguishable from an exit status alone, and they send the
98
+ * reader to three different places: a missing binary is an environment to
99
+ * provision, a refused credential is an access grant to obtain, and only the
100
+ * third is anything to do with the ticket.
101
+ *
102
+ * Collapsing them cost a real round trip. On Claude Code web, where `gh` is not
103
+ * pre-installed, every commit was refused with "issue #2202 does not exist or
104
+ * is inaccessible" — about an issue that was open and correct. The message
105
+ * accused the ticket, so that is where the reader went.
106
+ * @param {{status: number|null, error?: Error, stderr?: string}} result Spawn result.
107
+ * @param {string} ref Work item reference, for the message.
108
+ * @param {string} noun What the reference names.
109
+ * @returns {string} A message naming the actual fault.
110
+ */
71
111
  export function githubFailureReason(result, ref, noun) {
72
112
  if (result.error?.code === "ENOENT") {
73
113
  return (
@@ -91,13 +131,38 @@ export function githubFailureReason(result, ref, noun) {
91
131
  return `${noun} ${ref} does not exist or is inaccessible`;
92
132
  }
93
133
 
134
+ /**
135
+ * Wall-clock ceiling for any child process this script spawns.
136
+ *
137
+ * These run inside a git hook, so an unbounded call does not merely wait — it
138
+ * hangs the commit or push that invoked it, with no output explaining why. A
139
+ * tracker that has stopped answering must look like a tracker that is
140
+ * unreachable, which the degradation path already knows how to handle.
141
+ */
142
+ const CHILD_TIMEOUT_MS = Number(
143
+ process.env.LISA_WORK_ITEM_TIMEOUT_MS || 30_000
144
+ );
145
+
94
146
  function run(command, args, options = {}) {
95
147
  const result = spawnSync(command, args, {
96
148
  cwd: options.cwd ?? process.cwd(),
97
149
  encoding: "utf8",
98
150
  env: options.env ?? process.env,
99
151
  input: options.input,
152
+ timeout: options.timeout ?? CHILD_TIMEOUT_MS,
153
+ // SIGKILL, not the default SIGTERM. `timeout` sends killSignal and then
154
+ // keeps waiting for the child to exit, so a child that traps or ignores
155
+ // SIGTERM hangs the hook exactly as long as it would have without any
156
+ // timeout at all. A deadline a child can decline is not a deadline.
157
+ killSignal: "SIGKILL",
100
158
  });
159
+ // spawnSync reports a timeout via `error`, not a non-zero status, so the
160
+ // status check below would let a timed-out call through as success.
161
+ if (result.error && !options.allowFailure) {
162
+ throw new TrackerUnreachableError(
163
+ `${command} ${args.join(" ")} did not complete: ${result.error.message}`
164
+ );
165
+ }
101
166
  if (result.status !== 0 && !options.allowFailure) {
102
167
  throw new TrackingError(
103
168
  options.error ?? `${command} ${args.join(" ")} failed`
@@ -122,10 +187,24 @@ function secureCurl(args, entries, options = {}) {
122
187
  const input = `${entries
123
188
  .map(([name, value]) => `${name} = ${curlConfigValue(value)}`)
124
189
  .join("\n")}\n`;
125
- return run("curl", ["-fsS", "--config", "-", ...args], {
126
- ...options,
127
- input,
128
- });
190
+ // --max-time bounds curl itself, so it exits on its own rather than being
191
+ // killed by the spawnSync ceiling; --connect-timeout fails fast on a host
192
+ // that is not answering at all. Kept below CHILD_TIMEOUT_MS so curl's own
193
+ // error message is what surfaces.
194
+ return run(
195
+ "curl",
196
+ [
197
+ "-fsS",
198
+ "--connect-timeout",
199
+ "10",
200
+ "--max-time",
201
+ "25",
202
+ "--config",
203
+ "-",
204
+ ...args,
205
+ ],
206
+ { ...options, input }
207
+ );
129
208
  }
130
209
 
131
210
  function projectRoot() {
@@ -444,8 +523,8 @@ function parseTrailers(message) {
444
523
  .split("\n")
445
524
  .filter(Boolean)
446
525
  .flatMap(line => {
447
- const match = /^Work-Item:\s*(.+?)\s*$/i.exec(line);
448
- return match ? [match[1]] : [];
526
+ const value = workItemLineValue(line);
527
+ return value === null ? [] : [value];
449
528
  });
450
529
  }
451
530
 
@@ -557,13 +636,34 @@ function typeFromLabels(labels) {
557
636
  return namesFrom(labels).find(name => name.startsWith("type:"));
558
637
  }
559
638
 
639
+ /**
640
+ * Every sub-issue state for a GitHub issue, following pagination.
641
+ *
642
+ * Two things this gets right that the single-page version did not:
643
+ *
644
+ * A transport failure is classified through githubFailure, exactly as
645
+ * githubIssue does. Raising a bare TrackingError meant "gh is missing" and
646
+ * "the network is down" read as "this work item is invalid", so validateLive
647
+ * could not degrade and the hook hard-failed on a laptop with no connection.
648
+ *
649
+ * And it pages. `subIssues(first:100)` silently truncated, so an Epic with
650
+ * more than 100 children reported only the first page — assertLeaf then saw
651
+ * no open child beyond it and treated a container as a leaf, which is the
652
+ * precise condition leaf-only-lifecycle exists to prevent.
653
+ * @param {string} ref Canonical work-item ref, for error messages.
654
+ * @param {object} contract Resolved tracker contract.
655
+ * @param {string|number} number GitHub issue number.
656
+ * @returns {string[]} State of every sub-issue.
657
+ */
560
658
  function githubHierarchy(ref, contract, number) {
561
659
  const [owner, repo] = contract.repository.split("/");
562
660
  const query =
563
- "query($owner:String!,$repo:String!,$number:Int!){repository(owner:$owner,name:$repo){issue(number:$number){subIssues(first:100){nodes{state}}}}}";
564
- const result = run(
565
- "gh",
566
- [
661
+ "query($owner:String!,$repo:String!,$number:Int!,$after:String){repository(owner:$owner,name:$repo){issue(number:$number){subIssues(first:100,after:$after){nodes{state}pageInfo{hasNextPage endCursor}}}}}";
662
+ const states = [];
663
+ const cursor = { after: null };
664
+
665
+ do {
666
+ const args = [
567
667
  "api",
568
668
  "graphql",
569
669
  "-f",
@@ -574,19 +674,25 @@ function githubHierarchy(ref, contract, number) {
574
674
  `repo=${repo}`,
575
675
  "-F",
576
676
  `number=${number}`,
577
- ],
578
- { allowFailure: true }
579
- );
580
- if (result.status !== 0)
581
- throw new TrackingError(`GitHub issue ${ref} hierarchy is inaccessible`);
582
- const response = safeJson(result.stdout, `GitHub issue ${ref} hierarchy`);
583
- const issue = response.data?.repository?.issue;
584
- if (!issue || !Array.isArray(issue.subIssues?.nodes)) {
585
- throw new TrackingError(
586
- `GitHub issue ${ref} did not expose native sub-issue hierarchy`
587
- );
588
- }
589
- return issue.subIssues.nodes.map(child => child.state);
677
+ ];
678
+ if (cursor.after) args.push("-F", `after=${cursor.after}`);
679
+ const result = run("gh", args, { allowFailure: true });
680
+ if (result.status !== 0) throw githubFailure(result, ref);
681
+
682
+ const response = safeJson(result.stdout, `GitHub issue ${ref} hierarchy`);
683
+ const subIssues = response.data?.repository?.issue?.subIssues;
684
+ if (!Array.isArray(subIssues?.nodes)) {
685
+ throw new TrackingError(
686
+ `GitHub issue ${ref} did not expose native sub-issue hierarchy`
687
+ );
688
+ }
689
+ states.push(...subIssues.nodes.map(child => child.state));
690
+ cursor.after = subIssues.pageInfo?.hasNextPage
691
+ ? subIssues.pageInfo.endCursor
692
+ : null;
693
+ } while (cursor.after);
694
+
695
+ return states;
590
696
  }
591
697
 
592
698
  function githubIssue(ref, contract) {
@@ -1103,8 +1209,8 @@ function prWorkItem(body, contract) {
1103
1209
  const matches = String(body ?? "")
1104
1210
  .split(/\r?\n/)
1105
1211
  .flatMap(line => {
1106
- const match = /^Work-Item:\s*(.+?)\s*$/i.exec(line);
1107
- return match ? [match[1]] : [];
1212
+ const value = workItemLineValue(line);
1213
+ return value === null ? [] : [value];
1108
1214
  });
1109
1215
  if (matches.length !== 1)
1110
1216
  throw new TrackingError(
@@ -1152,9 +1258,25 @@ function currentPullRequest(number, repository = currentRepository()) {
1152
1258
  : undefined;
1153
1259
  }
1154
1260
 
1261
+ /**
1262
+ * Read a `--name <value>` option, falling back to an environment variable.
1263
+ *
1264
+ * A flag present but carrying no value — last on the line, or immediately
1265
+ * followed by another flag — used to yield `undefined` (or the next flag's
1266
+ * name) rather than falling back. `lisa … --ref` therefore silently discarded
1267
+ * a perfectly good value in the environment, and `--ref --json` bound the
1268
+ * literal string "--json". Both now behave as if the flag were absent.
1269
+ * @param {string[]} args Argument list.
1270
+ * @param {string} name Flag to read, including leading dashes.
1271
+ * @param {string} envName Environment variable to fall back to.
1272
+ * @returns {string | undefined} The resolved value, if any.
1273
+ */
1155
1274
  function option(args, name, envName) {
1156
1275
  const index = args.indexOf(name);
1157
- return index >= 0 ? args[index + 1] : process.env[envName];
1276
+ if (index < 0) return process.env[envName];
1277
+ const value = args[index + 1];
1278
+ if (value === undefined || value.startsWith("-")) return process.env[envName];
1279
+ return value;
1158
1280
  }
1159
1281
 
1160
1282
  function bind(args) {
@@ -10,7 +10,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
10
10
  "all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh": "1934a15e154fda3c2a40979a5cd6225661b14fe7bc77328a69ce499bea85dba7",
11
11
  "all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh": "d9ea58150aa27e7f0aa9a4ef155ed446d30bdfc932d01c64e2b8ca211aa0de7b",
12
12
  "all/copy-overwrite/scripts/lisa-hooks/sonar-secrets.sh": "bf4132e49ba18e2f7e941520c299c15aeeacfd220e489f3d2eb8397f2048157b",
13
- "all/copy-overwrite/scripts/lisa-work-item.mjs": "2d9ca0841db9e75ddfd95e3a4d485fd01aa639a512ef648996f565b7991d8e2b",
13
+ "all/copy-overwrite/scripts/lisa-work-item.mjs": "e30016a49deff1c3cd3ae7951262aeb2ef3d472bce76bbbe2a177db6017c7cad",
14
14
  "all/create-only/.claude/rules/PROJECT_RULES.md": "6e1c7923ad2a15356babc60c97e7f97be728d790af285b6a7cd7d1b4d39cd97f",
15
15
  "all/create-only/.lisaignore": "3c9827e7e98daa46510b5357cd6dd9406da1821e64cc46d2eea9f311cd6d06b9",
16
16
  "all/create-only/scripts/remote-agent-aws-setup.sh": "12d2204d34195ad4f81082e90a25dbbf7d2493debcc50c1cd37b32dc4648fc17",
package/package.json CHANGED
@@ -120,7 +120,7 @@
120
120
  }
121
121
  },
122
122
  "name": "@codyswann/lisa",
123
- "version": "2.342.3",
123
+ "version": "2.342.5",
124
124
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
125
125
  "main": "dist/index.js",
126
126
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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-cdk",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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-expo",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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": "2.342.3",
3
+ "version": "2.342.5",
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-phaser",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.342.3",
3
+ "version": "2.342.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"