@codyswann/lisa 2.25.0 → 2.25.2

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 (32) hide show
  1. package/.claude-plugin/marketplace.json +6 -0
  2. package/harper-fabric/package-lisa/package.lisa.json +20 -20
  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/rules/config-resolution.md +32 -1
  7. package/plugins/lisa/skills/atlassian-access/SKILL.md +32 -1
  8. package/plugins/lisa/skills/notion-access/SKILL.md +32 -1
  9. package/plugins/lisa/skills/setup-atlassian/SKILL.md +32 -1
  10. package/plugins/lisa/skills/setup-linear/SKILL.md +32 -1
  11. package/plugins/lisa/skills/setup-notion/SKILL.md +32 -1
  12. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-cdk/.codex-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-harper-fabric/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  18. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  20. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  26. package/plugins/src/base/rules/config-resolution.md +32 -1
  27. package/plugins/src/base/skills/atlassian-access/SKILL.md +32 -1
  28. package/plugins/src/base/skills/notion-access/SKILL.md +32 -1
  29. package/plugins/src/base/skills/setup-atlassian/SKILL.md +32 -1
  30. package/plugins/src/base/skills/setup-linear/SKILL.md +32 -1
  31. package/plugins/src/base/skills/setup-notion/SKILL.md +32 -1
  32. package/scripts/check-plugins-sync.sh +37 -0
@@ -38,6 +38,12 @@
38
38
  "description": "AWS CDK plugin",
39
39
  "category": "productivity"
40
40
  },
41
+ {
42
+ "name": "lisa-harper-fabric",
43
+ "source": "./plugins/lisa-harper-fabric",
44
+ "description": "Harper/Fabric-specific rules for TypeScript component apps (Claude + Codex)",
45
+ "category": "productivity"
46
+ },
41
47
  {
42
48
  "name": "lisa-rails",
43
49
  "source": "./plugins/lisa-rails",
@@ -72,26 +72,26 @@
72
72
  },
73
73
  "defaults": {
74
74
  "scripts": {
75
- "build": "tsc && node dist/src/build/build.js",
76
- "seed": "bun run build && node dist/src/scripts/seed.js",
77
- "verify": "bun run build && node dist/src/scripts/verify.js",
78
- "seed:rest": "bun run build && node dist/src/scripts/seed_via_rest.js",
79
- "verify:rest": "bun run build && node dist/src/scripts/verify_via_rest.js",
80
- "preview": "bun run build && node dist/src/scripts/preview_feed.js",
81
- "dev:server": "bun run build && node dist/src/scripts/dev_server.js",
82
- "deploy": "bun run build && node dist/src/scripts/deploy.js",
83
- "smoke": "bun run build && node dist/tests/web_smoke.js",
84
- "smoke:brokercheck": "bun run build && node dist/tests/brokercheck_web_smoke.js",
85
- "token": "bun run build && node dist/src/scripts/get_token.js",
86
- "crawl:wpjson": "bun run build && node dist/src/scripts/crawl_via_wpjson.js",
87
- "crawl:html": "bun run build && node dist/src/scripts/crawl_html.js",
88
- "crawl:playwright": "bun run build && node dist/src/scripts/crawl_playwright.js",
89
- "extract:fields": "bun run build && node dist/src/scripts/extract_fields.js",
90
- "extract:helper": "bun run build && node dist/src/scripts/extract_helper.js",
91
- "ingest": "bun run build && node dist/src/scripts/ingest.js",
92
- "load:extractions": "bun run build && node dist/src/scripts/load_extractions.js",
93
- "brokercheck": "bun run build && node dist/src/scripts/fetch_brokercheck.js",
94
- "brokercheck:crawl": "bun run build && node dist/src/scripts/brokercheck_crawl_all.js"
75
+ "build": "tsc && node dist/build/build.js",
76
+ "seed": "bun run build && node dist/scripts/seed.js",
77
+ "verify": "bun run build && node dist/scripts/verify.js",
78
+ "seed:rest": "bun run build && node dist/scripts/seed_via_rest.js",
79
+ "verify:rest": "bun run build && node dist/scripts/verify_via_rest.js",
80
+ "preview": "bun run build && node dist/scripts/preview_feed.js",
81
+ "dev:server": "bun run build && node dist/scripts/dev_server.js",
82
+ "deploy": "bun run build && node dist/scripts/deploy.js",
83
+ "smoke": "bun run build && bun tests/web_smoke.ts",
84
+ "smoke:brokercheck": "bun run build && bun tests/brokercheck_web_smoke.ts",
85
+ "token": "bun run build && node dist/scripts/get_token.js",
86
+ "crawl:wpjson": "bun run build && node dist/scripts/crawl_via_wpjson.js",
87
+ "crawl:html": "bun run build && node dist/scripts/crawl_html.js",
88
+ "crawl:playwright": "bun run build && node dist/scripts/crawl_playwright.js",
89
+ "extract:fields": "bun run build && node dist/scripts/extract_fields.js",
90
+ "extract:helper": "bun run build && node dist/scripts/extract_helper.js",
91
+ "ingest": "bun run build && node dist/scripts/ingest.js",
92
+ "load:extractions": "bun run build && node dist/scripts/load_extractions.js",
93
+ "brokercheck": "bun run build && node dist/scripts/fetch_brokercheck.js",
94
+ "brokercheck:crawl": "bun run build && node dist/scripts/brokercheck_crawl_all.js"
95
95
  }
96
96
  }
