create-byan-agent 2.19.2 → 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.
Files changed (49) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/README.md +4 -4
  3. package/install/src/byan-v2/generation/templates/default-agent.md +1 -1
  4. package/install/templates/.claude/CLAUDE.md +1 -1
  5. package/install/templates/.claude/hooks/fd-phase-guard.js +2 -2
  6. package/install/templates/.claude/hooks/mantra-validate.js +16 -8
  7. package/install/templates/.claude/hooks/strict-scope-guard.js +25 -7
  8. package/install/templates/.claude/rules/native-workflows.md +32 -0
  9. package/install/templates/.claude/skills/byan-byan/SKILL.md +5 -5
  10. package/install/templates/.claude/skills/byan-mantra-audit/SKILL.md +53 -0
  11. package/install/templates/.claude/skills/byan-merise-agile/SKILL.md +2 -2
  12. package/install/templates/.claude/skills/byan-native-dev-story/SKILL.md +83 -0
  13. package/install/templates/.claude/workflows/INDEX.md +35 -0
  14. package/install/templates/.claude/workflows/check-implementation-readiness.js +280 -0
  15. package/install/templates/.claude/workflows/code-review.js +179 -0
  16. package/install/templates/.claude/workflows/create-excalidraw-dataflow.js +214 -0
  17. package/install/templates/.claude/workflows/create-excalidraw-diagram.js +188 -0
  18. package/install/templates/.claude/workflows/create-excalidraw-flowchart.js +225 -0
  19. package/install/templates/.claude/workflows/create-excalidraw-wireframe.js +192 -0
  20. package/install/templates/.claude/workflows/create-story.js +216 -0
  21. package/install/templates/.claude/workflows/dev-story.js +100 -0
  22. package/install/templates/.claude/workflows/document-project.js +455 -0
  23. package/install/templates/.claude/workflows/qa-automate.js +169 -0
  24. package/install/templates/.claude/workflows/quick-dev.js +273 -0
  25. package/install/templates/.claude/workflows/sprint-planning.js +261 -0
  26. package/install/templates/.claude/workflows/testarch-atdd.js +287 -0
  27. package/install/templates/.claude/workflows/testarch-automate.js +229 -0
  28. package/install/templates/.claude/workflows/testarch-ci.js +184 -0
  29. package/install/templates/.claude/workflows/testarch-framework.js +267 -0
  30. package/install/templates/.claude/workflows/testarch-nfr.js +316 -0
  31. package/install/templates/.claude/workflows/testarch-test-design.js +293 -0
  32. package/install/templates/.claude/workflows/testarch-test-review.js +321 -0
  33. package/install/templates/.claude/workflows/testarch-trace.js +316 -0
  34. package/install/templates/.githooks/pre-commit +49 -15
  35. package/install/templates/_byan/config.yaml +15 -5
  36. package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-build-workflows.js +20 -0
  37. package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-lint-workflows.js +57 -0
  38. package/install/templates/_byan/mcp/byan-mcp-server/lib/native-loop.js +39 -0
  39. package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-generator.js +149 -0
  40. package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-lint.js +113 -0
  41. package/install/templates/_byan/workflow/simple/byan/feature-workflow.md +14 -11
  42. package/install/templates/docs/native-workflows-contract.md +84 -0
  43. package/package.json +2 -2
  44. package/src/byan-v2/data/agent-scopes.json +46 -0
  45. package/src/byan-v2/data/mantras.json +194 -8
  46. package/src/byan-v2/generation/mantra-audit.js +147 -0
  47. package/src/byan-v2/generation/mantra-validator.js +56 -6
  48. package/src/byan-v2/generation/scope-resolver.js +102 -0
  49. package/src/byan-v2/generation/templates/default-agent.md +1 -1
