@codyswann/lisa 2.170.0 → 2.171.1

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 (77) hide show
  1. package/dist/codex/scripts/install-pkgs.sh +33 -11
  2. package/dist/utils/package-manager-detect.d.ts +66 -0
  3. package/dist/utils/package-manager-detect.d.ts.map +1 -0
  4. package/dist/utils/package-manager-detect.js +109 -0
  5. package/dist/utils/package-manager-detect.js.map +1 -0
  6. package/dist/utils/postinstall-trampoline.d.ts +3 -32
  7. package/dist/utils/postinstall-trampoline.d.ts.map +1 -1
  8. package/dist/utils/postinstall-trampoline.js +22 -65
  9. package/dist/utils/postinstall-trampoline.js.map +1 -1
  10. package/package.json +1 -1
  11. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  13. package/plugins/lisa/hooks/install-pkgs.sh +34 -12
  14. package/plugins/lisa/skills/generate-claude-remote-build-script/SKILL.md +25 -3
  15. package/plugins/lisa-agy/plugin.json +1 -1
  16. package/plugins/lisa-agy/skills/generate-claude-remote-build-script/SKILL.md +25 -3
  17. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  20. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/hooks/install-pkgs.sh +34 -12
  24. package/plugins/lisa-copilot/skills/generate-claude-remote-build-script/SKILL.md +25 -3
  25. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cursor/hooks/install-pkgs.sh +34 -12
  27. package/plugins/lisa-cursor/skills/generate-claude-remote-build-script/SKILL.md +25 -3
  28. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo-agy/plugin.json +1 -1
  31. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric/skills/harper-caching/SKILL.md +265 -0
  36. package/plugins/lisa-harper-fabric/skills/harper-caching/agents/openai.yaml +4 -0
  37. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric-agy/skills/harper-caching/SKILL.md +265 -0
  39. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric-copilot/skills/harper-caching/SKILL.md +265 -0
  41. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-cursor/skills/harper-caching/SKILL.md +265 -0
  43. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  46. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  50. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  51. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  55. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  56. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-rails-agy/plugin.json +1 -1
  61. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  66. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  71. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  73. package/plugins/src/base/hooks/install-pkgs.sh +34 -12
  74. package/plugins/src/base/skills/generate-claude-remote-build-script/SKILL.md +25 -3
  75. package/plugins/src/harper-fabric/skills/harper-caching/SKILL.md +265 -0
  76. package/scripts/claude-remote-setup.sh +31 -3
  77. package/typescript/copy-contents/.husky/pre-push +8 -1
@@ -11,16 +11,38 @@ if [ -d "node_modules" ] || [ ! -f "package.json" ]; then
11
11
  exit 0
12
12
  fi
13
13
 
14
- if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
15
- command -v bun >/dev/null 2>&1 && bun install
16
- elif [ -f "pnpm-lock.yaml" ]; then
17
- command -v pnpm >/dev/null 2>&1 && pnpm install
18
- elif [ -f "yarn.lock" ]; then
19
- command -v yarn >/dev/null 2>&1 && yarn install
20
- elif [ -f "package-lock.json" ]; then
21
- command -v npm >/dev/null 2>&1 && npm install
22
- else
23
- command -v npm >/dev/null 2>&1 && npm install
24
- fi
14
+ # Detect the package manager this project wants, honoring explicit opt-outs.
15
+ # Precedence: packageManager field > engines "please-use-<pm>" sentinel >
16
+ # lockfile presence (minus any PM the engines forbid) > npm default.
17
+ #
18
+ # This must NOT key on lockfile presence alone. An npm-only project
19
+ # (engines.bun = "please-use-npm", CI runs `npm ci`) that picks up a stray
20
+ # bun.lock would otherwise get `bun install`, re-create the bun.lock, and break
21
+ # — the SE-5221 regression. The engines/packageManager signals are
22
+ # authoritative; lockfiles are only a fallback and never override an opt-out.
23
+ detect_package_manager() {
24
+ _field="" _forced="" _forbidden=""
25
+ if [ -f package.json ] && command -v jq >/dev/null 2>&1; then
26
+ _field=$(jq -r '(.packageManager // "") | sub("@.*$";"")' package.json 2>/dev/null)
27
+ _forced=$(jq -r 'first((.engines // {})[] | strings | capture("please-use-(?<pm>bun|npm|yarn|pnpm)")?.pm) // ""' package.json 2>/dev/null)
28
+ _forbidden=$(jq -r '[(.engines // {}) | to_entries[] | select(((.value|strings) // "") | test("please-use|do-not-use";"i")) | .key] | join(" ")' package.json 2>/dev/null)
29
+ fi
30
+ case "$_field" in bun | npm | yarn | pnpm) printf '%s\n' "$_field"; return 0 ;; esac
31
+ case "$_forced" in bun | npm | yarn | pnpm) printf '%s\n' "$_forced"; return 0 ;; esac
32
+ _pm_allowed() { case " $_forbidden " in *" $1 "*) return 1 ;; *) return 0 ;; esac; }
33
+ if { [ -f bun.lockb ] || [ -f bun.lock ]; } && _pm_allowed bun; then printf 'bun\n'; return 0; fi
34
+ if [ -f pnpm-lock.yaml ] && _pm_allowed pnpm; then printf 'pnpm\n'; return 0; fi
35
+ if [ -f yarn.lock ] && _pm_allowed yarn; then printf 'yarn\n'; return 0; fi
36
+ if [ -f package-lock.json ] && _pm_allowed npm; then printf 'npm\n'; return 0; fi
37
+ printf 'npm\n'
38
+ }
39
+
40
+ PACKAGE_MANAGER="$(detect_package_manager)"
41
+ case "$PACKAGE_MANAGER" in
42
+ bun) command -v bun >/dev/null 2>&1 && bun install ;;
43
+ pnpm) command -v pnpm >/dev/null 2>&1 && pnpm install ;;
44
+ yarn) command -v yarn >/dev/null 2>&1 && yarn install ;;
45
+ *) command -v npm >/dev/null 2>&1 && npm install ;;
46
+ esac
25
47
 
