@qatonic_innovations/qaios 0.6.0 → 0.6.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.
Files changed (38) hide show
  1. package/dist/{a11y-X3GULPJY.js → a11y-D2ESBYWX.js} +10 -5
  2. package/dist/{chunk-KAXYG56C.js → chunk-4D352FXP.js} +1 -1
  3. package/dist/{chunk-MABXT3RT.js → chunk-BZOQ4NNA.js} +29 -10
  4. package/dist/{chunk-YIZRJPII.js → chunk-DYAAVZGS.js} +1 -1
  5. package/dist/{chunk-SKSVFAPZ.js → chunk-EEFQVLZX.js} +26 -2
  6. package/dist/{chunk-3SEEYC6R.js → chunk-HZDJWR25.js} +13 -0
  7. package/dist/{chunk-6MCKYCGA.js → chunk-JCVLIA63.js} +2 -2
  8. package/dist/{chunk-ICKV4DDG.js → chunk-OOI2XRPM.js} +1 -1
  9. package/dist/{chunk-IFKXORJV.js → chunk-UOPD5XI2.js} +2 -2
  10. package/dist/{chunk-XKBSTVSC.js → chunk-VMTUIR5O.js} +573 -78
  11. package/dist/{chunk-RQP7ALWK.js → chunk-ZL6W6TH2.js} +42 -6
  12. package/dist/{config-3JZDCGLC.js → config-NRRBZZ35.js} +13 -4
  13. package/dist/config-schema.js +2 -2
  14. package/dist/{dist-P3PQVEIR.js → dist-QCMTQH2D.js} +1 -1
  15. package/dist/{doctor-AKOPTL62.js → doctor-4LUAESSS.js} +42 -4
  16. package/dist/{evidence-6RUORR7P.js → evidence-L2GG45YA.js} +3 -3
  17. package/dist/{explore-CMTPFLIB.js → explore-VJIQQBEG.js} +28 -26
  18. package/dist/{fix-OUIERLSI.js → fix-2QC6ZIX6.js} +16 -8
  19. package/dist/healing/scripts/capture-page.mjs +3 -1
  20. package/dist/{history-QPKCL64Y.js → history-UBEWZE2G.js} +17 -6
  21. package/dist/index.js +97 -64
  22. package/dist/{init-5DG222SD.js → init-64R4KSLV.js} +9 -4
  23. package/dist/manifest-seal-7HRI6C5U.js +5 -0
  24. package/dist/{mcp-NQQEZNQW.js → mcp-FE4XUYRP.js} +14 -3
  25. package/dist/{review-AWRKQMIE.js → review-HX34P7FQ.js} +9 -9
  26. package/dist/{run-XXK4SY7X.js → run-XFKBCGNB.js} +16 -7
  27. package/dist/schemas/config-layer-v1.schema.json +14 -0
  28. package/dist/schemas/config-v1.schema.json +14 -0
  29. package/dist/{snapshot-NWJXLNZC.js → snapshot-UTPP6UNI.js} +5 -4
  30. package/dist/snapshot-review-IBN3QV7G.js +7 -0
  31. package/dist/test-WXHGG4GY.js +10 -0
  32. package/dist/validation/worker.d.ts +2 -0
  33. package/dist/validation/worker.js +686 -0
  34. package/dist/{xray-BON5QPYR.js → xray-HK6PIENO.js} +2 -2
  35. package/package.json +2 -2
  36. package/dist/manifest-seal-QXGIQ4LI.js +0 -5
  37. package/dist/snapshot-review-LRRPNAYH.js +0 -7
  38. package/dist/test-W5BFE5IS.js +0 -10
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { resolveLlmClient, llmKeyCheck, warnAiSkipped, auditA11ySkill, defectCreateSkill } from './chunk-RQP7ALWK.js';
2
+ import { resolveLlmClient, capFromConfig, llmKeyCheck, warnAiSkipped, auditA11ySkill, defectCreateSkill } from './chunk-ZL6W6TH2.js';
3
3
  import './chunk-VSSX6F42.js';
