@arcadialdev/arcality 3.0.4 → 4.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/README.md +75 -6
- package/bin/arcality.mjs +26 -17
- package/package.json +2 -1
- package/playwright.config.js +22 -21
- package/scripts/gen-and-run.mjs +2610 -2608
- package/scripts/generate.mjs +215 -0
- package/scripts/init.mjs +278 -253
- package/scripts/rebrand-report.mjs +19 -18
- package/src/configManager.mjs +57 -51
- package/src/services/codebaseAnalyzer.mjs +59 -0
- package/src/services/generatedMissionSchema.mjs +76 -0
- package/src/services/generatedMissionStore.mjs +117 -0
- package/src/services/generationContext.mjs +242 -0
- package/src/services/missionGenerator.mjs +328 -0
- package/src/services/routeDiscovery.mjs +747 -0
- package/src/testRunner.ts +2 -1
- package/tests/_helpers/agentic-runner.bundle.spec.js +401 -60
package/README.md
CHANGED
|
@@ -53,11 +53,44 @@ Run the following to get the latest version:
|
|
|
53
53
|
npm update @arcadialdev/arcality
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
### ⚙️ Configuration (`arcality.config.json`)
|
|
57
|
-
After initializing with `npx arcality init`, a config file is created in the project root. Edit it to set your project name, base URL, and authentication details. The CLI reads this file on every run, ensuring consistent environment variables.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
### ⚙️ Configuration (`arcality.config.json`)
|
|
57
|
+
After initializing with `npx arcality init`, a config file is created in the project root. Edit it to set your project name, base URL, and authentication details. The CLI reads this file on every run, ensuring consistent environment variables.
|
|
58
|
+
|
|
59
|
+
### QA Context Governance
|
|
60
|
+
Arcality can load local business rules from `.arcality/qa-context.md` and governance metadata from `.arcality/qa-context.meta.json`.
|
|
61
|
+
|
|
62
|
+
The effective precedence order is:
|
|
63
|
+
|
|
64
|
+
1. Local `qa-context.md`
|
|
65
|
+
2. Backend collective memory
|
|
66
|
+
3. Base QA heuristics
|
|
67
|
+
|
|
68
|
+
If local business rules conflict with backend memory, Arcality now prioritizes the local file.
|
|
69
|
+
|
|
70
|
+
Example `.arcality/qa-context.meta.json`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"version": "1.0.0",
|
|
75
|
+
"updated_by": "qa.owner@company.com",
|
|
76
|
+
"approved_by": "qa.lead@company.com",
|
|
77
|
+
"owner_team": "QA",
|
|
78
|
+
"effective_from": "2026-06-15",
|
|
79
|
+
"change_summary": "Initial governance metadata for customer-specific QA rules.",
|
|
80
|
+
"tags": ["business-rules", "ui-navigation"]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Governance enforcement modes:
|
|
85
|
+
|
|
86
|
+
- `ARCALITY_QA_CONTEXT_GOVERNANCE=off`: disables governance checks
|
|
87
|
+
- `ARCALITY_QA_CONTEXT_GOVERNANCE=warn`: reports warnings but does not block execution
|
|
88
|
+
- `ARCALITY_QA_CONTEXT_GOVERNANCE=strict`: blocks execution when `qa-context.md` exists but governance metadata is missing or incomplete
|
|
89
|
+
|
|
90
|
+
In CI, Arcality defaults to `strict` governance mode unless you override `ARCALITY_QA_CONTEXT_GOVERNANCE`.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
---
|
|
61
94
|
|
|
62
95
|
## 💻 CLI Commands Cheatsheet
|
|
63
96
|
|
|
@@ -65,8 +98,10 @@ The Arcality flow is designed to be used globally or project-wide via `npx`. Bel
|
|
|
65
98
|
|
|
66
99
|
| Command | Description | Internal Behavior |
|
|
67
100
|
| :--- | :--- | :--- |
|
|
68
|
-
| `npx arcality` | **Interactive Menu**<br/>Launches a visual menu in the terminal to guide the user. | Prompts for the Mission to execute. Ideal for new users who want a guided experience. |
|
|
101
|
+
| `npx arcality` | **Interactive Menu**<br/>Launches a visual menu in the terminal to guide the user. | Prompts for the Mission to execute. Ideal for new users who want a guided experience. |
|
|
69
102
|
| `npx arcality init` | **Initial Configuration**<br/>Connects the current project to Arcadial. | Prompts for your API Key and Project ID, generates `arcality.config.json`, and validates the portal connection. |
|
|
103
|
+
| `npx arcality generate --dry-run` | **Dynamic Mission Discovery**<br/>Inspects the target codebase and previews the routes/pages that can become generated missions. | Runs framework detection, route discovery, context-aware mission planning, and prints a dry-run summary without writing YAML files. |
|
|
104
|
+
| `npx arcality generate --count 5` | **Generated Mission Writer**<br/>Creates YAML missions automatically from the discovered routes. | Generates validated Arcality YAML missions, deduplicates existing output, and stores cache metadata in `.arcality/cache/generate-state.json`. |
|
|
70
105
|
| `npx arcality run` | **Mission Runner (Agent Mode)**<br/>Launches the QA Agent directly. | Skips the interactive menu, scans the _package.json_ ("Ghost Mode"), and unleashes the AI agent. Ideal for CI/CD. |
|
|
71
106
|
| `npx arcality logs` | **Mission Logs**<br/>Shows the last 3 executed missions in a concise QA-friendly format. | Reads the local `.arcality/out` mission summaries and displays result, failure reason, last relevant steps, and report path. |
|
|
72
107
|
|
|
@@ -76,6 +111,40 @@ When running a saved collection from the interactive CLI, Arcality can execute m
|
|
|
76
111
|
|
|
77
112
|
Parallel execution opens multiple independent browser sessions. Arcality cannot validate the tested portal's internal session rules, user lock policies, shared test data constraints, or limits for multiple logins with the same account. If the portal does not support parallel sessions safely, run the collection sequentially with concurrency `1`.
|
|
78
113
|
|
|
114
|
+
### `generate` command
|
|
115
|
+
|
|
116
|
+
`npx arcality generate` is the mission-generation entrypoint. It analyzes the current codebase, discovers supported routes, enriches them with route signals, and writes Arcality mission YAML files under the configured output directory.
|
|
117
|
+
|
|
118
|
+
Examples:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npx arcality generate --dry-run
|
|
122
|
+
npx arcality generate --count 5
|
|
123
|
+
npx arcality generate --page "/users,/settings" --count 4
|
|
124
|
+
npx arcality generate --page "/checkout" --prompt "focus on validation and payment edge cases"
|
|
125
|
+
npx arcality generate --output-dir ".arcality/generated-review"
|
|
126
|
+
npx arcality generate --debug
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Current behavior:
|
|
130
|
+
|
|
131
|
+
- Supports automatic discovery for `Next.js`, `React Router` object configs, `React Router` nested JSX routes, and filesystem fallbacks for simpler SPA layouts.
|
|
132
|
+
- Detects route metadata such as dynamic params, example paths, and route families.
|
|
133
|
+
- Applies optional customer guidance from `.arcality/qa-context.md` and governance metadata from `.arcality/qa-context.meta.json`.
|
|
134
|
+
- Generates only the most useful route variants to reduce noise.
|
|
135
|
+
- Validates every generated mission against the Arcality mission schema before writing files.
|
|
136
|
+
- Deduplicates previously generated missions by mission identity.
|
|
137
|
+
|
|
138
|
+
Notes:
|
|
139
|
+
|
|
140
|
+
- `--prompt` is supported and refines the generated mission focus.
|
|
141
|
+
- `--page` accepts route fragments or exact route values.
|
|
142
|
+
- Generated missions are written under `<yamlOutputDir>/generated` by default.
|
|
143
|
+
- Local cache metadata is stored in `.arcality/cache/generate-state.json`.
|
|
144
|
+
- Regression coverage for this command is available through `npm.cmd run test:generate` on Windows or `npm run test:generate` where shell policy allows it.
|
|
145
|
+
|
|
146
|
+
- Discovery and mission generation are covered by regression tests.
|
|
147
|
+
|
|
79
148
|
|
|
80
149
|
---
|
|
81
150
|
|
package/bin/arcality.mjs
CHANGED
|
@@ -12,36 +12,45 @@ const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
|
12
12
|
// REFUERZO DE ARGUMENTOS: Capturamos TODO lo que venga de la consola
|
|
13
13
|
const rawArgs = process.argv.slice(2);
|
|
14
14
|
let isRun = false;
|
|
15
|
-
let isInit = false;
|
|
16
|
-
let isSetup = false;
|
|
17
|
-
let isLogs = false;
|
|
18
|
-
let isRunAll = false; // CI/CD mode: runs all missions from API headlessly
|
|
15
|
+
let isInit = false;
|
|
16
|
+
let isSetup = false;
|
|
17
|
+
let isLogs = false;
|
|
18
|
+
let isRunAll = false; // CI/CD mode: runs all missions from API headlessly
|
|
19
|
+
let isGenerate = false;
|
|
19
20
|
|
|
20
21
|
// Buscamos los comandos en cualquier posición para evitar filtros de NPM en Windows
|
|
21
22
|
rawArgs.forEach(arg => {
|
|
22
|
-
if (arg === 'run') isRun = true;
|
|
23
|
-
if (arg === 'init') isInit = true;
|
|
24
|
-
if (arg === 'setup') isSetup = true;
|
|
23
|
+
if (arg === 'run') isRun = true;
|
|
24
|
+
if (arg === 'init') isInit = true;
|
|
25
|
+
if (arg === 'setup') isSetup = true;
|
|
25
26
|
if (arg === 'logs') isLogs = true;
|
|
26
27
|
if (arg === '--logs') isLogs = true;
|
|
27
28
|
if (arg === '--run-all') isRunAll = true;
|
|
29
|
+
if (arg === 'generate') isGenerate = true;
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
if (isLogs) {
|
|
31
|
-
const logsScript = path.join(PACKAGE_ROOT, 'scripts', 'arcality-logs.mjs');
|
|
32
|
-
spawn('node', [logsScript, ...rawArgs.filter(a => a !== 'logs' && a !== '--logs')], {
|
|
33
|
+
const logsScript = path.join(PACKAGE_ROOT, 'scripts', 'arcality-logs.mjs');
|
|
34
|
+
spawn('node', [logsScript, ...rawArgs.filter(a => a !== 'logs' && a !== '--logs')], {
|
|
33
35
|
stdio: 'inherit',
|
|
34
36
|
cwd: process.cwd(),
|
|
35
37
|
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
36
38
|
}).on('exit', code => process.exit(code || 0));
|
|
37
|
-
} else if (isInit) {
|
|
38
|
-
const initScript = path.join(PACKAGE_ROOT, 'scripts', 'init.mjs');
|
|
39
|
-
spawn('node', [initScript, ...rawArgs.filter(a => a !== 'init')], {
|
|
40
|
-
stdio: 'inherit',
|
|
41
|
-
cwd: process.cwd(),
|
|
42
|
-
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
43
|
-
}).on('exit', code => process.exit(code || 0));
|
|
44
|
-
} else if (
|
|
39
|
+
} else if (isInit) {
|
|
40
|
+
const initScript = path.join(PACKAGE_ROOT, 'scripts', 'init.mjs');
|
|
41
|
+
spawn('node', [initScript, ...rawArgs.filter(a => a !== 'init')], {
|
|
42
|
+
stdio: 'inherit',
|
|
43
|
+
cwd: process.cwd(),
|
|
44
|
+
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
45
|
+
}).on('exit', code => process.exit(code || 0));
|
|
46
|
+
} else if (isGenerate) {
|
|
47
|
+
const generateScript = path.join(PACKAGE_ROOT, 'scripts', 'generate.mjs');
|
|
48
|
+
spawn('node', [generateScript, ...rawArgs.filter(a => a !== 'generate')], {
|
|
49
|
+
stdio: 'inherit',
|
|
50
|
+
cwd: process.cwd(),
|
|
51
|
+
env: { ...process.env, ARCALITY_ROOT: PACKAGE_ROOT }
|
|
52
|
+
}).on('exit', code => process.exit(code || 0));
|
|
53
|
+
} else if (isRunAll) {
|
|
45
54
|
// CI/CD HEADLESS MODE: Descarga y ejecuta todas las misiones del proyecto desde la API
|
|
46
55
|
// Uso: arcality --run-all [--workers=4] [--tags=smoke,regression] [--project-id=xxx]
|
|
47
56
|
const mainScript = path.join(PACKAGE_ROOT, 'scripts', 'gen-and-run.mjs');
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcadialdev/arcality",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "El primer ingeniero QA Autónomo integrado al CI/CD. Creado por Arcadial.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "node scripts/gen-and-run.mjs",
|
|
8
8
|
"arcality": "node scripts/gen-and-run.mjs",
|
|
9
|
+
"test:generate": "node --test tests/generate/*.test.mjs",
|
|
9
10
|
"postinstall": "node scripts/postinstall.mjs",
|
|
10
11
|
"setup": "node scripts/setup.mjs",
|
|
11
12
|
"build:runner": "npx esbuild tests/_helpers/agentic-runner.spec.ts --bundle --platform=node --target=node18 --format=cjs --external:@playwright/test --external:chalk --external:dotenv --external:node-fetch --external:js-yaml --external:axios --external:crypto --external:fs --external:path --outfile=tests/_helpers/agentic-runner.bundle.spec.js",
|
package/playwright.config.js
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
// playwright.config.js
|
|
2
2
|
'use strict';
|
|
3
3
|
const { defineConfig, devices } = require('@playwright/test');
|
|
4
|
+
const os = require('os');
|
|
4
5
|
const path = require('path');
|
|
5
6
|
|
|
6
7
|
// ── Dynamic reporter: JUnit is added when running in CI (Azure DevOps, GitHub Actions) ──
|
|
7
8
|
// The JUnit XML file enables native test result publishing in your pipeline dashboard.
|
|
8
9
|
// In local/interactive mode, the JUnit reporter is skipped — only Arcality's HTML reporter runs.
|
|
9
|
-
const reportsDir = process.env.REPORTS_DIR || path.join(
|
|
10
|
-
const playwrightOutputDir = process.env.PLAYWRIGHT_OUTPUT_DIR || path.join(
|
|
11
|
-
const isCI = process.env.CI === 'true';
|
|
12
|
-
|
|
13
|
-
const reporters = [
|
|
14
|
-
['line'],
|
|
15
|
-
[path.join(__dirname, 'tests', '_helpers', 'ArcalityReporter.js'), { outputDir: reportsDir }],
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
if (isCI) {
|
|
19
|
-
reporters.push(['junit', { outputFile: path.join(reportsDir, 'results.xml') }]);
|
|
20
|
-
}
|
|
10
|
+
const reportsDir = process.env.REPORTS_DIR || path.join(os.tmpdir(), 'arcality', 'reports');
|
|
11
|
+
const playwrightOutputDir = process.env.PLAYWRIGHT_OUTPUT_DIR || path.join(os.tmpdir(), 'arcality', 'playwright-output');
|
|
12
|
+
const isCI = process.env.CI === 'true';
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
const reporters = [
|
|
15
|
+
['line'],
|
|
16
|
+
[path.join(__dirname, 'tests', '_helpers', 'ArcalityReporter.js'), { outputDir: reportsDir }],
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
if (isCI) {
|
|
20
|
+
reporters.push(['junit', { outputFile: path.join(reportsDir, 'results.xml') }]);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = defineConfig({
|
|
24
|
+
testDir: path.join(__dirname, 'tests', '_helpers'),
|
|
25
|
+
testMatch: ['agentic-runner.bundle.spec.js'],
|
|
26
|
+
reporter: reporters,
|
|
27
|
+
outputDir: playwrightOutputDir,
|
|
28
|
+
use: {
|
|
28
29
|
// ── Dynamic BASE_URL ──
|
|
29
30
|
// Priority: CLI --base-url flag → arcality.config baseUrl → BASE_URL env → default
|
|
30
31
|
// This allows pipelines to inject the target environment dynamically:
|
|
31
32
|
// arcality --run-all --base-url=https://staging.myapp.com
|
|
32
33
|
baseURL: process.env.BASE_URL || 'http://localhost:3000',
|
|
33
|
-
video: 'on',
|
|
34
|
-
screenshot: 'on',
|
|
35
|
-
trace: 'on',
|
|
34
|
+
video: 'retain-on-failure',
|
|
35
|
+
screenshot: 'only-on-failure',
|
|
36
|
+
trace: 'retain-on-failure',
|
|
36
37
|
colorScheme: 'dark',
|
|
37
38
|
// In CI: headless is enforced by Playwright automatically when CI=true
|
|
38
39
|
headless: isCI ? true : undefined,
|