@agents-forge/aiqa 1.0.0

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 (43) hide show
  1. package/CLAUDE.md +112 -0
  2. package/README.md +281 -0
  3. package/dist/agent.d.ts +41 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +485 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/cli.d.ts +13 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +195 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.d.ts +59 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +53 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/index.d.ts +18 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +15 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/session.d.ts +50 -0
  20. package/dist/session.d.ts.map +1 -0
  21. package/dist/session.js +99 -0
  22. package/dist/session.js.map +1 -0
  23. package/dist/subagents/analyst.d.ts +3 -0
  24. package/dist/subagents/analyst.d.ts.map +1 -0
  25. package/dist/subagents/analyst.js +96 -0
  26. package/dist/subagents/analyst.js.map +1 -0
  27. package/dist/subagents/qa-engineer.d.ts +4 -0
  28. package/dist/subagents/qa-engineer.d.ts.map +1 -0
  29. package/dist/subagents/qa-engineer.js +139 -0
  30. package/dist/subagents/qa-engineer.js.map +1 -0
  31. package/dist/subagents/qa-planner.d.ts +3 -0
  32. package/dist/subagents/qa-planner.d.ts.map +1 -0
  33. package/dist/subagents/qa-planner.js +69 -0
  34. package/dist/subagents/qa-planner.js.map +1 -0
  35. package/dist/subagents/qa-reporter.d.ts +4 -0
  36. package/dist/subagents/qa-reporter.d.ts.map +1 -0
  37. package/dist/subagents/qa-reporter.js +94 -0
  38. package/dist/subagents/qa-reporter.js.map +1 -0
  39. package/dist/subagents/qa-reviewer.d.ts +3 -0
  40. package/dist/subagents/qa-reviewer.d.ts.map +1 -0
  41. package/dist/subagents/qa-reviewer.js +97 -0
  42. package/dist/subagents/qa-reviewer.js.map +1 -0
  43. package/package.json +65 -0