97
97
  }
package/package.json CHANGED
@@ -82,7 +82,7 @@
82
82
  "lodash": ">=4.18.1"
83
83
  },
84
84
  "name": "@codyswann/lisa",
85
- "version": "2.25.0",
85
+ "version": "2.25.2",
86
86
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
87
87
  "main": "dist/index.js",
88
88
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -341,7 +341,38 @@ read_notion_token() {
341
341
  Darwin) security find-generic-password -s lisa-notion -a "$workspace" -w 2>/dev/null ;;
342
342
  Linux) command -v secret-tool >/dev/null && \
343
343
  secret-tool lookup service lisa-notion account "$workspace" 2>/dev/null ;;
344
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-notion-${workspace}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
344
+ MINGW*|MSYS*|CYGWIN*)
345
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
346
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
347
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
348
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
349
+ LISA_CRED_TARGET="lisa-notion-${workspace}" powershell.exe -NoProfile -NonInteractive -Command '
350
+ Add-Type -TypeDefinition @"
351
+ using System;
352
+ using System.Runtime.InteropServices;
353
+ public static class LisaCred {
354
+ [StructLayout(LayoutKind.Sequential)]
355
+ private struct CREDENTIAL {
356
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
357
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
358
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
359
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
360
+ }
361
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
362
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
363
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
364
+ public static string Read(string target) {
365
+ IntPtr p;
366
+ if (!CredRead(target, 1, 0, out p)) { return null; }
367
+ try {
368
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
369
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
370
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
371
+ } finally { CredFree(p); }
372
+ }
373
+ }
374
+ "@
375
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
345
376
  esac
346
377
  }