4
4
  import { getQaiosVersion } from './chunk-RDZE7TZG.js';
5
- import { loadCommandConfig } from './chunk-ICKV4DDG.js';
5
+ import { loadCommandConfig } from './chunk-OOI2XRPM.js';
6
6
  import { ExitCode } from './chunk-EAMUH7ZB.js';
7
- import { loadProjectMemory, Storage, AuditLogger, WorkflowsRepository, runAxe, AxeRunError, ArtifactsRepository, SkillRunner, McpServersRepository, McpClient, fileDefect } from './chunk-XKBSTVSC.js';
8
- import { ulid } from './chunk-3SEEYC6R.js';
7
+ import { loadProjectMemory, Storage, AuditLogger, WorkflowsRepository, runAxe, AxeRunError, ArtifactsRepository, costCapGuard, SkillRunner, McpServersRepository, McpClient, fileDefect } from './chunk-VMTUIR5O.js';
8
+ import { ulid } from './chunk-HZDJWR25.js';
9
9
  import { createHash } from 'crypto';
10
10
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
11
11
  import path from 'path';
@@ -122,7 +122,6 @@ async function runA11y(opts) {
122
122
  const code = err instanceof AxeRunError ? err.code : "qaios.a11y.scan_failed";
123
123
  const message = err.message ?? String(err);
124
124
  finalize(workflowId, "failed");
125
- writeOut(`${GLYPH.failed} ${code}: ${message}`);
126
125
  return { exitCode: ExitCode.TOOL_ERROR, workflowId, error: { code, message } };
127
126
  }
128
127
  const violationCount = findings.filter((f) => f.kind === "violation").length;
@@ -184,6 +183,12 @@ async function runA11y(opts) {
184
183
  prior: {},
185
184
  auditLogger,
186
185
  llm,
186
+ beforeModelCall: costCapGuard({
187
+ db: storage.db,
188
+ auditLogger,
189
+ workflowId,
190
+ cap: capFromConfig(config)
191
+ }),
187
192
  ...opts.cancelSignal !== void 0 ? { cancelSignal: opts.cancelSignal } : {},
188
193
  ...memory !== null ? { qaiosMemoryFull: memory } : {}
189
194
  };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { QaiosConfig } from './chunk-3SEEYC6R.js';
2
+ import { QaiosConfig } from './chunk-HZDJWR25.js';
3
3
  import { readFileSync, statSync, copyFileSync, constants, writeFileSync, renameSync, rmSync, existsSync } from 'fs';
4
4
  import { randomUUID } from 'crypto';
5
5
  import path from 'path';
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { defectTargetArgs, defectMcpClient, renderRunSummary, buildRunSummary } from './chunk-SKSVFAPZ.js';
3
- import { llmKeyCheck, API_SPEC_TRUNCATE, resolveLlmClient, skills, keyRejectedError } from './chunk-RQP7ALWK.js';
2
+ import { defectTargetArgs, defectMcpClient, renderRunSummary, buildRunSummary } from './chunk-EEFQVLZX.js';
3
+ import { llmKeyCheck, API_SPEC_TRUNCATE, resolveLlmClient, capFromConfig, skills, keyRejectedError } from './chunk-ZL6W6TH2.js';
4
4
  import { isLlmFailure, API_KEY_MISSING } from './chunk-VSSX6F42.js';
5
5
  import { getQaiosVersion } from './chunk-RDZE7TZG.js';
6
- import { loadCommandConfigResolution } from './chunk-ICKV4DDG.js';
6
+ import { loadCommandConfigResolution } from './chunk-OOI2XRPM.js';
7
7
  import { ExitCode } from './chunk-EAMUH7ZB.js';
