@sun-asterisk/sungen 3.2.2-beta.1 → 3.2.2-beta.11

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 (45) hide show
  1. package/dist/cli/commands/depth-lint.d.ts +3 -0
  2. package/dist/cli/commands/depth-lint.d.ts.map +1 -0
  3. package/dist/cli/commands/depth-lint.js +88 -0
  4. package/dist/cli/commands/depth-lint.js.map +1 -0
  5. package/dist/cli/commands/gate.d.ts +3 -0
  6. package/dist/cli/commands/gate.d.ts.map +1 -0
  7. package/dist/cli/commands/gate.js +83 -0
  8. package/dist/cli/commands/gate.js.map +1 -0
  9. package/dist/cli/commands/journey.d.ts +3 -0
  10. package/dist/cli/commands/journey.d.ts.map +1 -0
  11. package/dist/cli/commands/journey.js +96 -0
  12. package/dist/cli/commands/journey.js.map +1 -0
  13. package/dist/cli/index.js +6 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/harness/depth-lint.d.ts +25 -0
  16. package/dist/harness/depth-lint.d.ts.map +1 -0
  17. package/dist/harness/depth-lint.js +118 -0
  18. package/dist/harness/depth-lint.js.map +1 -0
  19. package/dist/harness/journey.d.ts +68 -0
  20. package/dist/harness/journey.d.ts.map +1 -0
  21. package/dist/harness/journey.js +328 -0
  22. package/dist/harness/journey.js.map +1 -0
  23. package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +7 -0
  24. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +3 -0
  25. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +22 -3
  26. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +1 -0
  27. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +3 -0
  28. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +3 -0
  29. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +22 -3
  30. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +1 -0
  31. package/package.json +3 -3
  32. package/src/cli/commands/depth-lint.ts +51 -0
  33. package/src/cli/commands/gate.ts +44 -0
  34. package/src/cli/commands/journey.ts +59 -0
  35. package/src/cli/index.ts +6 -0
  36. package/src/harness/depth-lint.ts +122 -0
  37. package/src/harness/journey.ts +333 -0
  38. package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +7 -0
  39. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +3 -0
  40. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +22 -3
  41. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +1 -0
  42. package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +3 -0
  43. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +3 -0
  44. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +22 -3
  45. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +1 -0