347
378
  ```
@@ -79,7 +79,38 @@ read_atlassian_token() {
79
79
  case "$(uname -s)" in
80
80
  Darwin) security find-generic-password -s lisa-atlassian -a "$email" -w 2>/dev/null ;;
81
81
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-atlassian account "$email" 2>/dev/null ;;
82
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-atlassian-${email}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
82
+ MINGW*|MSYS*|CYGWIN*)
83
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
84
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
85
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
86
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
87
+ LISA_CRED_TARGET="lisa-atlassian-${email}" powershell.exe -NoProfile -NonInteractive -Command '
88
+ Add-Type -TypeDefinition @"
89
+ using System;
90
+ using System.Runtime.InteropServices;
91
+ public static class LisaCred {
92
+ [StructLayout(LayoutKind.Sequential)]
93
+ private struct CREDENTIAL {
94
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
95
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
96
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
97
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
98
+ }
99
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
100
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
101
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
102
+ public static string Read(string target) {
103
+ IntPtr p;
104
+ if (!CredRead(target, 1, 0, out p)) { return null; }
105
+ try {
106
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
107
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
108
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
109
+ } finally { CredFree(p); }
110
+ }
111
+ }
112
+ "@
113
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
83
114
  esac
84
115
  }
85
116
  TOKEN=$(read_atlassian_token "$EMAIL")
@@ -61,7 +61,38 @@ read_notion_token() {
61
61
  Darwin) security find-generic-password -s lisa-notion -a "$workspace" -w 2>/dev/null ;;
62
62
  Linux) command -v secret-tool >/dev/null && \
63
63
  secret-tool lookup service lisa-notion account "$workspace" 2>/dev/null ;;
64
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-notion-${workspace}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
64
+ MINGW*|MSYS*|CYGWIN*)
65
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
66
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
67
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
68
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
69
+ LISA_CRED_TARGET="lisa-notion-${workspace}" powershell.exe -NoProfile -NonInteractive -Command '
70
+ Add-Type -TypeDefinition @"
71
+ using System;
72
+ using System.Runtime.InteropServices;
73
+ public static class LisaCred {
74
+ [StructLayout(LayoutKind.Sequential)]
75
+ private struct CREDENTIAL {
76
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
77
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
78
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
79
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
80
+ }
81
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
82
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
83
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
84
+ public static string Read(string target) {
85
+ IntPtr p;
86
+ if (!CredRead(target, 1, 0, out p)) { return null; }
87
+ try {
88
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
89
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
90
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
91
+ } finally { CredFree(p); }
92
+ }
93
+ }
94
+ "@
95
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
65
96
  esac
66
97
  }
67
98
  TOKEN=$(read_notion_token "$WORKSPACE")
@@ -80,7 +80,38 @@ read_token() {
80
80
  case "$(uname -s)" in
81
81
  Darwin) security find-generic-password -s lisa-atlassian -a "$email" -w 2>/dev/null ;;
82
82
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-atlassian account "$email" 2>/dev/null ;;
83
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-atlassian-${email}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
83
+ MINGW*|MSYS*|CYGWIN*)
84
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
85
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
86
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
87
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
88
+ LISA_CRED_TARGET="lisa-atlassian-${email}" powershell.exe -NoProfile -NonInteractive -Command '
89
+ Add-Type -TypeDefinition @"
90
+ using System;
91
+ using System.Runtime.InteropServices;
92
+ public static class LisaCred {
93
+ [StructLayout(LayoutKind.Sequential)]
94
+ private struct CREDENTIAL {
95
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
96
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
97
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
98
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
99
+ }
100
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
101
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
102
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
103
+ public static string Read(string target) {
104
+ IntPtr p;
105
+ if (!CredRead(target, 1, 0, out p)) { return null; }
106
+ try {
107
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
108
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
109
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
110
+ } finally { CredFree(p); }
111
+ }
112
+ }
113
+ "@
114
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
84
115
  esac
85
116
  }
86
117
 
@@ -85,7 +85,38 @@ read_linear_key() { # $1=workspace slug
85
85
  case "$(uname -s)" in
86
86
  Darwin) security find-generic-password -s lisa-linear -a "$ws" -w 2>/dev/null ;;
87
87
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-linear account "$ws" 2>/dev/null ;;
88
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-linear-${ws}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
88
+ MINGW*|MSYS*|CYGWIN*)
89
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
90
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
91
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
92
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
93
+ LISA_CRED_TARGET="lisa-linear-${ws}" powershell.exe -NoProfile -NonInteractive -Command '
94
+ Add-Type -TypeDefinition @"
95
+ using System;
96
+ using System.Runtime.InteropServices;
97
+ public static class LisaCred {
98
+ [StructLayout(LayoutKind.Sequential)]
99
+ private struct CREDENTIAL {
100
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
101
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
102
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
103
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
104
+ }
105
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
106
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
107
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
108
+ public static string Read(string target) {
109
+ IntPtr p;
110
+ if (!CredRead(target, 1, 0, out p)) { return null; }
111
+ try {
112
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
113
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
114
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
115
+ } finally { CredFree(p); }
116
+ }
117
+ }
118
+ "@
119
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
89
120
  esac
90
121
  }
91
122
 
@@ -167,7 +167,38 @@ read_notion_token() {
167
167
  case "$(uname -s)" in
168
168
  Darwin) security find-generic-password -s lisa-notion -a "$workspace" -w 2>/dev/null ;;
169
169
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-notion account "$workspace" 2>/dev/null ;;
170
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-notion-${workspace}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
170
+ MINGW*|MSYS*|CYGWIN*)
171
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
172
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
173
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
174
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
175
+ LISA_CRED_TARGET="lisa-notion-${workspace}" powershell.exe -NoProfile -NonInteractive -Command '
176
+ Add-Type -TypeDefinition @"
177
+ using System;
178
+ using System.Runtime.InteropServices;
179
+ public static class LisaCred {
180
+ [StructLayout(LayoutKind.Sequential)]
181
+ private struct CREDENTIAL {
182
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
183
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
184
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
185
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
186
+ }
187
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
188
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
189
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
190
+ public static string Read(string target) {
191
+ IntPtr p;
192
+ if (!CredRead(target, 1, 0, out p)) { return null; }
193
+ try {
194
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
195
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
196
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
197
+ } finally { CredFree(p); }
198
+ }
199
+ }
200
+ "@
201
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
171
202
  esac
172
203
  }
173
204
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
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-expo",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
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-harper-fabric",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
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-nestjs",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
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-rails",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
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-typescript",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint 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.25.0",
3
+ "version": "2.25.2",
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-wiki",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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.25.0",
3
+ "version": "2.25.2",
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"
@@ -341,7 +341,38 @@ read_notion_token() {
341
341
  Darwin) security find-generic-password -s lisa-notion -a "$workspace" -w 2>/dev/null ;;
342
342
  Linux) command -v secret-tool >/dev/null && \
343
343
  secret-tool lookup service lisa-notion account "$workspace" 2>/dev/null ;;
344
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-notion-${workspace}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
344
+ MINGW*|MSYS*|CYGWIN*)
345
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
346
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
347
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
348
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
349
+ LISA_CRED_TARGET="lisa-notion-${workspace}" powershell.exe -NoProfile -NonInteractive -Command '
350
+ Add-Type -TypeDefinition @"
351
+ using System;
352
+ using System.Runtime.InteropServices;
353
+ public static class LisaCred {
354
+ [StructLayout(LayoutKind.Sequential)]
355
+ private struct CREDENTIAL {
356
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
357
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
358
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
359
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
360
+ }
361
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
362
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
363
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
364
+ public static string Read(string target) {
365
+ IntPtr p;
366
+ if (!CredRead(target, 1, 0, out p)) { return null; }
367
+ try {
368
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
369
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
370
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
371
+ } finally { CredFree(p); }
372
+ }
373
+ }
374
+ "@
375
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
345
376
  esac
346
377
  }
347
378
  ```