@@ -0,0 +1,316 @@
1
+ export const meta = {
2
+ name: 'testarch-nfr',
3
+ description: 'Native port of the BYAN testarch-nfr workflow (create mode): assess non-functional requirements before release with evidence-based PASS/CONCERNS/FAIL outcomes. Load context+knowledge, define NFR categories+thresholds, gather evidence, fan out 4 parallel domain subprocesses (security/performance/reliability/scalability), aggregate into an executive summary, generate the report, then return a structured verdict for the orchestrating skill to present at the human gate.',
4
+ phases: [
5
+ { title: 'CONTEXT', detail: 'step-01: load NFR requirements, evidence sources, knowledge base' },
6
+ { title: 'THRESHOLDS', detail: 'step-02: select NFR categories (ADR 8) + extract/UNKNOWN thresholds' },
7
+ { title: 'EVIDENCE', detail: 'step-03: gather measurable evidence per category; gaps -> CONCERNS' },
8
+ { title: 'ASSESS', detail: 'step-04: parallel fan-out of 4 NFR domain subprocesses (security/performance/reliability/scalability)' },
9
+ { title: 'AGGREGATE', detail: 'step-04e: read 4 outputs, overall risk, compliance, cross-domain risks, exec summary' },
10
+ { title: 'REPORT', detail: 'step-05: produce nfr-assessment.md, validate vs checklist, completion summary' },
11
+ ],
12
+ }
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // FD / STRICT STATE CONTRACT (re-asserted inline — enforcement-bridge).
16
+ //
17
+ // The in-CLI Workflow tool runs this script OUTSIDE the conversation turn, so
18
+ // BYAN's main-thread hooks (fd-phase-guard, strict-scope-guard, strict-stop-
19
+ // guard, mantra-validate) DO NOT fire here. This script therefore:
20
+ // - NEVER imports/requires _byan/.../lib/fd-state.js and NEVER writes
21
+ // fd-state.json directly (enforced by byan-lint-workflows.js).
22
+ // - uses NO wall-clock (wall-clock/wall-clock) and NO randomness (RNG):
23
+ // those break Workflow resume. The unique run id used by the source for
24
+ // the /tmp/tea-nfr-*-{timestamp}.json subprocess outputs is passed IN via
25
+ // args.runId (the source generated it with an injected timestamp).
26
+ // - returns DATA only. The orchestrating skill is the human-gated conductor;
27
+ // IT records FD/strict state via the byan_fd_* / byan_strict_* MCP tools
28
+ // AT the gate. The nfr-assessment.md report is the workflow's product,
29
+ // written by the REPORT leaf — that is the artifact, not platform state.
30
+ // ---------------------------------------------------------------------------
31
+
32
+ // Risk hierarchy mirrors steps-c/step-04e-aggregate-nfr.md (HIGH>MEDIUM>LOW>NONE).
33
+ // Inlined (sandbox forbids import) so the prose rule becomes a real reduction.
34
+ const RISK_RANK = { HIGH: 3, MEDIUM: 2, LOW: 1, NONE: 0 }
35
+ function overallRisk(levels) {
36
+ const max = levels.reduce((m, r) => Math.max(m, RISK_RANK[r] || 0), 0)
37
+ return Object.keys(RISK_RANK).find((k) => RISK_RANK[k] === max) || 'NONE'
38
+ }
39
+
40
+ // Per-domain subprocess output schema — mirrors the OUTPUT FORMAT JSON in
41
+ // steps-c/step-04a..04d (domain, risk_level, findings[], compliance, priority_actions, summary).
42
+ const DOMAIN_SCHEMA = {
43
+ type: 'object',
44
+ required: ['domain', 'risk_level', 'findings', 'summary'],
45
+ properties: {
46
+ domain: { type: 'string' },
47
+ risk_level: { type: 'string', enum: ['HIGH', 'MEDIUM', 'LOW', 'NONE'] },
48
+ findings: {
49
+ type: 'array',
50
+ items: {
51
+ type: 'object',
52
+ required: ['category', 'status'],
53
+ properties: {
54
+ category: { type: 'string' },
55
+ status: { type: 'string', enum: ['PASS', 'CONCERN', 'FAIL', 'N/A'] },
56
+ description: { type: 'string' },
57
+ evidence: { type: 'array', items: { type: 'string' } },
58
+ recommendations: { type: 'array', items: { type: 'string' } },
59
+ },
60
+ },
61
+ },
62
+ compliance: { type: 'object' },
63
+ priority_actions: { type: 'array', items: { type: 'string' } },
64
+ summary: { type: 'string' },
65
+ },
66
+ }
67
+
68
+ const story = (args && args.story) || (args && args.target) || 'the implementation under release review'
69
+ const runId = (args && args.runId) || (args && args.timestamp) || 'nfr-run'
70
+ const customCategories = (args && args.customNfrCategories) || ''
71
+
72
+ // === Step 1: Load Context & Knowledge Base (steps-c/step-01) ===
73
+ phase('CONTEXT')
74
+ const context = await agent(
75
+ `You are the Master Test Architect running testarch-nfr (create mode). Target: ${JSON.stringify(story)}. ` +
76
+ `Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-01-load-context.md and follow it.\n` +
77
+ `1) Verify prerequisites: implementation accessible for evaluation AND evidence sources available (test results, metrics, logs). If either is missing, set halt=true and name the missing inputs (do NOT invent evidence).\n` +
78
+ `2) Load knowledge fragments from the tea index (adr-quality-readiness-checklist, ci-burn-in, test-quality, playwright-config, error-handling).\n` +
79
+ `3) If available, read tech-spec.md (primary NFRs), PRD.md (product NFRs), story/test-design docs (feature NFRs).\n` +
80
+ `4) Summarize the loaded NFR sources and evidence availability.`,
81
+ {
82
+ label: 'load-context',
83
+ phase: 'CONTEXT',
84
+ schema: {
85
+ type: 'object',
86
+ required: ['halt'],
87
+ properties: {
88
+ halt: { type: 'boolean', description: 'true if prerequisites (implementation or evidence) are missing' },
89
+ missingInputs: { type: 'array', items: { type: 'string' } },
90
+ nfrSources: { type: 'array', items: { type: 'string' } },
91
+ evidenceAvailable: { type: 'array', items: { type: 'string' } },
92
+ summary: { type: 'string' },
93
+ },
94
+ },
95
+ }
96
+ )
97
+
98
+ if (context && context.halt) {
99
+ // step-01 mandatory rule: HALT if implementation or evidence is unavailable.
100
+ // Surface as a verdict (gap, not silent cut); the gate decides.
101
+ return {
102
+ workflow: 'testarch-nfr',
103
+ target: story,
104
+ status: 'halted-missing-inputs',
105
+ summary: 'NFR assessment halted at CONTEXT: prerequisites (implementation/evidence) missing.',
106
+ missingInputs: (context && context.missingInputs) || [],
107
+ steps: 6,
108
+ needsHumanGate: true,
109
+ }
110
+ }
111
+
112
+ // === Step 2: Define NFR Categories & Thresholds (steps-c/step-02) ===
113
+ phase('THRESHOLDS')
114
+ const thresholds = await agent(
115
+ `testarch-nfr step 2 (define thresholds). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-02-define-thresholds.md.\n` +
116
+ `Context summary: ${JSON.stringify((context && context.summary) || '')}.\n` +
117
+ `1) Select the 8 ADR Quality Readiness categories (Testability & Automation, Test Data Strategy, Scalability & Availability, Disaster Recovery, Security, Monitorability/Debuggability/Manageability, QoS/QoE, Deployability). Add any custom categories: ${JSON.stringify(customCategories)}.\n` +
118
+ `2) For each category extract thresholds from tech-spec (primary), PRD (secondary), story/test-design (feature-specific). NEVER guess a threshold: if unknown, mark it UNKNOWN and plan to report CONCERNS for it.\n` +
119
+ `3) Produce the NFR matrix: each category with its threshold or UNKNOWN status.`,
120
+ {
121
+ label: 'define-thresholds',
122
+ phase: 'THRESHOLDS',
123
+ schema: {
124
+ type: 'object',
125
+ required: ['matrix'],
126
+ properties: {
127
+ matrix: {
128
+ type: 'array',
129
+ items: {
130
+ type: 'object',
131
+ required: ['category', 'threshold'],
132
+ properties: {
133
+ category: { type: 'string' },
134
+ threshold: { type: 'string', description: 'concrete threshold or "UNKNOWN"' },
135
+ unknown: { type: 'boolean' },
136
+ },
137
+ },
138
+ },
139
+ notes: { type: 'string' },
140
+ },
141
+ },
142
+ }
143
+ )
144
+
145
+ // === Step 3: Gather Evidence (steps-c/step-03) ===
146
+ phase('EVIDENCE')
147
+ const evidence = await agent(
148
+ `testarch-nfr step 3 (gather evidence). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-03-gather-evidence.md.\n` +
149
+ `NFR matrix: ${JSON.stringify((thresholds && thresholds.matrix) || [])}.\n` +
150
+ `1) Collect MEASURABLE evidence per category: Performance (load tests, metrics, response-time data); Security (scans, auth tests, vuln reports); Reliability (error rates, burn-in runs, failover tests); Maintainability (test quality, code-health signals); Other (logs, monitoring, DR drills, deployability checks).\n` +
151
+ `2) Where evidence is MISSING for a category, mark that category CONCERNS (do not fabricate evidence).`,
152
+ {
153
+ label: 'gather-evidence',
154
+ phase: 'EVIDENCE',
155
+ schema: {
156
+ type: 'object',
157
+ required: ['evidenceByCategory'],
158
+ properties: {
159
+ evidenceByCategory: {
160
+ type: 'array',
161
+ items: {
162
+ type: 'object',
163
+ required: ['category'],
164
+ properties: {
165
+ category: { type: 'string' },
166
+ evidence: { type: 'array', items: { type: 'string' } },
167
+ missing: { type: 'boolean', description: 'true -> category marked CONCERNS for evidence gap' },
168
+ },
169
+ },
170
+ },
171
+ gaps: { type: 'array', items: { type: 'string' } },
172
+ notes: { type: 'string' },
173
+ },
174
+ },
175
+ }
176
+ )
177
+
178
+ // === Step 4: Orchestrate parallel NFR assessment — 4 subprocesses (steps-c/step-04 + 04a..04d) ===
179
+ // Source step-04 launches FOUR subprocesses in PARALLEL and waits for ALL.
180
+ // parallel() mirrors that fan-out exactly; each subprocess assesses ONE domain
181
+ // and writes /tmp/tea-nfr-<domain>-<runId>.json. runId is passed via args (no clock).
182
+ phase('ASSESS')
183
+ const sharedContext =
184
+ `Shared context — system: ${JSON.stringify((context && context.summary) || '')}; ` +
185
+ `thresholds: ${JSON.stringify((thresholds && thresholds.matrix) || [])}; ` +
186
+ `evidence: ${JSON.stringify((evidence && evidence.evidenceByCategory) || [])}. ` +
187
+ `Run id (use for the temp output file name): ${JSON.stringify(runId)}.`
188
+
189
+ const [security, performance, reliability, scalability] = await parallel([
190
+ () =>
191
+ agent(
192
+ `testarch-nfr subprocess 4A (SECURITY only). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-04a-subprocess-security.md.\n` +
193
+ `${sharedContext}\n` +
194
+ `Assess SECURITY ONLY (auth/authz, data protection, input validation, API security, secrets management). ` +
195
+ `Set per-finding status PASS/CONCERN/FAIL/N/A, a domain risk_level (HIGH/MEDIUM/LOW/NONE), compliance (SOC2/GDPR/HIPAA/PCI-DSS/ISO27001), priority_actions and a summary. ` +
196
+ `Write the JSON to /tmp/tea-nfr-security-${runId}.json. Do NOT assess other domains.`,
197
+ { label: 'sub-security', phase: 'ASSESS', schema: DOMAIN_SCHEMA }
198
+ ),
199
+ () =>
200
+ agent(
201
+ `testarch-nfr subprocess 4B (PERFORMANCE only). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-04b-subprocess-performance.md.\n` +
202
+ `${sharedContext}\n` +
203
+ `Assess PERFORMANCE ONLY (response times, throughput, resource usage, optimization/caching/CDN/indexing). ` +
204
+ `Set per-finding status, domain risk_level, compliance (SLA tiers), priority_actions and a summary. ` +
205
+ `Write the JSON to /tmp/tea-nfr-performance-${runId}.json. Do NOT assess other domains.`,
206
+ { label: 'sub-performance', phase: 'ASSESS', schema: DOMAIN_SCHEMA }
207
+ ),
208
+ () =>
209
+ agent(
210
+ `testarch-nfr subprocess 4C (RELIABILITY only). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-04c-subprocess-reliability.md.\n` +
211
+ `${sharedContext}\n` +
212
+ `Assess RELIABILITY ONLY (error handling/circuit breakers/retries, monitoring & observability, fault tolerance/failover/backup/DR, uptime & availability). ` +
213
+ `Set per-finding status, domain risk_level, compliance, priority_actions and a summary. ` +
214
+ `Write the JSON to /tmp/tea-nfr-reliability-${runId}.json. Do NOT assess other domains.`,
215
+ { label: 'sub-reliability', phase: 'ASSESS', schema: DOMAIN_SCHEMA }
216
+ ),
217
+ () =>
218
+ agent(
219
+ `testarch-nfr subprocess 4D (SCALABILITY only). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-04d-subprocess-scalability.md.\n` +
220
+ `${sharedContext}\n` +
221
+ `Assess SCALABILITY ONLY (horizontal scaling, vertical scaling, data scaling/sharding/replicas, traffic handling/CDN/queues). ` +
222
+ `Set per-finding status, domain risk_level, compliance (user-scale tiers), priority_actions and a summary. ` +
223
+ `Write the JSON to /tmp/tea-nfr-scalability-${runId}.json. Do NOT assess other domains.`,
224
+ { label: 'sub-scalability', phase: 'ASSESS', schema: DOMAIN_SCHEMA }
225
+ ),
226
+ ])
227
+
228
+ // === Step 4E: Aggregate the 4 domain assessments (steps-c/step-04e) ===
229
+ phase('AGGREGATE')
230
+ const domainRisks = [security, performance, reliability, scalability].map((d) => (d && d.risk_level) || 'NONE')
231
+ const computedOverall = overallRisk(domainRisks)
232
+ log(`domain risks: security=${domainRisks[0]} performance=${domainRisks[1]} reliability=${domainRisks[2]} scalability=${domainRisks[3]} -> overall=${computedOverall}`)
233
+
234
+ const aggregate = await agent(
235
+ `testarch-nfr step 4E (aggregate). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-04e-aggregate-nfr.md.\n` +
236
+ `Four domain outputs: security=${JSON.stringify(security)}; performance=${JSON.stringify(performance)}; reliability=${JSON.stringify(reliability)}; scalability=${JSON.stringify(scalability)}.\n` +
237
+ `Computed overall risk (HIGH>MEDIUM>LOW>NONE) is ${JSON.stringify(computedOverall)} — use it.\n` +
238
+ `Do NOT re-assess any domain (use the subprocess outputs). 1) Aggregate compliance per standard: FAIL if any domain FAILs, else PARTIAL if any PARTIAL/CONCERN, else PASS. ` +
239
+ `2) Identify cross-domain risks (e.g. performance+scalability concerns; security FAIL + reliability concern). ` +
240
+ `3) Aggregate priority actions, marking URGENT those from a HIGH-risk domain. ` +
241
+ `4) Produce an executive summary (overall risk, per-domain breakdown, compliance summary, cross-domain risks, prioritized actions).`,
242
+ {
243
+ label: 'aggregate',
244
+ phase: 'AGGREGATE',
245
+ schema: {
246
+ type: 'object',
247
+ required: ['overallRisk', 'riskBreakdown'],
248
+ properties: {
249
+ overallRisk: { type: 'string', enum: ['HIGH', 'MEDIUM', 'LOW', 'NONE'] },
250
+ riskBreakdown: {
251
+ type: 'object',
252
+ properties: {
253
+ security: { type: 'string' },
254
+ performance: { type: 'string' },
255
+ reliability: { type: 'string' },
256
+ scalability: { type: 'string' },
257
+ },
258
+ },
259
+ complianceSummary: { type: 'object' },
260
+ crossDomainRisks: { type: 'array', items: { type: 'object' } },
261
+ priorityActions: { type: 'array', items: { type: 'object' } },
262
+ executiveSummary: { type: 'string' },
263
+ },
264
+ },
265
+ }
266
+ )
267
+
268
+ // === Step 5: Generate Report & Validate (steps-c/step-05) ===
269
+ phase('REPORT')
270
+ const report = await agent(
271
+ `testarch-nfr step 5 (generate report & validate). Read _byan/workflow/simple/testarch/nfr-assess/steps-c/step-05-generate-report.md, the nfr-report-template.md, and the workflow checklist.md.\n` +
272
+ `Executive aggregate: ${JSON.stringify(aggregate)}.\n` +
273
+ `1) Using nfr-report-template.md, write the report to the configured output folder as nfr-assessment.md: per-category results (PASS/CONCERNS/FAIL), evidence summary, remediation actions, and a gate-ready YAML snippet if applicable. ` +
274
+ `2) Validate the report against checklist.md and fix any gaps. ` +
275
+ `3) Completion summary: overall NFR status, critical blockers or waivers needed, and the next recommended workflow (trace or release gate).`,
276
+ {
277
+ label: 'generate-report',
278
+ phase: 'REPORT',
279
+ schema: {
280
+ type: 'object',
281
+ required: ['reportPath', 'overallStatus', 'valid'],
282
+ properties: {
283
+ reportPath: { type: 'string' },
284
+ overallStatus: { type: 'string', enum: ['PASS', 'CONCERNS', 'FAIL'] },
285
+ valid: { type: 'boolean', description: 'true only if the report satisfies checklist.md' },
286
+ blockers: { type: 'array', items: { type: 'string' } },
287
+ waiversNeeded: { type: 'array', items: { type: 'string' } },
288
+ nextWorkflow: { type: 'string' },
289
+ gaps: { type: 'array', items: { type: 'string' } },
290
+ summary: { type: 'string' },
291
+ },
292
+ },
293
+ }
294
+ )
295
+
296
+ // Return DATA only. The orchestrating skill presents this at the human gate
297
+ // and records FD/strict state via MCP. No platform state is written here.
298
+ return {
299
+ workflow: 'testarch-nfr',
300
+ target: story,
301
+ status: report && report.valid ? 'nfr-assessed' : 'gaps-found',
302
+ overallRisk: (aggregate && aggregate.overallRisk) || computedOverall,
303
+ overallStatus: (report && report.overallStatus) || 'CONCERNS',
304
+ riskBreakdown: (aggregate && aggregate.riskBreakdown) || {
305
+ security: domainRisks[0],
306
+ performance: domainRisks[1],
307
+ reliability: domainRisks[2],
308
+ scalability: domainRisks[3],
309
+ },
310
+ reportPath: (report && report.reportPath) || '',
311
+ blockers: (report && report.blockers) || [],
312
+ nextWorkflow: (report && report.nextWorkflow) || 'trace',
313
+ steps: 6,
314
+ needsHumanGate: true,
315
+ result: report,
316
+ }
@@ -0,0 +1,293 @@
1
+ export const meta = {
2
+ name: 'testarch-test-design',
3
+ description: 'Native port of the BYAN testarch-test-design workflow (create mode): a dual-mode (system-level vs epic-level) test-design engine that detects mode, loads context + TEA knowledge fragments, performs testability + risk assessment, designs a coverage/priority/execution plan, then generates the output document(s) and validates them against the checklist. Returns a structured verdict for the orchestrating skill to present at the human gate.',
4
+ phases: [
5
+ { title: 'DETECT-MODE', detail: 'system-level vs epic-level + prerequisite check' },
6
+ { title: 'LOAD-CONTEXT', detail: 'load artifacts, config flags, TEA knowledge fragments' },
7
+ { title: 'RISK-AND-TESTABILITY', detail: 'testability review (system-level) + risk matrix (all modes)' },
8
+ { title: 'COVERAGE-PLAN', detail: 'coverage matrix, priorities, execution strategy, estimates, gates' },
9
+ { title: 'GENERATE-OUTPUT', detail: 'write template(s) and validate against checklist' },
10
+ ],
11
+ }
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // FD / STRICT STATE CONTRACT (re-asserted inline — enforcement-bridge).
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/RNG
22
+ // 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 mode-detection question and the team-review gate stay
26
+ // OUT of this script — the script surfaces them as verdict fields.
27
+ // The test-design document(s) ARE the workflow's product, written by the
28
+ // generate leaf — that is the artifact, not BYAN platform state.
29
+ // ---------------------------------------------------------------------------
30
+
31
+ // Inputs arrive via args (sandbox: no fs, no clock, no RNG). `mode` may force
32
+ // 'system-level' or 'epic-level'; default 'auto-detect' lets the detect leaf
33
+ // resolve it per the source priority order. `date` is passed in for stamping.
34
+ const requestedMode = (args && args.mode) || 'auto-detect'
35
+ const epicNum = (args && args.epicNum) || null
36
+ const designLevel = (args && args.designLevel) || 'full'
37
+ const date = (args && args.date) || null
38
+
39
+ const SOURCE = '_byan/workflow/simple/testarch/test-design'
40
+
41
+ // ---- STEP 1 : Detect Mode & Prerequisites (steps-c/step-01-detect-mode.md) --
42
+ phase('DETECT-MODE')
43
+ const DETECT_SCHEMA = {
44
+ type: 'object',
45
+ required: ['mode', 'prerequisitesMet'],
46
+ properties: {
47
+ mode: { type: 'string', enum: ['system-level', 'epic-level', 'ambiguous'], description: 'resolved mode; "ambiguous" if it cannot be decided without the user' },
48
+ rationale: { type: 'string', description: 'why this mode (user intent > file-based detection > ask)' },
49
+ prerequisitesMet: { type: 'boolean', description: 'true only if the mode-specific required inputs are present' },
50
+ missingInputs: { type: 'array', items: { type: 'string' }, description: 'required inputs that are missing (HALT condition)' },
51
+ needsUserDecision: { type: 'boolean', description: 'true if mode is ambiguous and the user must choose A/B' },
52
+ },
53
+ }
54
+ const detect = await agent(
55
+ `You are the Master Test Architect running step 1 of the BYAN testarch-test-design workflow. ` +
56
+ `Read the COMPLETE source step ${SOURCE}/steps-c/step-01-detect-mode.md and the workflow.yaml in that folder. ` +
57
+ `Requested mode: ${JSON.stringify(requestedMode)} (auto-detect means resolve it yourself).\n` +
58
+ `Mode detection priority order (mirror the source exactly): ` +
59
+ `(A) explicit user intent — PRD+ADR with no epic/stories => system-level; epic+stories with no PRD/ADR => epic-level; both present => prefer system-level first. ` +
60
+ `(B) file-based — if {implementation_artifacts}/sprint-status.yaml exists => epic-level, otherwise system-level. ` +
61
+ `(C) still unclear => mark mode "ambiguous" and needsUserDecision true (do NOT guess).\n` +
62
+ `Then run the mode-specific prerequisite check: system-level requires PRD (FR+NFR) + ADR/architecture decisions + architecture/tech-spec; ` +
63
+ `epic-level requires epic/story requirements with acceptance criteria (+ architecture context if available). ` +
64
+ `If required inputs are missing, set prerequisitesMet false and list them in missingInputs (HALT condition — do not fabricate inputs). ` +
65
+ `State which mode you will use and why.`,
66
+ { label: 'detect-mode', phase: 'DETECT-MODE', schema: DETECT_SCHEMA }
67
+ )
68
+
69
+ // HALT conditions are surfaced to the orchestrating skill, not decided here.
70
+ const blocked = !detect.prerequisitesMet || detect.mode === 'ambiguous'
71
+ if (blocked) {
72
+ log('detect-mode requires a human decision or missing inputs; halting before context load')
73
+ return {
74
+ workflow: 'testarch-test-design',
75
+ summary: detect.mode === 'ambiguous'
76
+ ? 'mode ambiguous — user must choose system-level (A) or epic-level (B)'
77
+ : `prerequisites missing for ${detect.mode} mode`,
78
+ mode: detect.mode,
79
+ designLevel,
80
+ steps: 1,
81
+ halted: true,
82
+ needsHumanGate: true,
83
+ needsUserDecision: detect.mode === 'ambiguous',
84
+ missingInputs: detect.missingInputs || [],
85
+ detect,
86
+ }
87
+ }
88
+
89
+ const mode = detect.mode
90
+ log(`mode resolved: ${mode} (${detect.rationale || 'no rationale'})`)
91
+
92
+ // ---- STEP 2 : Load Context & Knowledge Base (steps-c/step-02-load-context) --
93
+ phase('LOAD-CONTEXT')
94
+ const LOAD_SCHEMA = {
95
+ type: 'object',
96
+ required: ['loaded'],
97
+ properties: {
98
+ loaded: { type: 'array', items: { type: 'string' }, description: 'artifacts + knowledge fragments actually loaded' },
99
+ teaUsePlaywrightUtils: { type: 'boolean', description: 'value of tea_use_playwright_utils from config' },
100
+ techStack: { type: 'array', items: { type: 'string' } },
101
+ integrationPoints: { type: 'array', items: { type: 'string' } },
102
+ nfrs: { type: 'array', items: { type: 'string' }, description: 'performance/security/reliability/compliance NFRs (system-level)' },
103
+ existingCoverageGaps: { type: 'array', items: { type: 'string' }, description: 'gaps + flaky areas found by scanning tests/ spec e2e api (epic-level)' },
104
+ missing: { type: 'array', items: { type: 'string' }, description: 'inputs the user still needs to provide' },
105
+ },
106
+ }
107
+ const context = await agent(
108
+ `Master Test Architect, step 2 of testarch-test-design (mode: ${mode}). ` +
109
+ `Read the COMPLETE source step ${SOURCE}/steps-c/step-02-load-context.md.\n` +
110
+ `1. Load config from _byan/tea/config.yaml: read tea_use_playwright_utils, note output_folder.\n` +
111
+ `2. Load mode-specific artifacts. system-level: PRD (FR+NFR), ADRs/architecture decisions, architecture/tech-spec, epics for scope; ` +
112
+ `extract tech stack & dependencies, integration points, NFRs (perf/security/reliability/compliance). ` +
113
+ `epic-level: epic + story docs with acceptance criteria, PRD if available, architecture/tech-spec if available, prior system-level test-design outputs if available; ` +
114
+ `extract testable requirements, integration points, known coverage gaps.\n` +
115
+ `3. epic-level only: scan the repo for existing tests (tests/, spec, e2e, api folders), identify coverage gaps and flaky areas, note existing fixture/test patterns.\n` +
116
+ `4. Load ONLY the relevant TEA knowledge fragments via {project-root}/_byan/connaissance/testarch/tea-index.csv. ` +
117
+ `system-level required: adr-quality-readiness-checklist.md, test-levels-framework.md, risk-governance.md, test-quality.md. ` +
118
+ `epic-level required: risk-governance.md, probability-impact.md, test-levels-framework.md, test-priorities-matrix.md.\n` +
119
+ `5. Summarize what was loaded; flag anything missing in "missing" (do not invent content).`,
120
+ { label: 'load-context', phase: 'LOAD-CONTEXT', schema: LOAD_SCHEMA }
121
+ )
122
+ log(`loaded ${context.loaded.length} artifacts/fragments`)
123
+
124
+ // ---- STEP 3 : Testability & Risk Assessment (steps-c/step-03-...) ----------
125
+ phase('RISK-AND-TESTABILITY')
126
+ const RISK_SCHEMA = {
127
+ type: 'object',
128
+ required: ['risks'],
129
+ properties: {
130
+ testabilityConcerns: { type: 'array', items: { type: 'string' }, description: 'system-level: actionable controllability/observability/reliability concerns' },
131
+ testabilityStrengths: { type: 'array', items: { type: 'string' }, description: 'system-level: what is already strong' },
132
+ asrs: {
133
+ type: 'array',
134
+ description: 'Architecturally Significant Requirements (system-level), each ACTIONABLE or FYI',
135
+ items: {
136
+ type: 'object',
137
+ required: ['requirement', 'classification'],
138
+ properties: {
139
+ requirement: { type: 'string' },
140
+ classification: { type: 'string', enum: ['ACTIONABLE', 'FYI'] },
141
+ },
142
+ },
143
+ },
144
+ risks: {
145
+ type: 'array',
146
+ description: 'risk matrix — genuine risks, not features',
147
+ items: {
148
+ type: 'object',
149
+ required: ['id', 'category', 'probability', 'impact', 'score'],
150
+ properties: {
151
+ id: { type: 'string', description: 'unique id R-001, R-002, ...' },
152
+ category: { type: 'string', enum: ['TECH', 'SEC', 'PERF', 'DATA', 'BUS', 'OPS'] },
153
+ description: { type: 'string' },
154
+ probability: { type: 'integer', minimum: 1, maximum: 3 },
155
+ impact: { type: 'integer', minimum: 1, maximum: 3 },
156
+ score: { type: 'integer', minimum: 1, maximum: 9, description: 'probability * impact' },
157
+ mitigation: { type: 'string' },
158
+ owner: { type: 'string' },
159
+ timeline: { type: 'string' },
160
+ },
161
+ },
162
+ },
163
+ highRisks: { type: 'array', items: { type: 'string' }, description: 'ids of risks with score >= 6' },
164
+ },
165
+ }
166
+ const risk = await agent(
167
+ `Master Test Architect, step 3 of testarch-test-design (mode: ${mode}). ` +
168
+ `Read the COMPLETE source step ${SOURCE}/steps-c/step-03-risk-and-testability.md. Base every conclusion on evidence from the loaded artifacts.\n` +
169
+ `1. system-level ONLY: evaluate architecture for Controllability (state seeding, mockability, fault injection), Observability (logs, metrics, traces, deterministic assertions), Reliability (isolation, reproducibility, parallel safety). ` +
170
+ `Structure: actionable Testability Concerns FIRST, then a Testability Assessment Summary of strengths. ` +
171
+ `Identify ASRs and mark each ACTIONABLE or FYI.\n` +
172
+ `2. ALL modes: risk assessment using risk-governance.md + probability-impact.md. Identify GENUINE risks (not features). ` +
173
+ `Classify by category TECH/SEC/PERF/DATA/BUS/OPS. Score Probability (1-3) and Impact (1-3). Compute Risk Score = P*I. ` +
174
+ `Flag high risks (score >= 6). Define mitigation, owner, timeline for high risks.\n` +
175
+ `3. Summarize the highest risks and their mitigation priorities.`,
176
+ { label: 'risk-and-testability', phase: 'RISK-AND-TESTABILITY', schema: RISK_SCHEMA }
177
+ )
178
+ log(`${risk.risks.length} risks; ${(risk.highRisks || []).length} high (>=6)`)
179
+
180
+ // ---- STEP 4 : Coverage Plan & Execution Strategy (steps-c/step-04-...) ------
181
+ phase('COVERAGE-PLAN')
182
+ const COVERAGE_SCHEMA = {
183
+ type: 'object',
184
+ required: ['scenarios', 'qualityGates'],
185
+ properties: {
186
+ scenarios: {
187
+ type: 'array',
188
+ description: 'coverage matrix — atomic scenarios, one test level each, no duplicate coverage',
189
+ items: {
190
+ type: 'object',
191
+ required: ['testId', 'testLevel', 'priority'],
192
+ properties: {
193
+ testId: { type: 'string' },
194
+ requirement: { type: 'string' },
195
+ testLevel: { type: 'string', enum: ['E2E', 'API', 'Component', 'Unit'] },
196
+ priority: { type: 'string', enum: ['P0', 'P1', 'P2', 'P3'] },
197
+ riskLink: { type: 'string', description: 'risk id this scenario covers' },
198
+ notes: { type: 'string' },
199
+ },
200
+ },
201
+ },
202
+ executionStrategy: {
203
+ type: 'object',
204
+ description: 'simple PR / Nightly / Weekly model — no smoke/P0/P1/P2 tier structure, no re-listing tests',
205
+ properties: {
206
+ pr: { type: 'string' },
207
+ nightly: { type: 'string' },
208
+ weekly: { type: 'string' },
209
+ },
210
+ },
211
+ resourceEstimates: {
212
+ type: 'object',
213
+ description: 'interval ranges only, no false precision',
214
+ properties: {
215
+ p0: { type: 'string' },
216
+ p1: { type: 'string' },
217
+ p2: { type: 'string' },
218
+ p3: { type: 'string' },
219
+ total: { type: 'string' },
220
+ timeline: { type: 'string' },
221
+ },
222
+ },
223
+ qualityGates: {
224
+ type: 'object',
225
+ required: ['p0PassRate'],
226
+ properties: {
227
+ p0PassRate: { type: 'string', description: '100%' },
228
+ p1PassRate: { type: 'string', description: '>= 95%' },
229
+ highRiskMitigation: { type: 'string', description: 'complete before release' },
230
+ coverageTarget: { type: 'string', description: '>= 80% unless justified' },
231
+ },
232
+ },
233
+ },
234
+ }
235
+ const coverage = await agent(
236
+ `Master Test Architect, step 4 of testarch-test-design (mode: ${mode}, design level: ${designLevel}). ` +
237
+ `Read the COMPLETE source step ${SOURCE}/steps-c/step-04-coverage-plan.md. Avoid redundant coverage across test levels.\n` +
238
+ `1. Coverage matrix: for each requirement or risk-driven scenario, decompose into atomic scenarios; select ONE test level (E2E/API/Component/Unit) via test-levels-framework.md; no duplicate coverage; assign priority P0-P3 via test-priorities-matrix.md. ` +
239
+ `Priority rules: P0 = blocks core functionality + high risk + no workaround; P1 = critical paths + medium/high risk; P2 = secondary flows + low/medium risk; P3 = nice-to-have/exploratory/benchmarks. Link scenarios to risk ids from step 3.\n` +
240
+ `2. Execution strategy = simple PR / Nightly / Weekly. PR = all functional tests if <15 min; Nightly/Weekly = long-running/expensive (perf, chaos, large datasets). Do NOT re-list all tests; do NOT build a smoke/P0/P1/P2 tier structure.\n` +
241
+ `3. Resource estimates as INTERVAL RANGES only (e.g. P0 ~25-40h) — no false precision; total + timeline as ranges.\n` +
242
+ `4. Quality gates: P0 pass rate = 100%, P1 pass rate >= 95%, high-risk mitigations complete before release, coverage target >= 80% (adjust only if justified).`,
243
+ { label: 'coverage-plan', phase: 'COVERAGE-PLAN', schema: COVERAGE_SCHEMA }
244
+ )
245
+ log(`${coverage.scenarios.length} scenarios planned`)
246
+
247
+ // ---- STEP 5 : Generate Outputs & Validate (steps-c/step-05-...) ------------
248
+ phase('GENERATE-OUTPUT')
249
+ const GENERATE_SCHEMA = {
250
+ type: 'object',
251
+ required: ['outputs', 'checklistPass'],
252
+ properties: {
253
+ outputs: { type: 'array', items: { type: 'string' }, description: 'output file path(s) written' },
254
+ templateUsed: { type: 'array', items: { type: 'string' }, description: 'template file(s) used' },
255
+ checklistPass: { type: 'boolean', description: 'true only if all checklist.md criteria are satisfied' },
256
+ checklistFailures: { type: 'array', items: { type: 'string' }, description: 'checklist items not satisfied (fix before completion)' },
257
+ openAssumptions: { type: 'array', items: { type: 'string' } },
258
+ needsEpicNum: { type: 'boolean', description: 'epic-level only: true if epic_num was unclear and must be asked' },
259
+ },
260
+ }
261
+ const generate = await agent(
262
+ `Master Test Architect, step 5 of testarch-test-design (mode: ${mode}). ` +
263
+ `Read the COMPLETE source step ${SOURCE}/steps-c/step-05-generate-output.md and the checklist ${SOURCE}/checklist.md.\n` +
264
+ `1. Select template(s) by mode. system-level (Phase 3) => TWO documents: {output_folder}/test-design-architecture.md from test-design-architecture-template.md, and {output_folder}/test-design-qa.md from test-design-qa-template.md. ` +
265
+ `epic-level (Phase 4) => ONE document: {output_folder}/test-design-epic-${epicNum || '{epic_num}'}.md from test-design-template.md` +
266
+ `${mode === 'epic-level' && !epicNum ? ' — epic_num is NOT provided, set needsEpicNum true and do NOT invent it' : ''}.\n` +
267
+ `2. Populate the template(s) using the step-3 risk matrix and step-4 coverage plan: risk assessment matrix, coverage matrix + priorities, execution strategy, resource estimates (ranges), quality-gate criteria, and any mode-specific sections the template requires. ` +
268
+ `tea_use_playwright_utils=${context.teaUsePlaywrightUtils === undefined ? 'unknown' : context.teaUsePlaywrightUtils} (drive the QA-doc code-example imports accordingly).\n` +
269
+ `3. Validate the output(s) against checklist.md item-by-item. If any criterion is unmet, FIX it before reporting; list any residual failures in checklistFailures and set checklistPass false.\n` +
270
+ `4. Completion report: mode used, output file path(s), key risks + gate thresholds, open assumptions.`,
271
+ { label: 'generate-output', phase: 'GENERATE-OUTPUT', schema: GENERATE_SCHEMA }
272
+ )
273
+ log(`outputs: ${(generate.outputs || []).join(', ') || 'none'} | checklist ${generate.checklistPass ? 'PASS' : 'FAIL'}`)
274
+
275
+ // Single top-level return — DATA only. The team-review gate (checklist
276
+ // Post-Workflow Actions) is the human decision and stays with the skill.
277
+ return {
278
+ workflow: 'testarch-test-design',
279
+ summary: `test design (${mode}) — ${coverage.scenarios.length} scenarios, ${risk.risks.length} risks, checklist ${generate.checklistPass ? 'PASS' : 'FAIL'}`,
280
+ mode,
281
+ designLevel,
282
+ epicNum,
283
+ date,
284
+ steps: 5,
285
+ halted: false,
286
+ needsHumanGate: true,
287
+ checklistPass: generate.checklistPass,
288
+ outputs: generate.outputs || [],
289
+ highRisks: risk.highRisks || [],
290
+ needsEpicNum: !!generate.needsEpicNum,
291
+ checklistFailures: generate.checklistFailures || [],
292
+ result: { detect, context, risk, coverage, generate },
293
+ }