package/dist/cli.js ADDED
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @agents-forge/aiqa
4
+ * AI Assisted Quality Engineering — single unified agent
5
+ *
6
+ * Usage:
7
+ * npx @agents-forge/aiqa (interactive: prompts for URL + existing requirements)
8
+ * npx @agents-forge/aiqa https://my-app.com
9
+ * npx @agents-forge/aiqa https://my-app.com --grep @smoke
10
+ * npx @agents-forge/aiqa https://my-app.com --resume
11
+ */
12
+ import { runAIQA, detectProvider } from "./agent.js";
13
+ import { loadConfig, resolvePaths } from "./config.js";
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import * as readline from "node:readline/promises";
17
+ // ─── Banner ───────────────────────────────────────────────────────────────────
18
+ console.log(`
19
+ ╔══════════════════════════════════════════════════════════════╗
20
+ ║ ║
21
+ ║ 🤖 AIQA — AI Assisted Quality Engineering ║
22
+ ║ @agents-forge/aiqa ║
23
+ ║ ║
24
+ ║ analyst → qa-planner → qa-engineer ║
25
+ ║ → qa-reviewer → qa-reporter ║
26
+ ║ ║
27
+ ║ Powered by playwright-cli + Claude ║
28
+ ║ ║
29
+ ╚══════════════════════════════════════════════════════════════╝
30
+ `);
31
+ // ─── Load .env ────────────────────────────────────────────────────────────────
32
+ try {
33
+ const { config } = await import("dotenv");
34
+ config();
35
+ }
36
+ catch { }
37
+ // ─── Parse args ───────────────────────────────────────────────────────────────
38
+ const args = process.argv.slice(2);
39
+ if (args.includes("--help") || args.includes("-h")) {
40
+ console.log(`Usage:
41
+ aiqa [url] [options]
42
+
43
+ Arguments:
44
+ url Website URL to analyse. Omit it to be prompted interactively.
45
+
46
+ Options:
47
+ --grep <tag> Run only tests matching tag (@smoke, @regression, @p0 etc.)
48
+ --skip <agents> Comma-separated steps to skip
49
+ --dir <path> Output directory (default: current directory)
50
+ --resume Resume a previous pipeline run
51
+ --force, --yes, -y Skip the confirmation before overwriting an existing
52
+ playwright.config.ts (for CI / unattended runs)
53
+ --open When run inside VS Code, open the generated requirements,
54
+ test plan and summary report in Markdown preview
55
+ --verbose Show tool call details
56
+
57
+ Existing requirements (optional):
58
+ Place an existing requirements .md file in .aiqa/requirements/ before running.
59
+ The analyst will still explore the site, then MERGE your document with the newly
60
+ discovered requirements into .aiqa/requirements/requirements.md.
61
+
62
+ Config file (optional):
63
+ Drop an aiqa.config.ts (or .mjs/.js/.json) in the project root to set defaults for
64
+ any flag, the Claude model, and the .aiqa folder/subfolder names. CLI flags win.
65
+ import { defineConfig } from "@agents-forge/aiqa";
66
+ export default defineConfig({ url: "https://my-app.com", model: "claude-sonnet-4-6" });
67
+
68
+ Examples:
69
+ aiqa (interactive: asks for the URL + existing requirements)
70
+ aiqa https://www.saucedemo.com
71
+ aiqa https://my-app.com --grep @smoke
72
+ aiqa https://my-app.com --grep @regression --dir ./aiqa-output
73
+ aiqa https://my-app.com --skip qa-reviewer,qa-reporter
74
+ aiqa https://my-app.com --resume
75
+
76
+ Pipeline steps:
77
+ analyst Explores site with playwright-cli, captures snapshots → requirements/requirements.md
78
+ qa-planner Reads requirements + snapshots → test-plan/test_plan.md
79
+ qa-engineer Generates test cases + Playwright scripts (snapshot-aware) → test-scripts/
80
+ qa-reviewer Validates selectors against snapshots → reports/review_report.md
81
+ qa-reporter Runs tests, captures failure snapshots → reports/summary_report.md
82
+
83
+ Prerequisites:
84
+ npm install -g @playwright/cli@latest
85
+ playwright-cli install --skills
86
+ npx playwright install chromium
87
+
88
+ Authentication (auto-detected):
89
+ 1. ANTHROPIC_API_KEY in .env
90
+ 2. claude login
91
+ 3. gh auth login
92
+ `);
93
+ process.exit(0);
94
+ }
95
+ // Parse flags
96
+ const getFlag = (flag) => {
97
+ const idx = args.indexOf(flag);
98
+ return idx !== -1 ? args[idx + 1] : undefined;
99
+ };
100
+ // ─── Config file (aiqa.config.ts) ────────────────────────────────────────────
101
+ // CLI flags override config-file values, which override built-in defaults.
102
+ const flagDir = getFlag("--dir");
103
+ const { config: cfg, file: cfgFile } = await loadConfig(flagDir ?? process.cwd());
104
+ if (cfgFile)
105
+ console.log(`🛠️ Loaded config: ${path.basename(cfgFile)}`);
106
+ const grep = getFlag("--grep") ?? cfg.grep;
107
+ const cwd = flagDir ?? cfg.dir ?? process.cwd();
108
+ const verbose = args.includes("--verbose") || !!cfg.verbose;
109
+ const resume = args.includes("--resume") || !!cfg.resume;
110
+ const force = args.includes("--force") || args.includes("--yes") || args.includes("-y") || !!cfg.force;
111
+ const open = args.includes("--open") || !!cfg.open;
112
+ const model = cfg.model;
113
+ const paths = cfg.paths;
114
+ const resolved = resolvePaths(paths);
115
+ const validAgents = ["analyst", "qa-planner", "qa-engineer", "qa-reviewer", "qa-reporter"];
116
+ const skipRaw = getFlag("--skip");
117
+ const skip = skipRaw
118
+ ? skipRaw.split(",").map((s) => s.trim()).filter((s) => validAgents.includes(s))
119
+ : (cfg.skip ?? []);
120
+ // ─── Interactive prompts ────────────────────────────────────────────────────────
121
+ async function ask(question) {
122
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
123
+ try {
124
+ return (await rl.question(question)).trim();
125
+ }
126
+ finally {
127
+ rl.close();
128
+ }
129
+ }
130
+ // Create the requirements drop-folder up front so users can place an existing doc there.
131
+ const reqDir = path.join(cwd, resolved.base, resolved.requirements);
132
+ fs.mkdirSync(reqDir, { recursive: true });
133
+ const reqDirLabel = path.relative(cwd, reqDir) || reqDir;
134
+ // Target URL: positional argument, config `url`, or ask for it interactively.
135
+ let target = args[0] && !args[0].startsWith("-") ? args[0] : cfg.url;
136
+ const interactive = !target;
137
+ if (!target) {
138
+ target = await ask("🔗 Please enter the URL to analyse: ");
139
+ if (!target) {
140
+ console.error("❌ No URL provided — nothing to analyse.");
141
+ process.exit(1);
142
+ }
143
+ }
144
+ // Existing requirements doc (optional). The user drops a .md in .aiqa/requirements/.
145
+ if (interactive) {
146
+ await ask(`📄 If you have an existing requirements document, put the .md file in '${reqDirLabel}' ` +
147
+ `now, then press Enter (or just press Enter to skip): `);
148
+ }
149
+ const allMd = fs.existsSync(reqDir)
150
+ ? fs.readdirSync(reqDir).filter((f) => f.toLowerCase().endsWith(".md"))
151
+ : [];
152
+ // Prefer any doc that isn't named like our generated output. If the user named
153
+ // their file requirements.md (fresh run only), still pick it up — runAIQA will
154
+ // preserve it before writing the merged output.
155
+ let chosen = allMd.find((f) => f !== "requirements.md");
156
+ if (!chosen && !resume && allMd.includes("requirements.md"))
157
+ chosen = "requirements.md";
158
+ const existingRequirements = chosen ? path.join(reqDir, chosen) : cfg.existingRequirements;
159
+ if (existingRequirements) {
160
+ console.log(` ↳ Existing requirements detected: ${chosen} — the analyst will merge it with what it discovers.`);
161
+ }
162
+ else if (interactive) {
163
+ console.log(" ↳ No existing requirements — the analyst will build them from exploration.");
164
+ }
165
+ // ─── Auth ─────────────────────────────────────────────────────────────────────
166
+ const provider = detectProvider();
167
+ console.log(`🔐 Auth: ${provider}`);
168
+ if (provider === "anthropic" && !process.env.ANTHROPIC_API_KEY && !process.env.ANTHROPIC_AUTH_TOKEN) {
169
+ console.log("ℹ️ No API key — trying claude login session...");
170
+ }
171
+ // ─── Run ──────────────────────────────────────────────────────────────────────
172
+ try {
173
+ const result = await runAIQA({ target, grep, skip, cwd, verbose, resume, force, existingRequirements, open, model, paths });
174
+ const icon = result.passed ? "✅" : "⚠️";
175
+ const duration = Math.floor(result.totalDuration / 1000);
176
+ console.log(`\n${icon} AIQA complete in ${duration}s`);
177
+ console.log(`📄 Session: ${result.sessionFile}`);
178
+ console.log(`\n💡 Next steps:`);
179
+ console.log(` npx playwright test --ui (run the tests in UI mode)`);
180
+ console.log(` npx playwright show-report .aiqa/reports/playwright-report (view the last HTML report)`);
181
+ console.log(` npx @agents-forge/aiqa ${target} --resume (resume if needed)`);
182
+ process.exit(result.passed ? 0 : 1);
183
+ }
184
+ catch (err) {
185
+ console.error(`\n❌ ${err.message}`);
186
+ if (!process.env.ANTHROPIC_API_KEY) {
187
+ console.error(`
188
+ No authentication found:
189
+ Option 1: ANTHROPIC_API_KEY=sk-ant-... in .env
190
+ Option 2: claude login
191
+ Option 3: gh auth login`);
192
+ }
193
+ process.exit(1);
194
+ }
195
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ export type AgentId = "analyst" | "qa-planner" | "qa-engineer" | "qa-reviewer" | "qa-reporter";
2
+ /** Configurable .aiqa base + subfolder names. */
3
+ export interface AIQAPaths {
4
+ /** Base output folder. Default ".aiqa" */
5
+ base?: string;
6
+ /** Requirements folder. Default "requirements" */
7
+ requirements?: string;
8
+ /** Test plan folder. Default "test-plan" */
9
+ plan?: string;
10
+ /** Test cases folder. Default "test-cases" */
11
+ testCases?: string;
12
+ /** Spec files folder. Default "test-scripts" */
13
+ testScripts?: string;
14
+ /** Reports folder. Default "reports" */
15
+ reports?: string;
16
+ }
17
+ /**
18
+ * aiqa.config.ts shape. Every field is optional — CLI flags always override
19
+ * what's set here, which overrides the built-in defaults.
20
+ */
21
+ export interface AIQAConfig {
22
+ /** Default URL to analyse (skips the interactive prompt). */
23
+ url?: string;
24
+ /** Default test tag filter, e.g. "@smoke". */
25
+ grep?: string;
26
+ /** Subagents to skip. */
27
+ skip?: AgentId[];
28
+ /** Resume a previous run by default. */
29
+ resume?: boolean;
30
+ /** Skip the playwright.config.ts overwrite confirmation. */
31
+ force?: boolean;
32
+ /** Open the generated docs in VS Code Markdown preview after the run. */
33
+ open?: boolean;
34
+ /** Verbose tool logging. */
35
+ verbose?: boolean;
36
+ /** Output directory (where .aiqa/ is created). Default: cwd. */
37
+ dir?: string;
38
+ /** Path to an existing requirements .md to merge in. */
39
+ existingRequirements?: string;
40
+ /** Claude model id, e.g. "claude-sonnet-4-6". */
41
+ model?: string;
42
+ /** Override the .aiqa base + subfolder names. */
43
+ paths?: AIQAPaths;
44
+ }
45
+ export declare const DEFAULT_PATHS: Required<AIQAPaths>;
46
+ /** Typed helper for authoring aiqa.config.ts. */
47
+ export declare function defineConfig(config: AIQAConfig): AIQAConfig;
48
+ /** Apply defaults to a partial paths config. */
49
+ export declare function resolvePaths(paths?: AIQAPaths): Required<AIQAPaths>;
50
+ /**
51
+ * Find and load aiqa.config.{ts,mts,mjs,js,json} from `dir`.
52
+ * .ts/.js/.mjs are loaded via jiti (no build step); .json is parsed directly.
53
+ * Returns {} when no config file is present.
54
+ */
55
+ export declare function loadConfig(dir: string): Promise<{
56
+ config: AIQAConfig;
57
+ file?: string;
58
+ }>;
59
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,aAAa,GAAG,aAAa,GAAG,aAAa,CAAC;AAE/F,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IAEzB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,SAAS,CAO7C,CAAC;AAEF,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAE3D;AAED,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAEnE;AAUD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkB5F"}
package/dist/config.js ADDED
@@ -0,0 +1,53 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { createJiti } from "jiti";
4
+ export const DEFAULT_PATHS = {
5
+ base: ".aiqa",
6
+ requirements: "requirements",
7
+ plan: "test-plan",
8
+ testCases: "test-cases",
9
+ testScripts: "test-scripts",
10
+ reports: "reports",
11
+ };
12
+ /** Typed helper for authoring aiqa.config.ts. */
13
+ export function defineConfig(config) {
14
+ return config;
15
+ }
16
+ /** Apply defaults to a partial paths config. */
17
+ export function resolvePaths(paths) {
18
+ return { ...DEFAULT_PATHS, ...(paths ?? {}) };
19
+ }
20
+ const CONFIG_NAMES = [
21
+ "aiqa.config.ts",
22
+ "aiqa.config.mts",
23
+ "aiqa.config.mjs",
24
+ "aiqa.config.js",
25
+ "aiqa.config.json",
26
+ ];
27
+ /**
28
+ * Find and load aiqa.config.{ts,mts,mjs,js,json} from `dir`.
29
+ * .ts/.js/.mjs are loaded via jiti (no build step); .json is parsed directly.
30
+ * Returns {} when no config file is present.
31
+ */
32
+ export async function loadConfig(dir) {
33
+ for (const name of CONFIG_NAMES) {
34
+ const file = path.join(dir, name);
35
+ if (!fs.existsSync(file))
36
+ continue;
37
+ try {
38
+ if (name.endsWith(".json")) {
39
+ return { config: JSON.parse(fs.readFileSync(file, "utf-8")), file };
40
+ }
41
+ const jiti = createJiti(import.meta.url);
42
+ const mod = await jiti.import(file);
43
+ const config = (mod?.default ?? mod ?? {});
44
+ return { config, file };
45
+ }
46
+ catch (err) {
47
+ console.log(`⚠️ Failed to load ${name}: ${err?.message ?? err}`);
48
+ return { config: {} };
49
+ }
50
+ }
51
+ return { config: {} };
52
+ }
53
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAoDlC,MAAM,CAAC,MAAM,aAAa,GAAwB;IAChD,IAAI,EAAE,OAAO;IACb,YAAY,EAAE,cAAc;IAC5B,IAAI,EAAE,WAAW;IACjB,SAAS,EAAE,YAAY;IACvB,WAAW,EAAE,cAAc;IAC3B,OAAO,EAAE,SAAS;CACnB,CAAC;AAEF,iDAAiD;AACjD,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,YAAY,GAAG;IACnB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB;CACnB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAe,EAAE,IAAI,EAAE,CAAC;YACpF,CAAC;YACD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,GAAG,GAAQ,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,OAAO,IAAI,GAAG,IAAI,EAAE,CAAe,CAAC;YACzD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,KAAK,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;YAClE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @agents-forge/aiqa
3
+ *
4
+ * Single unified AI Quality Engineering Pipeline.
5
+ * One Claude session — analyst → qa-planner → qa-engineer → qa-reviewer → qa-reporter
6
+ * Context flows in memory. playwright-cli captures snapshots used across all steps.
7
+ *
8
+ * Usage:
9
+ * import { runAIQA } from "@agents-forge/aiqa";
10
+ * await runAIQA({ target: "https://my-app.com", grep: "@smoke" });
11
+ */
12
+ export { runAIQA, detectProvider } from "./agent.js";
13
+ export { SessionManager } from "./session.js";
14
+ export { defineConfig, loadConfig, resolvePaths } from "./config.js";
15
+ export type { AIQAInput, AIQAResult, Provider } from "./agent.js";
16
+ export type { Session, Snapshot, PipelineStatus } from "./session.js";
17
+ export type { AIQAConfig, AIQAPaths, AgentId } from "./config.js";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @agents-forge/aiqa
3
+ *
4
+ * Single unified AI Quality Engineering Pipeline.
5
+ * One Claude session — analyst → qa-planner → qa-engineer → qa-reviewer → qa-reporter
6
+ * Context flows in memory. playwright-cli captures snapshots used across all steps.
7
+ *
8
+ * Usage:
9
+ * import { runAIQA } from "@agents-forge/aiqa";
10
+ * await runAIQA({ target: "https://my-app.com", grep: "@smoke" });
11
+ */
12
+ export { runAIQA, detectProvider } from "./agent.js";
13
+ export { SessionManager } from "./session.js";
14
+ export { defineConfig, loadConfig, resolvePaths } from "./config.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { type AIQAPaths } from "./config.js";
2
+ export type PipelineStatus = "pending" | "in-progress" | "completed" | "failed" | "skipped";
3
+ export interface Snapshot {
4
+ page: string;
5
+ url: string;
6
+ filePath: string;
7
+ capturedAt: string;
8
+ }
9
+ export interface Session {
10
+ target: string;
11
+ runId: string;
12
+ baseUrl: string;
13
+ startedAt: string;
14
+ snapshots: Record<string, Snapshot>;
15
+ auth: {
16
+ type: "none" | "form" | "sso" | "cookies";
17
+ savedSession?: string;
18
+ };
19
+ outputs: {
20
+ requirements: string;
21
+ testPlan: string;
22
+ testCasesDir: string;
23
+ specsDir: string;
24
+ reviewReport: string;
25
+ summaryReport: string;
26
+ snapshotsDir: string;
27
+ sessionFile: string;
28
+ authState: string;
29
+ reportsDir: string;
30
+ testResultsDir: string;
31
+ playwrightConfig: string;
32
+ htmlReport: string;
33
+ };
34
+ pipeline: Record<string, PipelineStatus>;
35
+ modules: string[];
36
+ }
37
+ export declare class SessionManager {
38
+ private session;
39
+ private sessionPath;
40
+ constructor(workingDir: string, target: string, resume?: boolean, pathsConfig?: AIQAPaths);
41
+ get(): Session;
42
+ setStatus(step: string, status: PipelineStatus): void;
43
+ addSnapshot(page: string, url: string, filePath: string): void;
44
+ setModules(modules: string[]): void;
45
+ setAuth(auth: Session["auth"]): void;
46
+ isCompleted(step: string): boolean;
47
+ save(): void;
48
+ printStatus(): void;
49
+ }
50
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAI5D,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,aAAa,GACb,WAAW,GACX,QAAQ,GACR,SAAS,CAAC;AAEd,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;QAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAID,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAAS;gBAEhB,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAQ,EAAE,WAAW,GAAE,SAAc;IAsE3F,GAAG,IAAI,OAAO;IAEd,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc;IAK9C,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAKvD,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE;IAC5B,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;IAC7B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAElC,IAAI;IAIJ,WAAW;CAQZ"}
@@ -0,0 +1,99 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { DEFAULT_PATHS } from "./config.js";
4
+ // ─── Session manager ──────────────────────────────────────────────────────────
5
+ export class SessionManager {
6
+ session;
7
+ sessionPath;
8
+ constructor(workingDir, target, resume = false, pathsConfig = {}) {
9
+ const runId = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
10
+ const p = { ...DEFAULT_PATHS, ...pathsConfig };
11
+ const aiqaDir = path.join(workingDir, p.base);
12
+ const snapshotsDir = path.join(aiqaDir, "snapshots");
13
+ // Everything the pipeline produces lives under the base folder (.aiqa) so it
14
+ // never clutters the consumer's repo root. Only playwright.config.ts stays at
15
+ // the root, so `npx playwright test` can auto-discover it. Folder names are
16
+ // configurable via aiqa.config.ts → paths.
17
+ const reqDir = path.join(aiqaDir, p.requirements);
18
+ const planDir = path.join(aiqaDir, p.plan);
19
+ const testCasesDir = path.join(aiqaDir, p.testCases);
20
+ const specsDir = path.join(aiqaDir, p.testScripts);
21
+ const reportsDir = path.join(aiqaDir, p.reports);
22
+ const testResultsDir = path.join(reportsDir, "test-results");
23
+ let baseUrl = target;
24
+ try {
25
+ new URL(target);
26
+ }
27
+ catch {
28
+ baseUrl = "http://localhost:3000";
29
+ }
30
+ this.sessionPath = path.join(aiqaDir, "session.json");
31
+ if (resume && fs.existsSync(this.sessionPath)) {
32
+ const existing = JSON.parse(fs.readFileSync(this.sessionPath, "utf-8"));
33
+ if (existing.target === target) {
34
+ console.log(`\n♻️ Resuming existing session: ${existing.runId}`);
35
+ this.session = existing;
36
+ return;
37
+ }
38
+ }
39
+ this.session = {
40
+ target,
41
+ runId,
42
+ baseUrl,
43
+ startedAt: new Date().toISOString(),
44
+ snapshots: {},
45
+ auth: { type: "none" },
46
+ outputs: {
47
+ requirements: path.join(reqDir, "requirements.md"),
48
+ testPlan: path.join(planDir, "test_plan.md"),
49
+ testCasesDir,
50
+ specsDir,
51
+ reviewReport: path.join(reportsDir, "review_report.md"),
52
+ summaryReport: path.join(reportsDir, "summary_report.md"),
53
+ snapshotsDir,
54
+ sessionFile: this.sessionPath,
55
+ authState: path.join(aiqaDir, "auth-state.json"),
56
+ reportsDir,
57
+ testResultsDir,
58
+ playwrightConfig: path.join(workingDir, "playwright.config.ts"),
59
+ htmlReport: path.join(reportsDir, "playwright-report", "index.html"),
60
+ },
61
+ pipeline: {
62
+ analyst: "pending",
63
+ "qa-planner": "pending",
64
+ "qa-engineer": "pending",
65
+ "qa-reviewer": "pending",
66
+ "qa-reporter": "pending",
67
+ },
68
+ modules: [],
69
+ };
70
+ for (const dir of [snapshotsDir, reqDir, planDir, testCasesDir, specsDir, reportsDir, testResultsDir]) {
71
+ fs.mkdirSync(dir, { recursive: true });
72
+ }
73
+ this.save();
74
+ }
75
+ get() { return this.session; }
76
+ setStatus(step, status) {
77
+ this.session.pipeline[step] = status;
78
+ this.save();
79
+ }
80
+ addSnapshot(page, url, filePath) {
81
+ this.session.snapshots[page] = { page, url, filePath, capturedAt: new Date().toISOString() };
82
+ this.save();
83
+ }
84
+ setModules(modules) { this.session.modules = modules; this.save(); }
85
+ setAuth(auth) { this.session.auth = auth; this.save(); }
86
+ isCompleted(step) { return this.session.pipeline[step] === "completed"; }
87
+ save() {
88
+ fs.writeFileSync(this.sessionPath, JSON.stringify(this.session, null, 2), "utf-8");
89
+ }
90
+ printStatus() {
91
+ console.log("\n📊 Pipeline status:");
92
+ for (const [step, status] of Object.entries(this.session.pipeline)) {
93
+ const icon = status === "completed" ? "✅" : status === "failed" ? "❌" :
94
+ status === "in-progress" ? "🔄" : status === "skipped" ? "⏭️" : "⬜";
95
+ console.log(` ${icon} ${step}`);
96
+ }
97
+ }
98
+ }
99
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Session } from "../session.js";
2
+ export declare function buildAnalystPrompt(session: Session, existingRequirements?: string): string;
3
+ //# sourceMappingURL=analyst.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyst.d.ts","sourceRoot":"","sources":["../../src/subagents/analyst.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CA8F1F"}
@@ -0,0 +1,96 @@
1
+ export function buildAnalystPrompt(session, existingRequirements) {
2
+ return `You are acting as a Senior Business Analyst with 15+ years experience.
3
+
4
+ TARGET: "${session.target}"
5
+ SNAPSHOTS DIR: "${session.outputs.snapshotsDir}"
6
+ OUTPUT: "${session.outputs.requirements}"
7
+ ${existingRequirements ? `EXISTING REQUIREMENTS DOC: "${existingRequirements}"` : ""}
8
+ ${existingRequirements ? `
9
+ ## ⚠️ An existing requirements document was provided
10
+ Before you start exploring, use the Read tool to read the existing document:
11
+ "${existingRequirements}"
12
+ You will STILL fully explore the site below. Afterwards you will MERGE the existing
13
+ document with what you discover (see Phase 2) — never just copy it, and never discard it.
14
+ ` : ""}
15
+ ## Phase 1 — Explore with playwright-cli
16
+
17
+ Use the Bash tool to run playwright-cli commands.
18
+
19
+ ### 1. Open the target
20
+ \`\`\`bash
21
+ playwright-cli open "${session.target}"
22
+ \`\`\`
23
+
24
+ ### 2. For EACH page/state you visit:
25
+ a) Capture a snapshot and save it:
26
+ \`\`\`bash
27
+ playwright-cli snapshot > "${session.outputs.snapshotsDir}/<page-name>.yml"
28
+ \`\`\`
29
+ Use descriptive names: home.yml, login.yml, product-list.yml, cart.yml, checkout.yml etc.
30
+
31
+ b) Navigate to next page or state:
32
+ \`\`\`bash
33
+ playwright-cli click <ref> # click a button/link using ref from snapshot
34
+ playwright-cli navigate <url> # go to a specific URL
35
+ playwright-cli fill <ref> <value> # fill a form field
36
+ \`\`\`
37
+
38
+ ### 3. Explore ALL key areas:
39
+ - Home / landing page
40
+ - Navigation structure (every menu item)
41
+ - Authentication flows (login, register, forgot password)
42
+ - Core user journeys (search, add to cart, checkout, profile etc.)
43
+ - Error states (invalid login, empty forms, 404)
44
+ - Any modal dialogs or overlays
45
+
46
+ ### 4. If you hit a login wall:
47
+ Use AskFollowup to ask the user for credentials, then:
48
+ \`\`\`bash
49
+ playwright-cli fill <username-ref> "username"
50
+ playwright-cli fill <password-ref> "password"
51
+ playwright-cli click <submit-ref>
52
+ playwright-cli snapshot > "${session.outputs.snapshotsDir}/post-login.yml"
53
+ \`\`\`
54
+
55
+ ### 5. Save auth state if logged in:
56
+ \`\`\`bash
57
+ playwright-cli storage-state > "${session.outputs.authState}"
58
+ \`\`\`
59
+
60
+ ## Phase 2 — Write requirements.md
61
+ ${existingRequirements ? `
62
+ ### MERGE MODE (an existing requirements document was provided)
63
+ Write "${session.outputs.requirements}" as a clearly-sectioned MERGE. Do NOT ask the user —
64
+ merge automatically. Start the document with these two top-level parts BEFORE the standard
65
+ sections below:
66
+
67
+ > **## Part A — Existing Requirements (carried over)**
68
+ > Faithfully include / normalise every requirement from the provided document. Do not drop any.
69
+ > Tag each line with \`[existing]\`.
70
+ >
71
+ > **## Part B — Newly Discovered Requirements (addon from exploration)**
72
+ > The requirements you found by exploring the site that are NOT already covered in Part A.
73
+ > Tag each line with \`[discovered]\`.
74
+ >
75
+ > Then continue with the standard numbered sections below, drawing from BOTH parts.
76
+ ` : ""}
77
+ After exploration write "${session.outputs.requirements}" with these sections:
78
+
79
+ 1. **Executive Summary** — what this product does in plain language
80
+ 2. **Stakeholders & User Roles** — who uses it and their goals
81
+ 3. **User Journeys & Flows** — reference ACTUAL pages you visited with URLs
82
+ 4. **Functional Requirements** — MoSCoW table (FR-001, FR-002...)
83
+ 5. **Non-Functional Requirements** — performance, security, a11y (NFR-001...)
84
+ 6. **Data Requirements** — what data is created/read/updated/deleted
85
+ 7. **Integration Points** — APIs, third-party services spotted
86
+ 8. **Snapshot Index** — list every snapshot file captured with its URL
87
+ 9. **Assumptions & Constraints**
88
+ 10. **Open Questions**
89
+
90
+ ## Quality standards
91
+ - Reference REAL pages and element names from snapshots — not guessed
92
+ - Every requirement must be numbered (FR-001, NFR-001)
93
+ - User journeys must reference actual URLs you visited
94
+ - The snapshot index must list every .yml file saved`;
95
+ }
96
+ //# sourceMappingURL=analyst.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyst.js","sourceRoot":"","sources":["../../src/subagents/analyst.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,OAAgB,EAAE,oBAA6B;IAChF,OAAO;;WAEE,OAAO,CAAC,MAAM;kBACP,OAAO,CAAC,OAAO,CAAC,YAAY;WACnC,OAAO,CAAC,OAAO,CAAC,YAAY;EACrC,oBAAoB,CAAC,CAAC,CAAC,+BAA+B,oBAAoB,GAAG,CAAC,CAAC,CAAC,EAAE;EAClF,oBAAoB,CAAC,CAAC,CAAC;;;GAGtB,oBAAoB;;;CAGtB,CAAC,CAAC,CAAC,EAAE;;;;;;;uBAOiB,OAAO,CAAC,MAAM;;;;;;6BAMR,OAAO,CAAC,OAAO,CAAC,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;6BAyB5B,OAAO,CAAC,OAAO,CAAC,YAAY;;;;;kCAKvB,OAAO,CAAC,OAAO,CAAC,SAAS;;;;EAIzD,oBAAoB,CAAC,CAAC,CAAC;;SAEhB,OAAO,CAAC,OAAO,CAAC,YAAY;;;;;;;;;;;;;CAapC,CAAC,CAAC,CAAC,EAAE;2BACqB,OAAO,CAAC,OAAO,CAAC,YAAY;;;;;;;;;;;;;;;;;qDAiBF,CAAC;AACtD,CAAC"}