@@ -79,7 +79,38 @@ read_atlassian_token() {
79
79
  case "$(uname -s)" in
80
80
  Darwin) security find-generic-password -s lisa-atlassian -a "$email" -w 2>/dev/null ;;
81
81
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-atlassian account "$email" 2>/dev/null ;;
82
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-atlassian-${email}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
82
+ MINGW*|MSYS*|CYGWIN*)
83
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
84
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
85
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
86
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
87
+ LISA_CRED_TARGET="lisa-atlassian-${email}" powershell.exe -NoProfile -NonInteractive -Command '
88
+ Add-Type -TypeDefinition @"
89
+ using System;
90
+ using System.Runtime.InteropServices;
91
+ public static class LisaCred {
92
+ [StructLayout(LayoutKind.Sequential)]
93
+ private struct CREDENTIAL {
94
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
95
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
96
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
97
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
98
+ }
99
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
100
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
101
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
102
+ public static string Read(string target) {
103
+ IntPtr p;
104
+ if (!CredRead(target, 1, 0, out p)) { return null; }
105
+ try {
106
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
107
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
108
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
109
+ } finally { CredFree(p); }
110
+ }
111
+ }
112
+ "@
113
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
83
114
  esac
84
115
  }
85
116
  TOKEN=$(read_atlassian_token "$EMAIL")
