argusqa-os 9.4.6 → 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/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.4.6",
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;