supipowers 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -12
- package/package.json +11 -15
- package/skills/ui-design/SKILL.md +2 -2
- package/src/ai/final-message.ts +15 -1
- package/src/ai/schema-text.ts +60 -40
- package/src/ai/schema-validation.ts +88 -0
- package/src/ai/structured-output.ts +19 -19
- package/src/bootstrap.ts +2 -1
- package/src/commands/doctor.ts +3 -2
- package/src/commands/fix-pr.ts +166 -26
- package/src/commands/plan.ts +2 -1
- package/src/commands/update.ts +7 -5
- package/src/config/schema.ts +102 -139
- package/src/docs/contracts.ts +13 -23
- package/src/fix-pr/assessment.ts +63 -24
- package/src/fix-pr/contracts.ts +15 -23
- package/src/fix-pr/fetch-comments.ts +119 -0
- package/src/fix-pr/prompt-builder.ts +19 -8
- package/src/git/commit-contract.ts +13 -19
- package/src/git/commit.ts +168 -6
- package/src/harness/anti_slop/fallow-adapter.ts +4 -3
- package/src/harness/command.ts +12 -7
- package/src/harness/pipeline.ts +2 -8
- package/src/harness/stage-runner.ts +3 -0
- package/src/harness/stages/docs.ts +82 -0
- package/src/lsp/capabilities.ts +9 -12
- package/src/lsp/contracts.ts +15 -23
- package/src/mempalace/uv.ts +15 -7
- package/src/planning/approval-flow.ts +15 -17
- package/src/planning/planning-ask-tool.ts +13 -2
- package/src/planning/spec.ts +21 -27
- package/src/planning/system-prompt.ts +1 -1
- package/src/planning/validate.ts +4 -7
- package/src/platform/progress.ts +11 -0
- package/src/quality/contracts.ts +15 -23
- package/src/quality/schemas.ts +40 -67
- package/src/release/contracts.ts +19 -28
- package/src/review/types.ts +142 -186
- package/src/types.ts +15 -2
- package/src/ui-design/session.ts +13 -2
- package/src/ui-design/system-prompt.ts +2 -2
- package/src/ultraplan/contracts.ts +458 -524
- package/src/utils/exec-cli.ts +106 -0
- package/src/visual/scripts/npm-shrinkwrap.json +878 -0
- package/src/visual/scripts/package-lock.json +878 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
import type { ExecOptions, ExecResult } from "../platform/types.js";
|
|
5
|
+
import { findExecutable } from "./executable.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Cross-platform invocation for npm/npx that survives Windows `.cmd` shims.
|
|
9
|
+
*
|
|
10
|
+
* OMP's `platform.exec` is a thin wrapper over libuv's `uv_spawn`. On Windows
|
|
11
|
+
* that exposes two distinct bugs when the target is an npm-shipped CLI:
|
|
12
|
+
*
|
|
13
|
+
* 1. libuv does not consult `PATHEXT`, so spawning `"npm"` fails with
|
|
14
|
+
* `ENOENT: uv_spawn 'npm'` because the on-disk file is `npm.cmd`.
|
|
15
|
+
* 2. Even when callers resolve the absolute path, Node ≥18.20.2 hard-rejects
|
|
16
|
+
* spawning `.cmd`/`.bat` shims without `shell: true` (CVE-2024-27980).
|
|
17
|
+
* `ExecOptions` does not expose `shell`.
|
|
18
|
+
*
|
|
19
|
+
* Wrapping in `cmd.exe /d /s /c` is the canonical workaround, but only safe
|
|
20
|
+
* when the spawner sets `windowsVerbatimArguments: true` — Node's default
|
|
21
|
+
* CRT escaping double-quotes the command line and cmd's `/s` only strips one
|
|
22
|
+
* pair. We don't control the spawner, so we sidestep the whole problem by
|
|
23
|
+
* resolving the shim to the real `node <cli.js>` invocation, which is exactly
|
|
24
|
+
* what `npm.cmd` does internally. `node.exe` is a plain binary that libuv
|
|
25
|
+
* spawns without ceremony.
|
|
26
|
+
*
|
|
27
|
+
* Non-shim binaries (`bun`, `git`, `node`, `gh`, `rustup`, `go`, `pip`, …
|
|
28
|
+
* all ship as `.exe` on Windows) pass through untouched; POSIX always passes
|
|
29
|
+
* through.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export type ExecFn = (
|
|
33
|
+
cmd: string,
|
|
34
|
+
args: string[],
|
|
35
|
+
opts?: ExecOptions,
|
|
36
|
+
) => Promise<ExecResult>;
|
|
37
|
+
|
|
38
|
+
interface ResolvedInvocation {
|
|
39
|
+
cmd: string;
|
|
40
|
+
prefixArgs: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const NODE_SHIMS = new Set<string>(["npm", "npx"]);
|
|
44
|
+
const resolutionCache = new Map<string, ResolvedInvocation>();
|
|
45
|
+
|
|
46
|
+
function resolveNodeShim(command: string): ResolvedInvocation | null {
|
|
47
|
+
if (!NODE_SHIMS.has(command)) return null;
|
|
48
|
+
|
|
49
|
+
// node.exe is the executor; npm-cli.js / npx-cli.js sits next to it under
|
|
50
|
+
// node_modules/npm/bin/. We deliberately key off node's location (not the
|
|
51
|
+
// shim's) because `npm.cmd` can live in a user-global dir (e.g. nvm,
|
|
52
|
+
// %AppData%\npm) while the actual CLI bundle stays alongside node.
|
|
53
|
+
const nodeBin = findExecutable("node");
|
|
54
|
+
if (!nodeBin) return null;
|
|
55
|
+
|
|
56
|
+
const cliJs = join(
|
|
57
|
+
dirname(nodeBin),
|
|
58
|
+
"node_modules",
|
|
59
|
+
"npm",
|
|
60
|
+
"bin",
|
|
61
|
+
`${command}-cli.js`,
|
|
62
|
+
);
|
|
63
|
+
if (!existsSync(cliJs)) return null;
|
|
64
|
+
|
|
65
|
+
return { cmd: nodeBin, prefixArgs: [cliJs] };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveInvocation(command: string): ResolvedInvocation {
|
|
69
|
+
if (process.platform !== "win32") {
|
|
70
|
+
return { cmd: command, prefixArgs: [] };
|
|
71
|
+
}
|
|
72
|
+
const cached = resolutionCache.get(command);
|
|
73
|
+
if (cached) return cached;
|
|
74
|
+
|
|
75
|
+
const resolved = resolveNodeShim(command) ?? { cmd: command, prefixArgs: [] };
|
|
76
|
+
resolutionCache.set(command, resolved);
|
|
77
|
+
return resolved;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Drop-in replacement for `platform.exec` callers that invoke npm/npx by name.
|
|
82
|
+
* Other commands pass through unchanged.
|
|
83
|
+
*/
|
|
84
|
+
export function execCli(
|
|
85
|
+
exec: ExecFn,
|
|
86
|
+
command: string,
|
|
87
|
+
args: string[],
|
|
88
|
+
opts?: ExecOptions,
|
|
89
|
+
): Promise<ExecResult> {
|
|
90
|
+
const resolved = resolveInvocation(command);
|
|
91
|
+
return exec(resolved.cmd, [...resolved.prefixArgs, ...args], opts);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Wrap an `ExecFn` so every call routes through `execCli`. Use when threading
|
|
96
|
+
* an exec callback into helpers that dispatch arbitrary tools by string name
|
|
97
|
+
* (e.g. the deps installer which splits install-command strings).
|
|
98
|
+
*/
|
|
99
|
+
export function wrapExecForCli(exec: ExecFn): ExecFn {
|
|
100
|
+
return (cmd, args, opts) => execCli(exec, cmd, args, opts);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Clears cached CLI resolutions after PATH or tooling changes. */
|
|
104
|
+
export function clearExecCliResolutionCache(): void {
|
|
105
|
+
resolutionCache.clear();
|
|
106
|
+
}
|