@@ -61,7 +61,38 @@ read_notion_token() {
61
61
  Darwin) security find-generic-password -s lisa-notion -a "$workspace" -w 2>/dev/null ;;
62
62
  Linux) command -v secret-tool >/dev/null && \
63
63
  secret-tool lookup service lisa-notion account "$workspace" 2>/dev/null ;;
64
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-notion-${workspace}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
64
+ MINGW*|MSYS*|CYGWIN*)
65
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
66
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
67
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
68
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
69
+ LISA_CRED_TARGET="lisa-notion-${workspace}" powershell.exe -NoProfile -NonInteractive -Command '
70
+ Add-Type -TypeDefinition @"
71
+ using System;
72
+ using System.Runtime.InteropServices;
73
+ public static class LisaCred {
74
+ [StructLayout(LayoutKind.Sequential)]
75
+ private struct CREDENTIAL {
76
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
77
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
78
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
79
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
80
+ }
81
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
82
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
83
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
84
+ public static string Read(string target) {
85
+ IntPtr p;
86
+ if (!CredRead(target, 1, 0, out p)) { return null; }
87
+ try {
88
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
89
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
90
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
91
+ } finally { CredFree(p); }
92
+ }
93
+ }
94
+ "@
95
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
65
96
  esac
66
97
  }
67
98
  TOKEN=$(read_notion_token "$WORKSPACE")
@@ -80,7 +80,38 @@ read_token() {
80
80
  case "$(uname -s)" in
81
81
  Darwin) security find-generic-password -s lisa-atlassian -a "$email" -w 2>/dev/null ;;
82
82
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-atlassian account "$email" 2>/dev/null ;;
83
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-atlassian-${email}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
83
+ MINGW*|MSYS*|CYGWIN*)
84
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
85
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
86
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
87
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
88
+ LISA_CRED_TARGET="lisa-atlassian-${email}" powershell.exe -NoProfile -NonInteractive -Command '
89
+ Add-Type -TypeDefinition @"
90
+ using System;
91
+ using System.Runtime.InteropServices;
92
+ public static class LisaCred {
93
+ [StructLayout(LayoutKind.Sequential)]
94
+ private struct CREDENTIAL {
95
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
96
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
97
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
98
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
99
+ }
100
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
101
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
102
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
103
+ public static string Read(string target) {
104
+ IntPtr p;
105
+ if (!CredRead(target, 1, 0, out p)) { return null; }
106
+ try {
107
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
108
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
109
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
110
+ } finally { CredFree(p); }
111
+ }
112
+ }
113
+ "@
114
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
84
115
  esac
85
116
  }
86
117
 
@@ -85,7 +85,38 @@ read_linear_key() { # $1=workspace slug
85
85
  case "$(uname -s)" in
86
86
  Darwin) security find-generic-password -s lisa-linear -a "$ws" -w 2>/dev/null ;;
87
87
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-linear account "$ws" 2>/dev/null ;;
88
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-linear-${ws}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
88
+ MINGW*|MSYS*|CYGWIN*)
89
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
90
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
91
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
92
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
93
+ LISA_CRED_TARGET="lisa-linear-${ws}" powershell.exe -NoProfile -NonInteractive -Command '
94
+ Add-Type -TypeDefinition @"
95
+ using System;
96
+ using System.Runtime.InteropServices;
97
+ public static class LisaCred {
98
+ [StructLayout(LayoutKind.Sequential)]
99
+ private struct CREDENTIAL {
100
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
101
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
102
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
103
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
104
+ }
105
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
106
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
107
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
108
+ public static string Read(string target) {
109
+ IntPtr p;
110
+ if (!CredRead(target, 1, 0, out p)) { return null; }
111
+ try {
112
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
113
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
114
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
115
+ } finally { CredFree(p); }
116
+ }
117
+ }
118
+ "@
119
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
89
120
  esac
90
121
  }
91
122
 
@@ -167,7 +167,38 @@ read_notion_token() {
167
167
  case "$(uname -s)" in
168
168
  Darwin) security find-generic-password -s lisa-notion -a "$workspace" -w 2>/dev/null ;;
