argusqa-os 9.5.0 โ 9.5.1
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
CHANGED
|
@@ -79,7 +79,7 @@ The `landing/` directory contains the product landing page (React + Vite + Tailw
|
|
|
79
79
|
|
|
80
80
|
| ๐ด Critical / ๐ก Warning / ๐ต Info | โ๏ธ | ๐งช | ๐ |
|
|
81
81
|
| :---: | :---: | :---: | :---: |
|
|
82
|
-
| **114 distinct issue types detected** | **24 analysis engines** | **
|
|
82
|
+
| **114 distinct issue types detected** | **24 analysis engines** | **528 test assertions** | **126 test blocks** |
|
|
83
83
|
|
|
84
84
|
</div>
|
|
85
85
|
|
|
@@ -632,7 +632,7 @@ Then follow with: *"Here's the context โ what's causing these errors and how d
|
|
|
632
632
|
| `npm run server` | Start the Slack slash command + interaction server (port 3001) |
|
|
633
633
|
| `npm run init` | Interactive setup wizard โ generates `.env` + `targets.js` |
|
|
634
634
|
| `npm run test:unit` | Run 61 unit tests (no Chrome required) |
|
|
635
|
-
| `npm run test:harness` | Run
|
|
635
|
+
| `npm run test:harness` | Run 126-block correctness harness (requires Chrome) |
|
|
636
636
|
|
|
637
637
|
**`npm run crawl`** โ full audit of all configured routes:
|
|
638
638
|
|
|
@@ -876,7 +876,7 @@ argus/
|
|
|
876
876
|
โ โ โโโ browser.js # CdpBrowserAdapter โ facade over all chrome-devtools-mcp calls
|
|
877
877
|
โ โโโ domain/
|
|
878
878
|
โ โ โโโ finding.js # createFinding() factory โ canonical finding shape
|
|
879
|
-
โ โโโ registry.js # Analyzer plugin registry โ registerExpensive/getCheap/getExpensive
|
|
879
|
+
โ โโโ registry.js # Analyzer plugin registry โ registerCheap/registerExpensive/getCheap/getExpensive/clearAll
|
|
880
880
|
โ โโโ config/
|
|
881
881
|
โ โ โโโ targets.js # Routes to test, thresholds, config
|
|
882
882
|
โ โ โโโ schema.js # Zod validation schema; validateConfig() called inside runCrawl()
|
|
@@ -944,12 +944,12 @@ argus/
|
|
|
944
944
|
โ โโโ README.md # Setup guide, Supabase SQL schema, env vars, deployment
|
|
945
945
|
โโโ scripts/
|
|
946
946
|
โ โโโ dispatch-report.js # Standalone Slack re-dispatch script (re-posts last report.json to Slack)
|
|
947
|
-
โโโ test-harness/ # Fixture server + test runner (
|
|
947
|
+
โโโ test-harness/ # Fixture server + test runner (126 blocks, 528 hard assertions, 53 fixture pages)
|
|
948
948
|
โ โโโ README.md
|
|
949
949
|
โ โโโ server.js # Express fixture server (ports 3100 dev / 3101 staging)
|
|
950
950
|
โ โโโ harness-config.js # Route definitions + expected findings
|
|
951
|
-
โ โโโ validate.js # Test runner โ
|
|
952
|
-
โ โโโ pages/ #
|
|
951
|
+
โ โโโ validate.js # Test runner โ 126 numbered blocks ([80]โ[84] MCP/createFinding/withRetry/watch/init, [85]โ[93] Sprint 0.5 Tier 3, [94]โ[126] gap-close Sections 1โ6)
|
|
952
|
+
โ โโโ pages/ # 53 fixture HTML pages (one per detection category)
|
|
953
953
|
โ โโโ nextjs-fixture/ # Next.js app structure for C3 discovery tests (10 files)
|
|
954
954
|
โ โโโ source-fixture/ # Minimal app.js for C1 codebase-analyzer tests (env var audit)
|
|
955
955
|
โ โโโ static/
|
|
@@ -989,7 +989,7 @@ argus/
|
|
|
989
989
|
|
|
990
990
|
## Known MCP Tool Limitations
|
|
991
991
|
|
|
992
|
-
The Chrome DevTools MCP behavioral constraints below cause **3 permanent test failures** in the harness (`
|
|
992
|
+
The Chrome DevTools MCP behavioral constraints below cause **3 permanent test failures** in the harness (`525/528` pass). These are MCP-layer restrictions โ they cannot be fixed in Argus code. `validate.js` now exits with code 0 when only these 3 failures remain, making the CI harness gate reliable.
|
|
993
993
|
|
|
994
994
|
> **`type_text` clarification**: `type_text` does fire DOM `input` events when the element is properly focused first with `mcp.click({ uid })`. Always use uid-based focus โ passing `{ selector }` to `mcp.click` silently does nothing.
|
|
995
995
|
|
package/glama.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://glama.ai/mcp/schemas/server.json",
|
|
3
3
|
"name": "argus",
|
|
4
|
-
"description": "AI-powered QA harness that audits web apps via Chrome DevTools Protocol. Catches JS errors, network failures, a11y violations, SEO issues, security headers, CSS regressions, and more โ directly from Claude conversations. 6 MCP tools: argus_audit (fast 8-analyzer pass), argus_audit_full (Lighthouse + memory + responsive), argus_compare (dev vs staging diff), argus_last_report (retrieve last JSON report), argus_watch_snapshot (live tab snapshot without navigating), argus_get_context (LLM-optimized context + fix loop with snapshot_id diff).
|
|
4
|
+
"description": "AI-powered QA harness that audits web apps via Chrome DevTools Protocol. Catches JS errors, network failures, a11y violations, SEO issues, security headers, CSS regressions, and more โ directly from Claude conversations. 6 MCP tools: argus_audit (fast 8-analyzer pass), argus_audit_full (Lighthouse + memory + responsive), argus_compare (dev vs staging diff), argus_last_report (retrieve last JSON report), argus_watch_snapshot (live tab snapshot without navigating), argus_get_context (LLM-optimized context + fix loop with snapshot_id diff). 126 test blocks, 528 hard assertions, 54 detection categories.",
|
|
5
5
|
"maintainers": ["ironclawdevs27"],
|
|
6
6
|
"tools": [
|
|
7
7
|
{
|
package/package.json
CHANGED
package/src/mcp-server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Argus MCP Server (v9.
|
|
3
|
+
* Argus MCP Server (v9.5.1)
|
|
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
|
|
@@ -286,7 +286,7 @@ async function handleLastReport() {
|
|
|
286
286
|
// โโ Server bootstrap โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
287
287
|
|
|
288
288
|
const server = new Server(
|
|
289
|
-
{ name: 'argus', version: '9.
|
|
289
|
+
{ name: 'argus', version: '9.5.1' },
|
|
290
290
|
{ capabilities: { tools: {} } },
|
|
291
291
|
);
|
|
292
292
|
|
|
@@ -424,7 +424,8 @@ export async function crawlRouteCheap(route, baseUrl, mcp) {
|
|
|
424
424
|
|
|
425
425
|
// 0. Snapshot session-wide baselines BEFORE this route starts (D5).
|
|
426
426
|
const consoleBaseline = (await browser.listConsole().catch(() => [])).length;
|
|
427
|
-
const
|
|
427
|
+
const baselineNetList = await browser.listNetwork().catch(() => []);
|
|
428
|
+
const networkMaxReqId = baselineNetList.reduce((max, r) => Math.max(max, r._reqid ?? 0), 0);
|
|
428
429
|
// listConsoleRaw returns raw MCP response โ normalizeArray required before .length
|
|
429
430
|
const issuesBaselineRaw = await browser.listConsoleRaw({ types: ['issue'] }).catch(() => null);
|
|
430
431
|
const issuesBaseline = normalizeArray(issuesBaselineRaw).length;
|
|
@@ -468,8 +469,14 @@ export async function crawlRouteCheap(route, baseUrl, mcp) {
|
|
|
468
469
|
});
|
|
469
470
|
}
|
|
470
471
|
|
|
471
|
-
// 5. Console messages โ sliced from per-route baseline
|
|
472
|
-
|
|
472
|
+
// 5. Console messages โ sliced from per-route baseline.
|
|
473
|
+
// Guard: chrome-devtools-mcp list_console_messages resets per navigation. If the
|
|
474
|
+
// new page has fewer total messages than the pre-navigation baseline, the baseline
|
|
475
|
+
// refers to the previous page's context and slicing by it would give an empty array.
|
|
476
|
+
// Fall back to 0 (take all messages from the new page) in that case.
|
|
477
|
+
const allConsoleMsgs = await browser.listConsole().catch(() => []);
|
|
478
|
+
const consoleSliceAt = allConsoleMsgs.length > consoleBaseline ? consoleBaseline : 0;
|
|
479
|
+
const consoleMsgs = allConsoleMsgs.slice(consoleSliceAt);
|
|
473
480
|
for (const msg of consoleMsgs) {
|
|
474
481
|
const text = (msg.text ?? msg.message ?? '');
|
|
475
482
|
if (text.toLowerCase().includes('has been blocked by cors policy')) continue;
|
|
@@ -500,9 +507,9 @@ export async function crawlRouteCheap(route, baseUrl, mcp) {
|
|
|
500
507
|
}
|
|
501
508
|
}
|
|
502
509
|
|
|
503
|
-
// 6. Network requests โ
|
|
504
|
-
const networkReqs = (await browser.listNetwork())
|
|
505
|
-
.
|
|
510
|
+
// 6. Network requests โ filtered from per-route baseline by _reqid (cap AFTER filter, not before)
|
|
511
|
+
const networkReqs = (await browser.listNetwork().catch(() => []))
|
|
512
|
+
.filter(r => (r._reqid ?? 0) > networkMaxReqId).slice(0, 500);
|
|
506
513
|
for (const req of networkReqs) {
|
|
507
514
|
const severity = classifyNetworkRequest(req, route.critical);
|
|
508
515
|
if (severity !== null) {
|
|
@@ -172,7 +172,7 @@ const DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
172
172
|
* @param {number} port โ TCP port to listen on (default 3002)
|
|
173
173
|
* @returns {http.Server}
|
|
174
174
|
*/
|
|
175
|
-
function startDashboard(getFindings, target, port) {
|
|
175
|
+
export function startDashboard(getFindings, target, port) {
|
|
176
176
|
const server = http.createServer((req, res) => {
|
|
177
177
|
if (req.url === '/data' || req.url?.startsWith('/data?')) {
|
|
178
178
|
const payload = JSON.stringify({
|
|
@@ -234,7 +234,7 @@ function buildHtml(report) {
|
|
|
234
234
|
|
|
235
235
|
${flowSection}
|
|
236
236
|
|
|
237
|
-
<p style="text-align:center;font-size:12px;color:#9ca3af;margin-top:32px">Generated by <strong>Argus</strong> ยท ${esc(
|
|
237
|
+
<p style="text-align:center;font-size:12px;color:#9ca3af;margin-top:32px">Generated by <strong>Argus</strong> ยท ${esc(runDate)}</p>
|
|
238
238
|
</div>
|
|
239
239
|
</body>
|
|
240
240
|
</html>`;
|
package/src/utils/mcp-parsers.js
CHANGED
|
@@ -46,7 +46,7 @@ export function parseNetworkReqResponse(raw) {
|
|
|
46
46
|
if (typeof raw === 'object') return normalizeArray(raw);
|
|
47
47
|
if (typeof raw !== 'string') return [];
|
|
48
48
|
const reqs = [];
|
|
49
|
-
const re = /reqid=(\d+)\s+(\w+)\s+(\S+)\s+\[(\d+)
|
|
49
|
+
const re = /reqid=(\d+)\s+(\w+)\s+(\S+)\s+\[(\d+)[^\]]*\]/gm;
|
|
50
50
|
let m;
|
|
51
51
|
while ((m = re.exec(raw)) !== null) {
|
|
52
52
|
const [, reqid, method, url, statusStr] = m;
|