projscan 2.1.0 → 2.8.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/README.md +57 -26
- package/dist/analyzers/supplyChainCheck.d.ts +2 -0
- package/dist/analyzers/supplyChainCheck.js +400 -0
- package/dist/analyzers/supplyChainCheck.js.map +1 -0
- package/dist/cli/commands/agentBrief.d.ts +1 -0
- package/dist/cli/commands/agentBrief.js +68 -0
- package/dist/cli/commands/agentBrief.js.map +1 -0
- package/dist/cli/commands/bugHunt.d.ts +1 -0
- package/dist/cli/commands/bugHunt.js +59 -0
- package/dist/cli/commands/bugHunt.js.map +1 -0
- package/dist/cli/commands/evidencePack.d.ts +1 -0
- package/dist/cli/commands/evidencePack.js +70 -0
- package/dist/cli/commands/evidencePack.js.map +1 -0
- package/dist/cli/commands/qualityScorecard.d.ts +1 -0
- package/dist/cli/commands/qualityScorecard.js +61 -0
- package/dist/cli/commands/qualityScorecard.js.map +1 -0
- package/dist/cli/commands/regressionPlan.d.ts +1 -0
- package/dist/cli/commands/regressionPlan.js +77 -0
- package/dist/cli/commands/regressionPlan.js.map +1 -0
- package/dist/cli/commands/releaseTrain.d.ts +1 -0
- package/dist/cli/commands/releaseTrain.js +58 -0
- package/dist/cli/commands/releaseTrain.js.map +1 -0
- package/dist/cli/commands/workplan.d.ts +1 -0
- package/dist/cli/commands/workplan.js +136 -0
- package/dist/cli/commands/workplan.js.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/agentBrief.d.ts +6 -0
- package/dist/core/agentBrief.js +192 -0
- package/dist/core/agentBrief.js.map +1 -0
- package/dist/core/bugHunt.d.ts +6 -0
- package/dist/core/bugHunt.js +278 -0
- package/dist/core/bugHunt.js.map +1 -0
- package/dist/core/issueEngine.js +2 -0
- package/dist/core/issueEngine.js.map +1 -1
- package/dist/core/preflight.js +38 -4
- package/dist/core/preflight.js.map +1 -1
- package/dist/core/qualityScorecard.d.ts +6 -0
- package/dist/core/qualityScorecard.js +220 -0
- package/dist/core/qualityScorecard.js.map +1 -0
- package/dist/core/regressionPlan.d.ts +7 -0
- package/dist/core/regressionPlan.js +226 -0
- package/dist/core/regressionPlan.js.map +1 -0
- package/dist/core/releaseEvidence.d.ts +7 -0
- package/dist/core/releaseEvidence.js +174 -0
- package/dist/core/releaseEvidence.js.map +1 -0
- package/dist/core/releaseTrain.d.ts +5 -0
- package/dist/core/releaseTrain.js +348 -0
- package/dist/core/releaseTrain.js.map +1 -0
- package/dist/core/review.js +31 -2
- package/dist/core/review.js.map +1 -1
- package/dist/core/workplan.d.ts +12 -0
- package/dist/core/workplan.js +440 -0
- package/dist/core/workplan.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools/agentBrief.d.ts +2 -0
- package/dist/mcp/tools/agentBrief.js +39 -0
- package/dist/mcp/tools/agentBrief.js.map +1 -0
- package/dist/mcp/tools/bugHunt.d.ts +2 -0
- package/dist/mcp/tools/bugHunt.js +31 -0
- package/dist/mcp/tools/bugHunt.js.map +1 -0
- package/dist/mcp/tools/evidencePack.d.ts +2 -0
- package/dist/mcp/tools/evidencePack.js +39 -0
- package/dist/mcp/tools/evidencePack.js.map +1 -0
- package/dist/mcp/tools/qualityScorecard.d.ts +2 -0
- package/dist/mcp/tools/qualityScorecard.js +26 -0
- package/dist/mcp/tools/qualityScorecard.js.map +1 -0
- package/dist/mcp/tools/regressionPlan.d.ts +2 -0
- package/dist/mcp/tools/regressionPlan.js +47 -0
- package/dist/mcp/tools/regressionPlan.js.map +1 -0
- package/dist/mcp/tools/releaseTrain.d.ts +2 -0
- package/dist/mcp/tools/releaseTrain.js +27 -0
- package/dist/mcp/tools/releaseTrain.js.map +1 -0
- package/dist/mcp/tools/workplan.d.ts +2 -0
- package/dist/mcp/tools/workplan.js +70 -0
- package/dist/mcp/tools/workplan.js.map +1 -0
- package/dist/mcp/tools.js +14 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +4589 -0
- package/dist/tool-manifest.json +196 -3
- package/dist/types.d.ts +245 -1
- package/dist/utils/formatSupport.d.ts +8 -0
- package/dist/utils/formatSupport.js +8 -0
- package/dist/utils/formatSupport.js.map +1 -1
- package/package.json +9 -6
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const DEPENDENCY_SCOPES = [
|
|
4
|
+
'dependencies',
|
|
5
|
+
'devDependencies',
|
|
6
|
+
'optionalDependencies',
|
|
7
|
+
'peerDependencies',
|
|
8
|
+
];
|
|
9
|
+
const LIFECYCLE_SCRIPTS = new Set([
|
|
10
|
+
'preinstall',
|
|
11
|
+
'install',
|
|
12
|
+
'postinstall',
|
|
13
|
+
'prepare',
|
|
14
|
+
'prepublish',
|
|
15
|
+
'prepublishOnly',
|
|
16
|
+
]);
|
|
17
|
+
const HIDDEN_HOOK_FILES = new Set([
|
|
18
|
+
'.claude/settings.json',
|
|
19
|
+
'.vscode/settings.json',
|
|
20
|
+
'.vscode/tasks.json',
|
|
21
|
+
]);
|
|
22
|
+
const PAYLOAD_FILENAMES = new Set(['router_init.js', 'tanstack_runner.js']);
|
|
23
|
+
const MAX_JSON_MANIFEST_BYTES = 2 * 1024 * 1024;
|
|
24
|
+
const MAX_LOCKFILE_BYTES = 25 * 1024 * 1024;
|
|
25
|
+
const MAX_JS_PAYLOAD_SCAN_BYTES = 5 * 1024 * 1024;
|
|
26
|
+
const LARGE_JS_PAYLOAD_BYTES = 1024 * 1024;
|
|
27
|
+
const GITHUB_COMMIT_REF = /#[0-9a-f]{7,40}$/i;
|
|
28
|
+
const KNOWN_CONTENT_IOCS = [
|
|
29
|
+
{
|
|
30
|
+
value: 'github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c',
|
|
31
|
+
label: 'Mini Shai-Hulud malicious TanStack git dependency',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: '79ac49eedf774dd4b0cfa308722bc463cfe5885c',
|
|
35
|
+
label: 'Mini Shai-Hulud malicious TanStack git ref',
|
|
36
|
+
},
|
|
37
|
+
{ value: '@tanstack/setup', label: 'Mini Shai-Hulud fictitious package' },
|
|
38
|
+
{ value: 'git-tanstack.com', label: 'Mini Shai-Hulud lookalike domain' },
|
|
39
|
+
{ value: 'gh-token-monitor', label: 'GitHub token monitor persistence marker' },
|
|
40
|
+
{ value: 'filev2.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
41
|
+
{ value: 'seed1.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
42
|
+
{ value: 'seed2.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
43
|
+
{ value: 'seed3.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
44
|
+
{ value: 'litter.catbox.moe/h8nc9u.js', label: 'Mini Shai-Hulud second-stage payload URL' },
|
|
45
|
+
{ value: 'litter.catbox.moe/7rrc6l.mjs', label: 'Mini Shai-Hulud second-stage payload URL' },
|
|
46
|
+
];
|
|
47
|
+
const HIDDEN_HOOK_DANGER_PATTERNS = [
|
|
48
|
+
{ pattern: /gh-token-monitor/i, label: 'GitHub token monitor persistence marker' },
|
|
49
|
+
{ pattern: /git-tanstack\.com/i, label: 'Mini Shai-Hulud lookalike domain' },
|
|
50
|
+
{ pattern: /router_init\.js/i, label: 'Mini Shai-Hulud payload filename' },
|
|
51
|
+
{ pattern: /rm\s+-rf\s+(?:~|\$HOME|\/)/i, label: 'destructive home/root delete command' },
|
|
52
|
+
{ pattern: /pkill\s+-f\s+gh-token-monitor/i, label: 'token-monitor process control' },
|
|
53
|
+
{ pattern: /curl\b.+\|\s*(?:sh|bash)/i, label: 'download-and-execute shell pipeline' },
|
|
54
|
+
];
|
|
55
|
+
const OBFUSCATION_MARKERS = [
|
|
56
|
+
/while\s*\(\s*!!\[\]\s*\)/,
|
|
57
|
+
/_0x[a-f0-9]{4,}/i,
|
|
58
|
+
/String\s*\[\s*['"]fromCharCode['"]\s*\]/,
|
|
59
|
+
/\bFunction\s*\(\s*['"]/,
|
|
60
|
+
/\beval\s*\(/,
|
|
61
|
+
];
|
|
62
|
+
const MALICIOUS_PACKAGE_VERSIONS = new Map(Object.entries({
|
|
63
|
+
'@tanstack/arktype-adapter': ['1.166.12', '1.166.15'],
|
|
64
|
+
'@tanstack/eslint-plugin-router': ['1.161.9', '1.161.12'],
|
|
65
|
+
'@tanstack/eslint-plugin-start': ['0.0.4', '0.0.7'],
|
|
66
|
+
'@tanstack/history': ['1.161.9', '1.161.12'],
|
|
67
|
+
'@tanstack/nitro-v2-vite-plugin': ['1.154.12', '1.154.15'],
|
|
68
|
+
'@tanstack/react-router': ['1.169.5', '1.169.8'],
|
|
69
|
+
'@tanstack/react-router-devtools': ['1.166.16', '1.166.19'],
|
|
70
|
+
'@tanstack/react-router-ssr-query': ['1.166.15', '1.166.18'],
|
|
71
|
+
'@tanstack/react-start': ['1.167.68', '1.167.71'],
|
|
72
|
+
'@tanstack/react-start-client': ['1.166.51', '1.166.54'],
|
|
73
|
+
'@tanstack/react-start-rsc': ['0.0.47', '0.0.50'],
|
|
74
|
+
'@tanstack/react-start-server': ['1.166.55', '1.166.58'],
|
|
75
|
+
'@tanstack/router-cli': ['1.166.46', '1.166.49'],
|
|
76
|
+
'@tanstack/router-core': ['1.169.5', '1.169.8'],
|
|
77
|
+
'@tanstack/router-devtools': ['1.166.16', '1.166.19'],
|
|
78
|
+
'@tanstack/router-devtools-core': ['1.167.6', '1.167.9'],
|
|
79
|
+
'@tanstack/router-generator': ['1.166.45', '1.166.48'],
|
|
80
|
+
'@tanstack/router-plugin': ['1.167.38', '1.167.41'],
|
|
81
|
+
'@tanstack/router-ssr-query-core': ['1.168.3', '1.168.6'],
|
|
82
|
+
'@tanstack/router-utils': ['1.161.11', '1.161.14'],
|
|
83
|
+
'@tanstack/router-vite-plugin': ['1.166.53', '1.166.56'],
|
|
84
|
+
'@tanstack/solid-router': ['1.169.5', '1.169.8'],
|
|
85
|
+
'@tanstack/solid-router-devtools': ['1.166.16', '1.166.19'],
|
|
86
|
+
'@tanstack/solid-router-ssr-query': ['1.166.15', '1.166.18'],
|
|
87
|
+
'@tanstack/solid-start': ['1.167.65', '1.167.68'],
|
|
88
|
+
'@tanstack/solid-start-client': ['1.166.50', '1.166.53'],
|
|
89
|
+
'@tanstack/solid-start-server': ['1.166.54', '1.166.57'],
|
|
90
|
+
'@tanstack/start-client-core': ['1.168.5', '1.168.8'],
|
|
91
|
+
'@tanstack/start-fn-stubs': ['1.161.9', '1.161.12'],
|
|
92
|
+
'@tanstack/start-plugin-core': ['1.169.23', '1.169.26'],
|
|
93
|
+
'@tanstack/start-server-core': ['1.167.33', '1.167.36'],
|
|
94
|
+
'@tanstack/start-static-server-functions': ['1.166.44', '1.166.47'],
|
|
95
|
+
'@tanstack/start-storage-context': ['1.166.38', '1.166.41'],
|
|
96
|
+
'@tanstack/valibot-adapter': ['1.166.12', '1.166.15'],
|
|
97
|
+
'@tanstack/virtual-file-routes': ['1.161.10', '1.161.13'],
|
|
98
|
+
'@tanstack/vue-router': ['1.169.5', '1.169.8'],
|
|
99
|
+
'@tanstack/vue-router-devtools': ['1.166.16', '1.166.19'],
|
|
100
|
+
'@tanstack/vue-router-ssr-query': ['1.166.15', '1.166.18'],
|
|
101
|
+
'@tanstack/vue-start': ['1.167.61', '1.167.64'],
|
|
102
|
+
'@tanstack/vue-start-client': ['1.166.46', '1.166.49'],
|
|
103
|
+
'@tanstack/vue-start-server': ['1.166.50', '1.166.53'],
|
|
104
|
+
'@tanstack/zod-adapter': ['1.166.12', '1.166.15'],
|
|
105
|
+
}).map(([name, versions]) => [name, new Set(versions)]));
|
|
106
|
+
export async function check(rootPath, files) {
|
|
107
|
+
const issues = [];
|
|
108
|
+
const seen = new Set();
|
|
109
|
+
for (const file of files) {
|
|
110
|
+
if (isPackageManifest(file)) {
|
|
111
|
+
await scanPackageManifest(file, issues, seen);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (isPackageLock(file)) {
|
|
115
|
+
await scanPackageLock(file, issues, seen);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (HIDDEN_HOOK_FILES.has(normalizePath(file.relativePath))) {
|
|
119
|
+
await scanHiddenHook(file, issues, seen);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (isJavaScriptPayloadCandidate(file)) {
|
|
123
|
+
await scanJavaScriptPayload(file, issues, seen);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return issues;
|
|
127
|
+
}
|
|
128
|
+
async function scanPackageManifest(file, issues, seen) {
|
|
129
|
+
const manifest = await readJson(file.absolutePath, MAX_JSON_MANIFEST_BYTES);
|
|
130
|
+
if (!manifest)
|
|
131
|
+
return;
|
|
132
|
+
for (const scope of DEPENDENCY_SCOPES) {
|
|
133
|
+
const deps = manifest[scope];
|
|
134
|
+
if (!deps || typeof deps !== 'object')
|
|
135
|
+
continue;
|
|
136
|
+
for (const [name, rawSpec] of Object.entries(deps)) {
|
|
137
|
+
const spec = typeof rawSpec === 'string' ? rawSpec.trim() : '';
|
|
138
|
+
if (!spec)
|
|
139
|
+
continue;
|
|
140
|
+
const exactVersion = normalizeExactVersion(spec);
|
|
141
|
+
if (exactVersion && isKnownMaliciousVersion(name, exactVersion)) {
|
|
142
|
+
pushIssue(issues, seen, maliciousPackageIssue(name, exactVersion, file.relativePath));
|
|
143
|
+
}
|
|
144
|
+
const ioc = KNOWN_CONTENT_IOCS.find(({ value }) => spec.includes(value));
|
|
145
|
+
if (ioc) {
|
|
146
|
+
pushIssue(issues, seen, makeIssue({
|
|
147
|
+
id: `supply-chain-known-ioc-${safeId(name)}`,
|
|
148
|
+
title: `Known malicious dependency IOC: ${name}`,
|
|
149
|
+
description: `${name} is declared as "${spec}", which matches ${ioc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
150
|
+
severity: 'error',
|
|
151
|
+
file: file.relativePath,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
else if (isGithubCommitDependency(spec)) {
|
|
155
|
+
pushIssue(issues, seen, makeIssue({
|
|
156
|
+
id: `supply-chain-git-dependency-${safeId(name)}`,
|
|
157
|
+
title: `Dependency resolves directly to a GitHub commit: ${name}`,
|
|
158
|
+
description: `The ${scope} entry "${name}" points at "${spec}". GitHub commit dependencies can bypass normal registry review and can run lifecycle scripts during install; pin a vetted registry package or remove the dependency.`,
|
|
159
|
+
severity: 'warning',
|
|
160
|
+
file: file.relativePath,
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (manifest.scripts && typeof manifest.scripts === 'object') {
|
|
166
|
+
for (const [scriptName, rawCommand] of Object.entries(manifest.scripts)) {
|
|
167
|
+
if (!LIFECYCLE_SCRIPTS.has(scriptName))
|
|
168
|
+
continue;
|
|
169
|
+
const command = typeof rawCommand === 'string' ? rawCommand : String(rawCommand);
|
|
170
|
+
if (!shouldFlagLifecycleScript(scriptName, command))
|
|
171
|
+
continue;
|
|
172
|
+
pushIssue(issues, seen, makeIssue({
|
|
173
|
+
id: `supply-chain-lifecycle-${scriptName}`,
|
|
174
|
+
title: `Install lifecycle script present: ${scriptName}`,
|
|
175
|
+
description: `The package manifest defines "${scriptName}": "${command}". Install lifecycle scripts execute during dependency installation and are a common supply-chain execution path; verify this script before release or install.`,
|
|
176
|
+
severity: 'warning',
|
|
177
|
+
file: file.relativePath,
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function scanPackageLock(file, issues, seen) {
|
|
183
|
+
const lock = await readJson(file.absolutePath, MAX_LOCKFILE_BYTES);
|
|
184
|
+
if (!lock)
|
|
185
|
+
return;
|
|
186
|
+
for (const [entryPath, entry] of Object.entries(lock.packages ?? {})) {
|
|
187
|
+
const name = packageNameFromLockPath(entryPath);
|
|
188
|
+
const version = typeof entry.version === 'string' ? entry.version : null;
|
|
189
|
+
if (name && version && isKnownMaliciousVersion(name, version)) {
|
|
190
|
+
pushIssue(issues, seen, maliciousPackageIssue(name, version, file.relativePath));
|
|
191
|
+
}
|
|
192
|
+
const resolved = typeof entry.resolved === 'string' ? entry.resolved : '';
|
|
193
|
+
const resolvedIoc = KNOWN_CONTENT_IOCS.find(({ value }) => resolved.includes(value));
|
|
194
|
+
if (resolvedIoc) {
|
|
195
|
+
pushIssue(issues, seen, makeIssue({
|
|
196
|
+
id: `supply-chain-known-ioc-${safeId(name ?? entryPath)}`,
|
|
197
|
+
title: `Known malicious lockfile IOC: ${name ?? entryPath}`,
|
|
198
|
+
description: `The lockfile package entry resolves through ${resolvedIoc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
199
|
+
severity: 'error',
|
|
200
|
+
file: file.relativePath,
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
const manifestDeps = { ...(entry.dependencies ?? {}), ...(entry.optionalDependencies ?? {}) };
|
|
204
|
+
for (const [depName, rawSpec] of Object.entries(manifestDeps)) {
|
|
205
|
+
const spec = typeof rawSpec === 'string' ? rawSpec : '';
|
|
206
|
+
const ioc = KNOWN_CONTENT_IOCS.find(({ value }) => spec.includes(value) || resolved.includes(value));
|
|
207
|
+
if (!ioc)
|
|
208
|
+
continue;
|
|
209
|
+
pushIssue(issues, seen, makeIssue({
|
|
210
|
+
id: `supply-chain-known-ioc-${safeId(depName)}`,
|
|
211
|
+
title: `Known malicious lockfile IOC: ${depName}`,
|
|
212
|
+
description: `The lockfile contains ${ioc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
213
|
+
severity: 'error',
|
|
214
|
+
file: file.relativePath,
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
for (const [name, entry] of Object.entries(lock.dependencies ?? {})) {
|
|
219
|
+
const version = typeof entry.version === 'string' ? entry.version : null;
|
|
220
|
+
if (version && isKnownMaliciousVersion(name, version)) {
|
|
221
|
+
pushIssue(issues, seen, maliciousPackageIssue(name, version, file.relativePath));
|
|
222
|
+
}
|
|
223
|
+
const resolved = typeof entry.resolved === 'string' ? entry.resolved : '';
|
|
224
|
+
const resolvedIoc = KNOWN_CONTENT_IOCS.find(({ value }) => resolved.includes(value));
|
|
225
|
+
if (resolvedIoc) {
|
|
226
|
+
pushIssue(issues, seen, makeIssue({
|
|
227
|
+
id: `supply-chain-known-ioc-${safeId(name)}`,
|
|
228
|
+
title: `Known malicious lockfile IOC: ${name}`,
|
|
229
|
+
description: `The lockfile dependency resolves through ${resolvedIoc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
230
|
+
severity: 'error',
|
|
231
|
+
file: file.relativePath,
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function scanHiddenHook(file, issues, seen) {
|
|
237
|
+
const content = await readText(file.absolutePath, 256 * 1024);
|
|
238
|
+
if (!content)
|
|
239
|
+
return;
|
|
240
|
+
const matched = HIDDEN_HOOK_DANGER_PATTERNS.find(({ pattern }) => pattern.test(content));
|
|
241
|
+
if (!matched)
|
|
242
|
+
return;
|
|
243
|
+
pushIssue(issues, seen, makeIssue({
|
|
244
|
+
id: 'supply-chain-hidden-persistence-hook',
|
|
245
|
+
title: `Hidden editor/agent persistence hook in ${file.relativePath}`,
|
|
246
|
+
description: `${file.relativePath} contains ${matched.label}. Treat this as possible supply-chain persistence: remove the hook, inspect running processes, and rotate credentials if it may have executed.`,
|
|
247
|
+
severity: 'error',
|
|
248
|
+
file: file.relativePath,
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
async function scanJavaScriptPayload(file, issues, seen) {
|
|
252
|
+
const basename = path.basename(file.relativePath);
|
|
253
|
+
if (PAYLOAD_FILENAMES.has(basename)) {
|
|
254
|
+
pushIssue(issues, seen, makeIssue({
|
|
255
|
+
id: `supply-chain-payload-file-${safeId(basename)}`,
|
|
256
|
+
title: `Known malicious payload filename: ${basename}`,
|
|
257
|
+
description: `${basename} matches a known Mini Shai-Hulud payload/helper filename. Remove the file, inspect install artifacts, and rotate credentials on any machine where it may have run.`,
|
|
258
|
+
severity: 'error',
|
|
259
|
+
file: file.relativePath,
|
|
260
|
+
}));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (file.sizeBytes < LARGE_JS_PAYLOAD_BYTES || file.sizeBytes > MAX_JS_PAYLOAD_SCAN_BYTES)
|
|
264
|
+
return;
|
|
265
|
+
const content = await readText(file.absolutePath, MAX_JS_PAYLOAD_SCAN_BYTES);
|
|
266
|
+
if (!content)
|
|
267
|
+
return;
|
|
268
|
+
const ioc = KNOWN_CONTENT_IOCS.find(({ value }) => content.includes(value));
|
|
269
|
+
if (ioc) {
|
|
270
|
+
pushIssue(issues, seen, makeIssue({
|
|
271
|
+
id: `supply-chain-known-ioc-${safeId(basename)}`,
|
|
272
|
+
title: `Known malicious JavaScript IOC in ${file.relativePath}`,
|
|
273
|
+
description: `${file.relativePath} contains ${ioc.label}. Remove the artifact and rotate credentials on any machine where it may have run.`,
|
|
274
|
+
severity: 'error',
|
|
275
|
+
file: file.relativePath,
|
|
276
|
+
}));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const markerCount = OBFUSCATION_MARKERS.filter((pattern) => pattern.test(content)).length;
|
|
280
|
+
const hasLongLine = content.split(/\r?\n/, 4).some((line) => line.length > 50_000);
|
|
281
|
+
if (markerCount >= 2 || (markerCount >= 1 && hasLongLine)) {
|
|
282
|
+
pushIssue(issues, seen, makeIssue({
|
|
283
|
+
id: `supply-chain-obfuscated-payload-${safeId(basename)}`,
|
|
284
|
+
title: `Large obfuscated JavaScript payload: ${file.relativePath}`,
|
|
285
|
+
description: `${file.relativePath} is over 1 MB and contains obfuscation markers often seen in install-time malware. Inspect the artifact before installing or publishing.`,
|
|
286
|
+
severity: 'warning',
|
|
287
|
+
file: file.relativePath,
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function maliciousPackageIssue(name, version, file) {
|
|
292
|
+
return makeIssue({
|
|
293
|
+
id: `supply-chain-malicious-package-${name}`,
|
|
294
|
+
title: `Known malicious package version: ${name}@${version}`,
|
|
295
|
+
description: `${name}@${version} is listed in the May 11, 2026 TanStack Mini Shai-Hulud advisory. Remove the version from manifests/lockfiles, reinstall from a clean lockfile, and rotate credentials on any machine or CI runner that installed it.`,
|
|
296
|
+
severity: 'error',
|
|
297
|
+
file,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function makeIssue(input) {
|
|
301
|
+
return {
|
|
302
|
+
id: input.id,
|
|
303
|
+
title: input.title,
|
|
304
|
+
description: input.description,
|
|
305
|
+
severity: input.severity,
|
|
306
|
+
category: 'supply-chain',
|
|
307
|
+
fixAvailable: false,
|
|
308
|
+
locations: [{ file: input.file, line: 1 }],
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function pushIssue(issues, seen, issue) {
|
|
312
|
+
const file = issue.locations?.[0]?.file ?? '';
|
|
313
|
+
const key = `${issue.id}:${file}`;
|
|
314
|
+
if (seen.has(key))
|
|
315
|
+
return;
|
|
316
|
+
seen.add(key);
|
|
317
|
+
issues.push(issue);
|
|
318
|
+
}
|
|
319
|
+
function isKnownMaliciousVersion(name, version) {
|
|
320
|
+
return MALICIOUS_PACKAGE_VERSIONS.get(name)?.has(version) === true;
|
|
321
|
+
}
|
|
322
|
+
function shouldFlagLifecycleScript(scriptName, command) {
|
|
323
|
+
if (scriptName !== 'prepare')
|
|
324
|
+
return true;
|
|
325
|
+
return (/\b(?:bun|node|deno|python|ruby|bash|sh|curl|wget|powershell|pwsh|npx)\b/i.test(command) ||
|
|
326
|
+
/\b(?:npm\s+exec|pnpm\s+dlx|yarn\s+dlx)\b/i.test(command) ||
|
|
327
|
+
/(?:&&|\|\||\|)/.test(command));
|
|
328
|
+
}
|
|
329
|
+
function normalizeExactVersion(spec) {
|
|
330
|
+
const trimmed = spec.trim();
|
|
331
|
+
if (/^\d+\.\d+\.\d+(?:[-+].*)?$/.test(trimmed))
|
|
332
|
+
return trimmed;
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
function isGithubCommitDependency(spec) {
|
|
336
|
+
if (!GITHUB_COMMIT_REF.test(spec))
|
|
337
|
+
return false;
|
|
338
|
+
const withoutRef = spec.slice(0, spec.lastIndexOf('#'));
|
|
339
|
+
return (/^(?:github:)?[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\.git)?$/i.test(withoutRef) ||
|
|
340
|
+
/^(?:git\+https|https|git):\/\/github\.com\/.+/i.test(withoutRef) ||
|
|
341
|
+
/^(?:git\+ssh|ssh):\/\/git@github\.com[:/].+/i.test(withoutRef) ||
|
|
342
|
+
/^git@github\.com:.+/i.test(withoutRef));
|
|
343
|
+
}
|
|
344
|
+
function isPackageManifest(file) {
|
|
345
|
+
return path.basename(file.relativePath) === 'package.json' && !normalizePath(file.relativePath).includes('/node_modules/');
|
|
346
|
+
}
|
|
347
|
+
function isPackageLock(file) {
|
|
348
|
+
return path.basename(file.relativePath) === 'package-lock.json';
|
|
349
|
+
}
|
|
350
|
+
function isJavaScriptPayloadCandidate(file) {
|
|
351
|
+
const basename = path.basename(file.relativePath);
|
|
352
|
+
return PAYLOAD_FILENAMES.has(basename) || ['.js', '.mjs', '.cjs'].includes(file.extension);
|
|
353
|
+
}
|
|
354
|
+
function packageNameFromLockPath(entryPath) {
|
|
355
|
+
const marker = 'node_modules/';
|
|
356
|
+
const markerIndex = entryPath.lastIndexOf(marker);
|
|
357
|
+
if (markerIndex === -1)
|
|
358
|
+
return null;
|
|
359
|
+
const last = entryPath.slice(markerIndex + marker.length);
|
|
360
|
+
if (!last)
|
|
361
|
+
return null;
|
|
362
|
+
const segments = last.split('/');
|
|
363
|
+
if (segments[0]?.startsWith('@') && segments[1])
|
|
364
|
+
return `${segments[0]}/${segments[1]}`;
|
|
365
|
+
return segments[0] || null;
|
|
366
|
+
}
|
|
367
|
+
function safeId(value) {
|
|
368
|
+
return value.replace(/^@/, '').replace(/[^A-Za-z0-9._/-]+/g, '-').replace(/\/+/g, '-');
|
|
369
|
+
}
|
|
370
|
+
function normalizePath(value) {
|
|
371
|
+
return value.split(path.sep).join('/');
|
|
372
|
+
}
|
|
373
|
+
async function readJson(filePath, maxBytes) {
|
|
374
|
+
const content = await readText(filePath, maxBytes);
|
|
375
|
+
if (!content)
|
|
376
|
+
return null;
|
|
377
|
+
try {
|
|
378
|
+
return JSON.parse(content);
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function readText(filePath, maxBytes) {
|
|
385
|
+
try {
|
|
386
|
+
const handle = await fs.open(filePath, 'r');
|
|
387
|
+
try {
|
|
388
|
+
const buffer = Buffer.alloc(maxBytes);
|
|
389
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes, 0);
|
|
390
|
+
return buffer.subarray(0, bytesRead).toString('utf8');
|
|
391
|
+
}
|
|
392
|
+
finally {
|
|
393
|
+
await handle.close();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
//# sourceMappingURL=supplyChainCheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supplyChainCheck.js","sourceRoot":"","sources":["../../src/analyzers/supplyChainCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,iBAAiB,GAA+B;IACpD,cAAc;IACd,iBAAiB;IACjB,sBAAsB;IACtB,kBAAkB;CACnB,CAAC;AAEF,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,YAAY;IACZ,SAAS;IACT,aAAa;IACb,SAAS;IACT,YAAY;IACZ,gBAAgB;CACjB,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,uBAAuB;IACvB,uBAAuB;IACvB,oBAAoB;CACrB,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAC5E,MAAM,uBAAuB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAChD,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,yBAAyB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAClD,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAE9C,MAAM,kBAAkB,GAA4C;IAClE;QACE,KAAK,EAAE,iEAAiE;QACxE,KAAK,EAAE,mDAAmD;KAC3D;IACD;QACE,KAAK,EAAE,0CAA0C;QACjD,KAAK,EAAE,4CAA4C;KACpD;IACD,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,oCAAoC,EAAE;IACzE,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,kCAAkC,EAAE;IACxE,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,yCAAyC,EAAE;IAC/E,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,sCAAsC,EAAE;IACjF,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,sCAAsC,EAAE;IAChF,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,sCAAsC,EAAE;IAChF,EAAE,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,sCAAsC,EAAE;IAChF,EAAE,KAAK,EAAE,6BAA6B,EAAE,KAAK,EAAE,0CAA0C,EAAE;IAC3F,EAAE,KAAK,EAAE,8BAA8B,EAAE,KAAK,EAAE,0CAA0C,EAAE;CAC7F,CAAC;AAEF,MAAM,2BAA2B,GAA8C;IAC7E,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,yCAAyC,EAAE;IAClF,EAAE,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,kCAAkC,EAAE;IAC5E,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,kCAAkC,EAAE;IAC1E,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,sCAAsC,EAAE;IACzF,EAAE,OAAO,EAAE,gCAAgC,EAAE,KAAK,EAAE,+BAA+B,EAAE;IACrF,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,qCAAqC,EAAE;CACvF,CAAC;AAEF,MAAM,mBAAmB,GAAG;IAC1B,0BAA0B;IAC1B,kBAAkB;IAClB,yCAAyC;IACzC,wBAAwB;IACxB,aAAa;CACd,CAAC;AAEF,MAAM,0BAA0B,GAAG,IAAI,GAAG,CACxC,MAAM,CAAC,OAAO,CAAC;IACb,2BAA2B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACrD,gCAAgC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IACzD,+BAA+B,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IAC5C,gCAAgC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC1D,wBAAwB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAChD,iCAAiC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC3D,kCAAkC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC5D,uBAAuB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACjD,8BAA8B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACxD,2BAA2B,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;IACjD,8BAA8B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACxD,sBAAsB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAChD,uBAAuB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAC/C,2BAA2B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACrD,gCAAgC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACxD,4BAA4B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACtD,yBAAyB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACnD,iCAAiC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACzD,wBAAwB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAClD,8BAA8B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACxD,wBAAwB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAChD,iCAAiC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC3D,kCAAkC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC5D,uBAAuB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACjD,8BAA8B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACxD,8BAA8B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACxD,6BAA6B,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACrD,0BAA0B,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IACnD,6BAA6B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACvD,6BAA6B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACvD,yCAAyC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACnE,iCAAiC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC3D,2BAA2B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACrD,+BAA+B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACzD,sBAAsB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9C,+BAA+B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACzD,gCAAgC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC1D,qBAAqB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IAC/C,4BAA4B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACtD,4BAA4B,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACtD,uBAAuB,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;CAClD,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CACxD,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAAgB,EAAE,KAAkB;IAC9D,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAC9C,SAAS;QACX,CAAC;QACD,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1C,SAAS;QACX,CAAC;QACD,IAAI,iBAAiB,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;YAC5D,MAAM,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,IAAI,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,IAAe,EAAE,MAAe,EAAE,IAAiB;IACpF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAkB,IAAI,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;IAC7F,IAAI,CAAC,QAAQ;QAAE,OAAO;IAEtB,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,SAAS;QAChD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,YAAY,IAAI,uBAAuB,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC;gBAChE,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YACxF,CAAC;YACD,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YACzE,IAAI,GAAG,EAAE,CAAC;gBACR,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;oBACR,EAAE,EAAE,0BAA0B,MAAM,CAAC,IAAI,CAAC,EAAE;oBAC5C,KAAK,EAAE,mCAAmC,IAAI,EAAE;oBAChD,WAAW,EAAE,GAAG,IAAI,oBAAoB,IAAI,oBAAoB,GAAG,CAAC,KAAK,gJAAgJ;oBACzN,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,IAAI,CAAC,YAAY;iBACxB,CAAC,CACH,CAAC;YACJ,CAAC;iBAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;oBACR,EAAE,EAAE,+BAA+B,MAAM,CAAC,IAAI,CAAC,EAAE;oBACjD,KAAK,EAAE,oDAAoD,IAAI,EAAE;oBACjE,WAAW,EAAE,OAAO,KAAK,WAAW,IAAI,gBAAgB,IAAI,uKAAuK;oBACnO,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,IAAI,CAAC,YAAY;iBACxB,CAAC,CACH,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,OAAO,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7D,KAAK,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACxE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,SAAS;YACjD,MAAM,OAAO,GAAG,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACjF,IAAI,CAAC,yBAAyB,CAAC,UAAU,EAAE,OAAO,CAAC;gBAAE,SAAS;YAC9D,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;gBACR,EAAE,EAAE,0BAA0B,UAAU,EAAE;gBAC1C,KAAK,EAAE,qCAAqC,UAAU,EAAE;gBACxD,WAAW,EAAE,iCAAiC,UAAU,OAAO,OAAO,iKAAiK;gBACvO,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,IAAI,CAAC,YAAY;aACxB,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAe,EAAE,MAAe,EAAE,IAAiB;IAChF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAGxB,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,IAAI,IAAI,IAAI,OAAO,IAAI,uBAAuB,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAC9D,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACrF,IAAI,WAAW,EAAE,CAAC;YAChB,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;gBACR,EAAE,EAAE,0BAA0B,MAAM,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE;gBACzD,KAAK,EAAE,iCAAiC,IAAI,IAAI,SAAS,EAAE;gBAC3D,WAAW,EAAE,+CAA+C,WAAW,CAAC,KAAK,gJAAgJ;gBAC7N,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,IAAI,CAAC,YAAY;aACxB,CAAC,CACH,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9F,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YACrG,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;gBACR,EAAE,EAAE,0BAA0B,MAAM,CAAC,OAAO,CAAC,EAAE;gBAC/C,KAAK,EAAE,iCAAiC,OAAO,EAAE;gBACjD,WAAW,EAAE,yBAAyB,GAAG,CAAC,KAAK,gJAAgJ;gBAC/L,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,IAAI,CAAC,YAAY;aACxB,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;QACpE,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,IAAI,OAAO,IAAI,uBAAuB,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACtD,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACrF,IAAI,WAAW,EAAE,CAAC;YAChB,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;gBACR,EAAE,EAAE,0BAA0B,MAAM,CAAC,IAAI,CAAC,EAAE;gBAC5C,KAAK,EAAE,iCAAiC,IAAI,EAAE;gBAC9C,WAAW,EAAE,4CAA4C,WAAW,CAAC,KAAK,gJAAgJ;gBAC1N,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,IAAI,CAAC,YAAY;aACxB,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAe,EAAE,MAAe,EAAE,IAAiB;IAC/E,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC;IAC9D,IAAI,CAAC,OAAO;QAAE,OAAO;IAErB,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACzF,IAAI,CAAC,OAAO;QAAE,OAAO;IAErB,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;QACR,EAAE,EAAE,sCAAsC;QAC1C,KAAK,EAAE,2CAA2C,IAAI,CAAC,YAAY,EAAE;QACrE,WAAW,EAAE,GAAG,IAAI,CAAC,YAAY,aAAa,OAAO,CAAC,KAAK,gJAAgJ;QAC3M,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,IAAI,CAAC,YAAY;KACxB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,IAAe,EAAE,MAAe,EAAE,IAAiB;IACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;YACR,EAAE,EAAE,6BAA6B,MAAM,CAAC,QAAQ,CAAC,EAAE;YACnD,KAAK,EAAE,qCAAqC,QAAQ,EAAE;YACtD,WAAW,EAAE,GAAG,QAAQ,oKAAoK;YAC5L,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,IAAI,CAAC,YAAY;SACxB,CAAC,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,SAAS,GAAG,sBAAsB,IAAI,IAAI,CAAC,SAAS,GAAG,yBAAyB;QAAE,OAAO;IAClG,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,yBAAyB,CAAC,CAAC;IAC7E,IAAI,CAAC,OAAO;QAAE,OAAO;IAErB,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,IAAI,GAAG,EAAE,CAAC;QACR,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;YACR,EAAE,EAAE,0BAA0B,MAAM,CAAC,QAAQ,CAAC,EAAE;YAChD,KAAK,EAAE,qCAAqC,IAAI,CAAC,YAAY,EAAE;YAC/D,WAAW,EAAE,GAAG,IAAI,CAAC,YAAY,aAAa,GAAG,CAAC,KAAK,oFAAoF;YAC3I,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,IAAI,CAAC,YAAY;SACxB,CAAC,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1F,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACnF,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,WAAW,CAAC,EAAE,CAAC;QAC1D,SAAS,CACP,MAAM,EACN,IAAI,EACJ,SAAS,CAAC;YACR,EAAE,EAAE,mCAAmC,MAAM,CAAC,QAAQ,CAAC,EAAE;YACzD,KAAK,EAAE,wCAAwC,IAAI,CAAC,YAAY,EAAE;YAClE,WAAW,EAAE,GAAG,IAAI,CAAC,YAAY,0IAA0I;YAC3K,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,IAAI,CAAC,YAAY;SACxB,CAAC,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY;IACxE,OAAO,SAAS,CAAC;QACf,EAAE,EAAE,kCAAkC,IAAI,EAAE;QAC5C,KAAK,EAAE,oCAAoC,IAAI,IAAI,OAAO,EAAE;QAC5D,WAAW,EAAE,GAAG,IAAI,IAAI,OAAO,uNAAuN;QACtP,QAAQ,EAAE,OAAO;QACjB,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,KAMlB;IACC,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,cAAc;QACxB,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,MAAe,EAAE,IAAiB,EAAE,KAAY;IACjE,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;IAClC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY,EAAE,OAAe;IAC5D,OAAO,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;AACrE,CAAC;AAED,SAAS,yBAAyB,CAAC,UAAkB,EAAE,OAAe;IACpE,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,CACL,0EAA0E,CAAC,IAAI,CAAC,OAAO,CAAC;QACxF,2CAA2C,CAAC,IAAI,CAAC,OAAO,CAAC;QACzD,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,OAAO,CACL,2DAA2D,CAAC,IAAI,CAAC,UAAU,CAAC;QAC5E,gDAAgD,CAAC,IAAI,CAAC,UAAU,CAAC;QACjE,8CAA8C,CAAC,IAAI,CAAC,UAAU,CAAC;QAC/D,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CACxC,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAe;IACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,cAAc,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAC7H,CAAC;AAED,SAAS,aAAa,CAAC,IAAe;IACpC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,mBAAmB,CAAC;AAClE,CAAC;AAED,SAAS,4BAA4B,CAAC,IAAe;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAClD,OAAO,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,uBAAuB,CAAC,SAAiB;IAChD,MAAM,MAAM,GAAG,eAAe,CAAC;IAC/B,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,WAAW,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACxF,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC7B,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACzF,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,QAAQ,CAAI,QAAgB,EAAE,QAAgB;IAC3D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,QAAgB,EAAE,QAAgB;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACtC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;YAChE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxD,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerAgentBrief(): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
|
|
3
|
+
import { computeAgentBrief } from '../../core/agentBrief.js';
|
|
4
|
+
const INTENTS = ['next_agent', 'bug_hunt', 'release', 'refactor', 'hardening'];
|
|
5
|
+
export function registerAgentBrief() {
|
|
6
|
+
program
|
|
7
|
+
.command('agent-brief')
|
|
8
|
+
.description('Create a compact next-agent context packet with focus items and guardrails')
|
|
9
|
+
.option('--intent <intent>', 'next_agent, bug_hunt, release, refactor, or hardening', 'next_agent')
|
|
10
|
+
.option('--max-items <count>', 'maximum focus items to return', parsePositiveInt)
|
|
11
|
+
.action(async (cmdOpts) => {
|
|
12
|
+
setupLogLevel();
|
|
13
|
+
maybeCompactBanner();
|
|
14
|
+
const format = assertFormatSupported('agent-brief');
|
|
15
|
+
const intent = parseIntent(cmdOpts.intent);
|
|
16
|
+
try {
|
|
17
|
+
const report = await computeAgentBrief(getRootPath(), {
|
|
18
|
+
intent,
|
|
19
|
+
maxItems: cmdOpts.maxItems,
|
|
20
|
+
});
|
|
21
|
+
if (format === 'json') {
|
|
22
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
printAgentBrief(report);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
console.error(chalk.red(err instanceof Error ? err.message : String(err)));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function printAgentBrief(report) {
|
|
34
|
+
console.log(chalk.bold(`Agent Brief: ${report.intent}`));
|
|
35
|
+
console.log(report.summary);
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log(chalk.bold('Focus'));
|
|
38
|
+
for (const item of report.focus) {
|
|
39
|
+
printFocusItem(item);
|
|
40
|
+
}
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log(chalk.bold('Guardrails'));
|
|
43
|
+
for (const guardrail of report.guardrails) {
|
|
44
|
+
console.log(`- ${guardrail.label}: ${guardrail.command}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function printFocusItem(item) {
|
|
48
|
+
const files = item.files.length > 0 ? ` (${item.files.join(', ')})` : '';
|
|
49
|
+
console.log(`- ${chalk.bold(`[${item.priority}] ${item.title}`)}${files}`);
|
|
50
|
+
console.log(` ${item.why}`);
|
|
51
|
+
console.log(` run: ${item.commands.join(' && ')}`);
|
|
52
|
+
}
|
|
53
|
+
function parseIntent(value) {
|
|
54
|
+
if (typeof value === 'string' && INTENTS.includes(value)) {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
console.error(chalk.red(`Unsupported --intent ${String(value)}.`));
|
|
58
|
+
console.error(chalk.dim('Supported intents: next_agent, bug_hunt, release, refactor, hardening'));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
function parsePositiveInt(value) {
|
|
62
|
+
const parsed = Number.parseInt(value, 10);
|
|
63
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
64
|
+
throw new Error('value must be a positive integer');
|
|
65
|
+
}
|
|
66
|
+
return parsed;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=agentBrief.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentBrief.js","sourceRoot":"","sources":["../../../src/cli/commands/agentBrief.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerBugHunt(): void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
|
|
3
|
+
import { computeBugHunt } from '../../core/bugHunt.js';
|
|
4
|
+
export function registerBugHunt() {
|
|
5
|
+
program
|
|
6
|
+
.command('bug-hunt')
|
|
7
|
+
.description('Prioritize a bug-hunt fix queue from repo health, hotspots, preflight, and session evidence')
|
|
8
|
+
.option('--max-findings <count>', 'maximum number of findings to return', parsePositiveInt)
|
|
9
|
+
.option('--since <when>', 'git history window for hotspot evidence')
|
|
10
|
+
.action(async (cmdOpts) => {
|
|
11
|
+
setupLogLevel();
|
|
12
|
+
maybeCompactBanner();
|
|
13
|
+
const format = assertFormatSupported('bug-hunt');
|
|
14
|
+
try {
|
|
15
|
+
const report = await computeBugHunt(getRootPath(), {
|
|
16
|
+
maxFindings: cmdOpts.maxFindings,
|
|
17
|
+
since: cmdOpts.since,
|
|
18
|
+
});
|
|
19
|
+
if (format === 'json') {
|
|
20
|
+
console.log(JSON.stringify(report, null, 2));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
printBugHunt(report);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.error(chalk.red(err instanceof Error ? err.message : String(err)));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function printBugHunt(report) {
|
|
32
|
+
const color = report.verdict === 'block' ? chalk.red : report.verdict === 'fix' ? chalk.yellow : chalk.green;
|
|
33
|
+
console.log(color(`Bug Hunt: ${report.verdict}`));
|
|
34
|
+
console.log(report.summary);
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(chalk.bold('Fix Queue'));
|
|
37
|
+
for (const finding of report.fixQueue) {
|
|
38
|
+
printFinding(finding);
|
|
39
|
+
}
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(chalk.bold('Verify'));
|
|
42
|
+
for (const entry of report.verificationMatrix) {
|
|
43
|
+
console.log(`- ${entry.command}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function printFinding(finding) {
|
|
47
|
+
const files = finding.files.length > 0 ? ` (${finding.files.join(', ')})` : '';
|
|
48
|
+
console.log(`- ${chalk.bold(`[${finding.priority}] ${finding.title}`)}${files}`);
|
|
49
|
+
console.log(` ${finding.why}`);
|
|
50
|
+
console.log(` verify: ${finding.verification.commands.join(' && ')}`);
|
|
51
|
+
}
|
|
52
|
+
function parsePositiveInt(value) {
|
|
53
|
+
const parsed = Number.parseInt(value, 10);
|
|
54
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
55
|
+
throw new Error('value must be a positive integer');
|
|
56
|
+
}
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=bugHunt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bugHunt.js","sourceRoot":"","sources":["../../../src/cli/commands/bugHunt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerEvidencePack(): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { assertFormatSupported, getRootPath, maybeCompactBanner, program, setupLogLevel, } from '../_shared.js';
|
|
3
|
+
import { computeEvidencePack } from '../../core/releaseEvidence.js';
|
|
4
|
+
export function registerEvidencePack() {
|
|
5
|
+
program
|
|
6
|
+
.command('evidence-pack')
|
|
7
|
+
.description('Assemble approval evidence from product planning, bug-hunt, workplan, and preflight signals')
|
|
8
|
+
.option('--line <line>', 'product line to include, repeatable (default: next six minor lines)', collectLine, [])
|
|
9
|
+
.option('--website-prompt', 'include website-update prompt text')
|
|
10
|
+
.option('--max-findings <count>', 'maximum bug-hunt findings to include', parsePositiveInt)
|
|
11
|
+
.action(async (cmdOpts) => {
|
|
12
|
+
setupLogLevel();
|
|
13
|
+
maybeCompactBanner();
|
|
14
|
+
const format = assertFormatSupported('evidence-pack');
|
|
15
|
+
try {
|
|
16
|
+
const report = await computeEvidencePack(getRootPath(), {
|
|
17
|
+
lines: cmdOpts.line,
|
|
18
|
+
includeWebsitePrompt: cmdOpts.websitePrompt === true,
|
|
19
|
+
maxFindings: cmdOpts.maxFindings,
|
|
20
|
+
});
|
|
21
|
+
if (format === 'json') {
|
|
22
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
printEvidencePack(report);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
console.error(chalk.red(err instanceof Error ? err.message : String(err)));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function collectLine(value, previous) {
|
|
34
|
+
return [...previous, value];
|
|
35
|
+
}
|
|
36
|
+
function printEvidencePack(report) {
|
|
37
|
+
const color = report.verdict === 'blocked'
|
|
38
|
+
? chalk.red
|
|
39
|
+
: report.verdict === 'caution'
|
|
40
|
+
? chalk.yellow
|
|
41
|
+
: chalk.green;
|
|
42
|
+
console.log(color(`Evidence Pack: ${report.verdict}`));
|
|
43
|
+
console.log(report.summary);
|
|
44
|
+
console.log(`Version: ${report.currentVersion ?? 'unknown'}`);
|
|
45
|
+
console.log(`Product lines: ${report.train.lines.join(', ')}`);
|
|
46
|
+
console.log('');
|
|
47
|
+
console.log(chalk.bold('Artifacts'));
|
|
48
|
+
for (const artifact of report.artifacts) {
|
|
49
|
+
printArtifact(artifact);
|
|
50
|
+
}
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(chalk.bold('Approval'));
|
|
53
|
+
console.log(`- ${report.approval.recommendation}`);
|
|
54
|
+
for (const reason of report.approval.blockingReasons.slice(0, 5)) {
|
|
55
|
+
console.log(`- blocker: ${reason}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function printArtifact(artifact) {
|
|
59
|
+
console.log(`- ${chalk.bold(`[${artifact.status}] ${artifact.title}`)}`);
|
|
60
|
+
console.log(` ${artifact.summary}`);
|
|
61
|
+
console.log(` verify: ${artifact.commands.join(' && ')}`);
|
|
62
|
+
}
|
|
63
|
+
function parsePositiveInt(value) {
|
|
64
|
+
const parsed = Number.parseInt(value, 10);
|
|
65
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
66
|
+
throw new Error('value must be a positive integer');
|
|
67
|
+
}
|
|
68
|
+
return parsed;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=evidencePack.js.map
|