169
169
  Linux) command -v secret-tool >/dev/null && secret-tool lookup service lisa-notion account "$workspace" 2>/dev/null ;;
170
- MINGW*|MSYS*|CYGWIN*) cmdkey /list:"lisa-notion-${workspace}" 2>/dev/null | grep Password | awk '{print $NF}' ;;
170
+ MINGW*|MSYS*|CYGWIN*)
171
+ # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
172
+ # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
173
+ # back via the Win32 CredRead API through PowerShell; pass the target name via an env
174
+ # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
175
+ LISA_CRED_TARGET="lisa-notion-${workspace}" powershell.exe -NoProfile -NonInteractive -Command '
176
+ Add-Type -TypeDefinition @"
177
+ using System;
178
+ using System.Runtime.InteropServices;
179
+ public static class LisaCred {
180
+ [StructLayout(LayoutKind.Sequential)]
181
+ private struct CREDENTIAL {
182
+ public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
183
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
184
+ public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
185
+ public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
186
+ }
187
+ [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
188
+ private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
189
+ [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
190
+ public static string Read(string target) {
191
+ IntPtr p;
192
+ if (!CredRead(target, 1, 0, out p)) { return null; }
193
+ try {
194
+ CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
195
+ if (c.CredentialBlobSize == 0) { return String.Empty; }
196
+ return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
197
+ } finally { CredFree(p); }
198
+ }
199
+ }
200
+ "@
201
+ [LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
171
202
  esac
172
203
  }
173
204
 
@@ -43,3 +43,40 @@ if ! git diff --quiet -- plugins/; then
43
43
  fi
44
44
 
45
45
  echo "✓ Plugin artifacts are in sync with plugins/src."
46
+
47
+ # Marketplace coverage: every built plugin directory (plugins/lisa, plugins/lisa-*)
48
+ # must be registered in .claude-plugin/marketplace.json, and every marketplace
49
+ # entry must point at a directory that exists. The reproducibility check above
50
+ # only proves artifacts match plugins/src — it does NOT prove a built plugin is
51
+ # actually published. lisa-harper-fabric shipped built-but-unpublished for
52
+ # exactly this reason: install-claude-plugins.sh tried "lisa-harper-fabric@lisa"
53
+ # but the marketplace never advertised it, so resolution failed at install time.
54
+ MARKETPLACE="$ROOT_DIR/.claude-plugin/marketplace.json"
55
+ marketplace_fail=0
56
+
57
+ # Every built plugin dir needs a marketplace entry whose source points to it.
58
+ while IFS= read -r dir; do
59
+ name="$(basename "$dir")"
60
+ if ! jq -e --arg src "./plugins/$name" '.plugins[] | select(.source == $src)' "$MARKETPLACE" >/dev/null; then
61
+ echo "✗ Built plugin plugins/$name is not registered in .claude-plugin/marketplace.json (expected source \"./plugins/$name\")." >&2
62
+ marketplace_fail=1
63
+ fi
64
+ done < <(find "$ROOT_DIR/plugins" -maxdepth 1 -mindepth 1 -type d ! -name src | sort)
65
+
66
+ # Every marketplace entry must point at a directory that exists.
67
+ while IFS= read -r src; do
68
+ if [ ! -d "$ROOT_DIR/$src" ]; then
69
+ echo "✗ marketplace.json entry source \"$src\" does not exist as a built plugin directory." >&2
70
+ marketplace_fail=1
71
+ fi
72
+ done < <(jq -r '.plugins[].source' "$MARKETPLACE")
73
+
74
+ if [ "$marketplace_fail" -ne 0 ]; then
75
+ echo "" >&2
76
+ echo " Every plugins/lisa* directory must be registered in .claude-plugin/marketplace.json" >&2
77
+ echo " and every marketplace source must point to a real built directory. Edit the manifest" >&2
78
+ echo " at .claude-plugin/marketplace.json, then re-run: bun run check:plugins" >&2
79
+ exit 1
80
+ fi
81
+
82
+ echo "✓ Marketplace registers every built plugin."