@@ -0,0 +1,328 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runJourney = runJourney;
37
+ exports.waive = waive;
38
+ exports.signoff = signoff;
39
+ exports.renderJourneyBoard = renderJourneyBoard;
40
+ exports.runGate = runGate;
41
+ exports.renderGate = renderGate;
42
+ /**
43
+ * Journey board (epic #381, story S1) — the durable, read-only "you are here" view.
44
+ *
45
+ * Reconstructs the QA's position from artifacts ALREADY on disk (no recomputation, no context
46
+ * needed): the audit report (`.sungen/reports/<slug>-audit.json`) supplies the obligation status
47
+ * via its calibration axes + gate + findings; the ledger (`.sungen/ledger/<slug>.jsonl`) supplies
48
+ * the phase history ("you are here"). The output answers the three QA questions — what's next /
49
+ * what to review / what's doubtful — and persists `.sungen/journey/<slug>.{json,board.md}`.
50
+ *
51
+ * S1 = the read-only synthesis. S2 (this file) adds the **writable lifecycle**: persisted
52
+ * waivers (reason-required, anti-amnesia), reconcile (auto-close satisfied; re-surface a waiver
53
+ * when its evidence changed), via `runJourney` + `waive`. Gate-bound predicates + inter-phase
54
+ * gates are S3. Pure-deterministic, no AI.
55
+ */
56
+ const fs = __importStar(require("fs"));
57
+ const path = __importStar(require("path"));
58
+ const crypto = __importStar(require("crypto"));
59
+ const unit_paths_1 = require("./unit-paths");
60
+ function readJSON(p) {
61
+ try {
62
+ return fs.existsSync(p) ? JSON.parse(fs.readFileSync(p, 'utf-8')) : null;
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ function readLedgerPhases(p) {
69
+ if (!fs.existsSync(p))
70
+ return [];
71
+ const out = [];
72
+ for (const line of fs.readFileSync(p, 'utf-8').split('\n')) {
73
+ if (!line.trim())
74
+ continue;
75
+ try {
76
+ const d = JSON.parse(line);
77
+ if (d.step)
78
+ out.push(String(d.step));
79
+ }
80
+ catch { /* skip */ }
81
+ }
82
+ return out;
83
+ }
84
+ /** Findings that ask for HUMAN judgment (the review-queue seed), vs pure machine-repair targets. */
85
+ function isHumanFinding(f) {
86
+ return /@manual|MANUAL-|DEPTH-DEFERRED|UNSOURCEABLE|CAPABILITY-SUGGESTION|judgment|oracle|review/i.test(f);
87
+ }
88
+ /** S5 — pull an IDE-jumpable anchor out of a finding (VP id, scenario, or `file.ext:line`). */
89
+ function extractAnchor(text) {
90
+ const vp = text.match(/\bVP-[A-Z0-9-]+\b/);
91
+ const fl = text.match(/([\w./-]+\.(?:md|feature|ts|yaml)):(\d+)/);
92
+ return { vpId: vp ? vp[0] : undefined, file: fl ? fl[1] : undefined, line: fl ? Number(fl[2]) : undefined };
93
+ }
94
+ const SAT = 0.8; // axis at/above this = satisfied (below = needs-work)
95
+ function computeFresh(projectRoot, unit) {
96
+ const slug = (0, unit_paths_1.reportSlug)(unit);
97
+ const audit = readJSON(path.join(projectRoot, '.sungen', 'reports', `${slug}-audit.json`));
98
+ const phases = readLedgerPhases(path.join(projectRoot, '.sungen', 'ledger', `${slug}.jsonl`));
99
+ const from = [];
100
+ if (audit)
101
+ from.push('audit');
102
+ if (phases.length)
103
+ from.push('ledger');
104
+ const youAreHere = phases.length ? phases[phases.length - 1] : 'not started';
105
+ const ran = (p) => phases.some((s) => s === p || s.startsWith(p));
106
+ const obligations = [];
107
+ const needsYou = [];
108
+ if (!audit) {
109
+ // Nothing measured yet — the journey hasn't really begun.
110
+ obligations.push({ id: 'OB-create', title: 'Generate test cases', status: 'pending', detail: 'No audit report yet — run /sungen:create-test.' });
111
+ return {
112
+ unit, generatedFrom: from, youAreHere, phasesDone: phases, gateStatus: null, score: null,
113
+ obligations, needsYou, nextSuggested: 'Run `/sungen:create-test ' + unit + '` to begin.',
114
+ };
115
+ }
116
+ const ax = (audit.calibration && audit.calibration.axes) || {};
117
+ const depthThreshold = (audit.depth && audit.depth.threshold) || SAT;
118
+ const ob = (id, title, val, thr, detail) => ({
119
+ id, title,
120
+ status: val === undefined ? 'pending' : val >= thr ? 'satisfied' : 'needs-work',
121
+ detail: val === undefined ? detail : `${Math.round(val * 100)}% (need ${Math.round(thr * 100)}%) — ${detail}`,
122
+ });
123
+ obligations.push(ob('OB-spec', 'Spec readiness', ax.specFR, 1, 'FR/sections sufficient to design from'));
124
+ obligations.push(ob('OB-coverage', 'Viewpoint coverage', ax.coverage, SAT, 'critical themes covered'));
125
+ obligations.push(ob('OB-depth', 'Assertion depth', ax.businessDepth, depthThreshold, 'business-critical scenarios assert data'));
126
+ obligations.push(ob('OB-trace', 'Traceability', ax.taxonomy ?? ax.traceability, SAT, 'scenarios trace to viewpoints'));
127
+ // Automation obligation: automatable @manual still pending a driver = needs-work.
128
+ const autoPending = audit.automatableManual && audit.automatableManual.automatable > 0;
129
+ obligations.push({
130
+ id: 'OB-automation', title: 'Automation coverage',
131
+ status: autoPending ? 'needs-work' : 'satisfied',
132
+ detail: autoPending ? `${audit.automatableManual.automatable} @manual scenario(s) a driver could automate` : 'no capability-pending automatable cases',
133
+ });
134
+ // Human sign-off: always pending until S5 explicit signoff; carries the review-queue count.
135
+ const manualCount = (audit.manualOracle && audit.manualOracle.total) || 0;
136
+ obligations.push({
137
+ id: 'OB-signoff', title: 'Human sign-off', status: 'pending',
138
+ detail: `${needsYou.length} item(s) queued for your review (single sign-off at the end)`,
139
+ });
140
+ // Needs-you: human-judgment findings (the review-queue seed), with their anchors (titles) intact.
141
+ for (const f of (audit.findings || []))
142
+ if (isHumanFinding(f))
143
+ needsYou.push({ text: f, anchor: extractAnchor(f) });
144
+ // Re-stamp the signoff detail now that needsYou is filled.
145
+ const signoff = obligations.find((o) => o.id === 'OB-signoff');
146
+ if (signoff)
147
+ signoff.detail = `${needsYou.length} item(s) queued for your review · ${manualCount} @manual scenario(s)`;
148
+ // Next suggested = first non-satisfied obligation; if all satisfied but run-test not done → run.
149
+ const firstGap = obligations.find((o) => o.status !== 'satisfied' && o.id !== 'OB-signoff');
150
+ let nextSuggested;
151
+ if (firstGap)
152
+ nextSuggested = `Repair "${firstGap.title}" (${firstGap.detail}).`;
153
+ else if (!ran('run'))
154
+ nextSuggested = `Quality satisfied — run \`/sungen:run-test ${unit}\`.`;
155
+ else
156
+ nextSuggested = `All obligations satisfied — review the ${needsYou.length} queued item(s), then sign off & deliver.`;
157
+ return {
158
+ unit, generatedFrom: from, youAreHere, phasesDone: phases,
159
+ gateStatus: audit.gateStatus ?? null, score: (audit.score && audit.score.overall) ?? null,
160
+ obligations, needsYou, nextSuggested,
161
+ };
162
+ }
163
+ function statePath(projectRoot, slug) {
164
+ return path.join(projectRoot, '.sungen', 'journey', `${slug}.state.json`);
165
+ }
166
+ /** Evidence cursor: the audit report's content hash. A waiver is invalidated when this changes. */
167
+ function auditHashOf(projectRoot, slug) {
168
+ const p = path.join(projectRoot, '.sungen', 'reports', `${slug}-audit.json`);
169
+ return fs.existsSync(p) ? crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex') : '';
170
+ }
171
+ function loadState(p) { return readJSON(p); }
172
+ function saveState(p, s) {
173
+ fs.mkdirSync(path.dirname(p), { recursive: true });
174
+ fs.writeFileSync(p, JSON.stringify(s, null, 2), 'utf-8');
175
+ }
176
+ /** Recompute nextSuggested AFTER waivers are applied (a waived obligation is not a gap). */
177
+ function computeNext(r, unit) {
178
+ const gap = r.obligations.find((o) => o.status !== 'satisfied' && o.status !== 'waived' && o.id !== 'OB-signoff');
179
+ if (gap)
180
+ return `Repair "${gap.title}" (${gap.detail}).`;
181
+ if (!r.phasesDone.some((s) => s === 'run' || s.startsWith('run')))
182
+ return `Quality satisfied — run \`/sungen:run-test ${unit}\`.`;
183
+ return `All obligations satisfied/waived — review the ${r.needsYou.length} queued item(s), then sign off & deliver.`;
184
+ }
185
+ /**
186
+ * The public entry: compute fresh, then RECONCILE with the persisted state —
187
+ * - auto-close is automatic (fresh recompute reflects the current artifacts);
188
+ * - an active waiver (evidence unchanged) sets status='waived' (carries the reason);
189
+ * - a STALE waiver (audit changed since it was waived) is re-surfaced for re-decision (anti-amnesia).
190
+ * Then persist the current evidence cursor.
191
+ */
192
+ function runJourney(projectRoot, unit) {
193
+ const slug = (0, unit_paths_1.reportSlug)(unit);
194
+ const report = computeFresh(projectRoot, unit);
195
+ const sp = statePath(projectRoot, slug);
196
+ const state = loadState(sp) || { unit, auditHash: '', waivers: {} };
197
+ const curHash = auditHashOf(projectRoot, slug);
198
+ for (const ob of report.obligations) {
199
+ const w = state.waivers[ob.id];
200
+ if (!w)
201
+ continue;
202
+ if (w.auditHashAtWaive === curHash) {
203
+ ob.status = 'waived';
204
+ ob.waivedReason = w.reason;
205
+ ob.detail = `waived — ${w.reason}`;
206
+ }
207
+ else {
208
+ report.needsYou.unshift({ text: `⚠️ Waiver on "${ob.title}" is STALE (evidence changed since ${w.at}) — re-decide. Was: ${w.reason}`, anchor: { vpId: ob.id } });
209
+ }
210
+ }
211
+ // S5 — sign-off reconcile: a recorded sign-off satisfies OB-signoff while its evidence holds;
212
+ // if the audit changed since, the sign-off is STALE → re-surface for re-review (anti-amnesia).
213
+ const signoffOb = report.obligations.find((o) => o.id === 'OB-signoff');
214
+ if (signoffOb && state.signoff) {
215
+ if (state.signoff.auditHashAtSignoff === curHash) {
216
+ signoffOb.status = 'satisfied';
217
+ signoffOb.detail = `signed off${state.signoff.by ? ' by ' + state.signoff.by : ''} at ${state.signoff.at}`;
218
+ }
219
+ else {
220
+ report.needsYou.unshift({ text: `⚠️ Sign-off is STALE (suite changed since ${state.signoff.at}) — re-review and sign off again.`, anchor: { vpId: 'OB-signoff' } });
221
+ }
222
+ }
223
+ report.nextSuggested = computeNext(report, unit);
224
+ saveState(sp, { unit, auditHash: curHash, waivers: state.waivers, signoff: state.signoff });
225
+ return report;
226
+ }
227
+ /**
228
+ * Waive an obligation — REQUIRES a reason (anti-amnesia: a waiver leaves a recorded "why").
229
+ * Records the current evidence cursor so reconcile can invalidate it if the audit changes.
230
+ */
231
+ function waive(projectRoot, unit, obId, reason) {
232
+ if (!reason || !reason.trim()) {
233
+ throw new Error('A reason is required to waive (anti-amnesia: a waiver must record WHY). Use --reason "...".');
234
+ }
235
+ const slug = (0, unit_paths_1.reportSlug)(unit);
236
+ const fresh = computeFresh(projectRoot, unit);
237
+ const valid = fresh.obligations.map((o) => o.id);
238
+ if (!valid.includes(obId)) {
239
+ throw new Error(`Unknown obligation "${obId}". Valid: ${valid.join(', ')}`);
240
+ }
241
+ const sp = statePath(projectRoot, slug);
242
+ const state = loadState(sp) || { unit, auditHash: '', waivers: {} };
243
+ state.waivers[obId] = { reason: reason.trim(), at: new Date().toISOString(), auditHashAtWaive: auditHashOf(projectRoot, slug) };
244
+ saveState(sp, state);
245
+ return runJourney(projectRoot, unit);
246
+ }
247
+ /**
248
+ * Sign off — the single human gate (S5). Allowed ONLY when every other deliver-required
249
+ * obligation is satisfied or waived (you cannot sign off an unclean suite). Records who/when +
250
+ * the evidence cursor; reconcile invalidates it (stale → re-review) if the suite later changes.
251
+ */
252
+ function signoff(projectRoot, unit, by) {
253
+ const before = runJourney(projectRoot, unit);
254
+ const blockers = before.obligations.filter((o) => o.id !== 'OB-signoff' && o.status !== 'satisfied' && o.status !== 'waived');
255
+ if (blockers.length) {
256
+ throw new Error(`Cannot sign off — still open: ${blockers.map((b) => b.id).join(', ')}. Fix, or waive each with a reason, first.`);
257
+ }
258
+ const slug = (0, unit_paths_1.reportSlug)(unit);
259
+ const sp = statePath(projectRoot, slug);
260
+ const state = loadState(sp) || { unit, auditHash: '', waivers: {} };
261
+ state.signoff = { by, at: new Date().toISOString(), auditHashAtSignoff: auditHashOf(projectRoot, slug) };
262
+ saveState(sp, state);
263
+ return runJourney(projectRoot, unit);
264
+ }
265
+ const ICON = { satisfied: '✅', 'needs-work': '⚠️ ', pending: '⏳', waived: '🚫' };
266
+ function renderJourneyBoard(r) {
267
+ const L = [];
268
+ L.push(`# Journey — ${r.unit}`);
269
+ L.push('');
270
+ L.push(`📍 **You are here:** ${r.youAreHere}` + (r.phasesDone.length ? ` (phases: ${r.phasesDone.join(' → ')})` : ''));
271
+ if (r.gateStatus)
272
+ L.push(` gate: **${r.gateStatus}** · score: ${r.score ?? '—'}/10`);
273
+ L.push('');
274
+ L.push('## What must still be true');
275
+ for (const o of r.obligations)
276
+ L.push(`- ${ICON[o.status]} **${o.title}** — ${o.detail}`);
277
+ L.push('');
278
+ L.push(`## 🔎 Review queue — needs your judgment (${r.needsYou.length})`);
279
+ if (r.needsYou.length) {
280
+ for (const it of r.needsYou.slice(0, 20)) {
281
+ const a = it.anchor;
282
+ const tag = [a.vpId, a.file && `${a.file}${a.line ? ':' + a.line : ''}`].filter(Boolean).join(' · ');
283
+ L.push(`- ${it.text}${tag ? ` 〔${tag}〕` : ''}`);
284
+ }
285
+ }
286
+ else
287
+ L.push('- (nothing queued)');
288
+ L.push('');
289
+ L.push(`## → Next`);
290
+ L.push(`${r.nextSuggested}`);
291
+ L.push('');
292
+ return L.join('\n');
293
+ }
294
+ const PHASE_REQUIRED = {
295
+ // post-create (design quality): spec + coverage + depth + traceability must hold.
296
+ create: ['OB-spec', 'OB-coverage', 'OB-depth', 'OB-trace'],
297
+ // post-run: the design gates + automation coverage.
298
+ run: ['OB-spec', 'OB-coverage', 'OB-depth', 'OB-trace', 'OB-automation'],
299
+ // pre-delivery: everything automated PLUS the single human sign-off (S5).
300
+ deliver: ['OB-spec', 'OB-coverage', 'OB-depth', 'OB-trace', 'OB-automation', 'OB-signoff'],
301
+ };
302
+ function runGate(projectRoot, unit, phase) {
303
+ const r = runJourney(projectRoot, unit);
304
+ const required = PHASE_REQUIRED[phase];
305
+ const reqObs = r.obligations.filter((o) => required.includes(o.id));
306
+ const blockers = reqObs
307
+ .filter((o) => o.status !== 'satisfied' && o.status !== 'waived')
308
+ .map((o) => ({ id: o.id, title: o.title, detail: o.detail }));
309
+ const waivedCredit = reqObs.filter((o) => o.status === 'waived').map((o) => ({ id: o.id, title: o.title }));
310
+ return { unit, phase, status: blockers.length ? 'halt' : 'pass', required, blockers, waivedCredit };
311
+ }
312
+ function renderGate(v) {
313
+ const L = [];
314
+ L.push('');
315
+ L.push(`━━━ Gate: ${v.unit} @ phase "${v.phase}" → ${v.status === 'pass' ? '✅ PASS' : '⛔ HALT'} ━━━`);
316
+ if (v.blockers.length) {
317
+ L.push(' Blocking obligations (must be satisfied or explicitly waived):');
318
+ for (const b of v.blockers)
319
+ L.push(` • ${b.id} ${b.title} — ${b.detail}`);
320
+ L.push(' → Self-correct (repair / run-test), or `sungen journey --screen ' + v.unit + ' --waive <OB> --reason "..."` if accepted.');
321
+ }
322
+ else {
323
+ L.push(' All required obligations satisfied' + (v.waivedCredit.length ? ` (${v.waivedCredit.length} accepted via waiver)` : '') + '.');
324
+ }
325
+ L.push('');
326
+ return L.join('\n');
327
+ }
328
+ //# sourceMappingURL=journey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journey.js","sourceRoot":"","sources":["../../src/harness/journey.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoLA,gCAgCC;AAMD,sBAeC;AAOD,0BAYC;AAID,gDAuBC;AA6BD,0BASC;AAED,gCAaC;AA5UD;;;;;;;;;;;;;GAaG;AACH,uCAAyB;AACzB,2CAA6B;AAC7B,+CAAiC;AACjC,6CAA0C;AA4B1C,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC;QAAC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1G,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAC3B,IAAI,CAAC;YAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAAC,IAAI,CAAC,CAAC,IAAI;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oGAAoG;AACpG,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,2FAA2F,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7G,CAAC;AAED,+FAA+F;AAC/F,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAClE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC9G,CAAC;AAED,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,sDAAsD;AAEvE,SAAS,YAAY,CAAC,WAAmB,EAAE,IAAY;IACrD,MAAM,IAAI,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC,CAAC;IAC3F,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC;IAE9F,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEvC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAC7E,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1E,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,0DAA0D;QAC1D,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gDAAgD,EAAE,CAAC,CAAC;QACjJ,OAAO;YACL,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI;YACxF,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,2BAA2B,GAAG,IAAI,GAAG,aAAa;SACzF,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;IACrE,MAAM,EAAE,GAAG,CAAC,EAAU,EAAE,KAAa,EAAE,GAAuB,EAAE,GAAW,EAAE,MAAc,EAAc,EAAE,CAAC,CAAC;QAC3G,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY;QAC/E,MAAM,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,MAAM,EAAE;KAC9G,CAAC,CAAC;IAEH,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,uCAAuC,CAAC,CAAC,CAAC;IACzG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,oBAAoB,EAAE,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,yBAAyB,CAAC,CAAC,CAAC;IACvG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,EAAE,CAAC,aAAa,EAAE,cAAc,EAAE,yCAAyC,CAAC,CAAC,CAAC;IACjI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAEvH,kFAAkF;IAClF,MAAM,WAAW,GAAG,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC,WAAW,GAAG,CAAC,CAAC;IACvF,WAAW,CAAC,IAAI,CAAC;QACf,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,qBAAqB;QACjD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW;QAChD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,WAAW,8CAA8C,CAAC,CAAC,CAAC,yCAAyC;KACvJ,CAAC,CAAC;IAEH,4FAA4F;IAC5F,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1E,WAAW,CAAC,IAAI,CAAC;QACf,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS;QAC5D,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,8DAA8D;KACzF,CAAC,CAAC;IAEH,kGAAkG;IAClG,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QAAE,IAAI,cAAc,CAAC,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpH,2DAA2D;IAC3D,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IAC/D,IAAI,OAAO;QAAE,OAAO,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,qCAAqC,WAAW,sBAAsB,CAAC;IAEvH,iGAAiG;IACjG,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IAC5F,IAAI,aAAqB,CAAC;IAC1B,IAAI,QAAQ;QAAE,aAAa,GAAG,WAAW,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC;SAC5E,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,aAAa,GAAG,8CAA8C,IAAI,KAAK,CAAC;;QACzF,aAAa,GAAG,0CAA0C,QAAQ,CAAC,MAAM,2CAA2C,CAAC;IAE1H,OAAO;QACL,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM;QACzD,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI;QACzF,WAAW,EAAE,QAAQ,EAAE,aAAa;KACrC,CAAC;AACJ,CAAC;AAQD,SAAS,SAAS,CAAC,WAAmB,EAAE,IAAY;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;AAC5E,CAAC;AACD,mGAAmG;AACnG,SAAS,WAAW,CAAC,WAAmB,EAAE,IAAY;IACpD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;IAC7E,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtG,CAAC;AACD,SAAS,SAAS,CAAC,CAAS,IAAyB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,SAAS,SAAS,CAAC,CAAS,EAAE,CAAe;IAC3C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED,4FAA4F;AAC5F,SAAS,WAAW,CAAC,CAAgB,EAAE,IAAY;IACjD,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IAClH,IAAI,GAAG;QAAE,OAAO,WAAW,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC;IACzD,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,8CAA8C,IAAI,KAAK,CAAC;IAClI,OAAO,iDAAiD,CAAC,CAAC,QAAQ,CAAC,MAAM,2CAA2C,CAAC;AACvH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAC,WAAmB,EAAE,IAAY;IAC1D,MAAM,IAAI,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACpE,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAE/C,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC,CAAC,gBAAgB,KAAK,OAAO,EAAE,CAAC;YACnC,EAAE,CAAC,MAAM,GAAG,QAAQ,CAAC;YACrB,EAAE,CAAC,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;YAC3B,EAAE,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,KAAK,sCAAsC,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnK,CAAC;IACH,CAAC;IACD,8FAA8F;IAC9F,+FAA+F;IAC/F,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IACxE,IAAI,SAAS,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,KAAK,OAAO,EAAE,CAAC;YACjD,SAAS,CAAC,MAAM,GAAG,WAAW,CAAC;YAC/B,SAAS,CAAC,MAAM,GAAG,aAAa,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAC7G,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,6CAA6C,KAAK,CAAC,OAAO,CAAC,EAAE,mCAAmC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QACtK,CAAC;IACH,CAAC;IACD,MAAM,CAAC,aAAa,GAAG,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5F,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAgB,KAAK,CAAC,WAAmB,EAAE,IAAY,EAAE,IAAY,EAAE,MAAc;IACnF,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,6FAA6F,CAAC,CAAC;IACjH,CAAC;IACD,MAAM,IAAI,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACpE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,gBAAgB,EAAE,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;IAChI,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACrB,OAAO,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,SAAgB,OAAO,CAAC,WAAmB,EAAE,IAAY,EAAE,EAAW;IACpE,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,YAAY,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC9H,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IACrI,CAAC;IACD,MAAM,IAAI,GAAG,IAAA,uBAAU,EAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACpE,KAAK,CAAC,OAAO,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;IACzG,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACrB,OAAO,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,IAAI,GAA6B,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAE3G,SAAgB,kBAAkB,CAAC,CAAgB;IACjD,MAAM,CAAC,GAAa,EAAE,CAAC;IACvB,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxH,IAAI,CAAC,CAAC,UAAU;QAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,UAAU,eAAe,CAAC,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,CAAC;IACvF,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW;QAAE,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,CAAC,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1E,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrG,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;;QAAM,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAoBD,MAAM,cAAc,GAAgC;IAClD,kFAAkF;IAClF,MAAM,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC;IAC1D,oDAAoD;IACpD,GAAG,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,CAAC;IACxE,0EAA0E;IAC1E,OAAO,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,CAAC;CAC3F,CAAC;AAEF,SAAgB,OAAO,CAAC,WAAmB,EAAE,IAAY,EAAE,KAAgB;IACzE,MAAM,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5G,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACtG,CAAC;AAED,SAAgB,UAAU,CAAC,CAAc;IACvC,MAAM,CAAC,GAAa,EAAE,CAAC;IACvB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC;IACtG,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAC3E,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ;YAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC,CAAC,IAAI,CAAC,oEAAoE,GAAG,CAAC,CAAC,IAAI,GAAG,4CAA4C,CAAC,CAAC;IACvI,CAAC;SAAM,CAAC;QACN,CAAC,CAAC,IAAI,CAAC,sCAAsC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IAC1I,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC"}
@@ -77,6 +77,7 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
77
77
  - one **viewpoint theme** per shard — a `VP-` prefix from the viewpoint overview (`VP-SEC`, `VP-ERROR-EMPTY-STATE`, `VP-CAROUSEL`, …) — preferred when the viewpoint overview is rich (test-2/home had 47 items across many themes); **or**
78
78
  - one **`spec.md` section** per shard (the Mapping Contract walk, Table 1) — preferred when generating from spec.
79
79
  Each shard owns a disjoint `VP-` prefix ⇒ ids never collide. One shard → skip to 5c (no fan-out gain).
80
+ - **Budget-adaptive shard size (S4).** Size the fan-out to your context budget: `N = clamp(ceil(viewpoint_items / items_per_shard), 1, min(16, cores-2))`, where `items_per_shard` is **larger on a ~1M budget** (fewer, bigger shards; more held inline) and **smaller on a ~200k "Claude Standards" budget** (more, tighter shards + aggressive offload). The orchestrator keeps **only the compact summary each generator returns** (pointers to its fragment files) — never the raw fragments in-context. Each generator sees **only its slice** — its theme/section + the **one** matching `sungen-viewpoint` group + the relevant `spec.md` section(s); never load the other groups or the whole spec (lazy = context-cheap). If the budget is too tight even for one shard, **fall back to the sequential path (5d)** — same output, just slower; never fail for lack of budget.
80
81
 
81
82
  **5b. Parallel fan-out (Claude Code).** Spawn one **`sungen-generator`** sub-agent **per shard** (Task tool, `subagent_type: sungen-generator`) — issue all the Task calls **in a single message** so they run concurrently. Pass each: its shard (theme/section) + viewpoint slice, the **`sungen-discovery` report** (Step 3), only the `spec.md` section(s) it maps to, which one `sungen-viewpoint` group file holds its patterns, the unit (screen/flow) + name + tier, and its fragment paths `.sungen/fragments/<name>/<shard>.{feature,test-data.yaml}`. Each writes a **headerless** fragment + a test-data fragment and returns a compact summary. Small fragments also keep every generator under the output-token cap (the reason the single-pass path writes incrementally).
82
83
 
@@ -89,6 +90,11 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
89
90
 
90
91
  **5d. Sequential fallback.** Use the single-context incremental path (Step 2: tier-by-tier `Write`/`Edit` batches) when: only **one** shard applies, **Copilot / no sub-agents**, or a constrained setup. Same output, just no speedup. **For flows**: `[Screen:Element]` namespace refs, test-data namespaced by phase, `@flow` tag.
91
92
 
93
+ 5.4. **Depth self-check (deterministic — run BEFORE the audit).** Run `sungen depth-lint --screen <name>` (Bash). It reuses the audit's businessDepth classifier and splits every shallow business-critical scenario into two actionable buckets — act on them now so the audit/repair loop doesn't burn rounds on depth:
94
+ - **DEEPEN IN PLACE** — add a real value assertion to each (`User see all [X] contain {{v}}`, `User remember [X] as {{v}}` + `… with {{v}}`). The printed `template` is a **hint** keyed off the theme — apply judgment to the scenario's actual claim; do NOT paste a value assertion that doesn't fit (e.g. a carousel-visibility scenario should assert the product SET, not a price). If a flagged scenario is genuinely visibility/behavior (not data-correctness), that's an over-count — leave it and note it, never fake an assertion.
95
+ - **CROSS-SCREEN** — route to a flow (`/sungen:add-flow`) or tag `@manual:Mx` + reason; do NOT fake an on-screen data assertion. This removes it from the screen's depth denominator honestly.
96
+ Re-run `sungen depth-lint` until `deepen` is empty (or only honest over-counts remain), THEN proceed to the gate. This lifts first-pass `businessDepth` mechanically instead of via 2–3 organic repair rounds.
97
+
92
98
  5.5. **Quality gate & repair (harness — always run, do NOT skip).** Follow the `sungen-harness-audit` skill:
93
99
  - Run `sungen audit --screen <name>` (Bash) and read `gateStatus` + `findings` (deterministic, structural).
94
100
  - **Independent semantic review.** **Claude Code:** spawn the **`sungen-reviewer`** sub-agent (Task tool, `subagent_type: sungen-reviewer`) — it judges what the gate can't (does each scenario's steps PROVE its title/viewpoint, observable Thens, business-critical assertion depth) and returns `VERDICT` + `ISSUES` with concrete fixes. **Merge its NEEDS-REPAIR issues with the audit findings.** (Copilot / no sub-agents: run the same review inline using the `sungen-reviewer` criteria.)
@@ -100,6 +106,7 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
100
106
  - **BALANCE** → stop expanding secondary viewpoints; add business-core scenarios first.
101
107
  - **TRACE** → align `VP-` ids with the viewpoint-overview.
102
108
  - Stop when the gate PASSes and findings clear, **or** the budget is exhausted → report residual gaps honestly (never fake a pass).
109
+ - **Phase gate (boundary — do NOT skip).** Run `sungen gate --screen <name> --phase create` (Bash, exit 2 = HALT). It is the deterministic create-boundary: every required obligation (spec · coverage · depth · trace) must be **satisfied or explicitly waived**. On **HALT**, you have not cleared the phase — keep repairing the blocking obligation(s) within budget; if a blocker is a genuinely-accepted gap (e.g. cross-screen depth owned by a flow), record it with `sungen journey --screen <name> --waive <OB> --reason "..."` (reason mandatory). **Do not converge (step 6) past a HALT** without a fix or a reasoned waiver — no bad output crosses the boundary.
103
110
 
104
111
  5.6. **Record (reuse + observability).** Build the manifest and report usage:
105
112
  - `sungen manifest --screen <name>` — fingerprints for next-run change detection. On a **re-run**, start the whole command by `sungen manifest --screen <name> --diff` and only regenerate scenarios whose spec section changed (keep/regenerate/retire).
@@ -9,6 +9,8 @@ allowed-tools: Read, Grep, Bash, Glob, Edit, Write, AskUserQuestion, mcp__playwr
9
9
 
10
10
  You are a **Senior Developer**. Use `sungen-selector-fix`, `sungen-selector-keys`, and `sungen-error-mapping` skills.
11
11
 
12
+ > ⛔ **Source of truth — the live page is NOT the oracle; `.feature`/`test-data`/`spec.md` are.** Auto-fix is for **selector-resolution** failures (wrong locator → fix `selectors.yaml`). An **assertion-value** failure where the app contradicts the spec is a **CANDIDATE BUG → report it, let it FAIL** — never loosen the rule, weaken the assertion, edit the expected value/`.feature`, or hand-edit the generated `.spec.ts` to make it pass. See `sungen-error-mapping` § "Source of truth". (A `password > 8` test that fails on 6 chars is a bug to report, not a `>= 6` edit.)
13
+
12
14
  ## Parameters
13
15
 
14
16
  Parse from `$ARGUMENTS`:
@@ -102,6 +104,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
102
104
  9. **Integrity check & trace (always run after the final run).**
103
105
  - `sungen script-check --screen <name>` — verify the generated spec is a **1:1** of the Gherkin (every non-@manual scenario ↔ one `test()`, no drift). If it reports **DRIFT** (spec hand-edited or stale), re-run `sungen generate --screen <name>` so the spec matches the feature, then re-run — **never hand-edit the generated spec** (auto-fix must edit `selectors.yaml`, not the `.spec.ts`).
104
106
  - `sungen ledger record --screen <name> --step run --ms <elapsed>` (record this run), then `sungen trace --screen <name>` — show the process map + bottlenecks + **HUMAN-LOOP FOCUS** (the @manual scenarios the QA must verify) to the user.
107
+ - **Phase gate (boundary — do NOT skip).** `sungen gate --screen <name> --phase run` (exit 2 = HALT): the run-boundary obligations (incl. automation) must be **satisfied or explicitly waived**. On **HALT**, classify per `sungen-error-mapping` § Source of truth (#387): a **selector-resolution** failure → fix `selectors.yaml` + re-run; an **assertion-vs-spec** failure → **report it as a candidate bug / leave it FAIL** (never weaken the assertion or edit the expected to pass); a genuinely-accepted gap → `sungen journey --screen <name> --waive <OB> --reason "..."`. Do **not** declare the run "done" past a HALT without a fix, a reported bug, or a reasoned waiver.
105
108
  10. **Capability-pending offer (consent-gated).** If `sungen audit --screen <name>` reports `AUTOMATION-READY-PENDING` (or the run shows `@requires:<cap>` tests skipped "requires …"), these are **automation-ready** scenarios waiting on an opt-in driver. Use `AskUserQuestion` to offer: *"N scenario(s) are automation-ready — enable `<cap>` to run them? (`sungen capability add <cap>`)"*. **Only on the user's yes** run `sungen capability add <cap>` then re-run those specs; on no, leave them skipped (they are NOT failures and NOT manual). **Never auto-install.**
106
109
 
107
110
  ## Playwright command guidelines
@@ -21,6 +21,23 @@ Then choose the fix from the patterns below.
21
21
 
22
22
  ---
23
23
 
24
+ ## ⛔ Source of truth — classify EVERY failure before you "fix" it
25
+
26
+ `.feature` + `test-data.yaml` + `spec.md` are the **oracle**. The **live page is NOT** — it may be the thing that's broken. A failing test is not automatically a test to "make pass". Classify first:
27
+
28
+ - **Selector-resolution failure** (element not found / wrong locator / strict-mode / wrong element type) → the test looked in the wrong place. **Fix the locator in `selectors.yaml`** (re-snapshot, copy the exact accessible name). Legit auto-fix.
29
+ - **Assertion-value failure** (element FOUND, but observed value ≠ expected) → STOP and ask: *is the TEST wrong, or is the APP wrong?*
30
+ - Expected value/rule is wrong **relative to `spec.md`** (typo, stale test-data) → fix `test-data.yaml`/`.feature` so it matches the **spec** — never the live page.
31
+ - App behaviour contradicts `spec.md` (spec says X, app shows Y) → **CANDIDATE BUG**. **Report it** (let the test FAIL / surface to the QA in the run summary). **NEVER** change the expected value, loosen the rule, weaken the assertion (`toHaveText`→`toContainText` to dodge a mismatch), edit `.feature`, or edit the generated `.spec.ts` to make it pass.
32
+
33
+ > **Cardinal sin (do NOT do this):** a `password > 8 chars` rule fails on a 6-char input → "fix" it to `>= 6` so the test passes. The logic is now meaningless. A failing assertion is a **finding**, not a chore.
34
+
35
+ **Auto-fix loop scope:** the run-test auto-fix loop engages ONLY on **selector-resolution** failures. On an assertion-value failure where the app contradicts the spec → **HALT and report**, do not loop it into passing.
36
+
37
+ **Never hand-edit the generated `.spec.ts`** (e.g. inserting `page.evaluate`/`fetch` to bypass a broken control). `sungen script-check` regenerates the spec from `.feature` and flags any edit as DRIFT — regenerate, don't patch.
38
+
39
+ ---
40
+
24
41
  ## Fix Priority (try in order)
25
42
 
26
43
  1. **Auth issue** — page redirected to login? Fix auth first, everything else is noise
@@ -43,11 +60,13 @@ Then choose the fix from the patterns below.
43
60
  | not a select | Custom dropdown, not native `<select>` | Set `variant: 'custom'` |
44
61
  | Frame not found | iframe selector wrong or doesn't exist | Fix `frame` value, verify iframe in snapshot |
45
62
 
46
- ### Assertion errors → fix in `test-data.yaml` or `.feature`
63
+ ### Assertion errors → apply the Source-of-truth gate above FIRST
47
64
 
48
- | Error | Diagnosis | Fix |
65
+ > The "Fix" column below applies **only when the expected value was wrong relative to `spec.md`** (a test defect). If the app's value contradicts the spec, the row is a **candidate bug → report it, do not edit the expected to match live**. Never weaken `toHaveText`→`toContainText` just to pass.
66
+
67
+ | Error | Diagnosis | Fix (only if the TEST was wrong per spec) |
49
68
  |---|---|---|
50
- | toHaveText mismatch | Expected text differs from actual | Fix value in test-data. If element is input type → change Gherkin type to `field`/`textarea` (triggers `toHaveValue` instead) |
69
+ | toHaveText mismatch | Expected text differs from actual | If the test's expected was wrong per spec → fix value in test-data. If element is input type → change Gherkin type to `field`/`textarea` (triggers `toHaveValue`). If the app value contradicts spec → **report as bug**. |
51
70
  | toHaveValue mismatch | Expected value differs from actual | Fix value in test-data |
52
71
  | toContainText mismatch | Partial text not found | Fix expected partial text in test-data |
53
72
  | toBeVisible timeout | Element exists but hidden, or name wrong | Check: is element conditionally visible? Wrong name? Inside dialog? |
@@ -275,6 +275,7 @@ Security: [S1 – admin only]
275
275
 
276
276
  **Depth is a GATE dimension (harness-roadmap P1) — self-raise, never silently go shallow:**
277
277
  - For every data-correctness theme the catalog marks `depth.requires: data-assertion`, emit its `depth.template` shape by **default** — don't wait for the repair loop. `sungen audit` measures `businessDepth` (ratio of these scenarios that assert data) against an intent threshold (functional ≥ 0.70); below it the **gate FAILs**.
278
+ - **Verify depth deterministically before the gate:** run `sungen depth-lint --screen <name>`. It classifies every shallow business-critical scenario into **deepen-in-place** (add the theme's value assertion — the printed `template` is a hint, fit it to the actual claim) vs **cross-screen** (route to a flow / `@manual:Mx`). Clear the `deepen` list first — this is the mechanical way to hit `businessDepth` on the first pass instead of churning repair rounds. Never fake a value assertion onto a visibility/behavior scenario the lint over-counts; leave it and note the over-count.
278
279
  - `depth.cross_screen: true` (cart / detail / filter / brand correctness) → write the deep capture/compare shape as an **automated flow scenario** (in the flow — do NOT leave a full-step `@manual` duplicate on the screen). `@manual` is **only** for genuine judgment (M6 visual/UX · M8 not-worth · M9 human) or a missing capability (M1–M5/M7), and it **must** carry a reason code (`@manual:Mx`, or a reason comment the planner can infer). A `@manual` scenario that still has full automatable steps (a data assertion, no visual/mock/a11y judgment) is now flagged by `sungen audit` as `MANUAL-AUTOMATABLE`, and business-critical scenarios you defer to `@manual` are reported as `DEPTH-DEFERRED` (they do NOT silently inflate `businessDepth`). Deferring automatable work to `@manual` lowers quality — automate it in the flow instead.
279
280
  - **Pick the right `@manual:Mx` code — it decides which driver can later automate the case** (`sungen audit` flags a code↔reason mismatch). Tag the code that matches the **oracle the reason describes**:
280
281
 
@@ -66,7 +66,10 @@ If the unit is **api-first** (`qa/api/<name>/` or `qa/api/flows/<name>/`), the d
66
66
  4. Follow the `sungen-tc-generation` skill for section identification, viewpoint generation, and output format. **For flows**, use the "Flow Test Generation" section in the skill. When requirements exist, use the "Requirements-Driven Generation" strategy. **For Tier 1**, apply the **Lightweight Guard** — verify required fields, validation rules, business rules, security checks, and key state transitions all have TCs after generation. **For Tier 2+**, **MUST** apply the full **Mapping Contract** — walk every `spec.md` section top-to-bottom and produce the indicated TCs per Table 1; handle `test-viewpoint.md` per Table 2. Do not silently skip sections. Present sections as a numbered list and let user pick.
67
67
  5. Generate or update `.feature` + `test-data.yaml` following `sungen-gherkin-syntax` and `sungen-tc-generation` skills. Generate **group-by-group** (one viewpoint group at a time, tier-by-tier `Write`/`Edit` batches) to stay under the output-token cap. **For flows**: use `[Screen:Element]` namespace format, namespace test-data by phase, add `@flow` tag.
68
68
  > **No parallel fan-out here.** Copilot has no sub-agents, so generation is sequential (the Claude Code variant fans out one `sungen-generator` per viewpoint group and merges). Same output, no speedup.
69
+ > **Load lazily (budget, S4).** Per group, load **only** the one matching `sungen-viewpoint` group file + the relevant `spec.md` section(s) — never all five groups or the whole spec. On a tight (~200k) budget, write smaller tier-by-tier batches and keep prior batches on disk; this is what keeps generation inside a non-1M context.
70
+ 5.4. **Depth self-check (deterministic — BEFORE the audit).** Run `sungen depth-lint --screen ${input:name}`. It splits every shallow business-critical scenario into **DEEPEN IN PLACE** (add a real value assertion — the printed `template` is a theme-keyed hint, apply judgment to the actual claim; never fake one onto a visibility/behavior scenario) and **CROSS-SCREEN** (route to a flow / tag `@manual:Mx` + reason — removes it from the depth denominator honestly). Act on both, re-run until `deepen` is empty (or only honest over-counts remain), THEN gate. Lifts first-pass `businessDepth` mechanically instead of via 2–3 repair rounds.
69
71
  5.5. **Quality gate & repair (harness — always run).** Per `sungen-harness-audit`: run `sungen audit --screen ${input:name}` (structural), THEN do an **independent semantic review inline** using the `sungen-reviewer` criteria (does each scenario's steps PROVE its title/viewpoint? observable Thens? business-critical assertion depth?). Merge both sets of issues; if gate FAILs / findings exist, repair (budget 3) and re-audit — GATE missing theme → generate it (cross-screen → **automate it in the flow** via `/sungen:add-flow`, NOT a full `@manual` screen duplicate — `sungen audit` flags an automatable `@manual` as `MANUAL-AUTOMATABLE`; reserve `@manual:Mx` for true judgment/missing-capability); DEPTH → add data assertions; BALANCE → add business-core first; TRACE → align VP ids. Never fake a pass.
72
+ 5.5b. **Phase gate (boundary — do NOT skip).** Run `sungen gate --screen ${input:name} --phase create` (exit 2 = HALT): every required obligation (spec · coverage · depth · trace) must be **satisfied or explicitly waived**. On **HALT**, keep repairing within budget; a genuinely-accepted gap → `sungen journey --screen ${input:name} --waive <OB> --reason "..."` (reason mandatory). Do **not** converge (step 6) past a HALT without a fix or a reasoned waiver.
70
73
  5.6. **Record.** `sungen manifest --screen ${input:name}`. Ledger **each phase** (not just repair) — pick one `runId` at the start and pass it so `trace`/`ledger report` show THIS run, not a mix: `sungen ledger record --screen ${input:name} --run <runId> --step <discovery|viewpoint|gherkin|audit|repair:N> --ms <elapsed>`. On re-run, start with `sungen manifest --screen ${input:name} --diff` and only regenerate changed sections.
71
74
  6. **Converge — show the trace.** Run `sungen trace --screen ${input:name}` and present: process map (phases + repair rounds), bottlenecks, **HUMAN-LOOP FOCUS** (@manual to verify), audit score + gate + residual gaps. Then offer next steps based on which tier was just generated:
72
75
 
@@ -9,6 +9,8 @@ tools: [read, execute, edit, vscode/askQuestions, playwright/*]
9
9
 
10
10
  You are a **Senior Developer**. Use `sungen-selector-fix`, `sungen-selector-keys`, and `sungen-error-mapping` skills.
11
11
 
12
+ > ⛔ **Source of truth — the live page is NOT the oracle; `.feature`/`test-data`/`spec.md` are.** Auto-fix is for **selector-resolution** failures (wrong locator → fix `selectors.yaml`). An **assertion-value** failure where the app contradicts the spec is a **CANDIDATE BUG → report it, let it FAIL** — never loosen the rule, weaken the assertion, edit the expected value/`.feature`, or hand-edit the generated `.spec.ts` to make it pass. See `sungen-error-mapping` § "Source of truth". (A `password > 8` test that fails on 6 chars is a bug to report, not a `>= 6` edit.)
13
+
12
14
  ## Parameters
13
15
 
14
16
  Parse from `$ARGUMENTS`:
@@ -93,6 +95,7 @@ If the unit is **api-first**, skip every selector/capture phase (an API test has
93
95
  7. **Phase 3 — Full Run**: Run all tests. Fix only **new** failures (elements unique to `@normal`/`@low`). Max 1 attempt. Don't loop on low-priority failures.
94
96
  8. **Phase 4 — Regression**: One final full run. Report results. No more fix loops.
95
97
  9. **Integrity & trace (always run after the final run).** `sungen script-check --screen <name>` — verify the spec is a **1:1** of the Gherkin; if **DRIFT**, re-run `sungen generate --screen <name>` (never hand-edit the `.spec.ts` — auto-fix edits `selectors.yaml`). Then `sungen ledger record --screen <name> --step run --ms <elapsed>` and `sungen trace --screen <name>` to show the process map + bottlenecks + **HUMAN-LOOP FOCUS**.
98
+ 9b. **Phase gate (boundary — do NOT skip).** `sungen gate --screen <name> --phase run` (exit 2 = HALT): run-boundary obligations (incl. automation) must be **satisfied or explicitly waived**. On HALT, classify per `sungen-error-mapping` § Source of truth (#387): selector-resolution failure → fix `selectors.yaml` + re-run; assertion-vs-spec failure → **report as a candidate bug / leave it FAIL** (never weaken to pass); accepted gap → `sungen journey --screen <name> --waive <OB> --reason "..."`. Don't declare "done" past a HALT without a fix, a reported bug, or a reasoned waiver.
96
99
  10. **Capability-pending offer (consent-gated).** If `sungen audit` reports `AUTOMATION-READY-PENDING` (or `@requires:<cap>` tests are skipped "requires …"), offer: *"N scenario(s) are automation-ready — enable `<cap>` to run them? (`sungen capability add <cap>`)"*. Only on the user's yes, run `sungen capability add <cap>` + re-run; on no, leave skipped (not failures, not manual). **Never auto-install.**
97
100
 
98
101
  ## Playwright command guidelines
@@ -21,6 +21,23 @@ Then choose the fix from the patterns below.
21
21
 
22
22
  ---
23
23
 
24
+ ## ⛔ Source of truth — classify EVERY failure before you "fix" it
25
+
26
+ `.feature` + `test-data.yaml` + `spec.md` are the **oracle**. The **live page is NOT** — it may be the thing that's broken. A failing test is not automatically a test to "make pass". Classify first:
27
+
28
+ - **Selector-resolution failure** (element not found / wrong locator / strict-mode / wrong element type) → the test looked in the wrong place. **Fix the locator in `selectors.yaml`** (re-snapshot, copy the exact accessible name). Legit auto-fix.
29
+ - **Assertion-value failure** (element FOUND, but observed value ≠ expected) → STOP and ask: *is the TEST wrong, or is the APP wrong?*
30
+ - Expected value/rule is wrong **relative to `spec.md`** (typo, stale test-data) → fix `test-data.yaml`/`.feature` so it matches the **spec** — never the live page.
31
+ - App behaviour contradicts `spec.md` (spec says X, app shows Y) → **CANDIDATE BUG**. **Report it** (let the test FAIL / surface to the QA in the run summary). **NEVER** change the expected value, loosen the rule, weaken the assertion (`toHaveText`→`toContainText` to dodge a mismatch), edit `.feature`, or edit the generated `.spec.ts` to make it pass.
32
+
33
+ > **Cardinal sin (do NOT do this):** a `password > 8 chars` rule fails on a 6-char input → "fix" it to `>= 6` so the test passes. The logic is now meaningless. A failing assertion is a **finding**, not a chore.
34
+
35
+ **Auto-fix loop scope:** the run-test auto-fix loop engages ONLY on **selector-resolution** failures. On an assertion-value failure where the app contradicts the spec → **HALT and report**, do not loop it into passing.
36
+
37
+ **Never hand-edit the generated `.spec.ts`** (e.g. inserting `page.evaluate`/`fetch` to bypass a broken control). `sungen script-check` regenerates the spec from `.feature` and flags any edit as DRIFT — regenerate, don't patch.
38
+
39
+ ---
40
+
24
41
  ## Fix Priority (try in order)
25
42
 
26
43
  1. **Auth issue** — page redirected to login? Fix auth first, everything else is noise
@@ -43,11 +60,13 @@ Then choose the fix from the patterns below.
43
60
  | not a select | Custom dropdown, not native `<select>` | Set `variant: 'custom'` |
44
61
  | Frame not found | iframe selector wrong or doesn't exist | Fix `frame` value, verify iframe in snapshot |
45
62
 
46
- ### Assertion errors → fix in `test-data.yaml` or `.feature`
63
+ ### Assertion errors → apply the Source-of-truth gate above FIRST
47
64
 
48
- | Error | Diagnosis | Fix |
65
+ > The "Fix" column below applies **only when the expected value was wrong relative to `spec.md`** (a test defect). If the app's value contradicts the spec, the row is a **candidate bug → report it, do not edit the expected to match live**. Never weaken `toHaveText`→`toContainText` just to pass.
66
+
67
+ | Error | Diagnosis | Fix (only if the TEST was wrong per spec) |
49
68
  |---|---|---|
50
- | toHaveText mismatch | Expected text differs from actual | Fix value in test-data. If element is input type → change Gherkin type to `field`/`textarea` (triggers `toHaveValue` instead) |
69
+ | toHaveText mismatch | Expected text differs from actual | If the test's expected was wrong per spec → fix value in test-data. If element is input type → change Gherkin type to `field`/`textarea` (triggers `toHaveValue`). If the app value contradicts spec → **report as bug**. |
51
70
  | toHaveValue mismatch | Expected value differs from actual | Fix value in test-data |
52
71
  | toContainText mismatch | Partial text not found | Fix expected partial text in test-data |
53
72
  | toBeVisible timeout | Element exists but hidden, or name wrong | Check: is element conditionally visible? Wrong name? Inside dialog? |
@@ -275,6 +275,7 @@ Security: [S1 – admin only]
275
275
 
276
276
  **Depth is a GATE dimension (harness-roadmap P1) — self-raise, never silently go shallow:**
277
277
  - For every data-correctness theme the catalog marks `depth.requires: data-assertion`, emit its `depth.template` shape by **default** — don't wait for the repair loop. `sungen audit` measures `businessDepth` (ratio of these scenarios that assert data) against an intent threshold (functional ≥ 0.70); below it the **gate FAILs**.
278
+ - **Verify depth deterministically before the gate:** run `sungen depth-lint --screen <name>`. It classifies every shallow business-critical scenario into **deepen-in-place** (add the theme's value assertion — the printed `template` is a hint, fit it to the actual claim) vs **cross-screen** (route to a flow / `@manual:Mx`). Clear the `deepen` list first — this is the mechanical way to hit `businessDepth` on the first pass instead of churning repair rounds. Never fake a value assertion onto a visibility/behavior scenario the lint over-counts; leave it and note the over-count.
278
279
  - `depth.cross_screen: true` (cart / detail / filter / brand correctness) → write the deep capture/compare shape as an **automated flow scenario** (in the flow — do NOT leave a full-step `@manual` duplicate on the screen). `@manual` is **only** for genuine judgment (M6 visual/UX · M8 not-worth · M9 human) or a missing capability (M1–M5/M7), and it **must** carry a reason code (`@manual:Mx`, or a reason comment the planner can infer). A `@manual` scenario that still has full automatable steps (a data assertion, no visual/mock/a11y judgment) is now flagged by `sungen audit` as `MANUAL-AUTOMATABLE`, and business-critical scenarios you defer to `@manual` are reported as `DEPTH-DEFERRED` (they do NOT silently inflate `businessDepth`). Deferring automatable work to `@manual` lowers quality — automate it in the flow instead.
279
280
  - **Pick the right `@manual:Mx` code — it decides which driver can later automate the case** (`sungen audit` flags a code↔reason mismatch). Tag the code that matches the **oracle the reason describes**:
280
281
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sungen",
3
- "version": "3.2.2-beta.1",
3
+ "version": "3.2.2-beta.11",
4
4
  "description": "Deterministic E2E Test Compiler - Gherkin + Selectors → Playwright tests",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -12,7 +12,7 @@
12
12
  "copy-templates": "mkdir -p dist/generators/test-generator/adapters/playwright/templates/steps && mkdir -p dist/generators/test-generator/templates && mkdir -p dist/orchestrator/templates && mkdir -p dist/dashboard/templates && cp -r src/generators/test-generator/adapters/playwright/templates/*.hbs dist/generators/test-generator/adapters/playwright/templates/ 2>/dev/null || true && cp -r src/generators/test-generator/adapters/playwright/templates/steps dist/generators/test-generator/adapters/playwright/templates/ && mkdir -p dist/generators/test-generator/adapters/appium/templates/steps && cp -r src/generators/test-generator/adapters/appium/templates/*.hbs dist/generators/test-generator/adapters/appium/templates/ 2>/dev/null || true && cp -r src/generators/test-generator/adapters/appium/templates/steps dist/generators/test-generator/adapters/appium/templates/ && cp src/generators/test-generator/templates/*.hbs dist/generators/test-generator/templates/ 2>/dev/null || true && cp -r src/orchestrator/templates/* dist/orchestrator/templates/ && cp src/dashboard/templates/index.html dist/dashboard/templates/index.html && mkdir -p dist/harness/catalog && cp src/harness/catalog/*.yaml dist/harness/catalog/",
13
13
  "build:dashboard": "cd ../../dashboard && npm install --silent && npm run build && cd - && cp ../../dashboard/dist/index.html src/dashboard/templates/index.html",
14
14
  "dev": "tsx src/cli/index.ts",
15
- "test": "tsx tests/golden/run.ts && tsx tests/audit/run.ts && tsx tests/ingest/run.ts && tsx tests/eval/run.ts && tsx tests/exporter/run.ts && tsx tests/exporter/feature-parser-category.run.ts && tsx tests/exporter/api-detail-sheet.run.ts && tsx tests/api-runtime/base-path-url-join.run.ts && tsx tests/capabilities/run.ts && tsx tests/openapi/run.ts && tsx tests/packaging/run.ts",
15
+ "test": "tsx tests/golden/run.ts && tsx tests/audit/run.ts && tsx tests/ingest/run.ts && tsx tests/eval/run.ts && tsx tests/exporter/run.ts && tsx tests/exporter/feature-parser-category.run.ts && tsx tests/exporter/api-detail-sheet.run.ts && tsx tests/api-runtime/base-path-url-join.run.ts && tsx tests/capabilities/run.ts && tsx tests/openapi/run.ts && tsx tests/packaging/run.ts && tsx tests/journey/run.ts",
16
16
  "test:update": "tsx tests/golden/run.ts --update && tsx tests/audit/run.ts --update && tsx tests/ingest/run.ts --update",
17
17
  "prepublishOnly": "npm run build:dashboard && npm run build"
18
18
  },
@@ -33,7 +33,7 @@
33
33
  "node": ">=18.0.0"
34
34
  },
35
35
  "dependencies": {
36
- "@sungen/driver-ui": "3.2.2-beta.1",
36
+ "@sungen/driver-ui": "3.2.2-beta.11",
37
37
  "@anthropic-ai/sdk": "^0.71.0",
38
38
  "@babel/parser": "^7.28.5",
39
39
  "@babel/traverse": "^7.28.5",