26
48
  exit 0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Known package managers whose lockfiles must be regenerated when Lisa's apply
3
+ * mutates package.json (e.g., adds/updates resolutions or overrides entries).
4
+ */
5
+ export type PackageManager = "bun" | "npm" | "pnpm" | "yarn";
6
+ /**
7
+ * Description of a package manager's lockfile file + the command Lisa should run
8
+ * to rebuild the lockfile without running install scripts.
9
+ */
10
+ export interface LockfileRegenPlan {
11
+ readonly pm: PackageManager;
12
+ readonly lockfile: string;
13
+ /** Additional lockfile names for the same PM (e.g. bun.lockb for bun). */
14
+ readonly lockfileAlternatives?: readonly string[];
15
+ readonly command: string;
16
+ readonly args: readonly string[];
17
+ }
18
+ /**
19
+ * Per-PM lockfile + regen command mapping. The regen commands are all
20
+ * "sync lockfile without running scripts" variants — we do NOT want to
21
+ * re-run lifecycle scripts (that would re-trigger the trampoline).
22
+ *
23
+ * bun: `bun install` is the canonical way to sync bun.lock after package.json
24
+ * changes. As of bun 1.x there is no `--lockfile-only` flag; `bun install`
25
+ * is already fast when node_modules is up-to-date and will simply update
26
+ * bun.lock to match package.json. We pass `--ignore-scripts` to avoid re-running
27
+ * the parent PM's lifecycle hooks (which triggered this trampoline to begin with).
28
+ */
29
+ export declare const LOCKFILE_REGEN_PLANS: Readonly<Record<PackageManager, LockfileRegenPlan>>;
30
+ /**
31
+ * Read the set of package managers a project explicitly opts OUT of via its
32
+ * package.json `engines` field. The repo-wide convention is to pin an unwanted
33
+ * package manager to a sentinel string such as `"please-use-npm"` (e.g. an
34
+ * npm-only project sets `engines.bun = "please-use-npm"`). Such a manager must
35
+ * never have its lockfile regenerated — even if a stray lockfile for it is
36
+ * present — because doing so re-creates the stray lockfile via that manager's
37
+ * `install`. That is the SE-5221 regression: a stray `bun.lock` in an npm-only
38
+ * project kept alive by `bun install`, which then misroutes the pre-push hook's
39
+ * package-manager detection to the bun branch.
40
+ * @param projectDir - Absolute path to the project directory
41
+ * @returns Set of package managers the project forbids (possibly empty)
42
+ */
43
+ export declare function enginesForbiddenManagers(projectDir: string): ReadonlySet<PackageManager>;
44
+ /**
45
+ * Detect which package managers the project uses based on lockfile presence,
46
+ * excluding any manager the project explicitly forbids via `engines`.
47
+ *
48
+ * A project may have more than one lockfile (the CDK dual-lockfile pattern
49
+ * keeps `bun.lock` for local dev while publishing `package-lock.json` for
50
+ * consumers), in which case every present lockfile must be regenerated so both
51
+ * stay in sync with package.json.
52
+ *
53
+ * Managers opted out via an `engines` sentinel (e.g. `bun = "please-use-npm"`)
54
+ * are dropped even when their lockfile is present, so the reconciliation never
55
+ * re-creates a stray lockfile the project deliberately disallows (SE-5221).
56
+ * @param projectDir - Absolute path to the project directory
57
+ * @returns Ordered list of detected package managers (possibly empty)
58
+ */
59
+ export declare function detectPackageManagers(projectDir: string): readonly PackageManager[];
60
+ /**
61
+ * Get the regen plan (command/args/lockfile) for a given package manager.
62
+ * @param pm - Package manager to look up
63
+ * @returns Regen plan describing which command to spawn
64
+ */
65
+ export declare function getLockfileRegenPlan(pm: PackageManager): LockfileRegenPlan;
66
+ //# sourceMappingURL=package-manager-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manager-detect.d.ts","sourceRoot":"","sources":["../../src/utils/package-manager-detect.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAKD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CACzC,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,CA2BjC,CAAC;AAEX;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,GACjB,WAAW,CAAC,cAAc,CAAC,CAmB7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GACjB,SAAS,cAAc,EAAE,CAU3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,iBAAiB,CAE1E"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @file package-manager-detect.ts
3
+ * @description Package-manager detection + lockfile-regen plans shared by the
4
+ * postinstall reconciliation trampoline. Split out from postinstall-trampoline
5
+ * so the detection surface (which manager a project actually uses, and which it
6
+ * explicitly forbids via `engines`) lives in one cohesive, well-tested module.
7
+ * @module utils
8
+ */
9
+ import { existsSync, readFileSync } from "node:fs";
10
+ import * as path from "node:path";
11
+ const INSTALL = "install";
12
+ const IGNORE_SCRIPTS = "--ignore-scripts";
13
+ /**
14
+ * Per-PM lockfile + regen command mapping. The regen commands are all
15
+ * "sync lockfile without running scripts" variants — we do NOT want to
16
+ * re-run lifecycle scripts (that would re-trigger the trampoline).
17
+ *
18
+ * bun: `bun install` is the canonical way to sync bun.lock after package.json
19
+ * changes. As of bun 1.x there is no `--lockfile-only` flag; `bun install`
20
+ * is already fast when node_modules is up-to-date and will simply update
21
+ * bun.lock to match package.json. We pass `--ignore-scripts` to avoid re-running
22
+ * the parent PM's lifecycle hooks (which triggered this trampoline to begin with).
23
+ */
24
+ export const LOCKFILE_REGEN_PLANS = {
25
+ bun: {
26
+ pm: "bun",
27
+ lockfile: "bun.lock",
28
+ lockfileAlternatives: ["bun.lockb"],
29
+ command: "bun",
30
+ args: [INSTALL, IGNORE_SCRIPTS],
31
+ },
32
+ npm: {
33
+ pm: "npm",
34
+ lockfile: "package-lock.json",
35
+ command: "npm",
36
+ args: [INSTALL, "--package-lock-only", IGNORE_SCRIPTS],
37
+ },
38
+ pnpm: {
39
+ pm: "pnpm",
40
+ lockfile: "pnpm-lock.yaml",
41
+ command: "pnpm",
42
+ args: [INSTALL, "--lockfile-only", IGNORE_SCRIPTS],
43
+ },
44
+ yarn: {
45
+ pm: "yarn",
46
+ lockfile: "yarn.lock",
47
+ command: "yarn",
48
+ args: [INSTALL, "--mode", "update-lockfile"],
49
+ },
50
+ };
51
+ /**
52
+ * Read the set of package managers a project explicitly opts OUT of via its
53
+ * package.json `engines` field. The repo-wide convention is to pin an unwanted
54
+ * package manager to a sentinel string such as `"please-use-npm"` (e.g. an
55
+ * npm-only project sets `engines.bun = "please-use-npm"`). Such a manager must
56
+ * never have its lockfile regenerated — even if a stray lockfile for it is
57
+ * present — because doing so re-creates the stray lockfile via that manager's
58
+ * `install`. That is the SE-5221 regression: a stray `bun.lock` in an npm-only
59
+ * project kept alive by `bun install`, which then misroutes the pre-push hook's
60
+ * package-manager detection to the bun branch.
61
+ * @param projectDir - Absolute path to the project directory
62
+ * @returns Set of package managers the project forbids (possibly empty)
63
+ */
64
+ export function enginesForbiddenManagers(projectDir) {
65
+ try {
66
+ const pkg = JSON.parse(readFileSync(path.join(projectDir, "package.json"), "utf8"));
67
+ const engines = pkg.engines ?? {};
68
+ const managers = ["bun", "npm", "yarn", "pnpm"];
69
+ return new Set(managers.filter(pm => {
70
+ const value = engines[pm];
71
+ return (typeof value === "string" && /please-use|do-not-use/i.test(value));
72
+ }));
73
+ }
74
+ catch {
75
+ // No package.json, or it is unreadable/invalid — nothing is forbidden.
76
+ return new Set();
77
+ }
78
+ }
79
+ /**
80
+ * Detect which package managers the project uses based on lockfile presence,
81
+ * excluding any manager the project explicitly forbids via `engines`.
82
+ *
83
+ * A project may have more than one lockfile (the CDK dual-lockfile pattern
84
+ * keeps `bun.lock` for local dev while publishing `package-lock.json` for
85
+ * consumers), in which case every present lockfile must be regenerated so both
86
+ * stay in sync with package.json.
87
+ *
88
+ * Managers opted out via an `engines` sentinel (e.g. `bun = "please-use-npm"`)
89
+ * are dropped even when their lockfile is present, so the reconciliation never
90
+ * re-creates a stray lockfile the project deliberately disallows (SE-5221).
91
+ * @param projectDir - Absolute path to the project directory
92
+ * @returns Ordered list of detected package managers (possibly empty)
93
+ */
94
+ export function detectPackageManagers(projectDir) {
95
+ const forbidden = enginesForbiddenManagers(projectDir);
96
+ return Object.values(LOCKFILE_REGEN_PLANS)
97
+ .filter(plan => [plan.lockfile, ...(plan.lockfileAlternatives ?? [])].some(f => existsSync(path.join(projectDir, f))))
98
+ .map(plan => plan.pm)
99
+ .filter(pm => !forbidden.has(pm));
100
+ }
101
+ /**
102
+ * Get the regen plan (command/args/lockfile) for a given package manager.
103
+ * @param pm - Package manager to look up
104
+ * @returns Regen plan describing which command to spawn
105
+ */
106
+ export function getLockfileRegenPlan(pm) {
107
+ return LOCKFILE_REGEN_PLANS[pm];
108
+ }
109
+ //# sourceMappingURL=package-manager-detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manager-detect.js","sourceRoot":"","sources":["../../src/utils/package-manager-detect.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
- /**
3
- * Known package managers whose lockfiles must be regenerated when Lisa's apply
4
- * mutates package.json (e.g., adds/updates resolutions or overrides entries).
5
- */
6
- export type PackageManager = "bun" | "npm" | "pnpm" | "yarn";
7
- /**
8
- * Description of a package manager's lockfile file + the command Lisa should run
9
- * to rebuild the lockfile without running install scripts.
10
- */
11
- export interface LockfileRegenPlan {
12
- readonly pm: PackageManager;
13
- readonly lockfile: string;
14
- readonly command: string;
15
- readonly args: readonly string[];
16
- }
2
+ import { type LockfileRegenPlan, type PackageManager, LOCKFILE_REGEN_PLANS, detectPackageManagers, enginesForbiddenManagers, getLockfileRegenPlan } from "./package-manager-detect.js";
3
+ export { LOCKFILE_REGEN_PLANS, detectPackageManagers, enginesForbiddenManagers, getLockfileRegenPlan, };
4
+ export type { LockfileRegenPlan, PackageManager };
17
5
  /**
18
6
  * Determine whether this Lisa invocation is running as a package-manager lifecycle
19
7
  * script (postinstall, prepare, etc.). Works across npm, bun, yarn, and pnpm since
@@ -70,23 +58,6 @@ export declare function shouldSchedulePostinstallReconciliation(dryRun: boolean)
70
58
  * @returns Absolute path to the Lisa dist directory
71
59
  */