8
- import { generationErrorCode, failureReasonCode, loadProjectMemory, parseOpenApi, OpenApiParseError, inspectProjectFixtures, Storage, AuditLogger, Orchestrator, createGeneratedTestPreparer, summarizeGeneratedRun, generatedSpecFiles } from './chunk-XKBSTVSC.js';
8
+ import { generationErrorCode, failureReasonCode, loadProjectMemory, parseOpenApi, OpenApiParseError, checkStorageState, inspectProjectFixtures, inspectProjectHelpers, Storage, AuditLogger, Orchestrator, createGeneratedTestPreparer, summarizeGeneratedRun, generatedSpecFiles } from './chunk-VMTUIR5O.js';
9
9
  import { existsSync, readFileSync } from 'fs';
10
10
  import path from 'path';
11
11
 
@@ -97,7 +97,7 @@ function renderTextLine(event) {
97
97
  }
98
98
  case "gate_evaluated":
99
99
  if (event.decision === "pass")
100
- return `\u25B8 gate.${event.gateType.padEnd(16)} ${GLYPH.ok} passed
100
+ return `\u25B8 gate.${event.gateType.padEnd(16)} ${GLYPH.ok} passed${event.reason !== void 0 ? ` (${event.reason})` : ""}
101
101
  `;
102
102
  if (event.decision === "rejected") {
103
103
  return `\u25B8 gate.${event.gateType.padEnd(16)} ${GLYPH.failed} rejected
@@ -283,6 +283,16 @@ ${epSummary}`;
283
283
  if (!groundEnabled) args["noGround"] = true;
284
284
  args["groundCaptureTimeoutMs"] = testCfg?.groundCaptureTimeoutMs ?? 6e4;
285
285
  args["groundMaxPages"] = testCfg?.groundMaxPages ?? 5;
286
+ if (groundEnabled && testCfg?.groundStorageState !== void 0) {
287
+ const state = checkStorageState({ cwd, storageState: testCfg.groundStorageState });
288
+ if (!state.ok) {
289
+ return {
290
+ exitCode: ExitCode.USER_ERROR,
291
+ error: { code: state.code, message: state.message }
292
+ };
293
+ }
294
+ args["groundStorageState"] = state.path;
295
+ }
286
296
  }
287
297
  if (testType === "api" && parsedSpec !== null) {
288
298
  args["apiContext"] = {
@@ -312,6 +322,17 @@ ${epSummary}`;
312
322
  args["fixtures"] = testCfg.fixtures;
313
323
  args["projectFixtures"] = inspected.fixtures;
314
324
  }
325
+ if (testCfg.helpers !== void 0 && testCfg.helpers.length > 0) {
326
+ const inspected = await inspectProjectHelpers({ cwd, helpers: testCfg.helpers });
327
+ if (!inspected.ok) {
328
+ return {
329
+ exitCode: ExitCode.USER_ERROR,
330
+ error: { code: inspected.code, message: inspected.message }
331
+ };
332
+ }
333
+ args["helpers"] = testCfg.helpers;
334
+ args["projectHelpers"] = inspected.helpers;
335
+ }
315
336
  const mode = opts.mode ?? config.mode;
316
337
  const ownsStorage = opts.storage === void 0;
317
338
  const storage = opts.storage ?? Storage.open(path.join(qaiosDir, "workflows.db"), { skipMigrations: false });
@@ -327,10 +348,7 @@ ${epSummary}`;
327
348
  gateConfig.autoExpireOnTimeout = "auto_approve";
328
349
  gateConfig.approvedBy = "--yes";
329
350
  }
330
- const costCap = {
331
- maxCalls: config.llm.maxLlmCallsPerWorkflow,
332
- maxUsdCents: config.llm.costAlertThresholdUsdCents
333
- };
351
+ const costCap = capFromConfig(config);
334
352
  const filesWritten = [];
335
353
  if (opts.run === true) Object.assign(args, defectTargetArgs(config.defects));
336
354
  const defectClient = opts.run === true ? opts.mcpClient ?? defectMcpClient(config.defects, storage, auditLogger) : void 0;
@@ -464,6 +482,7 @@ Review notes (${qaiosMdSuggestions.length}) from the writing skill \u2014 worth
464
482
  files: byFile.files,
465
483
  otherResults: byFile.otherResults
466
484
  };
485
+ const blockedCount = Array.isArray(execOut.testResults) ? execOut.testResults.filter((tr) => tr.status === "blocked").length : 0;
467
486
  if (!opts.quiet && opts.json !== true) {
468
487
  process.stdout.write("\nRan only the spec files this workflow generated:\n");
469
488
  for (const f of byFile.files) {
@@ -479,7 +498,7 @@ Review notes (${qaiosMdSuggestions.length}) from the writing skill \u2014 worth
479
498
  }
480
499
  process.stdout.write(
481
500
  `
