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** | **394 test assertions** | **93 test blocks** |
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 93-block correctness harness (requires Chrome) |
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 (93 blocks, 394 hard assertions, 54 fixture pages)
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 โ€” 84 numbered blocks ([80] MCP server, [81] createFinding, [82] withRetry, [83] watch dashboard, [84] cli/init.js)
952
- โ”‚ โ”œโ”€โ”€ pages/ # 54 fixture pages (one per detection category)
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 (`391/394` 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.
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). 84 test blocks, 367 hard assertions, 54 detection categories.",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argusqa-os",
3
- "version": "9.5.0",
3
+ "version": "9.5.1",
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": [
package/src/mcp-server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Argus MCP Server (v9.4.6)
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.4.6' },
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 networkBaseline = (await browser.listNetwork().catch(() => [])).length;
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
- const consoleMsgs = (await browser.listConsole().catch(() => [])).slice(consoleBaseline);
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 โ€” sliced from per-route baseline (cap AFTER slice, not before)
504
- const networkReqs = (await browser.listNetwork())
505
- .slice(networkBaseline).slice(0, 500);
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(generatedAt)}</p>
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>`;
@@ -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+)\]/gm;
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;