@codyswann/lisa 2.324.1 → 2.325.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/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +27 -3
- package/dist/core/upstream-evidence-manifest.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/.codex-plugin/skills/lisa-detect-tooling/SKILL.md +60 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-detect-tooling/agents/openai.yaml +4 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +311 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +18 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +74 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +50 -3
- package/plugins/lisa/commands/detect-tooling.md +7 -0
- package/plugins/lisa/skills/lisa-detect-tooling/SKILL.md +60 -0
- package/plugins/lisa/skills/lisa-detect-tooling/agents/openai.yaml +4 -0
- package/plugins/lisa/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +311 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +18 -2
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +74 -3
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/toolchain.mjs +50 -3
- package/plugins/lisa-agy/commands/lisa/detect-tooling.md +7 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-detect-tooling/SKILL.md +60 -0
- package/plugins/lisa-agy/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +311 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +18 -2
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +74 -3
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/toolchain.mjs +50 -3
- 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/commands/lisa/detect-tooling.md +7 -0
- package/plugins/lisa-copilot/skills/lisa-detect-tooling/SKILL.md +60 -0
- package/plugins/lisa-copilot/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +311 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +18 -2
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +74 -3
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/toolchain.mjs +50 -3
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/commands/lisa/detect-tooling.md +7 -0
- package/plugins/lisa-cursor/skills/lisa-detect-tooling/SKILL.md +60 -0
- package/plugins/lisa-cursor/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +311 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +18 -2
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +74 -3
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/toolchain.mjs +50 -3
- 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/commands/detect-tooling.md +7 -0
- package/plugins/src/base/skills/lisa-detect-tooling/SKILL.md +60 -0
- package/plugins/src/base/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +311 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +18 -2
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +74 -3
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs +50 -3
|
@@ -221,8 +221,9 @@ function installTool(tool, binDir) {
|
|
|
221
221
|
* @param {boolean} dryRun Whether to plan only.
|
|
222
222
|
* @returns {Array<object>} The plan that was applied.
|
|
223
223
|
*/
|
|
224
|
-
function applyToolchain(tools, dryRun) {
|
|
225
|
-
const
|
|
224
|
+
function applyToolchain(tools, dryRun, options = {}) {
|
|
225
|
+
const { surface = "remote", consent = true } = options;
|
|
226
|
+
const plan = planToolchain(tools, probe, surface);
|
|
226
227
|
const blocked = plan.filter(
|
|
227
228
|
p => p.action === "missing" || p.action === "invalid"
|
|
228
229
|
);
|
|
@@ -234,6 +235,34 @@ function applyToolchain(tools, dryRun) {
|
|
|
234
235
|
mkdirSync(binDir, { recursive: true, mode: 0o755 });
|
|
235
236
|
const byName = new Map((tools.install ?? []).map(t => [t.name, t]));
|
|
236
237
|
|
|
238
|
+
// Installing is a different act on a laptop than in a container. A container
|
|
239
|
+
// is disposable and provisioning it silently is the whole point; a developer
|
|
240
|
+
// machine belongs to a person, and putting pinned binaries in their
|
|
241
|
+
// ~/.local/bin without being asked is not ours to decide. So the same
|
|
242
|
+
// manifest drives both, and only the consent differs.
|
|
243
|
+
//
|
|
244
|
+
// Reporting still happens either way — knowing the machine diverges from what
|
|
245
|
+
// the project declares is most of the value, and is what nothing did before.
|
|
246
|
+
if (!consent) {
|
|
247
|
+
const missing = plan.filter(step => step.action === "install");
|
|
248
|
+
if (missing.length === 0) {
|
|
249
|
+
console.log(" every declared tool is already present");
|
|
250
|
+
return plan;
|
|
251
|
+
}
|
|
252
|
+
console.log(
|
|
253
|
+
` ${missing.length} declared tool(s) are missing or below their pin:`
|
|
254
|
+
);
|
|
255
|
+
for (const step of missing) {
|
|
256
|
+
const tool = byName.get(step.name);
|
|
257
|
+
console.log(` ${step.name}${tool?.version ? ` ${tool.version}` : ""}`);
|
|
258
|
+
}
|
|
259
|
+
console.log(
|
|
260
|
+
"\n Not installing without confirmation. Re-run with --install-tools\n" +
|
|
261
|
+
" to provision them, or install them yourself."
|
|
262
|
+
);
|
|
263
|
+
return plan;
|
|
264
|
+
}
|
|
265
|
+
|
|
237
266
|
// Installing a binary somewhere nothing looks is the same as not installing
|
|
238
267
|
// it. `~/.local/bin` is on PATH by default on a developer workstation and is
|
|
239
268
|
// NOT on a minimal container, so the toolchain step reported `install bws`,
|
|
@@ -526,6 +555,40 @@ export function emitClaudeWeb({ bootstrapKey }) {
|
|
|
526
555
|
].join("\n");
|
|
527
556
|
}
|
|
528
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Report tooling the project appears to need but has not declared.
|
|
560
|
+
*
|
|
561
|
+
* Called before the toolchain is applied, because the manifest is the only
|
|
562
|
+
* thing that puts a binary on PATH and nothing populates it — so provisioning
|
|
563
|
+
* "the declared toolchain" happily succeeds while the tool a project actually
|
|
564
|
+
* uses is absent, and fails later at the moment of use instead of here.
|
|
565
|
+
*
|
|
566
|
+
* Informational, never blocking. The detector proposes and a human decides, so
|
|
567
|
+
* an undeclared tool must not stop a setup that was asked to provision what IS
|
|
568
|
+
* declared; failing here would make a advisory signal into a gate nobody chose.
|
|
569
|
+
* Its own absence is silent for the same reason: an older installed copy of the
|
|
570
|
+
* skills has no detector, and that is not a reason to refuse to provision.
|
|
571
|
+
* @param {Function} [exec] Seam for tests.
|
|
572
|
+
*/
|
|
573
|
+
function reportUndeclaredTooling(exec = execFileSync) {
|
|
574
|
+
let script;
|
|
575
|
+
try {
|
|
576
|
+
script = siblingScript("lisa-detect-tooling", "detect-tooling.mjs");
|
|
577
|
+
} catch {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
try {
|
|
581
|
+
const out = exec("node", [script], {
|
|
582
|
+
encoding: "utf8",
|
|
583
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
584
|
+
});
|
|
585
|
+
const text = String(out).trim();
|
|
586
|
+
if (text) console.log(`\n${text}\n`);
|
|
587
|
+
} catch {
|
|
588
|
+
// A detector that cannot run is a missing hint, not a failed setup.
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
529
592
|
/**
|
|
530
593
|
* Decide which phases this invocation runs.
|
|
531
594
|
*
|
|
@@ -640,8 +703,16 @@ async function main() {
|
|
|
640
703
|
}
|
|
641
704
|
|
|
642
705
|
if (phases.includes("toolchain")) {
|
|
706
|
+
reportUndeclaredTooling();
|
|
643
707
|
console.log("Toolchain:");
|
|
644
|
-
|
|
708
|
+
// A remote container consents by construction: it is disposable, nobody is
|
|
709
|
+
// watching, and provisioning it is why the script exists. Locally the
|
|
710
|
+
// operator opts in per run.
|
|
711
|
+
const remote = Boolean(materializeAt);
|
|
712
|
+
applyToolchain(cfg.tools, dryRun, {
|
|
713
|
+
surface: remote ? "remote" : "local",
|
|
714
|
+
consent: remote || process.argv.includes("--install-tools"),
|
|
715
|
+
});
|
|
645
716
|
}
|
|
646
717
|
|
|
647
718
|
if (phases.includes("secrets")) {
|
|
@@ -124,18 +124,65 @@ function planInstallable(tool, found) {
|
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
/** Surfaces a manifest entry may name. */
|
|
128
|
+
const KNOWN_SURFACES = new Set(["local", "remote"]);
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Whether a manifest entry applies to the surface being provisioned.
|
|
132
|
+
*
|
|
133
|
+
* One declaration per tool, not one block per surface. Most tools a project
|
|
134
|
+
* needs are needed *everywhere* — a Maestro or Sonar CLI is as required on a
|
|
135
|
+
* laptop as in a container — and duplicated blocks drift, which this repository
|
|
136
|
+
* has paid for more than once. What actually differs between surfaces is the
|
|
137
|
+
* install method and, more importantly, consent: a disposable container may
|
|
138
|
+
* install silently, a developer's machine may not.
|
|
139
|
+
*
|
|
140
|
+
* Omitting `surfaces` means every surface, because that is true of most tools
|
|
141
|
+
* and the failure of forgetting it should be "checked somewhere unnecessary"
|
|
142
|
+
* rather than "silently absent where it was needed".
|
|
143
|
+
* @param {object} tool Manifest entry.
|
|
144
|
+
* @param {string} surface Surface being provisioned.
|
|
145
|
+
* @returns {boolean} Whether this entry applies.
|
|
146
|
+
*/
|
|
147
|
+
export function appliesToSurface(tool, surface) {
|
|
148
|
+
const surfaces = tool.surfaces;
|
|
149
|
+
if (surfaces === undefined) return true;
|
|
150
|
+
// A typo must not silently widen scope. Treating any non-array as "omitted"
|
|
151
|
+
// meant `surfaces: "remote"` — an easy thing to write — quietly applied the
|
|
152
|
+
// entry to every surface, which for a platform-specific archive means
|
|
153
|
+
// offering a Linux binary to a laptop. Absent means everywhere; malformed
|
|
154
|
+
// means stop.
|
|
155
|
+
if (!Array.isArray(surfaces)) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`${tool.name}: surfaces must be an array, got ${typeof surfaces}.\n` +
|
|
158
|
+
`Omit it to mean every surface; write ["remote"] or ["local"] to narrow.`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (surfaces.length === 0) return true;
|
|
162
|
+
const unknown = surfaces.filter(entry => !KNOWN_SURFACES.has(entry));
|
|
163
|
+
if (unknown.length > 0) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`${tool.name}: unknown surface(s) ${unknown.join(", ")}.\n` +
|
|
166
|
+
`Known: ${[...KNOWN_SURFACES].join(", ")}.`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
return surfaces.includes(surface);
|
|
170
|
+
}
|
|
171
|
+
|
|
127
172
|
/**
|
|
128
173
|
* Produce the complete plan for a toolchain manifest.
|
|
129
174
|
* @param {{require?: object[], install?: object[]}} tools Manifest.
|
|
130
175
|
* @param {(name: string) => {version: string|null, present: boolean}} probe Version probe.
|
|
131
176
|
* @returns {Array<{name: string, action: string, reason: string}>} Ordered decisions.
|
|
132
177
|
*/
|
|
133
|
-
export function planToolchain(tools, probe) {
|
|
178
|
+
export function planToolchain(tools, probe, surface = "remote") {
|
|
134
179
|
const plan = [];
|
|
135
180
|
for (const tool of tools.require ?? [])
|
|
136
|
-
|
|
181
|
+
if (appliesToSurface(tool, surface))
|
|
182
|
+
plan.push(planRequired(tool, probe(tool.name)));
|
|
137
183
|
for (const tool of tools.install ?? [])
|
|
138
|
-
|
|
184
|
+
if (appliesToSurface(tool, surface))
|
|
185
|
+
plan.push(planInstallable(tool, probe(tool.name)));
|
|
139
186
|
return plan;
|
|
140
187
|
}
|
|
141
188
|
|