create-byan-agent 2.19.1 → 2.20.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/CHANGELOG.md +188 -0
- package/README.md +4 -4
- package/install/src/byan-v2/generation/templates/default-agent.md +1 -1
- package/install/templates/.claude/CLAUDE.md +1 -1
- package/install/templates/.claude/hooks/fd-phase-guard.js +2 -2
- package/install/templates/.claude/hooks/mantra-validate.js +16 -8
- package/install/templates/.claude/hooks/strict-scope-guard.js +25 -7
- package/install/templates/.claude/rules/native-workflows.md +32 -0
- package/install/templates/.claude/skills/byan-byan/SKILL.md +5 -5
- package/install/templates/.claude/skills/byan-mantra-audit/SKILL.md +53 -0
- package/install/templates/.claude/skills/byan-merise-agile/SKILL.md +2 -2
- package/install/templates/.claude/skills/byan-native-dev-story/SKILL.md +83 -0
- package/install/templates/.claude/workflows/INDEX.md +35 -0
- package/install/templates/.claude/workflows/check-implementation-readiness.js +280 -0
- package/install/templates/.claude/workflows/code-review.js +179 -0
- package/install/templates/.claude/workflows/create-excalidraw-dataflow.js +214 -0
- package/install/templates/.claude/workflows/create-excalidraw-diagram.js +188 -0
- package/install/templates/.claude/workflows/create-excalidraw-flowchart.js +225 -0
- package/install/templates/.claude/workflows/create-excalidraw-wireframe.js +192 -0
- package/install/templates/.claude/workflows/create-story.js +216 -0
- package/install/templates/.claude/workflows/dev-story.js +100 -0
- package/install/templates/.claude/workflows/document-project.js +455 -0
- package/install/templates/.claude/workflows/qa-automate.js +169 -0
- package/install/templates/.claude/workflows/quick-dev.js +273 -0
- package/install/templates/.claude/workflows/sprint-planning.js +261 -0
- package/install/templates/.claude/workflows/testarch-atdd.js +287 -0
- package/install/templates/.claude/workflows/testarch-automate.js +229 -0
- package/install/templates/.claude/workflows/testarch-ci.js +184 -0
- package/install/templates/.claude/workflows/testarch-framework.js +267 -0
- package/install/templates/.claude/workflows/testarch-nfr.js +316 -0
- package/install/templates/.claude/workflows/testarch-test-design.js +293 -0
- package/install/templates/.claude/workflows/testarch-test-review.js +321 -0
- package/install/templates/.claude/workflows/testarch-trace.js +316 -0
- package/install/templates/.githooks/pre-commit +49 -15
- package/install/templates/_byan/config.yaml +15 -5
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-build-workflows.js +20 -0
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-lint-workflows.js +57 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/native-loop.js +39 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-generator.js +149 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-lint.js +113 -0
- package/install/templates/_byan/workflow/simple/byan/feature-workflow.md +14 -11
- package/install/templates/docs/native-workflows-contract.md +84 -0
- package/package.json +2 -2
- package/src/byan-v2/data/agent-scopes.json +46 -0
- package/src/byan-v2/data/mantras.json +194 -8
- package/src/byan-v2/generation/mantra-audit.js +147 -0
- package/src/byan-v2/generation/mantra-validator.js +56 -6
- package/src/byan-v2/generation/scope-resolver.js +102 -0
- package/src/byan-v2/generation/templates/default-agent.md +1 -1
- package/update-byan-agent/bin/update-byan-agent.js +67 -72
- package/update-byan-agent/lib/apply-update.js +202 -0
- package/update-byan-agent/package.json +1 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'testarch-ci',
|
|
3
|
+
description: 'Native port of the BYAN testarch-ci workflow: scaffold a CI/CD quality pipeline (lint -> sharded test -> burn-in flaky detection -> report) with caching, artifacts, quality gates and notifications, then return a structured verdict for the orchestrating skill to present at the human gate.',
|
|
4
|
+
phases: [
|
|
5
|
+
{ title: 'PREFLIGHT', detail: 'verify git + test framework + local pass, detect CI platform and Node version' },
|
|
6
|
+
{ title: 'GENERATE', detail: 'generate the platform CI config (stages, sharding, burn-in, caching, artifacts)' },
|
|
7
|
+
{ title: 'QUALITY_GATES', detail: 'configure burn-in loop, quality thresholds and failure notifications' },
|
|
8
|
+
{ title: 'VALIDATE', detail: 'validate against checklist.md and produce the completion summary verdict' },
|
|
9
|
+
],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// FD / STRICT STATE CONTRACT (re-asserted inline — enforcement-bridge).
|
|
14
|
+
//
|
|
15
|
+
// The in-CLI Workflow tool runs this script OUTSIDE the conversation turn, so
|
|
16
|
+
// BYAN's main-thread hooks (fd-phase-guard, strict-scope-guard, strict-stop-
|
|
17
|
+
// guard, mantra-validate) DO NOT fire here. This script therefore:
|
|
18
|
+
// - NEVER imports/requires _byan/.../lib/fd-state.js and NEVER writes
|
|
19
|
+
// fd-state.json directly (enforced by byan-lint-workflows.js).
|
|
20
|
+
// - uses NO wall-clock and NO randomness primitive (Date/RNG break
|
|
21
|
+
// resume); any timestamp/id is passed in via args.
|
|
22
|
+
// - returns DATA only. The orchestrating skill is the human-gated conductor;
|
|
23
|
+
// IT records FD/strict state via the byan_fd_* / byan_strict_* MCP tools AT
|
|
24
|
+
// the gate, and IT owns the human "update or replace existing CI" decision.
|
|
25
|
+
// The CI config FILE (and helper scripts / docs) is the workflow's product,
|
|
26
|
+
// written by the generate/quality-gate leaves — that is the artifact, not
|
|
27
|
+
// BYAN platform state.
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
// Inputs (all optional; defaults mirror workflow.yaml variables).
|
|
31
|
+
const ciPlatform = (args && args.ci_platform) || 'auto' // auto | github-actions | gitlab-ci | circle-ci | jenkins
|
|
32
|
+
const testDir = (args && args.test_dir) || '{project-root}/tests'
|
|
33
|
+
const shards = (args && args.shards) || 4
|
|
34
|
+
const burnInIterations = (args && args.burn_in_iterations) || 10
|
|
35
|
+
|
|
36
|
+
const PREFLIGHT_SCHEMA = {
|
|
37
|
+
type: 'object',
|
|
38
|
+
required: ['ready', 'platform', 'blocking'],
|
|
39
|
+
properties: {
|
|
40
|
+
ready: { type: 'boolean', description: 'true ONLY if git repo, a test framework, and a passing local test command were all confirmed' },
|
|
41
|
+
gitOk: { type: 'boolean', description: 'true if .git/ exists (remote noted if available)' },
|
|
42
|
+
frameworkOk: { type: 'boolean', description: 'true if playwright.config.* or cypress.config.* exists AND the framework is in package.json' },
|
|
43
|
+
localTestsPass: { type: 'boolean', description: 'true if the main test command (e.g. npm run test:e2e) passes locally' },
|
|
44
|
+
framework: { type: 'string', description: 'playwright | cypress | other' },
|
|
45
|
+
platform: { type: 'string', description: 'resolved CI platform: github-actions | gitlab-ci | circle-ci | jenkins' },
|
|
46
|
+
nodeVersion: { type: 'string', description: 'from .nvmrc, or the default LTS if absent' },
|
|
47
|
+
existingCi: { type: 'string', description: 'path of any pre-existing CI config detected, or empty if none' },
|
|
48
|
+
blocking: { type: 'array', items: { type: 'string' }, description: 'HALT reasons when not ready (missing git, no framework, failing tests)' },
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const GENERATE_SCHEMA = {
|
|
53
|
+
type: 'object',
|
|
54
|
+
required: ['configPath', 'stages'],
|
|
55
|
+
properties: {
|
|
56
|
+
configPath: { type: 'string', description: 'path the CI config was written to (e.g. .github/workflows/test.yml or .gitlab-ci.yml)' },
|
|
57
|
+
stages: { type: 'array', items: { type: 'string' }, description: 'pipeline stages present, expect lint, test, burn-in, report' },
|
|
58
|
+
sharding: { type: 'boolean', description: 'true if parallel sharding (matrix, fail-fast:false) is configured' },
|
|
59
|
+
retries: { type: 'boolean', description: 'true if CI retries / timeouts are configured' },
|
|
60
|
+
caching: { type: 'boolean', description: 'true if dependency + browser caching keyed on the lockfile is configured' },
|
|
61
|
+
artifacts: { type: 'boolean', description: 'true if failure-only artifacts (HTML report, JUnit XML, traces/videos) are uploaded' },
|
|
62
|
+
notes: { type: 'string' },
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const GATES_SCHEMA = {
|
|
67
|
+
type: 'object',
|
|
68
|
+
required: ['burnInConfigured', 'qualityGates'],
|
|
69
|
+
properties: {
|
|
70
|
+
burnInConfigured: { type: 'boolean', description: 'true if the N-iteration burn-in flaky-detection loop with `|| exit 1` gating is in place' },
|
|
71
|
+
burnInIterations: { type: 'integer', description: 'configured burn-in iteration count' },
|
|
72
|
+
qualityGates: { type: 'array', items: { type: 'string' }, description: 'gates defined, e.g. "P0=100%", "P1>=95%", "fail CI on critical failures"' },
|
|
73
|
+
notifications: { type: 'boolean', description: 'true if failure notifications (Slack/email) and artifact links are configured' },
|
|
74
|
+
notes: { type: 'string' },
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const VALIDATE_SCHEMA = {
|
|
79
|
+
type: 'object',
|
|
80
|
+
required: ['valid', 'gaps', 'summary'],
|
|
81
|
+
properties: {
|
|
82
|
+
valid: { type: 'boolean', description: 'true ONLY if every checklist.md item the script covers (config created, stages+sharding, burn-in+artifacts, secrets documented, YAML syntactically valid) is satisfied' },
|
|
83
|
+
gaps: { type: 'array', items: { type: 'string' }, description: 'unmet checklist items; empty when valid' },
|
|
84
|
+
secretsDocumented: { type: 'boolean', description: 'true if required secrets/variables are documented' },
|
|
85
|
+
nextSteps: { type: 'array', items: { type: 'string' }, description: 'post-workflow actions for the human: set secrets, commit, push, open PR to trigger first run' },
|
|
86
|
+
summary: { type: 'string', description: 'one-line completion summary: platform + config path + key stages' },
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// --- Step 1: Preflight (steps-c/step-01-preflight.md) ----------------------
|
|
91
|
+
phase('PREFLIGHT')
|
|
92
|
+
const preflight = await agent(
|
|
93
|
+
`You are the Master Test Architect running testarch-ci preflight.\n` +
|
|
94
|
+
`Read the COMPLETE source step: _byan/workflow/simple/testarch/ci/steps-c/step-01-preflight.md.\n` +
|
|
95
|
+
`Verify, in order, exactly as the step mandates:\n` +
|
|
96
|
+
` 1. Git repository: .git/ exists (note remote if available). HALT reason if missing.\n` +
|
|
97
|
+
` 2. Test framework: playwright.config.* or cypress.config.* exists AND the framework is in package.json. HALT reason if missing.\n` +
|
|
98
|
+
` 3. Local tests pass: run the main test command (e.g. npm run test:e2e). HALT reason if failing.\n` +
|
|
99
|
+
` 4. Detect CI platform: scan for .github/workflows/*.yml, .gitlab-ci.yml, .circleci/config.yml, Jenkinsfile. ` +
|
|
100
|
+
`If found, record its path in existingCi (the human, not this script, decides update vs replace). ` +
|
|
101
|
+
`If none, infer from the git remote (github.com -> github-actions). ` +
|
|
102
|
+
`Requested ci_platform=${JSON.stringify(ciPlatform)} overrides detection unless it is "auto".\n` +
|
|
103
|
+
` 5. Read environment context: .nvmrc (default to current LTS if absent) and package.json caching strategy.\n` +
|
|
104
|
+
`Test directory under consideration: ${testDir}.\n` +
|
|
105
|
+
`Do NOT invent passing tests or a framework that is not there: report blocking honestly.`,
|
|
106
|
+
{ label: 'preflight', phase: 'PREFLIGHT', schema: PREFLIGHT_SCHEMA }
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if (!preflight.ready) {
|
|
110
|
+
// Mirror the source HALT: do not fabricate a pipeline on a failing preflight.
|
|
111
|
+
return {
|
|
112
|
+
workflow: 'testarch-ci',
|
|
113
|
+
summary: 'preflight HALT — CI scaffolding not started',
|
|
114
|
+
steps: 1,
|
|
115
|
+
halted: true,
|
|
116
|
+
needsHumanGate: true,
|
|
117
|
+
preflight,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --- Step 2: Generate pipeline (steps-c/step-02-generate-pipeline.md) -------
|
|
122
|
+
phase('GENERATE')
|
|
123
|
+
const generate = await agent(
|
|
124
|
+
`Read the COMPLETE source step: _byan/workflow/simple/testarch/ci/steps-c/step-02-generate-pipeline.md ` +
|
|
125
|
+
`and the matching template in _byan/workflow/simple/testarch/ci/ ` +
|
|
126
|
+
`(github-actions-template.yaml or gitlab-ci-template.yaml).\n` +
|
|
127
|
+
`Target platform: ${preflight.platform}. Node version: ${preflight.nodeVersion}. Framework: ${preflight.framework}.\n` +
|
|
128
|
+
`Select the output path by platform: github-actions -> .github/workflows/test.yml, gitlab-ci -> .gitlab-ci.yml, ` +
|
|
129
|
+
`circle-ci -> .circleci/config.yml, jenkins -> Jenkinsfile.\n` +
|
|
130
|
+
`Generate the CI config with these stages: lint, test (parallel shards), burn-in (flaky detection), report (aggregate + publish).\n` +
|
|
131
|
+
`Test execution requirements: ${shards} parallel shards with fail-fast:false, CI retries/timeouts configured, ` +
|
|
132
|
+
`failure-only artifacts (HTML report, JUnit XML, traces/videos), and dependency + browser caching keyed on the lockfile hash.\n` +
|
|
133
|
+
`Write the config to the chosen path. Return the path and what was configured. Do not claim a stage you did not write.`,
|
|
134
|
+
{ label: 'generate-pipeline', phase: 'GENERATE', schema: GENERATE_SCHEMA }
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
// --- Step 3: Quality gates & notifications (steps-c/step-03-...) ------------
|
|
138
|
+
phase('QUALITY_GATES')
|
|
139
|
+
const gates = await agent(
|
|
140
|
+
`Read the COMPLETE source step: _byan/workflow/simple/testarch/ci/steps-c/step-03-configure-quality-gates.md ` +
|
|
141
|
+
`(and ci-burn-in.md guidance via the tea knowledge index if reachable).\n` +
|
|
142
|
+
`CI config under edit: ${generate.configPath}.\n` +
|
|
143
|
+
`Configure, in order:\n` +
|
|
144
|
+
` 1. Burn-in: ${burnInIterations}-iteration loop for flaky detection, gating promotion on stability (`+'`'+`|| exit 1`+'`'+` per iteration).\n` +
|
|
145
|
+
` 2. Quality gates: minimum pass rates (P0 = 100%, P1 >= 95%), fail CI on critical test failures, ` +
|
|
146
|
+
`optionally require traceability / nfr-assess output before release.\n` +
|
|
147
|
+
` 3. Notifications: failure notifications (Slack/email) and artifact links.\n` +
|
|
148
|
+
`Return what was actually configured; do not assert a gate or notification you did not write.`,
|
|
149
|
+
{ label: 'quality-gates', phase: 'QUALITY_GATES', schema: GATES_SCHEMA }
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
// --- Step 4: Validate & summarize (steps-c/step-04-validate-and-summary.md) -
|
|
153
|
+
phase('VALIDATE')
|
|
154
|
+
const validate = await agent(
|
|
155
|
+
`Read the COMPLETE source step: _byan/workflow/simple/testarch/ci/steps-c/step-04-validate-and-summary.md ` +
|
|
156
|
+
`and the validation criteria in _byan/workflow/simple/testarch/ci/checklist.md.\n` +
|
|
157
|
+
`Validate the generated CI setup at ${generate.configPath} against the checklist:\n` +
|
|
158
|
+
` - config file created and YAML syntactically valid\n` +
|
|
159
|
+
` - stages and parallel sharding configured\n` +
|
|
160
|
+
` - burn-in loop and failure-only artifacts enabled\n` +
|
|
161
|
+
` - secrets/variables documented\n` +
|
|
162
|
+
`Generated stages reported: ${JSON.stringify(generate.stages)}; ` +
|
|
163
|
+
`burn-in configured: ${gates.burnInConfigured}; quality gates: ${JSON.stringify(gates.qualityGates)}.\n` +
|
|
164
|
+
`List any gaps honestly (do not pass over a missing item). Then produce the completion summary: ` +
|
|
165
|
+
`CI platform and config path, key stages enabled, artifacts and notifications, and the next steps the human must take ` +
|
|
166
|
+
`(set secrets, commit, push, open a PR to trigger the first run).`,
|
|
167
|
+
{ label: 'validate-and-summary', phase: 'VALIDATE', schema: VALIDATE_SCHEMA }
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
workflow: 'testarch-ci',
|
|
172
|
+
summary: validate.summary,
|
|
173
|
+
steps: 4,
|
|
174
|
+
halted: false,
|
|
175
|
+
needsHumanGate: true,
|
|
176
|
+
platform: preflight.platform,
|
|
177
|
+
configPath: generate.configPath,
|
|
178
|
+
result: {
|
|
179
|
+
preflight,
|
|
180
|
+
generate,
|
|
181
|
+
gates,
|
|
182
|
+
validate,
|
|
183
|
+
},
|
|
184
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
export const meta = {
|
|
2
|
+
name: 'testarch-framework',
|
|
3
|
+
description: 'Native port of the BYAN testarch-framework workflow (Create mode): initialize a production-ready E2E test framework (Playwright or Cypress) with directory structure, config, fixtures, data factories, sample tests, helpers, docs and package scripts, then validate against the checklist and return a structured completion verdict for the orchestrating skill to present at the human gate.',
|
|
4
|
+
phases: [
|
|
5
|
+
{ title: 'PREFLIGHT', detail: 'verify prerequisites (package.json, no existing E2E framework) and gather project context' },
|
|
6
|
+
{ title: 'SELECT', detail: 'select Playwright or Cypress and justify the choice (respect framework_preference)' },
|
|
7
|
+
{ title: 'SCAFFOLD', detail: 'create dir structure, config, env/node, fixtures+factories, sample tests+helpers' },
|
|
8
|
+
{ title: 'DOCS_SCRIPTS', detail: 'write tests/README.md and add the test:e2e package.json script' },
|
|
9
|
+
{ title: 'VALIDATE', detail: 'validate against checklist.md, fix gaps (bounded loop), and summarize' },
|
|
10
|
+
],
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// FD / STRICT STATE CONTRACT (re-asserted inline — byan-lint-workflows guard).
|
|
15
|
+
//
|
|
16
|
+
// The in-CLI Workflow tool runs this script OUTSIDE the conversation turn, so
|
|
17
|
+
// BYAN's main-thread hooks (fd-phase-guard, strict-scope-guard, strict-stop-
|
|
18
|
+
// guard, mantra-validate) DO NOT fire here. This script therefore:
|
|
19
|
+
// - NEVER imports/requires _byan/.../lib/fd-state.js and NEVER writes
|
|
20
|
+
// fd-state.json directly (enforced by byan-lint-workflows.js).
|
|
21
|
+
// - uses NO wall-clock and NO randomness primitive (wall-clock/wall-clock/
|
|
22
|
+
// RNG break resume); any date/id arrives via `args`.
|
|
23
|
+
// - returns DATA only. The orchestrating skill is the human-gated conductor;
|
|
24
|
+
// IT records FD/strict state via the byan_fd_* / byan_strict_* MCP tools
|
|
25
|
+
// AT the gate. The HALT in PREFLIGHT and the "fix gaps before completion"
|
|
26
|
+
// decision are surfaced as verdict fields, not enforced as side effects.
|
|
27
|
+
// The framework FILES (config, fixtures, factories, sample tests, tests/README,
|
|
28
|
+
// package scripts) are this workflow's product, written by the leaf agents —
|
|
29
|
+
// those are the artifacts, not BYAN platform state.
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
// Bounded validate->fix convergence guard. Mirrors step-05's prose rule
|
|
33
|
+
// ("Fix any gaps before completion") as a real counter the model cannot
|
|
34
|
+
// silently overrun. No unbounded loop: hard cap at MAX_FIX_PASSES.
|
|
35
|
+
const MAX_FIX_PASSES = 3
|
|
36
|
+
|
|
37
|
+
// Inputs arrive via args (no fs, no clock, no RNG inside the sandbox).
|
|
38
|
+
const projectRoot = (args && args.projectRoot) || '{project-root}'
|
|
39
|
+
const testDir = (args && args.testDir) || `${projectRoot}/tests`
|
|
40
|
+
const useTypescript = !(args && args.useTypescript === false) // workflow.yaml default: true
|
|
41
|
+
const frameworkPreference = (args && args.frameworkPreference) || 'auto' // auto | playwright | cypress
|
|
42
|
+
const projectSize = (args && args.projectSize) || 'auto' // auto | small | large
|
|
43
|
+
const runDate = (args && args.date) || 'unset' // system-generated date passed in by the conductor
|
|
44
|
+
|
|
45
|
+
// ── Step 1: Preflight ──────────────────────────────────────────────────────
|
|
46
|
+
// Source: steps-c/step-01-preflight.md — validate prerequisites, gather context.
|
|
47
|
+
// HALT on missing prerequisite is a real early-exit (returned as a verdict).
|
|
48
|
+
phase('PREFLIGHT')
|
|
49
|
+
const PREFLIGHT_SCHEMA = {
|
|
50
|
+
type: 'object',
|
|
51
|
+
required: ['readyToScaffold', 'projectType', 'frameworkAlreadyInstalled'],
|
|
52
|
+
properties: {
|
|
53
|
+
readyToScaffold: { type: 'boolean' },
|
|
54
|
+
haltReason: { type: 'string' }, // non-empty iff readyToScaffold === false
|
|
55
|
+
projectType: { type: 'string' }, // React, Vue, Angular, Next.js, Node, ...
|
|
56
|
+
bundler: { type: 'string' }, // Vite, Webpack, Rollup, esbuild, or N/A
|
|
57
|
+
frameworkAlreadyInstalled: { type: 'boolean' },
|
|
58
|
+
contextDocs: { type: 'array', items: { type: 'string' } }, // architecture.md, tech-spec*.md
|
|
59
|
+
authOrApiNotes: { type: 'string' },
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
const preflight = await agent(
|
|
63
|
+
[
|
|
64
|
+
'You are the Master Test Architect executing step-01-preflight of the testarch-framework workflow.',
|
|
65
|
+
`Source step file: ${projectRoot}/_byan/workflow/simple/testarch/framework/steps-c/step-01-preflight.md`,
|
|
66
|
+
'1. Validate prerequisites: package.json exists in project root; NO existing E2E framework',
|
|
67
|
+
' (playwright.config.*, cypress.config.*, cypress.json); project type/stack context is available.',
|
|
68
|
+
' If any prerequisite fails, set readyToScaffold=false and put the missing requirement in haltReason (HALT).',
|
|
69
|
+
`2. Gather context: read ${projectRoot}/package.json to identify framework, bundler, dependencies;`,
|
|
70
|
+
' check for architecture docs (architecture.md, tech-spec*.md); note auth requirements and APIs if documented.',
|
|
71
|
+
'3. Confirm findings: project type and bundler, whether a framework is already installed, relevant context docs.',
|
|
72
|
+
'Do NOT scaffold anything in this step. Report findings only.',
|
|
73
|
+
].join('\n'),
|
|
74
|
+
{ label: 'preflight', phase: 'PREFLIGHT', schema: PREFLIGHT_SCHEMA },
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
// HALT gate (mirrors "If any fail, HALT and report"). End early with a verdict;
|
|
78
|
+
// the human gate (handled by the orchestrating skill) decides what to do next.
|
|
79
|
+
if (!preflight.readyToScaffold) {
|
|
80
|
+
return {
|
|
81
|
+
workflow: 'testarch-framework',
|
|
82
|
+
mode: 'create',
|
|
83
|
+
summary: `Preflight HALT: ${preflight.haltReason || 'prerequisite(s) not met'}`,
|
|
84
|
+
halted: true,
|
|
85
|
+
haltedAt: 'PREFLIGHT',
|
|
86
|
+
steps: 1,
|
|
87
|
+
needsHumanGate: true,
|
|
88
|
+
preflight,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ── Step 2: Framework Selection ─────────────────────────────────────────────
|
|
93
|
+
// Source: steps-c/step-02-select-framework.md — default Playwright, respect
|
|
94
|
+
// framework_preference; justify the choice.
|
|
95
|
+
phase('SELECT')
|
|
96
|
+
const SELECT_SCHEMA = {
|
|
97
|
+
type: 'object',
|
|
98
|
+
required: ['framework', 'rationale'],
|
|
99
|
+
properties: {
|
|
100
|
+
framework: { type: 'string', enum: ['playwright', 'cypress'] },
|
|
101
|
+
rationale: { type: 'string' },
|
|
102
|
+
preferenceRespected: { type: 'boolean' },
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
const selection = await agent(
|
|
106
|
+
[
|
|
107
|
+
'Execute step-02-select-framework of the testarch-framework workflow.',
|
|
108
|
+
`Source step file: ${projectRoot}/_byan/workflow/simple/testarch/framework/steps-c/step-02-select-framework.md`,
|
|
109
|
+
`Inputs: framework_preference=${frameworkPreference}, project_size=${projectSize}.`,
|
|
110
|
+
'Default to Playwright unless strong reasons suggest Cypress.',
|
|
111
|
+
'Playwright when: large/complex repo, multi-browser, heavy API+UI integration, CI speed/parallelism matters.',
|
|
112
|
+
'Cypress when: small team prioritizes DX, component-testing focus, simpler setup.',
|
|
113
|
+
'If framework_preference is explicitly playwright or cypress, respect it (set preferenceRespected=true).',
|
|
114
|
+
'Announce the selected framework and the reasoning.',
|
|
115
|
+
`Context: projectType=${preflight.projectType}, bundler=${preflight.bundler || 'N/A'}.`,
|
|
116
|
+
].join('\n'),
|
|
117
|
+
{ label: 'select-framework', phase: 'SELECT', schema: SELECT_SCHEMA },
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
// ── Step 3: Scaffold Framework ──────────────────────────────────────────────
|
|
121
|
+
// Source: steps-c/step-03-scaffold-framework.md — dirs, config, env/node,
|
|
122
|
+
// fixtures+factories (knowledge-base driven), sample tests + helpers.
|
|
123
|
+
phase('SCAFFOLD')
|
|
124
|
+
const SCAFFOLD_SCHEMA = {
|
|
125
|
+
type: 'object',
|
|
126
|
+
required: ['directoriesCreated', 'configFile', 'filesCreated'],
|
|
127
|
+
properties: {
|
|
128
|
+
directoriesCreated: { type: 'array', items: { type: 'string' } },
|
|
129
|
+
configFile: { type: 'string' }, // playwright.config.ts | cypress.config.ts
|
|
130
|
+
envFiles: { type: 'array', items: { type: 'string' } }, // .env.example, .nvmrc
|
|
131
|
+
fixturesCreated: { type: 'array', items: { type: 'string' } },
|
|
132
|
+
factoriesCreated: { type: 'array', items: { type: 'string' } },
|
|
133
|
+
sampleTests: { type: 'array', items: { type: 'string' } },
|
|
134
|
+
helpersCreated: { type: 'array', items: { type: 'string' } },
|
|
135
|
+
knowledgeFragmentsApplied: { type: 'array', items: { type: 'string' } },
|
|
136
|
+
filesCreated: { type: 'array', items: { type: 'string' } },
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
const scaffold = await agent(
|
|
140
|
+
[
|
|
141
|
+
'Execute step-03-scaffold-framework of the testarch-framework workflow.',
|
|
142
|
+
`Source step file: ${projectRoot}/_byan/workflow/simple/testarch/framework/steps-c/step-03-scaffold-framework.md`,
|
|
143
|
+
`Selected framework: ${selection.framework}. use_typescript=${useTypescript}.`,
|
|
144
|
+
`1. Create dir structure under ${testDir}: e2e/, support/fixtures/, support/helpers/, support/page-objects/ (optional).`,
|
|
145
|
+
`2. Generate the framework config (${selection.framework === 'cypress' ? 'cypress.config.ts' : 'playwright.config.ts'}):`,
|
|
146
|
+
' timeouts (action 15s, navigation 30s, test 60s), BASE_URL env fallback, retain-on-failure artifacts',
|
|
147
|
+
' (trace/screenshot/video), reporters HTML+JUnit+console, parallelism enabled (CI tuned). TypeScript if use_typescript.',
|
|
148
|
+
'3. Environment & Node: .env.example with TEST_ENV/BASE_URL/API_URL; .nvmrc on current LTS (prefer Node 24+).',
|
|
149
|
+
`4. Fixtures & factories: read ${projectRoot}/_byan/tea/config.yaml and use the knowledge index`,
|
|
150
|
+
` ${projectRoot}/_byan/connaissance/testarch/tea-index.csv based on config.tea_use_playwright_utils.`,
|
|
151
|
+
' If Playwright Utils enabled, load: overview.md, fixtures-composition.md, auth-session.md, api-request.md,',
|
|
152
|
+
' burn-in.md, network-error-monitor.md, data-factories.md and recommend @seontechnologies/playwright-utils.',
|
|
153
|
+
' If disabled, load: fixture-architecture.md, data-factories.md, network-first.md, playwright-config.md, test-quality.md.',
|
|
154
|
+
' Implement: fixture index with mergeTests, auto-cleanup hooks, Faker-based data factories with overrides.',
|
|
155
|
+
'5. Sample tests in e2e/ (Given/When/Then, data-testid strategy, factory usage, network interception if applicable),',
|
|
156
|
+
' plus helpers for API clients, network utilities, auth (only those needed).',
|
|
157
|
+
'List every directory and file created and every knowledge fragment applied.',
|
|
158
|
+
].join('\n'),
|
|
159
|
+
{ label: 'scaffold-framework', phase: 'SCAFFOLD', schema: SCAFFOLD_SCHEMA },
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
// ── Step 4: Documentation & Scripts ─────────────────────────────────────────
|
|
163
|
+
// Source: steps-c/step-04-docs-and-scripts.md — tests/README.md + package.json
|
|
164
|
+
// test:e2e script.
|
|
165
|
+
phase('DOCS_SCRIPTS')
|
|
166
|
+
const DOCS_SCHEMA = {
|
|
167
|
+
type: 'object',
|
|
168
|
+
required: ['readmePath', 'scriptsAdded'],
|
|
169
|
+
properties: {
|
|
170
|
+
readmePath: { type: 'string' }, // {test_dir}/README.md
|
|
171
|
+
readmeSections: { type: 'array', items: { type: 'string' } },
|
|
172
|
+
scriptsAdded: { type: 'array', items: { type: 'string' } }, // at minimum test:e2e
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
const docs = await agent(
|
|
176
|
+
[
|
|
177
|
+
'Execute step-04-docs-and-scripts of the testarch-framework workflow.',
|
|
178
|
+
`Source step file: ${projectRoot}/_byan/workflow/simple/testarch/framework/steps-c/step-04-docs-and-scripts.md`,
|
|
179
|
+
`1. Create ${testDir}/README.md with: setup instructions; running tests (local/headed/debug);`,
|
|
180
|
+
' architecture overview (fixtures, factories, helpers); best practices (selectors, isolation, cleanup);',
|
|
181
|
+
' CI integration notes; knowledge base references.',
|
|
182
|
+
'2. Update package.json scripts: add at minimum test:e2e = the framework execution command',
|
|
183
|
+
` for ${selection.framework}.`,
|
|
184
|
+
'List the README path, its sections, and every script added.',
|
|
185
|
+
].join('\n'),
|
|
186
|
+
{ label: 'docs-and-scripts', phase: 'DOCS_SCRIPTS', schema: DOCS_SCHEMA },
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
// ── Step 5: Validate & Summarize ────────────────────────────────────────────
|
|
190
|
+
// Source: steps-c/step-05-validate-and-summary.md — validate against
|
|
191
|
+
// checklist.md, "Fix any gaps before completion", then summarize.
|
|
192
|
+
// Bounded validate->fix loop (hard cap MAX_FIX_PASSES); last pass must be clean.
|
|
193
|
+
phase('VALIDATE')
|
|
194
|
+
const VALIDATE_SCHEMA = {
|
|
195
|
+
type: 'object',
|
|
196
|
+
required: ['checklistPassed', 'gaps'],
|
|
197
|
+
properties: {
|
|
198
|
+
checklistPassed: { type: 'boolean' },
|
|
199
|
+
gaps: { type: 'array', items: { type: 'string' } }, // non-empty iff checklistPassed === false
|
|
200
|
+
fixesApplied: { type: 'array', items: { type: 'string' } },
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
let validation = { checklistPassed: false, gaps: [], fixesApplied: [] }
|
|
204
|
+
let fixPasses = 0
|
|
205
|
+
while (fixPasses < MAX_FIX_PASSES) {
|
|
206
|
+
fixPasses += 1
|
|
207
|
+
validation = await agent(
|
|
208
|
+
[
|
|
209
|
+
`Execute step-05-validate-and-summary of the testarch-framework workflow (pass ${fixPasses}/${MAX_FIX_PASSES}).`,
|
|
210
|
+
`Source step file: ${projectRoot}/_byan/workflow/simple/testarch/framework/steps-c/step-05-validate-and-summary.md`,
|
|
211
|
+
`Validate the scaffold against the checklist: ${projectRoot}/_byan/workflow/simple/testarch/framework/checklist.md`,
|
|
212
|
+
'Verify: preflight success; directory structure created; config correctness (timeouts, BASE_URL, artifacts,',
|
|
213
|
+
'reporters, parallelism); fixtures/factories created with auto-cleanup; sample tests; helpers; docs and the',
|
|
214
|
+
'test:e2e script present; no placeholders/secrets; imports resolve.',
|
|
215
|
+
'If any item fails, FIX the gap now (write/patch the offending file) and record the fix in fixesApplied,',
|
|
216
|
+
'then re-check. Set checklistPassed=true only when every checklist item holds; otherwise list remaining gaps.',
|
|
217
|
+
`Context: framework=${selection.framework}, config=${scaffold.configFile}, readme=${docs.readmePath}.`,
|
|
218
|
+
].join('\n'),
|
|
219
|
+
{ label: `validate-pass-${fixPasses}`, phase: 'VALIDATE', schema: VALIDATE_SCHEMA },
|
|
220
|
+
)
|
|
221
|
+
if (validation.checklistPassed) break
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const converged = validation.checklistPassed
|
|
225
|
+
const unresolvedGaps = converged ? [] : validation.gaps
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
workflow: 'testarch-framework',
|
|
229
|
+
mode: 'create',
|
|
230
|
+
summary: converged
|
|
231
|
+
? `${selection.framework} test framework scaffolded and validated clean (${fixPasses} validate pass(es)).`
|
|
232
|
+
: `${selection.framework} test framework scaffolded; ${unresolvedGaps.length} gap(s) unresolved after ${MAX_FIX_PASSES} fix passes.`,
|
|
233
|
+
halted: false,
|
|
234
|
+
steps: 5,
|
|
235
|
+
date: runDate,
|
|
236
|
+
framework: selection.framework,
|
|
237
|
+
frameworkRationale: selection.rationale,
|
|
238
|
+
artifacts: {
|
|
239
|
+
directories: scaffold.directoriesCreated,
|
|
240
|
+
configFile: scaffold.configFile,
|
|
241
|
+
envFiles: scaffold.envFiles || [],
|
|
242
|
+
fixtures: scaffold.fixturesCreated || [],
|
|
243
|
+
factories: scaffold.factoriesCreated || [],
|
|
244
|
+
sampleTests: scaffold.sampleTests || [],
|
|
245
|
+
helpers: scaffold.helpersCreated || [],
|
|
246
|
+
readme: docs.readmePath,
|
|
247
|
+
scripts: docs.scriptsAdded,
|
|
248
|
+
knowledgeFragmentsApplied: scaffold.knowledgeFragmentsApplied || [],
|
|
249
|
+
},
|
|
250
|
+
validation: {
|
|
251
|
+
converged,
|
|
252
|
+
fixPasses,
|
|
253
|
+
maxFixPasses: MAX_FIX_PASSES,
|
|
254
|
+
unresolvedGaps,
|
|
255
|
+
fixesApplied: validation.fixesApplied || [],
|
|
256
|
+
},
|
|
257
|
+
// Post-workflow user actions (checklist.md) — surfaced for the human gate,
|
|
258
|
+
// never executed by this script.
|
|
259
|
+
nextSteps: [
|
|
260
|
+
'Copy .env.example to .env and fill values',
|
|
261
|
+
'Run npm install to install test dependencies',
|
|
262
|
+
'Run npm run test:e2e to verify setup',
|
|
263
|
+
'Review tests/README.md',
|
|
264
|
+
'Consider downstream workflows: ci, test-design, atdd',
|
|
265
|
+
],
|
|
266
|
+
needsHumanGate: true,
|
|
267
|
+
}
|