482
- Test execution result: ${runSummary.passedCount} passed, ${runSummary.failedCount} failed` + (runSummary.flakyCount > 0 ? `, ${runSummary.flakyCount} flaky` : "") + (runSummary.skippedCount > 0 ? `, ${runSummary.skippedCount} skipped` : "") + `
501
+ Test execution result: ${runSummary.passedCount} passed, ${runSummary.failedCount} failed` + (runSummary.flakyCount > 0 ? `, ${runSummary.flakyCount} flaky` : "") + (runSummary.skippedCount > 0 ? `, ${runSummary.skippedCount} skipped` : "") + (blockedCount > 0 ? `, ${blockedCount} blocked (missing contract or fixture)` : "") + `
483
502
  `
484
503
  );
485
504
  }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { QAIOS_CONFIG_VERSION, QaiosConfig } from './chunk-3SEEYC6R.js';
2
+ import { QAIOS_CONFIG_VERSION, QaiosConfig } from './chunk-HZDJWR25.js';
3
3
  import { zodToJsonSchema } from 'zod-to-json-schema';
4
4
 
5
5
  var CONFIG_SCHEMA_FILE = `config-v${QAIOS_CONFIG_VERSION}.schema.json`;
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { getQaiosVersion } from './chunk-RDZE7TZG.js';
3
- import { McpClient, McpServersRepository } from './chunk-XKBSTVSC.js';
3
+ import { McpClient, McpServersRepository } from './chunk-VMTUIR5O.js';
4
4
 
5
5
  // src/defect-filing.ts
6
6
  function defectTargetArgs(defects) {
@@ -144,11 +144,26 @@ function buildRunSummary(db, workflowId) {
144
144
  WHERE workflow_id = ? AND event = 'execution.completed' ORDER BY id DESC LIMIT 1`
145
145
  ).get(workflowId);
146
146
  const runError = lastRun !== void 0 ? str(JSON.parse(lastRun.p)["errorReason"]) : void 0;
147
+ const stoppedRow = db.prepare(
148
+ `SELECT payload_json AS p FROM audit_log
149
+ WHERE workflow_id = ? AND skill_id = 'classify.result'
150
+ AND json_extract(payload_json, '$.kind') = 'classification.stopped'
151
+ ORDER BY id DESC LIMIT 1`
152
+ ).get(workflowId);
153
+ let aiStopped;
154
+ if (stoppedRow !== void 0) {
155
+ const p = JSON.parse(stoppedRow.p);
156
+ aiStopped = {
157
+ reason: str(p.reason) ?? "AI unavailable",
158
+ unclassified: Array.isArray(p.unclassified) ? p.unclassified.filter((t) => typeof t === "string") : []
159
+ };
160
+ }
147
161
  return {
148
162
  classifications: [...byTest.values()],
149
163
  heal,
150
164
  defects,
151
- ...runError !== void 0 ? { runError } : {}
165
+ ...runError !== void 0 ? { runError } : {},
166
+ ...aiStopped !== void 0 ? { aiStopped } : {}
152
167
  };
153
168
  }
154
169
  function oneLine(text) {
@@ -171,6 +186,15 @@ function renderRunSummary(summary, opts) {
171
186
  }
172
187
  blocks.push(lines.join("\n"));
173
188
  }
