@codyswann/lisa 2.330.1 → 2.331.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  2. package/dist/core/upstream-evidence-manifest.js +5 -4
  3. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
  8. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +13 -1
  9. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
  10. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
  11. package/plugins/lisa/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
  12. package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +13 -1
  13. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
  14. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
  15. package/plugins/lisa-agy/plugin.json +1 -1
  16. package/plugins/lisa-agy/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
  17. package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +13 -1
  18. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
  19. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
  20. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  23. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-copilot/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
  27. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +13 -1
  28. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
  29. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
  30. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-cursor/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
  32. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +13 -1
  33. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
  34. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
  35. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-expo-agy/plugin.json +1 -1
  38. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  43. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  48. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  53. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  58. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails-agy/plugin.json +1 -1
  63. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  68. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  73. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  75. package/plugins/src/base/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
  76. package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +13 -1
  77. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
  78. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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.330.1",
3
+ "version": "2.331.0",
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"
@@ -563,7 +563,8 @@ export function proposedEntries(proposal) {
563
563
  // the checksum cannot vouch for, which is the one property that makes a
564
564
  // pinned entry worth reviewing.
565
565
  const archive = platform => ({
566
- install: "<release-tar or release-zip, whichever this platform ships>",
566
+ install:
567
+ "<release-tar | release-zip | release-tree — tree when the archive is a directory whose entry point loads its own siblings>",
567
568
  url: `<release url for this exact version, for ${platform}>`,
568
569
  sha256: `<sha256 published with the ${platform} release>`,
569
570
  });
@@ -165,16 +165,28 @@ by platform. Before that existed, the only way to keep a Linux binary off a lapt
165
165
 
166
166
  Expected shape for most projects: a short `require` list, an empty or near-empty `install` list, and the provider CLI as the only thing always provisioned.
167
167
 
168
- ### The three `install` methods
168
+ ### The four `install` methods
169
169
 
170
170
  | `install` | Required fields | Use it when |
171
171
  | --- | --- | --- |
172
172
  | `release-zip` | `url` **and** `sha256` | The vendor publishes a Linux zip of the release. |
173
173
  | `release-tar` | `url` **and** `sha256` — plus `binary` in practice | The vendor publishes no zip for Linux, only a `.tar.gz`. |
174
+ | `release-tree` | `url`, `sha256` **and** `binary` | The archive is a **directory**, not a single binary — an entry point that resolves its own siblings at run time. |
174
175
  | `npm-global` | `package` | The tool ships on the npm registry. |
175
176
 
176
177
  Anything else is rejected by name at plan time, so a typo fails loudly rather than silently installing nothing.
177
178
 
179
+ **`release-tree` exists because the single-file kinds fail silently on a tree.** They extract the archive and copy *one* file onto PATH, which is right for a static binary and wrong for anything that locates its own resources. Maestro is the case that forced it — one 314 MB zip containing:
180
+
181
+ ```text
182
+ maestro/bin/maestro <- launcher
183
+ maestro/lib/*.jar <- 100+ MB of classpath
184
+ ```
185
+
186
+ and a launcher that computes `CLASSPATH=$APP_HOME/lib/*` where `APP_HOME` is the parent of wherever the script itself sits. Declared as `release-zip` with `binary: maestro/bin/maestro`, the launcher lands in `~/.local/bin`, `APP_HOME` resolves to `~/.local`, and the classpath points at an empty directory. **The install reports success and the tool dies at first use** with `Could not find or load main class` — exactly the failure this manifest exists to turn into a loud setup error.
187
+
188
+ So `release-tree` extracts the whole archive to `~/.local/share/<name>/<version>` and puts a **wrapper** on PATH that `exec`s the entry point in place. Not a copy, and deliberately not a symlink either: a launcher that does not resolve symlinks before computing its own location would read the link's directory as its home and look for its resources beside the link — the same broken install, narrowed to a subset of tools. `binary` has no default here, because the archive root is a directory and guessing would install a directory as a binary.
189
+
178
190
  Both archive kinds carry the **same** obligation and differ only in how they are unpacked: `url` and `sha256` are both mandatory, the checksum is verified *before* the archive is unpacked, and a version bump must move the checksum in the same reviewed commit. Neither is a weaker path than the other — `release-tar` exists because some tools worth pinning simply do not publish a zip. `gh` is the case that forced it: it ships `.deb`, `.rpm` and `.tar.gz` and nothing else, so a zip-only installer could not pin the CLI that Lisa's own commit guardrails shell out to.
179
191
 
180
192
  **`binary` means something different for a tarball.** It defaults to the tool's `name` and is resolved relative to the unpacked directory. Release tarballs almost always nest their contents under a versioned top-level directory, so for `release-tar` it must be the path *within* the archive — `gh_2.83.0_linux_amd64/bin/gh`, not `gh`. A bare name there resolves to nothing after a download that otherwise succeeded, and the install fails at the copy step rather than at the fetch, which reads as a broken release when it is a manifest mistake. Bump the version and this path moves with it, alongside the `url` and the `sha256`.
@@ -212,6 +212,94 @@ function installReleaseTar(tool, binDir) {
212
212
  }
213
213
  }