72
60
  export declare function getLisaDistDir(moduleUrl: string): string;
73
- /**
74
- * Detect which package managers the project uses based on lockfile presence.
75
- *
76
- * A project may have more than one lockfile (the CDK dual-lockfile pattern
77
- * keeps `bun.lock` for local dev while publishing `package-lock.json` for
78
- * consumers), in which case every present lockfile must be regenerated so both
79
- * stay in sync with package.json.
80
- * @param projectDir - Absolute path to the project directory
81
- * @returns Ordered list of detected package managers (possibly empty)
82
- */
83
- export declare function detectPackageManagers(projectDir: string): readonly PackageManager[];
84
- /**
85
- * Get the regen plan (command/args/lockfile) for a given package manager.
86
- * @param pm - Package manager to look up
87
- * @returns Regen plan describing which command to spawn
88
- */
89
- export declare function getLockfileRegenPlan(pm: PackageManager): LockfileRegenPlan;
90
61
  /**
91
62
  * Hash a file's contents (sha256, hex-encoded). Returns null if the file
92
63
  * does not exist or cannot be read. Used to detect whether Lisa mutated
@@ -1 +1 @@
1
- {"version":3,"file":"postinstall-trampoline.d.ts","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAwC3C;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AA6DD;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,OAAO,CASvC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,OAAO,GACd,OAAO,CAYT;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,GACjB,SAAS,cAAc,EAAE,CAI3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,iBAAiB,CAE1E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAMjB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmCf"}
1
+ {"version":3,"file":"postinstall-trampoline.d.ts","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAU3C,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AAkCrC,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,GACrB,CAAC;AACF,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC;AAkBlD;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,OAAO,CASvC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,OAAO,GACd,OAAO,CAYT;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAMjB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmCf"}
@@ -1,9 +1,10 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
- import { existsSync, readFileSync } from "node:fs";
3
+ import { readFileSync } from "node:fs";
4
4
  import * as path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { PM_PATH_ENV_NAMES, PM_PATH_ENV_PREFIXES, sanitizeEnvForReconciliation, } from "./pm-env.js";
7
+ import { LOCKFILE_REGEN_PLANS, detectPackageManagers, enginesForbiddenManagers, getLockfileRegenPlan, } from "./package-manager-detect.js";
7
8
  /**
8
9
  * Env var set by npm/bun/yarn/pnpm when running lifecycle scripts (postinstall, etc.).
9
10
  * Used to detect whether Lisa was invoked as a postinstall child of a package manager.
@@ -28,45 +29,10 @@ const POLL_INTERVAL_MS = 100;
28
29
  * writes a moment to quiesce before Lisa re-applies its changes.
29
30
  */
