@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.
- package/CLAUDE.md +112 -0
- package/README.md +281 -0
- package/dist/agent.d.ts +41 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +485 -0
- package/dist/agent.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +195 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +59 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/session.d.ts +50 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +99 -0
- package/dist/session.js.map +1 -0
- package/dist/subagents/analyst.d.ts +3 -0
- package/dist/subagents/analyst.d.ts.map +1 -0
- package/dist/subagents/analyst.js +96 -0
- package/dist/subagents/analyst.js.map +1 -0
- package/dist/subagents/qa-engineer.d.ts +4 -0
- package/dist/subagents/qa-engineer.d.ts.map +1 -0
- package/dist/subagents/qa-engineer.js +139 -0
- package/dist/subagents/qa-engineer.js.map +1 -0
- package/dist/subagents/qa-planner.d.ts +3 -0
- package/dist/subagents/qa-planner.d.ts.map +1 -0
- package/dist/subagents/qa-planner.js +69 -0
- package/dist/subagents/qa-planner.js.map +1 -0
- package/dist/subagents/qa-reporter.d.ts +4 -0
- package/dist/subagents/qa-reporter.d.ts.map +1 -0
- package/dist/subagents/qa-reporter.js +94 -0
- package/dist/subagents/qa-reporter.js.map +1 -0
- package/dist/subagents/qa-reviewer.d.ts +3 -0
- package/dist/subagents/qa-reviewer.d.ts.map +1 -0
- package/dist/subagents/qa-reviewer.js +97 -0
- package/dist/subagents/qa-reviewer.js.map +1 -0
- 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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/session.js
ADDED
|
@@ -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 @@
|
|
|
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"}
|