189
+ if (summary.aiStopped !== void 0) {
190
+ const s = summary.aiStopped;
191
+ const lines = [
192
+ `\u26A0 Classification stopped (${s.reason}).`,
193
+ ` ${s.unclassified.length} failure(s) not classified; no heal or defect was attempted. The test results above stand.`,
194
+ ...s.unclassified.map((t) => ` \u25CB ${t}`)
195
+ ];
196
+ blocks.push(lines.join("\n"));
197
+ }
174
198
  const h = summary.heal;
175
199
  if (h !== null) {
176
200
  const lines = [];
@@ -817,6 +817,12 @@ var QaiosConfig = z.object({
817
817
  fixtures: z.string().optional().describe(
818
818
  "Project-relative path of a Playwright fixtures module that exports test (and optionally expect); generated tests import it and use its fixtures."
819
819
  ),
820
+ // v0.6: existing project modules generated tests may import and reuse
821
+ // (page objects, data builders, API clients). Their exports are read
822
+ // from the types and shown to write.web; never executed by QAIOS.
823
+ helpers: z.array(z.string().min(1)).max(20).optional().describe(
824
+ "Project-relative paths of existing .ts modules (page objects, data builders, API clients) that generated tests may import and reuse."
825
+ ),
820
826
  // 0.5 DOM grounding: when true (default), `qaios test` captures the
821
827
  // live page at `app.baseUrl` before writing and feeds the real DOM
822
828
  // to write.web so it generates locators against actual elements
@@ -837,6 +843,13 @@ var QaiosConfig = z.object({
837
843
  // shares groundCaptureTimeoutMs as its total time budget.
838
844
  groundMaxPages: z.number().int().positive().max(50).default(5).describe(
839
845
  "Most same-origin pages to capture for grounding; groundCaptureTimeoutMs is the total time budget."
846
+ ),
847
+ // Pages behind sign-in redirect the capture browser to the login page.
848
+ // A Playwright storage state (cookies + local storage, usually written
849
+ // by the project's auth setup step) lets grounding open them signed in.
850
+ // Only the path is kept; QAIOS never runs project code to sign in.
851
+ groundStorageState: z.string().min(1).optional().describe(
852
+ "Project-relative path of a Playwright storage state (cookies and local storage) that grounding loads, so pages behind sign-in can be captured."
840
853
  )
841
854
  }).default({}),
842
855
  visual: z.object({
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { loadCommandConfig } from './chunk-ICKV4DDG.js';
3
- import { Storage, sealWorkflowManifest, AuditLogger } from './chunk-XKBSTVSC.js';
2
+ import { loadCommandConfig } from './chunk-OOI2XRPM.js';
3
+ import { Storage, sealWorkflowManifest, AuditLogger } from './chunk-VMTUIR5O.js';
4
4
  import { existsSync } from 'fs';
5
5
  import path from 'path';
6
6
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { resolveConfigLayers } from './chunk-XKBSTVSC.js';
2
+ import { resolveConfigLayers } from './chunk-VMTUIR5O.js';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import path from 'path';
5
5
  import { parse } from 'yaml';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { reviewSigner } from './chunk-6MCKYCGA.js';
2
+ import { reviewSigner } from './chunk-JCVLIA63.js';
3
3
  import { ExitCode } from './chunk-EAMUH7ZB.js';
4
- import { executeBaselineUpdate, openReview, visualProposal, visualSummary, decideReview, Storage, AuditLogger, VisualBaselinesRepository, VisualDiffsRepository, cleanupCommittedBaselineUpdates } from './chunk-XKBSTVSC.js';
4
+ import { executeBaselineUpdate, openReview, visualProposal, visualSummary, decideReview, Storage, AuditLogger, VisualBaselinesRepository, VisualDiffsRepository, cleanupCommittedBaselineUpdates } from './chunk-VMTUIR5O.js';
5
5
  import { existsSync } from 'fs';
6
6
  import path from 'path';
7
7