argusqa-os 9.6.1 → 9.6.3
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/package.json +3 -2
- package/src/cli/pr-validate.js +7 -9
- package/src/mcp-server.js +2 -2
- package/src/utils/mcp-client.js +1 -1
- package/src/utils/pr-diff-analyzer.js +43 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "argusqa-os",
|
|
3
|
-
"version": "9.6.
|
|
3
|
+
"version": "9.6.3",
|
|
4
4
|
"mcpName": "io.github.ironclawdevs27/argus",
|
|
5
5
|
"description": "Argus — AI-powered automated dev-testing platform using Chrome DevTools MCP and Claude Code",
|
|
6
6
|
"keywords": [
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"bin": {
|
|
34
34
|
"argus": "src/cli/init.js",
|
|
35
35
|
"argus-mcp": "src/mcp-server.js",
|
|
36
|
-
"argusqa-os": "src/mcp-server.js"
|
|
36
|
+
"argusqa-os": "src/mcp-server.js",
|
|
37
|
+
"argus-pr-validate": "src/cli/pr-validate.js"
|
|
37
38
|
},
|
|
38
39
|
"scripts": {
|
|
39
40
|
"setup": "node -e \"import('fs').then(fs => fs.default.mkdirSync('./reports', { recursive: true }))\"",
|
package/src/cli/pr-validate.js
CHANGED
|
@@ -154,16 +154,14 @@ async function loadRoutes() {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
// 3.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
} catch { /* targets.js may not export routes in all environments */ }
|
|
164
|
-
|
|
165
|
-
// 4. Final fallback — audit root path only
|
|
157
|
+
// 3. Final fallback — audit root path only
|
|
158
|
+
// NOTE: We deliberately do NOT fall back to the package's targets.js here.
|
|
159
|
+
// targets.js contains the developer's own demo routes with app-specific
|
|
160
|
+
// waitFor selectors (e.g. [data-testid="dashboard"]) that do not exist on
|
|
161
|
+
// user apps — falling back to them causes false-positive load_failure
|
|
162
|
+
// findings and incorrectly blocks merges.
|
|
166
163
|
console.log('[argus] No routes configured — falling back to root path audit');
|
|
164
|
+
console.log('[argus] Tip: add argus.routes.json to your repo root to audit specific routes.');
|
|
167
165
|
return [{ path: '/', name: 'home' }];
|
|
168
166
|
}
|
|
169
167
|
|
package/src/mcp-server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Argus MCP Server (v9.6.
|
|
3
|
+
* Argus MCP Server (v9.6.3)
|
|
4
4
|
*
|
|
5
5
|
* Exposes Argus as an MCP server so Claude (or any MCP client) can call
|
|
6
6
|
* argus_audit, argus_audit_full, argus_compare, argus_last_report, and
|
|
@@ -447,7 +447,7 @@ async function handleLastReport() {
|
|
|
447
447
|
// ── Server bootstrap ──────────────────────────────────────────────────────────
|
|
448
448
|
|
|
449
449
|
const server = new Server(
|
|
450
|
-
{ name: 'argus', version: '9.6.
|
|
450
|
+
{ name: 'argus', version: '9.6.3' },
|
|
451
451
|
{ capabilities: { tools: {} } },
|
|
452
452
|
);
|
|
453
453
|
|
package/src/utils/mcp-client.js
CHANGED
|
@@ -57,7 +57,7 @@ const TOOL_TIMEOUT_MS = parseInt(process.env.MCP_TOOL_TIMEOUT_MS ?? '30000', 10)
|
|
|
57
57
|
export async function createMcpClient() {
|
|
58
58
|
// On Windows, npx is npx.cmd — shell:true resolves this cross-platform.
|
|
59
59
|
const proc = spawn('npx', [
|
|
60
|
-
'-y', 'chrome-devtools-mcp@
|
|
60
|
+
'-y', 'chrome-devtools-mcp@1.1.1',
|
|
61
61
|
`--browser-url=${BROWSER_URL}`,
|
|
62
62
|
'--headless=true',
|
|
63
63
|
'--viewport=1920x1080',
|
|
@@ -36,8 +36,6 @@ export function parsePrUrl(prUrl) {
|
|
|
36
36
|
*/
|
|
37
37
|
export async function fetchPrFiles(prUrl, githubToken) {
|
|
38
38
|
const { owner, repo, prNumber } = parsePrUrl(prUrl);
|
|
39
|
-
const apiUrl =
|
|
40
|
-
`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files?per_page=100`;
|
|
41
39
|
const headers = {
|
|
42
40
|
Accept: 'application/vnd.github+json',
|
|
43
41
|
'X-GitHub-Api-Version': '2022-11-28',
|
|
@@ -45,15 +43,41 @@ export async function fetchPrFiles(prUrl, githubToken) {
|
|
|
45
43
|
...(githubToken ? { Authorization: `Bearer ${githubToken}` } : {}),
|
|
46
44
|
};
|
|
47
45
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
const allFiles = [];
|
|
47
|
+
const MAX_PAGES = 3; // caps at 300 files; avoids runaway requests on mega-PRs
|
|
48
|
+
|
|
49
|
+
for (let page = 1; page <= MAX_PAGES; page++) {
|
|
50
|
+
const apiUrl = `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files?per_page=100&page=${page}`;
|
|
51
|
+
const res = await fetch(apiUrl, { headers });
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
const body = await res.text().catch(() => '');
|
|
54
|
+
throw new Error(`GitHub API ${res.status}: ${body || res.statusText}`);
|
|
55
|
+
}
|
|
56
|
+
const files = await res.json();
|
|
57
|
+
allFiles.push(...files.map(f => f.filename));
|
|
58
|
+
if (files.length < 100) break; // last page reached
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (allFiles.length >= 300) {
|
|
62
|
+
console.log('::warning::PR has 300+ changed files — Argus analyzed the first 300. Routes affected by later files may be missed.');
|
|
52
63
|
}
|
|
53
|
-
|
|
54
|
-
return
|
|
64
|
+
|
|
65
|
+
return allFiles;
|
|
55
66
|
}
|
|
56
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Files that are never relevant to app routes — CI configs, docs, repo metadata.
|
|
70
|
+
* Changes to ONLY these files cause mapFilesToRoutes to return [] (skip audit).
|
|
71
|
+
*/
|
|
72
|
+
const EXCLUDED_PATTERNS = [
|
|
73
|
+
/^\.github\//i,
|
|
74
|
+
/^docs?\//i,
|
|
75
|
+
/\.md$/i,
|
|
76
|
+
/^(LICENSE|CHANGELOG|CONTRIBUTING|CODE_OF_CONDUCT|SECURITY)(\..*)?$/i,
|
|
77
|
+
/^\.gitignore$/i,
|
|
78
|
+
/^\.gitattributes$/i,
|
|
79
|
+
];
|
|
80
|
+
|
|
57
81
|
/**
|
|
58
82
|
* Patterns that indicate an infrastructure-level file whose change can affect
|
|
59
83
|
* every route — framework configs, root layouts, global stylesheets, package.json.
|
|
@@ -88,15 +112,22 @@ export function mapFilesToRoutes(changedFiles, routes) {
|
|
|
88
112
|
if (!routes || routes.length === 0) return [];
|
|
89
113
|
if (!changedFiles || changedFiles.length === 0) return routes;
|
|
90
114
|
|
|
115
|
+
// Strip files that are never app-route-relevant (CI configs, docs, repo metadata)
|
|
116
|
+
const appFiles = changedFiles.filter(
|
|
117
|
+
f => !EXCLUDED_PATTERNS.some(re => re.test(f)),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// README-only / CI-only PR — skip the audit entirely
|
|
121
|
+
if (appFiles.length === 0) return [];
|
|
122
|
+
|
|
91
123
|
// Infrastructure change → full audit
|
|
92
|
-
if (
|
|
124
|
+
if (appFiles.some(f => INFRA_PATTERNS.some(re => re.test(f)))) {
|
|
93
125
|
return routes;
|
|
94
126
|
}
|
|
95
127
|
|
|
96
|
-
// Build a flat set of lowercase slugs from
|
|
128
|
+
// Build a flat set of lowercase slugs from app-relevant changed files
|
|
97
129
|
const fileSlugs = new Set(
|
|
98
|
-
|
|
99
|
-
// Strip extension, split on separators, keep non-trivial tokens
|
|
130
|
+
appFiles.flatMap(f =>
|
|
100
131
|
f.toLowerCase()
|
|
101
132
|
.replace(/\.[^./\\]+$/, '')
|
|
102
133
|
.split(/[/\\._-]+/)
|