30
31
  const SETTLE_DELAY_MS = 250;
31
- /**
32
- * Per-PM lockfile + regen command mapping. The regen commands are all
33
- * "sync lockfile without running scripts" variants — we do NOT want to
34
- * re-run lifecycle scripts (that would re-trigger the trampoline).
35
- *
36
- * bun: `bun install` is the canonical way to sync bun.lock after package.json
37
- * changes. As of bun 1.x there is no `--lockfile-only` flag; `bun install`
38
- * is already fast when node_modules is up-to-date and will simply update
39
- * bun.lock to match package.json. We pass `--ignore-scripts` to avoid re-running
40
- * the parent PM's lifecycle hooks (which triggered this trampoline to begin with).
41
- */
42
- const INSTALL = "install";
43
- const IGNORE_SCRIPTS = "--ignore-scripts";
44
- const LOCKFILE_REGEN_PLANS = {
45
- bun: {
46
- pm: "bun",
47
- lockfile: "bun.lock",
48
- command: "bun",
49
- args: [INSTALL, IGNORE_SCRIPTS],
50
- },
51
- npm: {
52
- pm: "npm",
53
- lockfile: "package-lock.json",
54
- command: "npm",
55
- args: [INSTALL, "--package-lock-only", IGNORE_SCRIPTS],
56
- },
57
- pnpm: {
58
- pm: "pnpm",
59
- lockfile: "pnpm-lock.yaml",
60
- command: "pnpm",
61
- args: [INSTALL, "--lockfile-only", IGNORE_SCRIPTS],
62
- },
63
- yarn: {
64
- pm: "yarn",
65
- lockfile: "yarn.lock",
66
- command: "yarn",
67
- args: [INSTALL, "--mode", "update-lockfile"],
68
- },
69
- };
32
+ // Re-export the package-manager detection surface (imported above from
33
+ // package-manager-detect.ts) so existing importers/tests can keep importing it
34
+ // from this module.
35
+ export { LOCKFILE_REGEN_PLANS, detectPackageManagers, enginesForbiddenManagers, getLockfileRegenPlan, };
70
36
  /**
71
37
  * Read an env var by name without widening the project-wide process.env ban.
72
38
  * Lisa's CLI isn't a Lambda handler or Nest service; it has to introspect its
@@ -171,29 +137,6 @@ export function getLisaDistDir(moduleUrl) {
171
137
  // Walk from <dist>/utils/postinstall-trampoline.js → <dist>
172
138
  return path.resolve(path.dirname(filename), "..");
173
139
  }
174
- /**
175
- * Detect which package managers the project uses based on lockfile presence.
176
- *
177
- * A project may have more than one lockfile (the CDK dual-lockfile pattern
178
- * keeps `bun.lock` for local dev while publishing `package-lock.json` for
179
- * consumers), in which case every present lockfile must be regenerated so both
180
- * stay in sync with package.json.
181
- * @param projectDir - Absolute path to the project directory
182
- * @returns Ordered list of detected package managers (possibly empty)
183
- */
184
- export function detectPackageManagers(projectDir) {
185
- return Object.values(LOCKFILE_REGEN_PLANS)
186
- .filter(plan => existsSync(path.join(projectDir, plan.lockfile)))
187
- .map(plan => plan.pm);
188
- }
189
- /**
190
- * Get the regen plan (command/args/lockfile) for a given package manager.
191
- * @param pm - Package manager to look up
192
- * @returns Regen plan describing which command to spawn
193
- */
194
- export function getLockfileRegenPlan(pm) {
195
- return LOCKFILE_REGEN_PLANS[pm];
196
- }
197
140
  /**
198
141
  * Hash a file's contents (sha256, hex-encoded). Returns null if the file
199
142
  * does not exist or cannot be read. Used to detect whether Lisa mutated
@@ -407,10 +350,24 @@ function buildTrampolineHelpers(literals) {
407
350
  catch { return null; }
408
351
  }
409
352
 
353
+ function enginesForbiddenManagers(dir) {
354
+ try {
355
+ const pkg = JSON.parse(readFileSync(path.join(dir, "package.json"), "utf8"));
356
+ const engines = (pkg && pkg.engines) || {};
357
+ return ["bun", "npm", "yarn", "pnpm"].filter(
358
+ (pm) => typeof engines[pm] === "string" && /please-use|do-not-use/i.test(engines[pm])
359
+ );
360
+ } catch {
361
+ return [];
362
+ }
363
+ }
364
+
410
365
  function detectPackageManagers(dir) {
366
+ const forbidden = enginesForbiddenManagers(dir);
411
367
  return Object.values(LOCKFILE_PLANS)
412
- .filter((plan) => existsSync(path.join(dir, plan.lockfile)))
413
- .map((plan) => plan.pm);
368
+ .filter((plan) => [plan.lockfile].concat(plan.lockfileAlternatives || []).some((f) => existsSync(path.join(dir, f))))
369
+ .map((plan) => plan.pm)
370
+ .filter((pm) => forbidden.indexOf(pm) === -1);
414
371
  }
415
372
 
416
373
  async function waitForParent() {
@@ -1 +1 @@
1
- {"version":3,"file":"postinstall-trampoline.js","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postinstall-trampoline.js","sourceRoot":"","sources":["../../src/utils/postinstall-trampoline.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -85,7 +85,7 @@
85
85
  "lodash": ">=4.18.1"
86
86
  },
87
87
  "name": "@codyswann/lisa",
88
- "version": "2.170.0",
88
+ "version": "2.171.1",
89
89
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
90
90
  "main": "dist/index.js",
91
91
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.170.0",
3
+ "version": "2.171.1",
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.170.0",
3
+ "version": "2.171.1",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -8,18 +8,40 @@ if [ -d "node_modules" ]; then
8
8
  exit 0
9
9
  fi
10
10
 
11
- # Detect package manager based on lock file presence
12
- if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
13
- bun install
14
- elif [ -f "pnpm-lock.yaml" ]; then
15
- pnpm install
16
- elif [ -f "yarn.lock" ]; then
17
- yarn install
18
- elif [ -f "package-lock.json" ]; then
19
- npm install
20
- else
21
- npm install
22
- fi
11
+ # Detect the package manager this project wants, honoring explicit opt-outs.
12
+ # Precedence: packageManager field > engines "please-use-<pm>" sentinel >
13
+ # lockfile presence (minus any PM the engines forbid) > npm default.
14
+ #
15
+ # This must NOT key on lockfile presence alone. An npm-only project
16
+ # (engines.bun = "please-use-npm", CI runs `npm ci`) that picks up a stray
17
+ # bun.lock would otherwise get `bun install`, re-create the bun.lock, and break
18
+ # the SE-5221 regression. The engines/packageManager signals are
19
+ # authoritative; lockfiles are only a fallback and never override an opt-out.
20
+ detect_package_manager() {
21
+ _field="" _forced="" _forbidden=""
22
+ if [ -f package.json ] && command -v jq >/dev/null 2>&1; then
23
+ _field=$(jq -r '(.packageManager // "") | sub("@.*$";"")' package.json 2>/dev/null)
24
+ _forced=$(jq -r 'first((.engines // {})[] | strings | capture("please-use-(?<pm>bun|npm|yarn|pnpm)")?.pm) // ""' package.json 2>/dev/null)
25
+ _forbidden=$(jq -r '[(.engines // {}) | to_entries[] | select(((.value|strings) // "") | test("please-use|do-not-use";"i")) | .key] | join(" ")' package.json 2>/dev/null)
26
+ fi
27
+ case "$_field" in bun | npm | yarn | pnpm) printf '%s\n' "$_field"; return 0 ;; esac
28
+ case "$_forced" in bun | npm | yarn | pnpm) printf '%s\n' "$_forced"; return 0 ;; esac
29
+ _pm_allowed() { case " $_forbidden " in *" $1 "*) return 1 ;; *) return 0 ;; esac; }
30
+ if { [ -f bun.lockb ] || [ -f bun.lock ]; } && _pm_allowed bun; then printf 'bun\n'; return 0; fi
31
+ if [ -f pnpm-lock.yaml ] && _pm_allowed pnpm; then printf 'pnpm\n'; return 0; fi
32
+ if [ -f yarn.lock ] && _pm_allowed yarn; then printf 'yarn\n'; return 0; fi
33
+ if [ -f package-lock.json ] && _pm_allowed npm; then printf 'npm\n'; return 0; fi
34
+ printf 'npm\n'
35
+ }
36
+
37
+ PACKAGE_MANAGER="$(detect_package_manager)"
38
+ echo "Detected package manager: ${PACKAGE_MANAGER}"
39
+ case "$PACKAGE_MANAGER" in
40
+ bun) bun install ;;
41
+ pnpm) pnpm install ;;
42
+ yarn) yarn install ;;
43
+ *) npm install ;;
44
+ esac
23
45
 
24
46
  # The tools below use Linux-specific binaries and paths — skip on other platforms.
25
47
  if [ "$(uname -s)" != "Linux" ]; then
@@ -101,12 +101,34 @@ need() { command -v "$1" >/dev/null 2>&1; }
101
101
  require() { need "$1" || { echo "FATAL: required tool '$1' missing and install failed" >&2; exit 1; }; }
102
102
 
103
103
  # --- package manager (REQUIRED) ---
104
- if ! need bun; then
104
+ # Resolve the PM from packageManager/engines/lockfiles — emit the manager the
105
+ # `packageManager` inventory field reported, NEVER a hardcoded bun. An npm-only
106
+ # project (engines.bun = "please-use-npm") must install with npm; emitting
107
+ # `bun install` would create a stray bun.lock and break it (the SE-5221
108
+ # regression). Only install/PATH-export the manager actually selected below.
109
+ detect_package_manager() {
110
+ _field="" _forced="" _forbidden=""
111
+ if [ -f package.json ] && command -v jq >/dev/null 2>&1; then
112
+ _field=$(jq -r '(.packageManager // "") | sub("@.*$";"")' package.json 2>/dev/null)
113
+ _forced=$(jq -r 'first((.engines // {})[] | strings | capture("please-use-(?<pm>bun|npm|yarn|pnpm)")?.pm) // ""' package.json 2>/dev/null)
114
+ _forbidden=$(jq -r '[(.engines // {}) | to_entries[] | select(((.value|strings) // "") | test("please-use|do-not-use";"i")) | .key] | join(" ")' package.json 2>/dev/null)
115
+ fi
116
+ case "$_field" in bun | npm | yarn | pnpm) printf '%s\n' "$_field"; return 0 ;; esac
117
+ case "$_forced" in bun | npm | yarn | pnpm) printf '%s\n' "$_forced"; return 0 ;; esac
118
+ _pm_allowed() { case " $_forbidden " in *" $1 "*) return 1 ;; *) return 0 ;; esac; }
119
+ { [ -f bun.lockb ] || [ -f bun.lock ]; } && _pm_allowed bun && { printf 'bun\n'; return 0; }
120
+ [ -f pnpm-lock.yaml ] && _pm_allowed pnpm && { printf 'pnpm\n'; return 0; }
121
+ [ -f yarn.lock ] && _pm_allowed yarn && { printf 'yarn\n'; return 0; }
122
+ [ -f package-lock.json ] && _pm_allowed npm && { printf 'npm\n'; return 0; }
123
+ printf 'npm\n'
124
+ }
125
+ PM="$(detect_package_manager)"
126
+ if [ "$PM" = "bun" ] && ! need bun; then
105
127
  curl -fsSL https://bun.sh/install | bash
128
+ export PATH="$HOME/.bun/bin:$PATH"
106
129
  fi
107
- export PATH="$HOME/.bun/bin:$PATH"
108
130
  # NOTE: bun has known proxy package-fetch issues in cloud sessions; retry to survive transient proxy errors.
109
- for i in 1 2 3; do bun install && break || sleep 5; done
131
+ for i in 1 2 3; do "$PM" install && break || sleep 5; done
110
132
 
111
133
  # --- required CLIs ---
112
134
  need gh || (sudo apt-get update -y && sudo apt-get install -y gh)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.170.0",
3
+ "version": "2.171.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -101,12 +101,34 @@ need() { command -v "$1" >/dev/null 2>&1; }
101
101
  require() { need "$1" || { echo "FATAL: required tool '$1' missing and install failed" >&2; exit 1; }; }
102
102
 
103
103
  # --- package manager (REQUIRED) ---
104
- if ! need bun; then
104
+ # Resolve the PM from packageManager/engines/lockfiles — emit the manager the
105
+ # `packageManager` inventory field reported, NEVER a hardcoded bun. An npm-only
106
+ # project (engines.bun = "please-use-npm") must install with npm; emitting
107
+ # `bun install` would create a stray bun.lock and break it (the SE-5221
108
+ # regression). Only install/PATH-export the manager actually selected below.
109
+ detect_package_manager() {
110
+ _field="" _forced="" _forbidden=""
111
+ if [ -f package.json ] && command -v jq >/dev/null 2>&1; then
112
+ _field=$(jq -r '(.packageManager // "") | sub("@.*$";"")' package.json 2>/dev/null)
113
+ _forced=$(jq -r 'first((.engines // {})[] | strings | capture("please-use-(?<pm>bun|npm|yarn|pnpm)")?.pm) // ""' package.json 2>/dev/null)
114
+ _forbidden=$(jq -r '[(.engines // {}) | to_entries[] | select(((.value|strings) // "") | test("please-use|do-not-use";"i")) | .key] | join(" ")' package.json 2>/dev/null)
115
+ fi
116
+ case "$_field" in bun | npm | yarn | pnpm) printf '%s\n' "$_field"; return 0 ;; esac
117
+ case "$_forced" in bun | npm | yarn | pnpm) printf '%s\n' "$_forced"; return 0 ;; esac
118
+ _pm_allowed() { case " $_forbidden " in *" $1 "*) return 1 ;; *) return 0 ;; esac; }
119
+ { [ -f bun.lockb ] || [ -f bun.lock ]; } && _pm_allowed bun && { printf 'bun\n'; return 0; }
120
+ [ -f pnpm-lock.yaml ] && _pm_allowed pnpm && { printf 'pnpm\n'; return 0; }
121
+ [ -f yarn.lock ] && _pm_allowed yarn && { printf 'yarn\n'; return 0; }
122
+ [ -f package-lock.json ] && _pm_allowed npm && { printf 'npm\n'; return 0; }
123
+ printf 'npm\n'
124
+ }
125
+ PM="$(detect_package_manager)"
126
+ if [ "$PM" = "bun" ] && ! need bun; then
105
127
  curl -fsSL https://bun.sh/install | bash
128
+ export PATH="$HOME/.bun/bin:$PATH"
106
129
  fi
107
- export PATH="$HOME/.bun/bin:$PATH"
108
130
  # NOTE: bun has known proxy package-fetch issues in cloud sessions; retry to survive transient proxy errors.
109
- for i in 1 2 3; do bun install && break || sleep 5; done
131
+ for i in 1 2 3; do "$PM" install && break || sleep 5; done
110
132
 
111
133
  # --- required CLIs ---
112
134
  need gh || (sudo apt-get update -y && sudo apt-get install -y gh)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.170.0",
3
+ "version": "2.171.1",
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.170.0",
3
+ "version": "2.171.1",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"