@webpresso/agent-kit 3.1.26 → 3.1.30
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/catalog/AGENTS.md.tpl +7 -11
- package/catalog/agent/commands/verify.md +2 -2
- package/catalog/agent/rules/changeset-release.md +4 -2
- package/catalog/agent/rules/ci-cost-local-first.md +139 -0
- package/catalog/agent/rules/ci-test-perf.md +5 -1
- package/catalog/agent/rules/cmd-execution.md +9 -0
- package/catalog/agent/rules/pre-implementation.md +2 -1
- package/catalog/agent/rules/test-scan-perf.md +80 -0
- package/catalog/agent/rules/workflow-skills-routing.md +9 -4
- package/catalog/agent/skills/autopilot/SKILL.md +48 -11
- package/catalog/agent/skills/claude/SKILL.md +7 -0
- package/catalog/agent/skills/codex/SKILL.md +7 -0
- package/catalog/agent/skills/fix/SKILL.md +36 -8
- package/catalog/agent/skills/grok/SKILL.md +7 -0
- package/catalog/agent/skills/investigate/SKILL.md +12 -1
- package/catalog/agent/skills/pll/SKILL.md +53 -48
- package/catalog/agent/skills/team/SKILL.md +26 -9
- package/catalog/agent/skills/ultragoal/SKILL.md +147 -19
- package/catalog/agent/skills/verify/SKILL.md +89 -51
- package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +8 -0
- package/dist/esm/audit/blueprint-lifecycle-sql.js +25 -1
- package/dist/esm/audit/blueprint-pr-coverage.js +68 -7
- package/dist/esm/audit/registry.d.ts +4 -4
- package/dist/esm/audit/registry.js +3 -0
- package/dist/esm/audit/roadmap-links.js +6 -0
- package/dist/esm/audit/test-scan-perf.d.ts +18 -0
- package/dist/esm/audit/test-scan-perf.js +275 -0
- package/dist/esm/blueprint/lifecycle/engine.d.ts +9 -0
- package/dist/esm/blueprint/lifecycle/engine.js +53 -6
- package/dist/esm/blueprint/lifecycle/review-provenance.d.ts +6 -0
- package/dist/esm/blueprint/lifecycle/review-provenance.js +93 -12
- package/dist/esm/blueprint/markdown/helpers.js +6 -2
- package/dist/esm/ci/act-replay.js +110 -7
- package/dist/esm/ci/act-runner.d.ts +4 -0
- package/dist/esm/ci/act-runner.js +85 -26
- package/dist/esm/ci/act-worktree-git.d.ts +11 -0
- package/dist/esm/ci/act-worktree-git.js +219 -0
- package/dist/esm/ci/native-session-memory-cache.d.ts +9 -1
- package/dist/esm/ci/native-session-memory-cache.js +9 -1
- package/dist/esm/ci/vitest-ci-shards.d.ts +6 -4
- package/dist/esm/ci/vitest-ci-shards.js +6 -4
- package/dist/esm/cli/auto-update/guard-tombstone.d.ts +25 -0
- package/dist/esm/cli/auto-update/guard-tombstone.js +67 -0
- package/dist/esm/cli/auto-update/installer.d.ts +4 -17
- package/dist/esm/cli/auto-update/installer.js +6 -57
- package/dist/esm/cli/auto-update/self-invocation.d.ts +37 -0
- package/dist/esm/cli/auto-update/self-invocation.js +62 -0
- package/dist/esm/cli/commands/audit.js +4 -0
- package/dist/esm/cli/commands/blueprint/mutations.js +35 -18
- package/dist/esm/cli/commands/blueprint/router.js +27 -2
- package/dist/esm/cli/commands/ci.d.ts +8 -1
- package/dist/esm/cli/commands/ci.js +80 -21
- package/dist/esm/cli/commands/dash/index.js +3 -3
- package/dist/esm/cli/commands/dash/keymap.js +1 -0
- package/dist/esm/cli/commands/dash/launch-preferences.d.ts +15 -0
- package/dist/esm/cli/commands/dash/launch-preferences.js +46 -17
- package/dist/esm/cli/commands/dash/plan-once-attention.d.ts +32 -0
- package/dist/esm/cli/commands/dash/plan-once-attention.js +50 -0
- package/dist/esm/cli/commands/dash/plan-once-label.d.ts +7 -0
- package/dist/esm/cli/commands/dash/plan-once-label.js +5 -0
- package/dist/esm/cli/commands/dash/plan-once-membership.d.ts +67 -0
- package/dist/esm/cli/commands/dash/plan-once-membership.js +151 -0
- package/dist/esm/cli/commands/dash/plan-once-merge.d.ts +143 -0
- package/dist/esm/cli/commands/dash/plan-once-merge.js +238 -0
- package/dist/esm/cli/commands/dash/plan-once-schema.d.ts +73 -0
- package/dist/esm/cli/commands/dash/plan-once-schema.js +119 -0
- package/dist/esm/cli/commands/dash/plan-once.d.ts +142 -0
- package/dist/esm/cli/commands/dash/plan-once.js +261 -0
- package/dist/esm/cli/commands/dash/tui/attention-hud.d.ts +9 -0
- package/dist/esm/cli/commands/dash/tui/attention-hud.js +9 -0
- package/dist/esm/cli/commands/dash/tui/chat-bridge.d.ts +41 -0
- package/dist/esm/cli/commands/dash/tui/chat-bridge.js +73 -0
- package/dist/esm/cli/commands/dash/tui/chat-mode.d.ts +47 -0
- package/dist/esm/cli/commands/dash/tui/chat-mode.js +98 -0
- package/dist/esm/cli/commands/dash/tui/frame.d.ts +3 -0
- package/dist/esm/cli/commands/dash/tui/frame.js +3 -1
- package/dist/esm/cli/commands/dash/tui/ipc-protocol.d.ts +87 -0
- package/dist/esm/cli/commands/dash/tui/ipc-protocol.js +128 -0
- package/dist/esm/cli/commands/dash/tui/native-host.d.ts +34 -0
- package/dist/esm/cli/commands/dash/tui/native-host.js +256 -0
- package/dist/esm/cli/commands/dash/tui/native-path.d.ts +11 -0
- package/dist/esm/cli/commands/dash/tui/native-path.js +41 -0
- package/dist/esm/cli/commands/dash/tui/palette.d.ts +1 -1
- package/dist/esm/cli/commands/dash/tui/palette.js +14 -0
- package/dist/esm/cli/commands/dash/tui/runtime.js +311 -4
- package/dist/esm/cli/commands/dash/tui/state.d.ts +41 -0
- package/dist/esm/cli/commands/dash/tui/state.js +257 -4
- package/dist/esm/cli/commands/format.js +0 -2
- package/dist/esm/cli/commands/init/config.d.ts +0 -1
- package/dist/esm/cli/commands/init/config.js +1 -4
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.d.ts +5 -6
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.js +6 -13
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.d.ts +0 -2
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.js +0 -2
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.d.ts +6 -3
- package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.js +39 -26
- package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +1 -1
- package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +61 -23
- package/dist/esm/cli/commands/logs.d.ts +15 -0
- package/dist/esm/cli/commands/logs.js +192 -3
- package/dist/esm/cli/commands/package-manager.js +2 -1
- package/dist/esm/cli/commands/quality-log-store.d.ts +1 -0
- package/dist/esm/cli/commands/quality-log-store.js +187 -51
- package/dist/esm/cli/commands/review.js +5 -8
- package/dist/esm/cli/commands/secrets.d.ts +1 -0
- package/dist/esm/cli/commands/secrets.js +4 -1
- package/dist/esm/cli/commands/self-install-guard.d.ts +14 -32
- package/dist/esm/cli/commands/self-install-guard.js +17 -63
- package/dist/esm/cli/direct-provider-launch.js +25 -1
- package/dist/esm/hooks/doctor.d.ts +15 -0
- package/dist/esm/hooks/doctor.js +56 -0
- package/dist/esm/hooks/guard-switch/index.js +8 -4
- package/dist/esm/hooks/post-tool/lint-after-edit.js +6 -4
- package/dist/esm/hooks/precompact/index.js +5 -3
- package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +4 -4
- package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +0 -1
- package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +8 -5
- package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.d.ts +9 -7
- package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.js +126 -14
- package/dist/esm/hooks/sessionstart/index.d.ts +10 -0
- package/dist/esm/hooks/sessionstart/index.js +61 -4
- package/dist/esm/hooks/shared/types.d.ts +11 -0
- package/dist/esm/hooks/shared/types.js +21 -0
- package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
- package/dist/esm/mcp/tools/audit.d.ts +2 -1
- package/dist/esm/mcp/tools/audit.js +10 -0
- package/dist/esm/mcp/tools/audits.d.ts +1 -0
- package/dist/esm/mcp/tools/ci-act.js +9 -11
- package/dist/esm/paths/state-root.js +9 -0
- package/dist/esm/review/authority.js +17 -2
- package/dist/esm/review/availability.js +18 -5
- package/dist/esm/review/subject.d.ts +15 -0
- package/dist/esm/review/subject.js +105 -10
- package/dist/esm/runtime/executor.d.ts +1 -0
- package/dist/esm/runtime/executor.js +2 -1
- package/dist/esm/secret-gate/runner.d.ts +1 -0
- package/dist/esm/secret-gate/runner.js +4 -1
- package/dist/esm/session-memory/current-session.js +2 -0
- package/dist/esm/session-memory/native-runtime.js +5 -3
- package/dist/esm/session-memory/native-warm-markers.d.ts +18 -0
- package/dist/esm/session-memory/native-warm-markers.js +22 -0
- package/dist/esm/session-memory/sync/types.d.ts +4 -0
- package/dist/esm/session-memory/types.d.ts +3 -1
- package/dist/esm/session-memory/types.js +2 -0
- package/dist/esm/ultragoal/runtime.js +44 -2
- package/dist/esm/worktrees/current.d.ts +1 -0
- package/dist/esm/worktrees/current.js +1 -0
- package/dist/esm/worktrees/project-agent-surfaces.d.ts +1 -0
- package/dist/esm/worktrees/project-agent-surfaces.js +2 -1
- package/package.json +17 -14
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, symlinkSync, } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
5
|
+
export function prepareActGitWorkspace(cwd) {
|
|
6
|
+
const sourceCwd = resolve(cwd);
|
|
7
|
+
const linked = readLinkedWorktreeGitMetadata(sourceCwd);
|
|
8
|
+
if (!linked) {
|
|
9
|
+
return {
|
|
10
|
+
cwd: sourceCwd,
|
|
11
|
+
prepared: false,
|
|
12
|
+
cleanup() { },
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
assertExistingDirectory(linked.gitDir, "linked-worktree gitdir");
|
|
16
|
+
const commonDir = resolveGitCommonDir(linked.gitDir);
|
|
17
|
+
assertExistingDirectory(commonDir, "linked-worktree commondir");
|
|
18
|
+
const tempRoot = mkdtempSync(join(tmpdir(), "wp-ci-act-worktree-"));
|
|
19
|
+
const preparedCwd = join(tempRoot, "workspace");
|
|
20
|
+
try {
|
|
21
|
+
const head = git(sourceCwd, ["rev-parse", "HEAD"]);
|
|
22
|
+
git(sourceCwd, ["rev-parse", "--is-inside-work-tree"]);
|
|
23
|
+
execFileSync("git", [
|
|
24
|
+
"clone",
|
|
25
|
+
"--local",
|
|
26
|
+
"--no-hardlinks",
|
|
27
|
+
"--dissociate",
|
|
28
|
+
"--no-checkout",
|
|
29
|
+
sourceCwd,
|
|
30
|
+
preparedCwd,
|
|
31
|
+
], {
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
34
|
+
});
|
|
35
|
+
syncOriginRemote(sourceCwd, preparedCwd);
|
|
36
|
+
git(preparedCwd, ["checkout", "--detach", "--quiet", head]);
|
|
37
|
+
overlayWorkingTreeChanges(sourceCwd, preparedCwd);
|
|
38
|
+
assertPreparedGitMetadataIsSelfContained(preparedCwd);
|
|
39
|
+
return {
|
|
40
|
+
cwd: preparedCwd,
|
|
41
|
+
prepared: true,
|
|
42
|
+
cleanup() {
|
|
43
|
+
rmSync(tempRoot, { recursive: true, force: true });
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
rmSync(tempRoot, { recursive: true, force: true });
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function readLinkedWorktreeGitMetadata(cwd) {
|
|
53
|
+
const gitPath = join(cwd, ".git");
|
|
54
|
+
if (!existsSync(gitPath)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const stat = lstatSync(gitPath);
|
|
58
|
+
if (stat.isDirectory())
|
|
59
|
+
return null;
|
|
60
|
+
if (!stat.isFile()) {
|
|
61
|
+
throw new Error(`Cannot prepare ci act workspace: ${gitPath} is not a file or directory.`);
|
|
62
|
+
}
|
|
63
|
+
const content = readFileSync(gitPath, "utf8").trim();
|
|
64
|
+
const match = /^gitdir:\s*(.+)$/u.exec(content);
|
|
65
|
+
if (!match?.[1]) {
|
|
66
|
+
throw new Error(`Cannot prepare ci act workspace: ${gitPath} is not a valid gitdir file.`);
|
|
67
|
+
}
|
|
68
|
+
return { gitDir: resolve(cwd, match[1]) };
|
|
69
|
+
}
|
|
70
|
+
function resolveGitCommonDir(gitDir) {
|
|
71
|
+
const commonDirPath = join(gitDir, "commondir");
|
|
72
|
+
if (!existsSync(commonDirPath))
|
|
73
|
+
return gitDir;
|
|
74
|
+
const raw = readFileSync(commonDirPath, "utf8").trim();
|
|
75
|
+
if (!raw)
|
|
76
|
+
throw new Error(`Cannot prepare ci act workspace: ${commonDirPath} is empty.`);
|
|
77
|
+
return resolve(gitDir, raw);
|
|
78
|
+
}
|
|
79
|
+
function overlayWorkingTreeChanges(sourceCwd, preparedCwd) {
|
|
80
|
+
const changed = parseGitDiffNameStatus(splitGitNullOutput(gitRaw(sourceCwd, ["diff", "--name-status", "--find-renames", "-z", "HEAD", "--"])));
|
|
81
|
+
const untracked = splitGitNullOutput(gitRaw(sourceCwd, ["ls-files", "--others", "--exclude-standard", "-z"]));
|
|
82
|
+
const copyPaths = new Set([...changed.copyPaths, ...untracked]);
|
|
83
|
+
for (const relativePath of changed.removePaths) {
|
|
84
|
+
assertSafeGitRelativePath(relativePath);
|
|
85
|
+
rmSync(join(preparedCwd, relativePath), { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
for (const relativePath of copyPaths) {
|
|
88
|
+
assertSafeGitRelativePath(relativePath);
|
|
89
|
+
const sourcePath = join(sourceCwd, relativePath);
|
|
90
|
+
const preparedPath = join(preparedCwd, relativePath);
|
|
91
|
+
const sourceStat = tryLstat(sourcePath);
|
|
92
|
+
if (!sourceStat) {
|
|
93
|
+
rmSync(preparedPath, { recursive: true, force: true });
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
mkdirSync(dirname(preparedPath), { recursive: true });
|
|
97
|
+
if (sourceStat.isSymbolicLink()) {
|
|
98
|
+
rmSync(preparedPath, { recursive: true, force: true });
|
|
99
|
+
symlinkSync(readlinkSync(sourcePath), preparedPath);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
rmSync(preparedPath, { recursive: true, force: true });
|
|
103
|
+
cpSync(sourcePath, preparedPath, { recursive: true, force: true, errorOnExist: false });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function tryLstat(path) {
|
|
107
|
+
try {
|
|
108
|
+
return lstatSync(path);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function parseGitDiffNameStatus(entries) {
|
|
118
|
+
const copyPaths = new Set();
|
|
119
|
+
const removePaths = new Set();
|
|
120
|
+
for (let index = 0; index < entries.length;) {
|
|
121
|
+
const status = entries[index++];
|
|
122
|
+
if (!status)
|
|
123
|
+
continue;
|
|
124
|
+
if (status.startsWith("R")) {
|
|
125
|
+
const oldPath = entries[index++];
|
|
126
|
+
const newPath = entries[index++];
|
|
127
|
+
if (oldPath)
|
|
128
|
+
removePaths.add(oldPath);
|
|
129
|
+
if (newPath)
|
|
130
|
+
copyPaths.add(newPath);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (status.startsWith("C")) {
|
|
134
|
+
index++;
|
|
135
|
+
const newPath = entries[index++];
|
|
136
|
+
if (newPath)
|
|
137
|
+
copyPaths.add(newPath);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const path = entries[index++];
|
|
141
|
+
if (!path)
|
|
142
|
+
continue;
|
|
143
|
+
if (status.startsWith("D")) {
|
|
144
|
+
removePaths.add(path);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
copyPaths.add(path);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { copyPaths, removePaths };
|
|
151
|
+
}
|
|
152
|
+
function syncOriginRemote(sourceCwd, preparedCwd) {
|
|
153
|
+
const originUrl = tryGit(sourceCwd, ["remote", "get-url", "origin"]);
|
|
154
|
+
if (originUrl) {
|
|
155
|
+
git(preparedCwd, ["remote", "set-url", "origin", originUrl]);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
tryGit(preparedCwd, ["remote", "remove", "origin"]);
|
|
159
|
+
}
|
|
160
|
+
function assertPreparedGitMetadataIsSelfContained(preparedCwd) {
|
|
161
|
+
const gitPath = join(preparedCwd, ".git");
|
|
162
|
+
if (!existsSync(gitPath) || !lstatSync(gitPath).isDirectory()) {
|
|
163
|
+
throw new Error("Cannot prepare ci act workspace: prepared .git metadata is not a directory.");
|
|
164
|
+
}
|
|
165
|
+
const commonDir = resolve(preparedCwd, git(preparedCwd, ["rev-parse", "--git-common-dir"]));
|
|
166
|
+
const relative = commonDirRelativeToPrepared(preparedCwd, commonDir);
|
|
167
|
+
if (relative === null) {
|
|
168
|
+
throw new Error(`Cannot prepare ci act workspace: prepared git common dir escaped the execution workspace (${commonDir}).`);
|
|
169
|
+
}
|
|
170
|
+
const alternatesPath = join(commonDir, "objects", "info", "alternates");
|
|
171
|
+
if (existsSync(alternatesPath) && readFileSync(alternatesPath, "utf8").trim().length > 0) {
|
|
172
|
+
throw new Error(`Cannot prepare ci act workspace: prepared git objects still depend on alternates (${alternatesPath}).`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function commonDirRelativeToPrepared(preparedCwd, commonDir) {
|
|
176
|
+
const normalizedRoot = resolve(preparedCwd);
|
|
177
|
+
const normalizedCommon = resolve(commonDir);
|
|
178
|
+
if (normalizedCommon === normalizedRoot)
|
|
179
|
+
return "";
|
|
180
|
+
if (normalizedCommon.startsWith(`${normalizedRoot}${sep}`)) {
|
|
181
|
+
return normalizedCommon.slice(normalizedRoot.length + 1);
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
function splitGitNullOutput(output) {
|
|
186
|
+
return output.split("\0").filter((entry) => entry.length > 0);
|
|
187
|
+
}
|
|
188
|
+
function assertSafeGitRelativePath(relativePath) {
|
|
189
|
+
if (relativePath.length === 0 ||
|
|
190
|
+
relativePath.startsWith("/") ||
|
|
191
|
+
relativePath === ".." ||
|
|
192
|
+
relativePath.startsWith("../") ||
|
|
193
|
+
relativePath.includes("/../")) {
|
|
194
|
+
throw new Error(`Unsafe git path returned while preparing ci act workspace: ${relativePath}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function assertExistingDirectory(path, label) {
|
|
198
|
+
if (!existsSync(path) || !lstatSync(path).isDirectory()) {
|
|
199
|
+
throw new Error(`Cannot prepare ci act workspace: ${label} is missing or unreadable: ${path}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function git(cwd, args) {
|
|
203
|
+
return gitRaw(cwd, args).trim();
|
|
204
|
+
}
|
|
205
|
+
function tryGit(cwd, args) {
|
|
206
|
+
try {
|
|
207
|
+
return git(cwd, args);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function gitRaw(cwd, args) {
|
|
214
|
+
return execFileSync("git", [...args], {
|
|
215
|
+
cwd,
|
|
216
|
+
encoding: "utf8",
|
|
217
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
218
|
+
});
|
|
219
|
+
}
|
|
@@ -26,7 +26,15 @@ export declare const NATIVE_SESSION_MEMORY_TRUST_CACHED_NODE_ENV = "WP_NATIVE_SE
|
|
|
26
26
|
* Absolute cache dir still comes from env-paths / CACHE_ROOT override at runtime.
|
|
27
27
|
*/
|
|
28
28
|
export declare const NATIVE_SESSION_MEMORY_CACHE_HASH_GLOBS: readonly ["native/session-memory-engine/Cargo.lock", "native/session-memory-engine/Cargo.toml", "native/session-memory-engine/crates/**/*.rs", "native/session-memory-engine/crates/**/Cargo.toml"];
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Default **env-paths** Linux cache location when `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT`
|
|
31
|
+
* is unset (`$HOME/.cache/webpresso-agent-kit/session-memory-engine`).
|
|
32
|
+
*
|
|
33
|
+
* Agent-kit self-CI does **not** use this path for the warm cache: it overrides via
|
|
34
|
+
* `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT` → `${{ runner.temp }}/sm-native-cache` (see
|
|
35
|
+
* the Test job warm cache step in `.github/workflows/ci.agent-kit.yml`). This helper
|
|
36
|
+
* documents the unset-override default only — not the workflow `path:`.
|
|
37
|
+
*/
|
|
30
38
|
export declare function defaultLinuxNativeSessionMemoryCachePath(home?: string): string;
|
|
31
39
|
/**
|
|
32
40
|
* Trust is only safe on an exact primary-key GHA cache hit (sources match the key).
|
|
@@ -31,7 +31,15 @@ export const NATIVE_SESSION_MEMORY_CACHE_HASH_GLOBS = [
|
|
|
31
31
|
"native/session-memory-engine/crates/**/*.rs",
|
|
32
32
|
"native/session-memory-engine/crates/**/Cargo.toml",
|
|
33
33
|
];
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Default **env-paths** Linux cache location when `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT`
|
|
36
|
+
* is unset (`$HOME/.cache/webpresso-agent-kit/session-memory-engine`).
|
|
37
|
+
*
|
|
38
|
+
* Agent-kit self-CI does **not** use this path for the warm cache: it overrides via
|
|
39
|
+
* `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT` → `${{ runner.temp }}/sm-native-cache` (see
|
|
40
|
+
* the Test job warm cache step in `.github/workflows/ci.agent-kit.yml`). This helper
|
|
41
|
+
* documents the unset-override default only — not the workflow `path:`.
|
|
42
|
+
*/
|
|
35
43
|
export function defaultLinuxNativeSessionMemoryCachePath(home = "~") {
|
|
36
44
|
return `${home}/.cache/${NATIVE_SESSION_MEMORY_CACHE_ENV_NAME}/${NATIVE_SESSION_MEMORY_CACHE_SUBDIR}`;
|
|
37
45
|
}
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* All shards together still run every file discovered by vitest.config.ts
|
|
5
5
|
* projects; each shard is a slice via `vitest run --shard=i/n`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Three shards on ubicloud-standard-2 cut billed runner-minutes (fewer
|
|
8
|
+
* parallel installs × smaller class) while keeping full suite coverage.
|
|
9
|
+
* Wall-clock per shard may rise vs the prior 6×standard-4 layout; that is an
|
|
10
|
+
* intentional minutes-vs-wall tradeoff (see docs/ci-test-perf.md).
|
|
9
11
|
*/
|
|
10
|
-
export declare const VITEST_CI_SHARD_TOTAL =
|
|
11
|
-
export declare const VITEST_CI_SHARD_INDICES: readonly [1, 2, 3
|
|
12
|
+
export declare const VITEST_CI_SHARD_TOTAL = 3;
|
|
13
|
+
export declare const VITEST_CI_SHARD_INDICES: readonly [1, 2, 3];
|
|
12
14
|
/** CLI args for a single shard (excludes `vitest` binary). */
|
|
13
15
|
export declare function vitestCiShardArgs(shardIndex: number, shardTotal?: number): string[];
|
|
14
16
|
/** Matrix values for GitHub Actions strategy.matrix.shard */
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* All shards together still run every file discovered by vitest.config.ts
|
|
5
5
|
* projects; each shard is a slice via `vitest run --shard=i/n`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Three shards on ubicloud-standard-2 cut billed runner-minutes (fewer
|
|
8
|
+
* parallel installs × smaller class) while keeping full suite coverage.
|
|
9
|
+
* Wall-clock per shard may rise vs the prior 6×standard-4 layout; that is an
|
|
10
|
+
* intentional minutes-vs-wall tradeoff (see docs/ci-test-perf.md).
|
|
9
11
|
*/
|
|
10
|
-
export const VITEST_CI_SHARD_TOTAL =
|
|
11
|
-
export const VITEST_CI_SHARD_INDICES = [1, 2, 3
|
|
12
|
+
export const VITEST_CI_SHARD_TOTAL = 3;
|
|
13
|
+
export const VITEST_CI_SHARD_INDICES = [1, 2, 3];
|
|
12
14
|
/** CLI args for a single shard (excludes `vitest` binary). */
|
|
13
15
|
export function vitestCiShardArgs(shardIndex, shardTotal = VITEST_CI_SHARD_TOTAL) {
|
|
14
16
|
if (!Number.isInteger(shardIndex) || shardIndex < 1 || shardIndex > shardTotal) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability tombstone for the self-install guard.
|
|
3
|
+
*
|
|
4
|
+
* Cycle-free leaf: no imports of the guard command or installer scheduler.
|
|
5
|
+
* Static-importable from the guard so mid-update installId package-tree
|
|
6
|
+
* deletion cannot race a package-local dynamic import.
|
|
7
|
+
*
|
|
8
|
+
* NOT a concurrency gate — the heartbeat lease in install-lock.ts owns
|
|
9
|
+
* mutual exclusion. Best-effort writes only.
|
|
10
|
+
*/
|
|
11
|
+
export interface Tombstone {
|
|
12
|
+
autoInstallInProgress: {
|
|
13
|
+
pid: number;
|
|
14
|
+
ts: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build the canonical tombstone shape. Exported for testability.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildTombstone(pid: number, ts: number): Tombstone;
|
|
21
|
+
/**
|
|
22
|
+
* Record the guard's pid + start time in the notifier cache for humans and
|
|
23
|
+
* `wp update`'s cache-reconcile step.
|
|
24
|
+
*/
|
|
25
|
+
export declare function writeGuardTombstone(): void;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability tombstone for the self-install guard.
|
|
3
|
+
*
|
|
4
|
+
* Cycle-free leaf: no imports of the guard command or installer scheduler.
|
|
5
|
+
* Static-importable from the guard so mid-update installId package-tree
|
|
6
|
+
* deletion cannot race a package-local dynamic import.
|
|
7
|
+
*
|
|
8
|
+
* NOT a concurrency gate — the heartbeat lease in install-lock.ts owns
|
|
9
|
+
* mutual exclusion. Best-effort writes only.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
12
|
+
import { dirname } from "node:path";
|
|
13
|
+
import { getSurfacePath } from "#paths/state-root.js";
|
|
14
|
+
import { writeJsonFile } from "#shared-utils/write-json-file.js";
|
|
15
|
+
import { logUpdateError } from "./log.js";
|
|
16
|
+
/**
|
|
17
|
+
* Build the canonical tombstone shape. Exported for testability.
|
|
18
|
+
*/
|
|
19
|
+
export function buildTombstone(pid, ts) {
|
|
20
|
+
return { autoInstallInProgress: { pid, ts } };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Record the guard's pid + start time in the notifier cache for humans and
|
|
24
|
+
* `wp update`'s cache-reconcile step.
|
|
25
|
+
*/
|
|
26
|
+
export function writeGuardTombstone() {
|
|
27
|
+
try {
|
|
28
|
+
const configPath = resolveConfigPath();
|
|
29
|
+
if (configPath === null)
|
|
30
|
+
return;
|
|
31
|
+
writeTombstone(configPath, buildTombstone(process.pid, Date.now()));
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
logUpdateError(err);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function resolveConfigPath() {
|
|
38
|
+
try {
|
|
39
|
+
return getSurfacePath("update-notifier-cache.json", "user");
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function readRaw(configPath) {
|
|
46
|
+
if (!existsSync(configPath))
|
|
47
|
+
return {};
|
|
48
|
+
try {
|
|
49
|
+
const text = readFileSync(configPath, "utf-8");
|
|
50
|
+
if (text.trim().length === 0)
|
|
51
|
+
return {};
|
|
52
|
+
const parsed = JSON.parse(text);
|
|
53
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
54
|
+
return {};
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function writeTombstone(configPath, tombstone) {
|
|
62
|
+
const dir = dirname(configPath);
|
|
63
|
+
if (!existsSync(dir))
|
|
64
|
+
mkdirSync(dir, { recursive: true });
|
|
65
|
+
const merged = { ...readRaw(configPath), ...tombstone };
|
|
66
|
+
writeJsonFile(configPath, merged, { atomic: true, indent: 0, trailingNewline: false });
|
|
67
|
+
}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* releases the lease. Concurrency control, the observability tombstone,
|
|
14
14
|
* verification, and repair all live in the guard — this module only decides
|
|
15
15
|
* WHETHER to spawn and wires the detached stdio to auto-update.log.
|
|
16
|
+
* Guard argv uses the cycle-free self-invocation leaf (never a full import of
|
|
17
|
+
* the guard command module).
|
|
16
18
|
*
|
|
17
19
|
* Invariants:
|
|
18
20
|
* - Synchronous: returns before the install starts.
|
|
@@ -25,15 +27,11 @@
|
|
|
25
27
|
* from a successful CLI run.
|
|
26
28
|
*/
|
|
27
29
|
export { isProcessAlive } from "./install-lock.js";
|
|
30
|
+
/** Re-export for existing call sites and tests (implementation in guard-tombstone). */
|
|
31
|
+
export { buildTombstone, writeGuardTombstone, type Tombstone } from "./guard-tombstone.js";
|
|
28
32
|
export interface InstallPlan {
|
|
29
33
|
command: string[];
|
|
30
34
|
}
|
|
31
|
-
export interface Tombstone {
|
|
32
|
-
autoInstallInProgress: {
|
|
33
|
-
pid: number;
|
|
34
|
-
ts: number;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
35
|
export interface ScheduleResult {
|
|
38
36
|
/** Did we actually fork the guard child? */
|
|
39
37
|
spawned: boolean;
|
|
@@ -56,14 +54,3 @@ export interface ScheduleDeferredInstallOptions {
|
|
|
56
54
|
* holds the lease, the guard itself exits 12 without running anything.
|
|
57
55
|
*/
|
|
58
56
|
export declare function scheduleDeferredInstall(plan: InstallPlan, options?: ScheduleDeferredInstallOptions): ScheduleResult;
|
|
59
|
-
/**
|
|
60
|
-
* Observability tombstone written by the self-install guard when it takes
|
|
61
|
-
* the lease: records the guard's pid + start time in the notifier cache for
|
|
62
|
-
* humans and `wp update`'s cache-reconcile step. NOT a concurrency gate —
|
|
63
|
-
* the heartbeat lease in install-lock.ts owns mutual exclusion. Best-effort.
|
|
64
|
-
*/
|
|
65
|
-
export declare function writeGuardTombstone(): void;
|
|
66
|
-
/**
|
|
67
|
-
* Build the canonical tombstone shape. Exported for testability.
|
|
68
|
-
*/
|
|
69
|
-
export declare function buildTombstone(pid: number, ts: number): Tombstone;
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* releases the lease. Concurrency control, the observability tombstone,
|
|
14
14
|
* verification, and repair all live in the guard — this module only decides
|
|
15
15
|
* WHETHER to spawn and wires the detached stdio to auto-update.log.
|
|
16
|
+
* Guard argv uses the cycle-free self-invocation leaf (never a full import of
|
|
17
|
+
* the guard command module).
|
|
16
18
|
*
|
|
17
19
|
* Invariants:
|
|
18
20
|
* - Synchronous: returns before the install starts.
|
|
@@ -24,14 +26,15 @@
|
|
|
24
26
|
* `logUpdateError` and swallowed; the user never sees an exception
|
|
25
27
|
* from a successful CLI run.
|
|
26
28
|
*/
|
|
27
|
-
import { closeSync, existsSync, mkdirSync, openSync
|
|
29
|
+
import { closeSync, existsSync, mkdirSync, openSync } from "node:fs";
|
|
28
30
|
import { spawn } from "node:child_process";
|
|
29
31
|
import { dirname } from "node:path";
|
|
30
32
|
import { getSurfacePath } from "#paths/state-root.js";
|
|
31
|
-
import { writeJsonFile } from "#shared-utils/write-json-file.js";
|
|
32
|
-
import { buildSelfInvocationCommand } from "#cli/commands/self-install-guard.js";
|
|
33
33
|
import { logUpdateError } from "./log.js";
|
|
34
|
+
import { buildSelfInvocationCommand } from "./self-invocation.js";
|
|
34
35
|
export { isProcessAlive } from "./install-lock.js";
|
|
36
|
+
/** Re-export for existing call sites and tests (implementation in guard-tombstone). */
|
|
37
|
+
export { buildTombstone, writeGuardTombstone } from "./guard-tombstone.js";
|
|
35
38
|
/**
|
|
36
39
|
* Schedule a deferred install for the supplied package-manager command,
|
|
37
40
|
* routed through the self-install guard. Synchronous — spawn() returns
|
|
@@ -66,37 +69,6 @@ export function scheduleDeferredInstall(plan, options = {}) {
|
|
|
66
69
|
return { spawned: false, reason: "spawn error" };
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Observability tombstone written by the self-install guard when it takes
|
|
71
|
-
* the lease: records the guard's pid + start time in the notifier cache for
|
|
72
|
-
* humans and `wp update`'s cache-reconcile step. NOT a concurrency gate —
|
|
73
|
-
* the heartbeat lease in install-lock.ts owns mutual exclusion. Best-effort.
|
|
74
|
-
*/
|
|
75
|
-
export function writeGuardTombstone() {
|
|
76
|
-
try {
|
|
77
|
-
const configPath = resolveConfigPath();
|
|
78
|
-
if (configPath === null)
|
|
79
|
-
return;
|
|
80
|
-
writeTombstone(configPath, buildTombstone(process.pid, Date.now()));
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
logUpdateError(err);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Build the canonical tombstone shape. Exported for testability.
|
|
88
|
-
*/
|
|
89
|
-
export function buildTombstone(pid, ts) {
|
|
90
|
-
return { autoInstallInProgress: { pid, ts } };
|
|
91
|
-
}
|
|
92
|
-
function resolveConfigPath() {
|
|
93
|
-
try {
|
|
94
|
-
return getSurfacePath("update-notifier-cache.json", "user");
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
72
|
function resolveLogPath() {
|
|
101
73
|
try {
|
|
102
74
|
return getSurfacePath("auto-update.log", "user");
|
|
@@ -105,29 +77,6 @@ function resolveLogPath() {
|
|
|
105
77
|
return null;
|
|
106
78
|
}
|
|
107
79
|
}
|
|
108
|
-
function readRaw(configPath) {
|
|
109
|
-
if (!existsSync(configPath))
|
|
110
|
-
return {};
|
|
111
|
-
try {
|
|
112
|
-
const text = readFileSync(configPath, "utf-8");
|
|
113
|
-
if (text.trim().length === 0)
|
|
114
|
-
return {};
|
|
115
|
-
const parsed = JSON.parse(text);
|
|
116
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
117
|
-
return {};
|
|
118
|
-
return parsed;
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
return {};
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function writeTombstone(configPath, tombstone) {
|
|
125
|
-
const dir = dirname(configPath);
|
|
126
|
-
if (!existsSync(dir))
|
|
127
|
-
mkdirSync(dir, { recursive: true });
|
|
128
|
-
const merged = { ...readRaw(configPath), ...tombstone };
|
|
129
|
-
writeJsonFile(configPath, merged, { atomic: true, indent: 0, trailingNewline: false });
|
|
130
|
-
}
|
|
131
80
|
function openLogForAppend(logPath) {
|
|
132
81
|
const dir = dirname(logPath);
|
|
133
82
|
if (!existsSync(dir))
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cycle-free leaf: how `wp` re-invokes itself for self-install-guard.
|
|
3
|
+
*
|
|
4
|
+
* Lives outside `self-install-guard.ts` so deferred install, `wp update`, and
|
|
5
|
+
* setup can build guard argv without importing the full guard command module
|
|
6
|
+
* (which would re-create installer ↔ guard cycles and tempt dynamic imports).
|
|
7
|
+
*
|
|
8
|
+
* Survival rule: prefer a **stable** global launcher (`~/.vite-plus/bin/wp` or
|
|
9
|
+
* PATH `wp` outside an installId package tree). Re-execing
|
|
10
|
+
* `node …/agent-kit#id/…/cli.js` dies after `vp update -g` deletes the pre-swap
|
|
11
|
+
* tree mid-guard.
|
|
12
|
+
*/
|
|
13
|
+
export interface SelfInvocationOptions {
|
|
14
|
+
readonly execPath?: string;
|
|
15
|
+
readonly argv1?: string;
|
|
16
|
+
/** Injectable stable launcher for tests; `null` forces legacy argv1 path. */
|
|
17
|
+
readonly stableWp?: string | null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build argv to re-invoke wp with the given subcommand args.
|
|
21
|
+
* - Prefer stable non-versioned launcher when available.
|
|
22
|
+
* - Bun-compiled binary: process.execPath IS the binary (argv[1] is /$bunfs).
|
|
23
|
+
* - Source/dev lane without a stable launcher: `<runtime> <script>`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildSelfInvocationCommand(args: readonly string[], options?: SelfInvocationOptions): string[];
|
|
26
|
+
export interface ResolveStableWpLauncherOptions {
|
|
27
|
+
readonly home?: string;
|
|
28
|
+
readonly pathEnv?: string;
|
|
29
|
+
readonly existsSync?: (path: string) => boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A launcher that survives installId package-tree deletion during global update.
|
|
33
|
+
* Rejects paths under `agent-kit#<uuid>/` (versioned store payload).
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveStableWpLauncher(options?: ResolveStableWpLauncherOptions): string | null;
|
|
36
|
+
/** True when path lives inside a vite-plus installId package tree. */
|
|
37
|
+
export declare function isVersionedAgentKitPayloadPath(filePath: string): boolean;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cycle-free leaf: how `wp` re-invokes itself for self-install-guard.
|
|
3
|
+
*
|
|
4
|
+
* Lives outside `self-install-guard.ts` so deferred install, `wp update`, and
|
|
5
|
+
* setup can build guard argv without importing the full guard command module
|
|
6
|
+
* (which would re-create installer ↔ guard cycles and tempt dynamic imports).
|
|
7
|
+
*
|
|
8
|
+
* Survival rule: prefer a **stable** global launcher (`~/.vite-plus/bin/wp` or
|
|
9
|
+
* PATH `wp` outside an installId package tree). Re-execing
|
|
10
|
+
* `node …/agent-kit#id/…/cli.js` dies after `vp update -g` deletes the pre-swap
|
|
11
|
+
* tree mid-guard.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync } from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
/**
|
|
16
|
+
* Build argv to re-invoke wp with the given subcommand args.
|
|
17
|
+
* - Prefer stable non-versioned launcher when available.
|
|
18
|
+
* - Bun-compiled binary: process.execPath IS the binary (argv[1] is /$bunfs).
|
|
19
|
+
* - Source/dev lane without a stable launcher: `<runtime> <script>`.
|
|
20
|
+
*/
|
|
21
|
+
export function buildSelfInvocationCommand(args, options = {}) {
|
|
22
|
+
const stableWp = options.stableWp !== undefined ? options.stableWp : resolveStableWpLauncher();
|
|
23
|
+
if (typeof stableWp === "string" && stableWp.length > 0) {
|
|
24
|
+
return [stableWp, ...args];
|
|
25
|
+
}
|
|
26
|
+
const execPath = options.execPath ?? process.execPath;
|
|
27
|
+
const argv1 = options.argv1 ?? process.argv[1] ?? "";
|
|
28
|
+
if (argv1.startsWith("/$bunfs"))
|
|
29
|
+
return [execPath, ...args];
|
|
30
|
+
return [execPath, argv1, ...args];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A launcher that survives installId package-tree deletion during global update.
|
|
34
|
+
* Rejects paths under `agent-kit#<uuid>/` (versioned store payload).
|
|
35
|
+
*/
|
|
36
|
+
export function resolveStableWpLauncher(options = {}) {
|
|
37
|
+
const exists = options.existsSync ?? existsSync;
|
|
38
|
+
const home = options.home ?? process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
39
|
+
const candidates = [];
|
|
40
|
+
if (home) {
|
|
41
|
+
candidates.push(path.join(home, ".vite-plus", "bin", "wp"));
|
|
42
|
+
}
|
|
43
|
+
const pathEnv = options.pathEnv ?? process.env.PATH ?? "";
|
|
44
|
+
for (const dir of pathEnv.split(path.delimiter)) {
|
|
45
|
+
if (!dir)
|
|
46
|
+
continue;
|
|
47
|
+
candidates.push(path.join(dir, "wp"));
|
|
48
|
+
}
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
if (!exists(candidate))
|
|
51
|
+
continue;
|
|
52
|
+
if (isVersionedAgentKitPayloadPath(candidate))
|
|
53
|
+
continue;
|
|
54
|
+
return candidate;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
/** True when path lives inside a vite-plus installId package tree. */
|
|
59
|
+
export function isVersionedAgentKitPayloadPath(filePath) {
|
|
60
|
+
const normalized = filePath.replaceAll("\\", "/");
|
|
61
|
+
return /\/@webpresso\/agent-kit#[^/]+\//u.test(normalized);
|
|
62
|
+
}
|
|
@@ -27,6 +27,7 @@ export const REPO_AUDIT_REGISTRY = {
|
|
|
27
27
|
includeRuntimePlans: options.runtimePlans,
|
|
28
28
|
baseRef: options.baseRef ?? options.base,
|
|
29
29
|
changedOnly: options.changedOnly,
|
|
30
|
+
affectedFiles: options.affectedFiles,
|
|
30
31
|
}),
|
|
31
32
|
"blueprint-trust": async (root) => (await import("#audit/blueprint-trust")).auditBlueprintTrust(root),
|
|
32
33
|
"roadmap-links": async (root, options) => (await import("#audit/roadmap-links")).auditRoadmapLinks(root, {
|
|
@@ -122,6 +123,9 @@ export const REPO_AUDIT_REGISTRY = {
|
|
|
122
123
|
"secrets-config": async (root) => (await import("#audit/secrets-config")).auditSecretsConfig(root),
|
|
123
124
|
"consumer-agent-kit-dependency": async (root) => (await import("#audit/consumer-agent-kit-dependency")).auditConsumerAgentKitDependency(root),
|
|
124
125
|
"ci-test-perf": async (root) => (await import("#audit/ci-test-perf")).auditCiTestPerf(root),
|
|
126
|
+
"test-scan-perf": async (root, options) => (await import("#audit/test-scan-perf")).auditTestScanPerf(root, {
|
|
127
|
+
affectedFiles: options.affectedFiles,
|
|
128
|
+
}),
|
|
125
129
|
"worktree-main-ownership": async (root) => (await import("#audit/worktree-main-ownership")).auditWorktreeMainOwnership(root),
|
|
126
130
|
sast: async (root, options) => (await import("#audit/sast")).auditSast(root, {
|
|
127
131
|
bin: options.bin,
|