@codyswann/lisa 2.226.2 → 2.228.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.
- package/all/copy-contents/gitignore +2 -0
- package/dist/cli/ui-cmd.d.ts +21 -1
- package/dist/cli/ui-cmd.d.ts.map +1 -1
- package/dist/cli/ui-cmd.js +49 -3
- package/dist/cli/ui-cmd.js.map +1 -1
- package/dist/core/lisa.d.ts +74 -1
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +165 -25
- package/dist/core/lisa.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/rules/eager/history-audit.md +27 -0
- package/plugins/lisa/rules/reference/history-audit.md +42 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/rules/eager/history-audit.md +27 -0
- package/plugins/lisa-copilot/rules/reference/history-audit.md +42 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/history-audit-reference.mdc +47 -0
- package/plugins/lisa-cursor/rules/history-audit.mdc +32 -0
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/eager/history-audit.md +27 -0
- package/plugins/src/base/rules/reference/history-audit.md +42 -0
- package/scripts/install-claude-plugins.sh +89 -9
- package/ui/README.md +1 -0
- package/ui/index.html +143 -8
package/dist/cli/ui-cmd.d.ts
CHANGED
|
@@ -9,6 +9,25 @@ export interface UiCmdOptions {
|
|
|
9
9
|
/** Set false (via --no-sync) to skip the config sync on startup */
|
|
10
10
|
readonly sync?: boolean;
|
|
11
11
|
}
|
|
12
|
+
/** Secret/variable and generated-artifact status exposed to the console. */
|
|
13
|
+
export interface RemoteEnvironmentStatus {
|
|
14
|
+
/** Whether each supported variable is visible to the `lisa ui` process. */
|
|
15
|
+
readonly variables: Readonly<Record<string, boolean>>;
|
|
16
|
+
/** Whether each remote-environment startup artifact exists in the project. */
|
|
17
|
+
readonly artifacts: Readonly<Record<string, boolean>>;
|
|
18
|
+
}
|
|
19
|
+
/** Variables the remote AWS bootstrap understands. Values are never exposed. */
|
|
20
|
+
export declare const REMOTE_ENVIRONMENT_VARIABLES: readonly ["LISA_AWS_BOOTSTRAP_JSON", "LISA_REMOTE_AGENT", "LISA_AWS_DEFAULT_PROFILE"];
|
|
21
|
+
/** Project-relative artifacts used by remote coding environments. */
|
|
22
|
+
export declare const REMOTE_ENVIRONMENT_ARTIFACTS: readonly ["scripts/remote-agent-aws-setup.sh", ".cursor/environment.json", ".github/workflows/copilot-setup-steps.yml"];
|
|
23
|
+
/**
|
|
24
|
+
* Inspect remote-environment readiness without ever reading a variable value
|
|
25
|
+
* into the browser payload.
|
|
26
|
+
* @param destDir - Project root
|
|
27
|
+
* @param environment - Environment visible to the Lisa process
|
|
28
|
+
* @returns Boolean-only variable and artifact status
|
|
29
|
+
*/
|
|
30
|
+
export declare function inspectRemoteEnvironment(destDir: string, environment?: NodeJS.ProcessEnv): RemoteEnvironmentStatus;
|
|
12
31
|
/**
|
|
13
32
|
* Locate the packaged `ui/index.html` by walking up from this module until a
|
|
14
33
|
* directory containing `ui/index.html` is found (works from both `src/` and
|
|
@@ -22,9 +41,10 @@ export declare function findUiHtml(startDir: string): string;
|
|
|
22
41
|
* escaped so a value containing `</script>` cannot break out of the tag.
|
|
23
42
|
* @param html - Packaged console HTML
|
|
24
43
|
* @param config - Merged live config
|
|
44
|
+
* @param remoteEnvironment - Boolean-only secret and startup-artifact status
|
|
25
45
|
* @returns HTML with the injected config
|
|
26
46
|
*/
|
|
27
|
-
export declare function injectLiveConfig(html: string, config: JsonObject): string;
|
|
47
|
+
export declare function injectLiveConfig(html: string, config: JsonObject, remoteEnvironment?: RemoteEnvironmentStatus): string;
|
|
28
48
|
/**
|
|
29
49
|
* Run the `lisa ui` command: sync, then serve the console until interrupted.
|
|
30
50
|
* @param targetPath - Project path argument (defaults to the current directory)
|
package/dist/cli/ui-cmd.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIrE,6CAA6C;AAC7C,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUnD;AAmBD
|
|
1
|
+
{"version":3,"file":"ui-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIrE,6CAA6C;AAC7C,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AAED,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,uFAI/B,CAAC;AAEX,qEAAqE;AACrE,eAAO,MAAM,4BAA4B,yHAI/B,CAAC;AAYX;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAM,CAAC,UAAoC,GACvD,uBAAuB,CAezB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUnD;AAmBD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,iBAAiB,GAAE,uBAGlB,GACA,MAAM,CAQR;AAED;;;;;GAKG;AACH,wBAAsB,KAAK,CACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAqCtB"}
|
package/dist/cli/ui-cmd.js
CHANGED
|
@@ -18,6 +18,46 @@ import { deepMerge, readJsonOrNull } from "../utils/index.js";
|
|
|
18
18
|
import { printSyncReport } from "./sync-cmd.js";
|
|
19
19
|
/** Default port for the settings console. */
|
|
20
20
|
export const DEFAULT_UI_PORT = 4780;
|
|
21
|
+
/** Variables the remote AWS bootstrap understands. Values are never exposed. */
|
|
22
|
+
export const REMOTE_ENVIRONMENT_VARIABLES = [
|
|
23
|
+
"LISA_AWS_BOOTSTRAP_JSON",
|
|
24
|
+
"LISA_REMOTE_AGENT",
|
|
25
|
+
"LISA_AWS_DEFAULT_PROFILE",
|
|
26
|
+
];
|
|
27
|
+
/** Project-relative artifacts used by remote coding environments. */
|
|
28
|
+
export const REMOTE_ENVIRONMENT_ARTIFACTS = [
|
|
29
|
+
"scripts/remote-agent-aws-setup.sh",
|
|
30
|
+
".cursor/environment.json",
|
|
31
|
+
".github/workflows/copilot-setup-steps.yml",
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Read the CLI process environment through one explicit, reviewable exception.
|
|
35
|
+
* Only boolean presence checks derived from this map reach the browser.
|
|
36
|
+
* @returns Current process environment
|
|
37
|
+
*/
|
|
38
|
+
function getProcessEnvironment() {
|
|
39
|
+
// eslint-disable-next-line no-restricted-syntax -- CLI status view must inspect externally supplied remote-environment variables once
|
|
40
|
+
return process.env;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Inspect remote-environment readiness without ever reading a variable value
|
|
44
|
+
* into the browser payload.
|
|
45
|
+
* @param destDir - Project root
|
|
46
|
+
* @param environment - Environment visible to the Lisa process
|
|
47
|
+
* @returns Boolean-only variable and artifact status
|
|
48
|
+
*/
|
|
49
|
+
export function inspectRemoteEnvironment(destDir, environment = getProcessEnvironment()) {
|
|
50
|
+
return {
|
|
51
|
+
variables: Object.fromEntries(REMOTE_ENVIRONMENT_VARIABLES.map(name => [
|
|
52
|
+
name,
|
|
53
|
+
typeof environment[name] === "string" && environment[name].length > 0,
|
|
54
|
+
])),
|
|
55
|
+
artifacts: Object.fromEntries(REMOTE_ENVIRONMENT_ARTIFACTS.map(relativePath => [
|
|
56
|
+
relativePath,
|
|
57
|
+
existsSync(path.join(destDir, relativePath)),
|
|
58
|
+
])),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
21
61
|
/**
|
|
22
62
|
* Locate the packaged `ui/index.html` by walking up from this module until a
|
|
23
63
|
* directory containing `ui/index.html` is found (works from both `src/` and
|
|
@@ -53,11 +93,16 @@ async function readMergedConfig(destDir) {
|
|
|
53
93
|
* escaped so a value containing `</script>` cannot break out of the tag.
|
|
54
94
|
* @param html - Packaged console HTML
|
|
55
95
|
* @param config - Merged live config
|
|
96
|
+
* @param remoteEnvironment - Boolean-only secret and startup-artifact status
|
|
56
97
|
* @returns HTML with the injected config
|
|
57
98
|
*/
|
|
58
|
-
export function injectLiveConfig(html, config
|
|
99
|
+
export function injectLiveConfig(html, config, remoteEnvironment = {
|
|
100
|
+
variables: {},
|
|
101
|
+
artifacts: {},
|
|
102
|
+
}) {
|
|
59
103
|
const payload = JSON.stringify(config).replace(/<\//g, "<\\/");
|
|
60
|
-
const
|
|
104
|
+
const remotePayload = JSON.stringify(remoteEnvironment).replace(/<\//g, "<\\/");
|
|
105
|
+
const tag = `<script>window.LISA_LIVE_CONFIG = ${payload}; window.LISA_REMOTE_ENVIRONMENT = ${remotePayload};</script>`;
|
|
61
106
|
return html.replace("</body>", `${tag}\n</body>`);
|
|
62
107
|
}
|
|
63
108
|
/**
|
|
@@ -80,7 +125,8 @@ export async function runUi(targetPath, options = {}) {
|
|
|
80
125
|
const htmlPath = findUiHtml(moduleDir);
|
|
81
126
|
const html = await readFile(htmlPath, "utf8");
|
|
82
127
|
const config = await readMergedConfig(destDir);
|
|
83
|
-
const
|
|
128
|
+
const remoteEnvironment = inspectRemoteEnvironment(destDir);
|
|
129
|
+
const page = injectLiveConfig(html, config, remoteEnvironment);
|
|
84
130
|
const server = http.createServer((request, response) => {
|
|
85
131
|
const url = request.url ?? "/";
|
|
86
132
|
if (url === "/" || url.startsWith("/index.html") || url.startsWith("/#")) {
|
package/dist/cli/ui-cmd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-cmd.js","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAmB,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ui-cmd.js","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAmB,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAkBpC,gFAAgF;AAChF,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,yBAAyB;IACzB,mBAAmB;IACnB,0BAA0B;CAClB,CAAC;AAEX,qEAAqE;AACrE,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,mCAAmC;IACnC,0BAA0B;IAC1B,2CAA2C;CACnC,CAAC;AAEX;;;;GAIG;AACH,SAAS,qBAAqB;IAC5B,sIAAsI;IACtI,OAAO,OAAO,CAAC,GAAG,CAAC;AACrB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAe,EACf,cAAiC,qBAAqB,EAAE;IAExD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,WAAW,CAC3B,4BAA4B,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,IAAI;YACJ,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAE,CAAC,MAAM,GAAG,CAAC;SACvE,CAAC,CACH;QACD,SAAS,EAAE,MAAM,CAAC,WAAW,CAC3B,4BAA4B,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAC/C,YAAY;YACZ,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;SAC7C,CAAC,CACH;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAAC,OAAe;IAC7C,MAAM,SAAS,GAAG,MAAM,cAAc,CACpC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CACxC,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,cAAc,CAChC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAyB,CAAC,CAC9C,CAAC;IACF,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,OAAO,SAAS,CAAC,eAAe,EAAE,WAAW,CAAe,CAAC;AAC/D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,MAAkB,EAClB,oBAA6C;IAC3C,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,EAAE;CACd;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAC7D,MAAM,EACN,MAAM,CACP,CAAC;IACF,MAAM,GAAG,GAAG,qCAAqC,OAAO,sCAAsC,aAAa,YAAY,CAAC;IACxH,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,GAAG,WAAW,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,UAA8B,EAC9B,UAAwB,EAAE;IAE1B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC;IACvE,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5C,eAAe,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAE/D,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC;QAC/B,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzE,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACxE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;QAC1D,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;QAChC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACjC,MAAM,SAAS,GACb,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/core/lisa.d.ts
CHANGED
|
@@ -226,11 +226,76 @@ export declare class Lisa {
|
|
|
226
226
|
*/
|
|
227
227
|
private registerPlugins;
|
|
228
228
|
/**
|
|
229
|
-
* Install each plugin and refresh the Lisa marketplace cache
|
|
229
|
+
* Install each plugin and refresh the Lisa marketplace cache.
|
|
230
|
+
*
|
|
231
|
+
* Version-gated (perf): `claude plugin marketplace update` is a network git
|
|
232
|
+
* pull of the Lisa repo and every `claude plugin install` spawns the Claude
|
|
233
|
+
* CLI (seconds each); re-running all of it on every apply made a single
|
|
234
|
+
* `bun add` cost minutes across the repeated apply passes. A full sync
|
|
235
|
+
* (marketplace refresh + install every plugin) still runs whenever the
|
|
236
|
+
* installed Lisa version differs from the `.claude/.lisa-plugins-synced`
|
|
237
|
+
* marker; between version changes only plugins missing for this project are
|
|
238
|
+
* installed, so the self-heal property (a removed plugin comes back on the
|
|
239
|
+
* next install) survives at the cost of one `claude plugin list` call.
|
|
230
240
|
* @param execAsync - Promisified exec function for running shell commands
|
|
231
241
|
* @param plugins - Plugin identifiers from enabledPlugins (e.g. "lisa@lisa")
|
|
232
242
|
*/
|
|
233
243
|
private installPluginsAndUpdateMarketplace;
|
|
244
|
+
/**
|
|
245
|
+
* Decide whether this apply needs a full plugin sync and which plugins to
|
|
246
|
+
* install.
|
|
247
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
248
|
+
* @param plugins - Plugin identifiers from enabledPlugins
|
|
249
|
+
* @returns Sync plan: fullSync (version changed), plugins to install, and
|
|
250
|
+
* the current Lisa version
|
|
251
|
+
*/
|
|
252
|
+
private computePluginSyncPlan;
|
|
253
|
+
/**
|
|
254
|
+
* Refresh the cached Lisa marketplace via the Claude CLI.
|
|
255
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
256
|
+
* @param announce - Whether to log the outcome (silent for the pre-install
|
|
257
|
+
* best-effort refresh)
|
|
258
|
+
* @returns Promise that resolves when the refresh attempt completes
|
|
259
|
+
*/
|
|
260
|
+
private updateLisaMarketplace;
|
|
261
|
+
/**
|
|
262
|
+
* Install a single plugin at project scope via the Claude CLI.
|
|
263
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
264
|
+
* @param plugin - Plugin identifier (already validated)
|
|
265
|
+
* @returns Promise that resolves when the install attempt completes
|
|
266
|
+
*/
|
|
267
|
+
private installPlugin;
|
|
268
|
+
/**
|
|
269
|
+
* Exec options shared by all Claude CLI plugin commands.
|
|
270
|
+
* @returns Options object with the project cwd and POSIX shell
|
|
271
|
+
*/
|
|
272
|
+
private pluginExecOptions;
|
|
273
|
+
/**
|
|
274
|
+
* Absolute path of the plugin sync marker recording the last fully-synced
|
|
275
|
+
* Lisa version for this project. Shared with install-claude-plugins.sh.
|
|
276
|
+
* @returns Marker path under the project's .claude directory
|
|
277
|
+
*/
|
|
278
|
+
private pluginSyncMarkerPath;
|
|
279
|
+
/**
|
|
280
|
+
* Absolute path of the host project's package.json.
|
|
281
|
+
* @returns package.json path under the destination directory
|
|
282
|
+
*/
|
|
283
|
+
private hostPackageJsonPath;
|
|
284
|
+
/**
|
|
285
|
+
* Read the plugin ids already installed for this project via
|
|
286
|
+
* `claude plugin list --json`.
|
|
287
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
288
|
+
* @returns Set of installed plugin ids, or null when the list cannot be
|
|
289
|
+
* obtained (older CLI, parse failure) so callers fall back to installing
|
|
290
|
+
* everything — the pre-existing behavior
|
|
291
|
+
*/
|
|
292
|
+
private readInstalledPluginIds;
|
|
293
|
+
/**
|
|
294
|
+
* Record the Lisa version whose plugin set was last fully synced.
|
|
295
|
+
* @param version - Lisa package version to record
|
|
296
|
+
* @returns Promise that resolves when the marker is written (best-effort)
|
|
297
|
+
*/
|
|
298
|
+
private writePluginSyncMarker;
|
|
234
299
|
/**
|
|
235
300
|
* Finalize operation
|
|
236
301
|
* @returns Promise that resolves when finalization is complete
|
|
@@ -387,6 +452,14 @@ export declare class Lisa {
|
|
|
387
452
|
* The trampoline is always fully detached so the package manager can exit
|
|
388
453
|
* normally; the child then detects the exit and re-runs Lisa. See
|
|
389
454
|
* utils/postinstall-trampoline.ts for details.
|
|
455
|
+
*
|
|
456
|
+
* Skipped when this apply did not mutate package.json: the trampoline exists
|
|
457
|
+
* solely to redo package.json changes that the parent package manager's
|
|
458
|
+
* end-of-command rewrite clobbers (#383). With no mutation there is nothing
|
|
459
|
+
* to clobber — the rewrite restores identical content — and scheduling a
|
|
460
|
+
* detached re-apply (plus its lockfile regen) is pure waste. File-based
|
|
461
|
+
* template writes are not clobbered and need no reconciliation.
|
|
462
|
+
* @param prePackageJsonHash - Hash of package.json captured before apply mutated anything (null if the file did not exist)
|
|
390
463
|
* @returns Promise that resolves immediately after the detached child is spawned
|
|
391
464
|
*/
|
|
392
465
|
private schedulePostinstallReconciliation;
|
package/dist/core/lisa.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lisa.d.ts","sourceRoot":"","sources":["../../src/core/lisa.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"lisa.d.ts","sourceRoot":"","sources":["../../src/core/lisa.ts"],"names":[],"mappings":"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"}
|
package/dist/core/lisa.js
CHANGED
|
@@ -4,6 +4,7 @@ import { existsSync } from "node:fs";
|
|
|
4
4
|
import { readFile, stat } from "node:fs/promises";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import pc from "picocolors";
|
|
7
|
+
import { getPackageVersion } from "../cli/version.js";
|
|
7
8
|
import { installAgentsMd } from "../codex/agents-md-installer.js";
|
|
8
9
|
import { installCodexProjectOverlay } from "../codex/project-overlay.js";
|
|
9
10
|
import { installAgyPlugin } from "../agy/plugin-installer.js";
|
|
@@ -491,49 +492,171 @@ export class Lisa {
|
|
|
491
492
|
await this.installPluginsAndUpdateMarketplace(execAsync, plugins);
|
|
492
493
|
}
|
|
493
494
|
/**
|
|
494
|
-
* Install each plugin and refresh the Lisa marketplace cache
|
|
495
|
+
* Install each plugin and refresh the Lisa marketplace cache.
|
|
496
|
+
*
|
|
497
|
+
* Version-gated (perf): `claude plugin marketplace update` is a network git
|
|
498
|
+
* pull of the Lisa repo and every `claude plugin install` spawns the Claude
|
|
499
|
+
* CLI (seconds each); re-running all of it on every apply made a single
|
|
500
|
+
* `bun add` cost minutes across the repeated apply passes. A full sync
|
|
501
|
+
* (marketplace refresh + install every plugin) still runs whenever the
|
|
502
|
+
* installed Lisa version differs from the `.claude/.lisa-plugins-synced`
|
|
503
|
+
* marker; between version changes only plugins missing for this project are
|
|
504
|
+
* installed, so the self-heal property (a removed plugin comes back on the
|
|
505
|
+
* next install) survives at the cost of one `claude plugin list` call.
|
|
495
506
|
* @param execAsync - Promisified exec function for running shell commands
|
|
496
507
|
* @param plugins - Plugin identifiers from enabledPlugins (e.g. "lisa@lisa")
|
|
497
508
|
*/
|
|
498
509
|
async installPluginsAndUpdateMarketplace(execAsync, plugins) {
|
|
499
510
|
const { logger } = this.deps;
|
|
500
511
|
const validPluginName = /^[\w@./-]+$/;
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
shell: "/bin/sh",
|
|
506
|
-
});
|
|
512
|
+
const { fullSync, toInstall, version } = await this.computePluginSyncPlan(execAsync, plugins);
|
|
513
|
+
if (!fullSync && toInstall.length === 0) {
|
|
514
|
+
logger.info(pc.gray(`Plugins already in sync for Lisa ${version}; skipping`));
|
|
515
|
+
return;
|
|
507
516
|
}
|
|
508
|
-
|
|
517
|
+
logger.info("Registering plugins with Claude Code (project scope)...");
|
|
518
|
+
if (fullSync) {
|
|
509
519
|
// Best-effort cache refresh. Individual plugin installs below will still
|
|
510
520
|
// report whether the marketplace entry is available.
|
|
521
|
+
await this.updateLisaMarketplace(execAsync, false);
|
|
511
522
|
}
|
|
512
|
-
for (const plugin of
|
|
523
|
+
for (const plugin of toInstall) {
|
|
513
524
|
if (!validPluginName.test(plugin)) {
|
|
514
525
|
logger.warn(`Skipping invalid plugin name: ${plugin}`);
|
|
515
526
|
continue;
|
|
516
527
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
528
|
+
await this.installPlugin(execAsync, plugin);
|
|
529
|
+
}
|
|
530
|
+
// Post-install refresh must run whenever installs happened: installing can
|
|
531
|
+
// register the marketplace for the first time, and without a refresh newly
|
|
532
|
+
// added skills are not discovered ("Unknown skill" in nightly CI — #320).
|
|
533
|
+
await this.updateLisaMarketplace(execAsync, true);
|
|
534
|
+
if (fullSync) {
|
|
535
|
+
await this.writePluginSyncMarker(version);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Decide whether this apply needs a full plugin sync and which plugins to
|
|
540
|
+
* install.
|
|
541
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
542
|
+
* @param plugins - Plugin identifiers from enabledPlugins
|
|
543
|
+
* @returns Sync plan: fullSync (version changed), plugins to install, and
|
|
544
|
+
* the current Lisa version
|
|
545
|
+
*/
|
|
546
|
+
async computePluginSyncPlan(execAsync, plugins) {
|
|
547
|
+
const version = getPackageVersion();
|
|
548
|
+
const syncedVersion = await readFile(this.pluginSyncMarkerPath(), "utf-8")
|
|
549
|
+
.then(content => content.trim())
|
|
550
|
+
.catch(() => null);
|
|
551
|
+
const fullSync = syncedVersion !== version;
|
|
552
|
+
const installed = fullSync
|
|
553
|
+
? null
|
|
554
|
+
: await this.readInstalledPluginIds(execAsync);
|
|
555
|
+
const toInstall = installed === null
|
|
556
|
+
? plugins
|
|
557
|
+
: plugins.filter(plugin => !installed.has(plugin));
|
|
558
|
+
return { fullSync, toInstall, version };
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Refresh the cached Lisa marketplace via the Claude CLI.
|
|
562
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
563
|
+
* @param announce - Whether to log the outcome (silent for the pre-install
|
|
564
|
+
* best-effort refresh)
|
|
565
|
+
* @returns Promise that resolves when the refresh attempt completes
|
|
566
|
+
*/
|
|
567
|
+
async updateLisaMarketplace(execAsync, announce) {
|
|
568
|
+
const { logger } = this.deps;
|
|
569
|
+
try {
|
|
570
|
+
await execAsync("claude plugin marketplace update lisa", this.pluginExecOptions());
|
|
571
|
+
if (announce) {
|
|
572
|
+
logger.success("Updated marketplace: lisa");
|
|
523
573
|
}
|
|
524
|
-
|
|
525
|
-
|
|
574
|
+
}
|
|
575
|
+
catch {
|
|
576
|
+
if (announce) {
|
|
577
|
+
logger.warn("Could not update marketplace: lisa");
|
|
526
578
|
}
|
|
527
579
|
}
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Install a single plugin at project scope via the Claude CLI.
|
|
583
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
584
|
+
* @param plugin - Plugin identifier (already validated)
|
|
585
|
+
* @returns Promise that resolves when the install attempt completes
|
|
586
|
+
*/
|
|
587
|
+
async installPlugin(execAsync, plugin) {
|
|
588
|
+
const { logger } = this.deps;
|
|
589
|
+
try {
|
|
590
|
+
await execAsync(`claude plugin install ${plugin} --scope project`, this.pluginExecOptions());
|
|
591
|
+
logger.success(`Registered plugin: ${plugin}`);
|
|
592
|
+
}
|
|
593
|
+
catch {
|
|
594
|
+
logger.warn(`Could not register plugin: ${plugin}`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Exec options shared by all Claude CLI plugin commands.
|
|
599
|
+
* @returns Options object with the project cwd and POSIX shell
|
|
600
|
+
*/
|
|
601
|
+
pluginExecOptions() {
|
|
602
|
+
return { cwd: this.config.destDir, shell: "/bin/sh" };
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Absolute path of the plugin sync marker recording the last fully-synced
|
|
606
|
+
* Lisa version for this project. Shared with install-claude-plugins.sh.
|
|
607
|
+
* @returns Marker path under the project's .claude directory
|
|
608
|
+
*/
|
|
609
|
+
pluginSyncMarkerPath() {
|
|
610
|
+
return path.join(this.config.destDir, ".claude", ".lisa-plugins-synced");
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Absolute path of the host project's package.json.
|
|
614
|
+
* @returns package.json path under the destination directory
|
|
615
|
+
*/
|
|
616
|
+
hostPackageJsonPath() {
|
|
617
|
+
return path.join(this.config.destDir, "package.json");
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Read the plugin ids already installed for this project via
|
|
621
|
+
* `claude plugin list --json`.
|
|
622
|
+
* @param execAsync - Promisified exec function for running shell commands
|
|
623
|
+
* @returns Set of installed plugin ids, or null when the list cannot be
|
|
624
|
+
* obtained (older CLI, parse failure) so callers fall back to installing
|
|
625
|
+
* everything — the pre-existing behavior
|
|
626
|
+
*/
|
|
627
|
+
async readInstalledPluginIds(execAsync) {
|
|
528
628
|
try {
|
|
529
|
-
await execAsync("claude plugin
|
|
629
|
+
const result = (await execAsync("claude plugin list --json", {
|
|
530
630
|
cwd: this.config.destDir,
|
|
531
631
|
shell: "/bin/sh",
|
|
532
|
-
});
|
|
533
|
-
|
|
632
|
+
}));
|
|
633
|
+
const parsed = JSON.parse(String(result.stdout ?? ""));
|
|
634
|
+
if (!Array.isArray(parsed)) {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
const destPath = path.resolve(this.config.destDir);
|
|
638
|
+
const ids = parsed
|
|
639
|
+
.filter((entry) => typeof entry.id === "string" &&
|
|
640
|
+
entry.projectPath === destPath)
|
|
641
|
+
.map(entry => entry.id);
|
|
642
|
+
return new Set(ids);
|
|
534
643
|
}
|
|
535
644
|
catch {
|
|
536
|
-
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Record the Lisa version whose plugin set was last fully synced.
|
|
650
|
+
* @param version - Lisa package version to record
|
|
651
|
+
* @returns Promise that resolves when the marker is written (best-effort)
|
|
652
|
+
*/
|
|
653
|
+
async writePluginSyncMarker(version) {
|
|
654
|
+
try {
|
|
655
|
+
await fse.ensureDir(path.join(this.config.destDir, ".claude"));
|
|
656
|
+
await fse.writeFile(this.pluginSyncMarkerPath(), `${version}\n`, "utf-8");
|
|
657
|
+
}
|
|
658
|
+
catch {
|
|
659
|
+
// Best-effort: a missing marker only costs a redundant full sync next run.
|
|
537
660
|
}
|
|
538
661
|
}
|
|
539
662
|
/* v8 ignore stop */
|
|
@@ -602,8 +725,12 @@ export class Lisa {
|
|
|
602
725
|
await this.loadPendingDeletions();
|
|
603
726
|
await this.loadCreateOnlyOwnership();
|
|
604
727
|
await this.loadCopyOverwriteOwnership();
|
|
728
|
+
// Captured BEFORE any mutation (migrations included): the hash gates both
|
|
729
|
+
// the detached trampoline and the in-process lockfile reconcile, and
|
|
730
|
+
// before-strategies migrations can wire scripts.postinstall — a change the
|
|
731
|
+
// package manager's end-of-command rewrite would clobber (#383).
|
|
732
|
+
const prePackageJsonHash = hashFile(this.hostPackageJsonPath());
|
|
605
733
|
await this.runMigrationsBeforeStrategies();
|
|
606
|
-
const prePackageJsonHash = hashFile(path.join(this.config.destDir, "package.json"));
|
|
607
734
|
await this.processConfigurations();
|
|
608
735
|
if (this.selfApply) {
|
|
609
736
|
this.deps.logger.info(pc.gray("Self-apply (Lisa source repo): skipped deletions.json processing"));
|
|
@@ -622,7 +749,7 @@ export class Lisa {
|
|
|
622
749
|
await this.finalize();
|
|
623
750
|
this.printSummary();
|
|
624
751
|
await this.printMigrationNotices(this.config.destDir);
|
|
625
|
-
await this.schedulePostinstallReconciliation();
|
|
752
|
+
await this.schedulePostinstallReconciliation(prePackageJsonHash);
|
|
626
753
|
await this.reconcileLockfilesInProcess(prePackageJsonHash);
|
|
627
754
|
return this.getSuccessResult();
|
|
628
755
|
}
|
|
@@ -657,7 +784,7 @@ export class Lisa {
|
|
|
657
784
|
return;
|
|
658
785
|
if (shouldSchedulePostinstallReconciliation(this.config.dryRun))
|
|
659
786
|
return;
|
|
660
|
-
const pkgPath =
|
|
787
|
+
const pkgPath = this.hostPackageJsonPath();
|
|
661
788
|
const postHash = hashFile(pkgPath);
|
|
662
789
|
if (prePackageJsonHash === null ||
|
|
663
790
|
postHash === null ||
|
|
@@ -987,9 +1114,22 @@ export class Lisa {
|
|
|
987
1114
|
* The trampoline is always fully detached so the package manager can exit
|
|
988
1115
|
* normally; the child then detects the exit and re-runs Lisa. See
|
|
989
1116
|
* utils/postinstall-trampoline.ts for details.
|
|
1117
|
+
*
|
|
1118
|
+
* Skipped when this apply did not mutate package.json: the trampoline exists
|
|
1119
|
+
* solely to redo package.json changes that the parent package manager's
|
|
1120
|
+
* end-of-command rewrite clobbers (#383). With no mutation there is nothing
|
|
1121
|
+
* to clobber — the rewrite restores identical content — and scheduling a
|
|
1122
|
+
* detached re-apply (plus its lockfile regen) is pure waste. File-based
|
|
1123
|
+
* template writes are not clobbered and need no reconciliation.
|
|
1124
|
+
* @param prePackageJsonHash - Hash of package.json captured before apply mutated anything (null if the file did not exist)
|
|
990
1125
|
* @returns Promise that resolves immediately after the detached child is spawned
|
|
991
1126
|
*/
|
|
992
|
-
async schedulePostinstallReconciliation() {
|
|
1127
|
+
async schedulePostinstallReconciliation(prePackageJsonHash) {
|
|
1128
|
+
const postHash = hashFile(this.hostPackageJsonPath());
|
|
1129
|
+
if (prePackageJsonHash === postHash) {
|
|
1130
|
+
this.deps.logger.info(pc.gray("Postinstall reconciliation skipped: package.json unchanged by this apply"));
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
993
1133
|
if (!shouldSchedulePostinstallReconciliation(this.config.dryRun)) {
|
|
994
1134
|
return;
|
|
995
1135
|
}
|