214
214
 
215
+ /**
216
+ * Where a tree-shaped tool's extracted contents live.
217
+ *
218
+ * Versioned so a re-pin lands beside the old copy rather than on top of it, and
219
+ * outside `binDir` because only the entry point belongs on PATH.
220
+ * @param {object} tool Manifest entry.
221
+ * @param {string} binDir Directory holding the symlink.
222
+ * @returns {string} Absolute prefix for this tool and version.
223
+ */
224
+ export function treePrefix(tool, binDir) {
225
+ return join(binDir, "..", "share", tool.name, String(tool.version));
226
+ }
227
+
228
+ /**
229
+ * Install a pinned archive that is a DIRECTORY, not a single binary.
230
+ *
231
+ * `release-zip` and `release-tar` extract and then copy one file onto PATH,
232
+ * which is right for a static binary and silently wrong for anything that
233
+ * resolves its own siblings at run time. Maestro is the case that forced this:
234
+ *
235
+ * maestro/bin/maestro <- launcher
236
+ * maestro/lib/*.jar <- 100+ MB of classpath
237
+ *
238
+ * and the launcher computes `CLASSPATH=$APP_HOME/lib/*` where `APP_HOME` is the
239
+ * parent of wherever the script itself sits. Copy that launcher to
240
+ * `~/.local/bin` and APP_HOME becomes `~/.local`, so the classpath resolves to
241
+ * an empty directory. The install reports success and the tool fails at first
242
+ * use — the failure this manifest exists to turn into a loud setup error.
243
+ *
244
+ * So the whole tree is extracted and the entry point is SYMLINKED. A symlink,
245
+ * not a copy, precisely so that resolution walks back into the extracted tree.
246
+ * @param {object} tool Manifest entry.
247
+ * @param {string} binDir Directory to link the entry point into.
248
+ */
249
+ function installReleaseTree(tool, binDir) {
250
+ const temporary = join(binDir, `.${tool.name}-download`);
251
+ const prefix = treePrefix(tool, binDir);
252
+ mkdirSync(temporary, { recursive: true });
253
+ try {
254
+ const archive = join(temporary, "download.archive");
255
+ execFileSync("curl", ["-fsSL", tool.url, "-o", archive], {
256
+ stdio: "inherit",
257
+ });
258
+ // Verify before unpacking, as everywhere else here: an unexpected archive
259
+ // must fail before any of its contents reach the filesystem.
260
+ verifyChecksum(archive, tool.sha256, tool.name);
261
+
262
+ // Replace rather than layer. Extracting over a previous version leaves both
263
+ // sets of jars on the classpath, which fails in a way that looks like a
264
+ // version bug rather than a stale install.
265
+ rmSync(prefix, { recursive: true, force: true });
266
+ mkdirSync(prefix, { recursive: true });
267
+ if (tool.url.endsWith(".zip")) {
268
+ execFileSync("unzip", ["-q", "-o", archive, "-d", prefix], {
269
+ stdio: "inherit",
270
+ });
271
+ } else {
272
+ execFileSync("tar", ["-xzf", archive, "-C", prefix], {
273
+ stdio: "inherit",
274
+ });
275
+ }
276
+
277
+ const entry = join(prefix, tool.binary);
278
+ if (!existsSync(entry)) {
279
+ throw new Error(
280
+ `${tool.name}: "binary" points at ${tool.binary}, which is not in the ` +
281
+ `archive.\nList the archive and use the path to the entry point ` +
282
+ `inside it, such as "maestro/bin/maestro".`
283
+ );
284
+ }
285
+ chmodSync(entry, 0o755);
286
+
287
+ // A WRAPPER, not a symlink. Both keep the tree intact, but a symlink only
288
+ // works for launchers that resolve symlinks before computing their own
289
+ // location — gradle's template does, and plenty of others do not. One that
290
+ // does not sees the link's directory as its home and looks for its
291
+ // classpath beside the link instead of beside itself, which is the same
292
+ // broken install this kind exists to prevent, reintroduced for a subset of
293
+ // tools. Exec'ing the absolute path removes the assumption entirely.
294
+ const shim = join(binDir, tool.name);
295
+ rmSync(shim, { force: true });
296
+ writeFileSync(shim, `#!/bin/sh\nexec ${JSON.stringify(entry)} "$@"\n`);
297
+ chmodSync(shim, 0o755);
298
+ } finally {
299
+ rmSync(temporary, { recursive: true, force: true });
300
+ }
301
+ }
302
+
215
303
  /**
216
304
  * Install a pinned global npm package.
217
305
  * @param {object} tool Manifest entry.
@@ -239,6 +327,7 @@ export function installTool(tool, binDir) {
239
327
  assertPinned(tool);
240
328
  if (tool.install === "release-zip") installReleaseZip(tool, binDir);
241
329
  else if (tool.install === "release-tar") installReleaseTar(tool, binDir);
330
+ else if (tool.install === "release-tree") installReleaseTree(tool, binDir);
242
331
  else installNpmGlobal(tool);
243
332
  }
244
333
 
@@ -334,6 +334,26 @@ export function assertPinned(tool) {
334
334
  }
335
335
  return;
336
336
  }
337
+ // A tree carries the same checksum obligation and one more: which file inside
338
+ // it is the entry point. There is no sane default — the archive root is a
339
+ // directory, so guessing would install a directory as a binary.
340
+ if (tool.install === "release-tree") {
341
+ if (!tool.url || !tool.sha256) {
342
+ throw new Error(
343
+ `${tool.name}: a release-tree install needs both url and sha256.\n` +
344
+ `A version bump must move the checksum in the same reviewed commit.`
345
+ );
346
+ }
347
+ if (!tool.binary) {
348
+ throw new Error(
349
+ `${tool.name}: a release-tree install needs "binary" — the path to the ` +
350
+ `entry point INSIDE the archive, such as "maestro/bin/maestro".\n` +
351
+ `Unlike the single-file kinds there is nothing to fall back to: the ` +
352
+ `archive root is a directory.`
353
+ );
354
+ }
355
+ return;
356
+ }
337
357
  if (tool.install === "npm-global") {
338
358
  if (!tool.package)
339
359
  throw new Error(`${tool.name}: npm-global install needs a package`);
@@ -341,6 +361,6 @@ export function assertPinned(tool) {
341
361
  }
342
362
  throw new Error(
343
363
  `${tool.name}: unknown install method "${tool.install}".\n` +
344
- `Supported: release-zip, release-tar, npm-global.`
364
+ `Supported: release-zip, release-tar, release-tree, npm-global.`
345
365
  );
346
366
  }