@sun-asterisk/sungen 3.2.21-beta.1 → 3.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +0 -8
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +0 -7
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/trace.d.ts.map +1 -1
- package/dist/cli/commands/trace.js +0 -9
- package/dist/cli/commands/trace.js.map +1 -1
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +0 -11
- package/dist/exporters/matrix/export.js.map +1 -1
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +0 -15
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +0 -2
- package/dist/exporters/matrix/types.d.ts.map +1 -1
- package/dist/exporters/matrix/types.js.map +1 -1
- package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
- package/dist/exporters/playwright-report-parser.js +0 -1
- package/dist/exporters/playwright-report-parser.js.map +1 -1
- package/dist/exporters/types.d.ts +0 -2
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +1 -6
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +0 -5
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +19 -27
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +0 -22
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/harness/audit.d.ts +0 -2
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +9 -79
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/flow-plan.d.ts +0 -3
- package/dist/harness/flow-plan.d.ts.map +1 -1
- package/dist/harness/flow-plan.js +2 -6
- package/dist/harness/flow-plan.js.map +1 -1
- package/dist/harness/parse.d.ts +0 -5
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +1 -29
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +1 -13
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/spec-coverage.d.ts.map +1 -1
- package/dist/harness/spec-coverage.js +5 -29
- package/dist/harness/spec-coverage.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/commands/add-flow.md +3 -41
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +0 -10
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +16 -35
- package/dist/orchestrator/templates/qa-context.md +1 -14
- package/package.json +3 -3
- package/src/cli/commands/audit.ts +0 -8
- package/src/cli/commands/delivery.ts +0 -6
- package/src/cli/commands/trace.ts +0 -9
- package/src/exporters/matrix/export.ts +0 -11
- package/src/exporters/matrix/render-xlsx.ts +0 -15
- package/src/exporters/matrix/types.ts +0 -2
- package/src/exporters/playwright-report-parser.ts +0 -2
- package/src/exporters/types.ts +0 -2
- package/src/generators/test-generator/diagnostics.ts +1 -6
- package/src/generators/test-generator/patterns/index.ts +24 -30
- package/src/generators/test-generator/step-mapper.ts +0 -22
- package/src/harness/audit.ts +10 -82
- package/src/harness/flow-plan.ts +3 -10
- package/src/harness/parse.ts +1 -31
- package/src/harness/sensors.ts +1 -13
- package/src/harness/spec-coverage.ts +4 -26
- package/src/orchestrator/templates/ai-src/commands/add-flow.md +3 -41
- package/src/orchestrator/templates/ai-src/commands/create-test.md +0 -10
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +16 -35
- package/src/orchestrator/templates/qa-context.md +1 -14
- package/dist/harness/flow-contract.d.ts +0 -71
- package/dist/harness/flow-contract.d.ts.map +0 -1
- package/dist/harness/flow-contract.js +0 -235
- package/dist/harness/flow-contract.js.map +0 -1
- package/dist/harness/perf.d.ts +0 -40
- package/dist/harness/perf.d.ts.map +0 -1
- package/dist/harness/perf.js +0 -136
- package/dist/harness/perf.js.map +0 -1
- package/src/harness/flow-contract.ts +0 -229
- package/src/harness/perf.ts +0 -112
|
@@ -1,235 +0,0 @@
|
|
|
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.flowContractPath = flowContractPath;
|
|
37
|
-
exports.loadFlowContract = loadFlowContract;
|
|
38
|
-
exports.phaseOf = phaseOf;
|
|
39
|
-
exports.flowQuality = flowQuality;
|
|
40
|
-
exports.statefulDepthFor = statefulDepthFor;
|
|
41
|
-
/**
|
|
42
|
-
* Flow Contract — the declared boundary of a flow, and the sensors that verify
|
|
43
|
-
* the suite against it. (#569, docs/spec/sungen-flow-quality-spec.md)
|
|
44
|
-
*
|
|
45
|
-
* A flow is the SMALLEST complete business action chain: one clear trigger ending
|
|
46
|
-
* in ONE observable, valuable outcome. Nothing enforced that: `add-flow` asked only
|
|
47
|
-
* "which screens, in order?", so a real example mixed three business goals (cart,
|
|
48
|
-
* filter, product-detail) in one "flow", and the harness scored flows with screen
|
|
49
|
-
* machinery — a registration flow was judged against the `form` page-type checklist
|
|
50
|
-
* (coverage 0%), and every flow audit showed taxonomy=0% because flow phase ids
|
|
51
|
-
* (FL-HP-001) don't even parse as categories.
|
|
52
|
-
*
|
|
53
|
-
* The contract is a declaration the QA owns (AI proposes at add-flow; a filled
|
|
54
|
-
* contract is an INPUT to generation, never an output — same rule as
|
|
55
|
-
* test-viewpoint.md). These sensors are deterministic checks against it:
|
|
56
|
-
*
|
|
57
|
-
* - outcome proof — the flow proves its own goal with an automated data assertion
|
|
58
|
-
* - scope creep — scenarios that never touch the outcome are a second goal
|
|
59
|
-
* - phase coverage — HP / ER / EH journey phases, the flow's coverage axis
|
|
60
|
-
* - handoff — a cross-screen transition is followed by an assertion
|
|
61
|
-
* - stateful depth — generalizes the cart-hardcoded regression dims to any
|
|
62
|
-
* declared collection (order, application, submission …)
|
|
63
|
-
*/
|
|
64
|
-
const fs = __importStar(require("fs"));
|
|
65
|
-
const path = __importStar(require("path"));
|
|
66
|
-
const yaml_1 = require("yaml");
|
|
67
|
-
const read_text_1 = require("./read-text");
|
|
68
|
-
const DEFAULT_PHASES = ['HP', 'ER', 'EH'];
|
|
69
|
-
function flowContractPath(unitDir) {
|
|
70
|
-
return path.join(unitDir, 'requirements', 'flow-contract.yaml');
|
|
71
|
-
}
|
|
72
|
-
/** Load + validate. Returns null when absent; a present-but-broken file returns errors. */
|
|
73
|
-
function loadFlowContract(unitDir) {
|
|
74
|
-
const p = flowContractPath(unitDir);
|
|
75
|
-
if (!fs.existsSync(p))
|
|
76
|
-
return { contract: null, errors: [] };
|
|
77
|
-
let raw;
|
|
78
|
-
try {
|
|
79
|
-
raw = (0, yaml_1.parse)((0, read_text_1.readTextFile)(p));
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
return { contract: null, errors: [`flow-contract.yaml does not parse: ${e.message}`] };
|
|
83
|
-
}
|
|
84
|
-
if (!raw || typeof raw !== 'object')
|
|
85
|
-
return { contract: null, errors: ['flow-contract.yaml is empty'] };
|
|
86
|
-
const errors = [];
|
|
87
|
-
if (!raw.goal || typeof raw.goal !== 'string')
|
|
88
|
-
errors.push('missing `goal:` (Verb + outcome, e.g. "Place an order for a product added from home")');
|
|
89
|
-
const outcome = raw.outcome;
|
|
90
|
-
if (!outcome || typeof outcome.screen !== 'string' || !outcome.screen.trim()) {
|
|
91
|
-
errors.push('missing `outcome.screen:` — the screen namespace that carries the final proof');
|
|
92
|
-
}
|
|
93
|
-
if (errors.length > 0)
|
|
94
|
-
return { contract: null, errors };
|
|
95
|
-
const phases = Array.isArray(raw.phases) && raw.phases.length > 0
|
|
96
|
-
? raw.phases.map((x) => String(x).toUpperCase())
|
|
97
|
-
: DEFAULT_PHASES;
|
|
98
|
-
return {
|
|
99
|
-
contract: {
|
|
100
|
-
goal: String(raw.goal),
|
|
101
|
-
actor: raw.actor !== undefined ? String(raw.actor) : undefined,
|
|
102
|
-
trigger: raw.trigger !== undefined ? String(raw.trigger) : undefined,
|
|
103
|
-
precondition: raw.precondition !== undefined ? String(raw.precondition) : undefined,
|
|
104
|
-
outcome: { screen: String(outcome.screen).toLowerCase(), assertion: outcome.assertion !== undefined ? String(outcome.assertion) : undefined },
|
|
105
|
-
value: raw.value !== undefined ? String(raw.value) : undefined,
|
|
106
|
-
phases,
|
|
107
|
-
stateful: raw.stateful !== undefined ? String(raw.stateful).toLowerCase() : undefined,
|
|
108
|
-
budgets: (raw.budgets && typeof raw.budgets === 'object') ? raw.budgets : undefined,
|
|
109
|
-
},
|
|
110
|
-
errors: [],
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
/** `[screen:element]` namespaces referenced by a scenario's steps, in step order. */
|
|
114
|
-
function namespacesInOrder(s) {
|
|
115
|
-
const out = [];
|
|
116
|
-
for (const m of s.stepsText.matchAll(/\[([a-z0-9_.-]+):/g))
|
|
117
|
-
out.push(m[1]);
|
|
118
|
-
return out;
|
|
119
|
-
}
|
|
120
|
-
function touchesOutcome(s, outcomeScreen) {
|
|
121
|
-
return namespacesInOrder(s).includes(outcomeScreen);
|
|
122
|
-
}
|
|
123
|
-
/** Phase of a scenario: its declared phase token (FL-HP-001 / VP-FLOW-ER-02 / MS-EH-005)
|
|
124
|
-
* when present, else vocabulary detection. */
|
|
125
|
-
function phaseOf(s, declared) {
|
|
126
|
-
const id = (s.vpId ?? '').toUpperCase();
|
|
127
|
-
for (const ph of declared) {
|
|
128
|
-
if (new RegExp(`(^|-)${ph}(-|$)`).test(id))
|
|
129
|
-
return ph;
|
|
130
|
-
}
|
|
131
|
-
const hay = s.haystack;
|
|
132
|
-
if (declared.includes('EH') && /\b(direct access|without (a |the )?(submit|login)|browser back|refresh|expired|tamper|unauthoriz|redirect(ed)? (back )?to|guard)\b/.test(hay))
|
|
133
|
-
return 'EH';
|
|
134
|
-
if (declared.includes('ER') && /\b(invalid|error|required|validation|malformed|blocked|then correct|recover)\b/.test(hay))
|
|
135
|
-
return 'ER';
|
|
136
|
-
if (declared.includes('HP') && s.hasDataAssertion)
|
|
137
|
-
return 'HP';
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Verify the suite against the contract. Deterministic; a flow without a contract
|
|
142
|
-
* returns hasContract:false and neutral values (the audit reports the checklist).
|
|
143
|
-
*/
|
|
144
|
-
function flowQuality(unitDir, scenarios) {
|
|
145
|
-
const { contract, errors } = loadFlowContract(unitDir);
|
|
146
|
-
const neutral = {
|
|
147
|
-
hasContract: false, errors, outcomeProven: false, outcomeManualOnly: false,
|
|
148
|
-
offGoal: [], offGoalRatio: 0, offGoalCategories: [],
|
|
149
|
-
phases: [], phaseRatio: 1, handoffs: { total: 0, asserted: 0, ratio: 1 },
|
|
150
|
-
};
|
|
151
|
-
if (!contract)
|
|
152
|
-
return neutral;
|
|
153
|
-
const outcomeScreen = contract.outcome.screen;
|
|
154
|
-
// --- Outcome proof: the flow proves its own goal, by automation -------------
|
|
155
|
-
const proofs = scenarios.filter((s) => touchesOutcome(s, outcomeScreen) && s.hasDataAssertion);
|
|
156
|
-
const outcomeProven = proofs.some((s) => !s.manual);
|
|
157
|
-
const outcomeManualOnly = !outcomeProven && proofs.length > 0;
|
|
158
|
-
// --- Scope creep: a scenario that never touches the outcome and is not a ----
|
|
159
|
-
// guard/error phase is evidence of a SECOND business goal in this flow.
|
|
160
|
-
const declaredPhases = contract.phases;
|
|
161
|
-
const offGoalScenarios = scenarios.filter((s) => {
|
|
162
|
-
if (touchesOutcome(s, outcomeScreen))
|
|
163
|
-
return false;
|
|
164
|
-
const ph = phaseOf(s, declaredPhases);
|
|
165
|
-
return ph !== 'EH' && ph !== 'ER'; // guards/error-recovery legitimately stop early
|
|
166
|
-
});
|
|
167
|
-
const offGoalRatio = scenarios.length ? offGoalScenarios.length / scenarios.length : 0;
|
|
168
|
-
const offGoalCategories = Array.from(new Set(offGoalScenarios.map((s) => s.category ?? s.vpId?.replace(/-\d+.*$/, '') ?? '?')));
|
|
169
|
-
// --- Phase coverage: the flow's coverage axis (UI never demanded) -----------
|
|
170
|
-
const demanded = declaredPhases.filter((p) => p !== 'UI');
|
|
171
|
-
const phases = demanded.map((phase) => {
|
|
172
|
-
const inPhase = scenarios.filter((s) => phaseOf(s, declaredPhases) === phase);
|
|
173
|
-
// HP must additionally prove the outcome — a data assertion elsewhere is not the goal.
|
|
174
|
-
const relevant = phase === 'HP' ? inPhase.filter((s) => touchesOutcome(s, outcomeScreen)) : inPhase;
|
|
175
|
-
return {
|
|
176
|
-
phase,
|
|
177
|
-
covered: relevant.length > 0,
|
|
178
|
-
automated: relevant.some((s) => !s.manual),
|
|
179
|
-
};
|
|
180
|
-
});
|
|
181
|
-
const phaseRatio = demanded.length
|
|
182
|
-
? phases.filter((p) => p.covered && p.automated).length / demanded.length
|
|
183
|
-
: 1;
|
|
184
|
-
// --- Handoff integrity: no blind tail after a cross-namespace transition. ---
|
|
185
|
-
// A transition counts as asserted when ANY assertion follows it — in the entered
|
|
186
|
-
// namespace or later. Demanding the assertion in the entered namespace itself
|
|
187
|
-
// flagged two legitimate shapes: a guard that asserts the REDIRECT target
|
|
188
|
-
// ("go to [Checkout] → see [Home] page"), and a passthrough click en route
|
|
189
|
-
// ("click [Cart:Checkout]" asserting on the next screen). What the sensor
|
|
190
|
-
// actually guards against is a flow that clicks through screens and ends blind.
|
|
191
|
-
let total = 0;
|
|
192
|
-
let asserted = 0;
|
|
193
|
-
for (const s of scenarios) {
|
|
194
|
-
if (s.manual)
|
|
195
|
-
continue;
|
|
196
|
-
const steps = s.steps ?? [];
|
|
197
|
-
let current = null;
|
|
198
|
-
for (let i = 0; i < steps.length; i++) {
|
|
199
|
-
const ns = (steps[i].text.match(/\[([A-Za-z0-9_.-]+):/) || [])[1]?.toLowerCase() ?? null;
|
|
200
|
-
if (!ns)
|
|
201
|
-
continue;
|
|
202
|
-
if (current !== null && ns !== current) {
|
|
203
|
-
total++;
|
|
204
|
-
if (steps.slice(i).some((st) => st.bucket === 'then'))
|
|
205
|
-
asserted++;
|
|
206
|
-
}
|
|
207
|
-
current = ns;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
const handoffs = { total, asserted, ratio: total ? asserted / total : 1 };
|
|
211
|
-
return {
|
|
212
|
-
hasContract: true, contract, errors: [],
|
|
213
|
-
outcomeProven, outcomeManualOnly,
|
|
214
|
-
offGoal: offGoalScenarios.map((s) => s.name.slice(0, 80)),
|
|
215
|
-
offGoalRatio, offGoalCategories,
|
|
216
|
-
phases, phaseRatio, handoffs,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Generalized stateful regression depth: the contract names the mutated collection,
|
|
221
|
-
* so the three dims (count-proof · teardown · multi-source) stop being cart-only.
|
|
222
|
-
*/
|
|
223
|
-
function statefulDepthFor(collection, scenarios) {
|
|
224
|
-
const hay = scenarios.map((s) => s.haystack);
|
|
225
|
-
const any = (re) => hay.some((h) => re.test(h));
|
|
226
|
-
const noun = collection.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
227
|
-
const countProof = any(new RegExp(`\\b(quantity|qty|row count|count|number of|two (rows|lines|items)|\\d+ (rows|lines|items))\\b`));
|
|
228
|
-
const teardown = any(/\b(remove|delete|clear|cancel|withdraw)(?:s|d|ed|ing|n)?\b/) && any(new RegExp(`\\b(empty|emptied|no items|zero|removed|cleared|cancelled|withdrawn|0 items)\\b|empty[- ]${noun}`));
|
|
229
|
-
const adds = hay.filter((h) => new RegExp(`\\b(add|submit|create|place).{0,40}${noun}|${noun}.{0,40}\\b(add|submit|create|place)`).test(h));
|
|
230
|
-
const multiSource = any(/\b(recommended|related|you may also|another source|both sources|second (list|source))\b/) && adds.length > 0;
|
|
231
|
-
const dims = [['count-proof', countProof], ['teardown', teardown], ['multi-source', multiSource]];
|
|
232
|
-
const missing = dims.filter(([, v]) => !v).map(([k]) => k);
|
|
233
|
-
return { countProof, teardown, multiSource, missing, ratio: (dims.length - missing.length) / dims.length };
|
|
234
|
-
}
|
|
235
|
-
//# sourceMappingURL=flow-contract.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flow-contract.js","sourceRoot":"","sources":["../../src/harness/flow-contract.ts"],"names":[],"mappings":"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"}
|
package/dist/harness/perf.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export interface PerfConfig {
|
|
2
|
-
/** 0..100 — e.g. 75 for p75. */
|
|
3
|
-
percentile: number;
|
|
4
|
-
defaults: Record<string, number>;
|
|
5
|
-
units: Record<string, Record<string, number>>;
|
|
6
|
-
}
|
|
7
|
-
export interface PerfVerdict {
|
|
8
|
-
unit: string;
|
|
9
|
-
metric: string;
|
|
10
|
-
percentile: number;
|
|
11
|
-
budgetMs: number;
|
|
12
|
-
measuredMs: number;
|
|
13
|
-
samples: number;
|
|
14
|
-
pass: boolean;
|
|
15
|
-
/** Titles of the slowest offenders (only when failing), for the report. */
|
|
16
|
-
slowest: Array<{
|
|
17
|
-
title: string;
|
|
18
|
-
ms: number;
|
|
19
|
-
}>;
|
|
20
|
-
}
|
|
21
|
-
export declare function perfConfigPath(projectRoot: string): string;
|
|
22
|
-
/** Absent file → null (perf reporting is opt-in; nothing changes until configured). */
|
|
23
|
-
export declare function loadPerfConfig(projectRoot: string): PerfConfig | null;
|
|
24
|
-
/**
|
|
25
|
-
* Nearest-rank percentile (ceil), the standard "≥pXX of samples meet the budget"
|
|
26
|
-
* reading: p75 of [a…] is the value at ceil(0.75·n) in the sorted list. One
|
|
27
|
-
* sample → that sample. Deterministic, no interpolation.
|
|
28
|
-
*/
|
|
29
|
-
export declare function percentileOf(p: number, values: number[]): number;
|
|
30
|
-
/** Budget for a metric on a unit: per-unit override, else defaults, else none. */
|
|
31
|
-
export declare function budgetFor(config: PerfConfig, unit: string, metric: string): number | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* The scenario_ms verdict for one unit's run. `durations` = per-test wall-clock ms
|
|
34
|
-
* (a @cases scenario contributes one sample per row-test — each is a real run).
|
|
35
|
-
*/
|
|
36
|
-
export declare function perfVerdict(config: PerfConfig, unit: string, samples: Array<{
|
|
37
|
-
title: string;
|
|
38
|
-
ms: number;
|
|
39
|
-
}>): PerfVerdict | null;
|
|
40
|
-
//# sourceMappingURL=perf.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../../src/harness/perf.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,2EAA2E;IAC3E,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAuBrE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAKhE;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9F;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5C,WAAW,GAAG,IAAI,CAOpB"}
|
package/dist/harness/perf.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
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.perfConfigPath = perfConfigPath;
|
|
37
|
-
exports.loadPerfConfig = loadPerfConfig;
|
|
38
|
-
exports.percentileOf = percentileOf;
|
|
39
|
-
exports.budgetFor = budgetFor;
|
|
40
|
-
exports.perfVerdict = perfVerdict;
|
|
41
|
-
/**
|
|
42
|
-
* Performance budgets — config + percentile math + the per-unit verdict. (#569)
|
|
43
|
-
*
|
|
44
|
-
* A flow's regression value includes "still fast enough": after a lib/framework
|
|
45
|
-
* upgrade the main journeys must not only pass but hold their response-time
|
|
46
|
-
* budget. Sungen had no perf concept at all — the Playwright JSON parser even
|
|
47
|
-
* dropped the `duration` field Playwright already emits on every result.
|
|
48
|
-
*
|
|
49
|
-
* Scope discipline:
|
|
50
|
-
* - This is config + measurement + report over runs sungen already makes.
|
|
51
|
-
* Real load tests stay @manual:M8 → a dedicated tool.
|
|
52
|
-
* - The AUDIT never reads it: the quality score is documented as a pure
|
|
53
|
-
* function of the design artifacts ("reads no test-results, live page, or
|
|
54
|
-
* clock"). Perf reports where runs are already read — `sungen delivery`
|
|
55
|
-
* and the dashboard. Advisory: a blown budget never fails the design gate.
|
|
56
|
-
*
|
|
57
|
-
* Config: qa/perf.yaml
|
|
58
|
-
* percentile: p75 # default p75 — "≥75% of runs meet the budget"
|
|
59
|
-
* defaults:
|
|
60
|
-
* scenario_ms: 30000 # whole-scenario wall clock (Playwright duration)
|
|
61
|
-
* page_load_ms: 3000 # Phase B — needs per-transition runtime timing
|
|
62
|
-
* transition_ms: 2000 # Phase B
|
|
63
|
-
* units:
|
|
64
|
-
* place-order: { scenario_ms: 20000 }
|
|
65
|
-
*/
|
|
66
|
-
const fs = __importStar(require("fs"));
|
|
67
|
-
const path = __importStar(require("path"));
|
|
68
|
-
const yaml_1 = require("yaml");
|
|
69
|
-
const read_text_1 = require("./read-text");
|
|
70
|
-
function perfConfigPath(projectRoot) {
|
|
71
|
-
return path.join(projectRoot, 'qa', 'perf.yaml');
|
|
72
|
-
}
|
|
73
|
-
/** Absent file → null (perf reporting is opt-in; nothing changes until configured). */
|
|
74
|
-
function loadPerfConfig(projectRoot) {
|
|
75
|
-
const p = perfConfigPath(projectRoot);
|
|
76
|
-
if (!fs.existsSync(p))
|
|
77
|
-
return null;
|
|
78
|
-
let raw;
|
|
79
|
-
try {
|
|
80
|
-
raw = (0, yaml_1.parse)((0, read_text_1.readTextFile)(p));
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
if (!raw || typeof raw !== 'object')
|
|
86
|
-
return null;
|
|
87
|
-
const pctRaw = String(raw.percentile ?? 'p75').toLowerCase().replace(/^p/, '');
|
|
88
|
-
const percentile = Math.min(100, Math.max(1, Number(pctRaw) || 75));
|
|
89
|
-
const num = (o) => {
|
|
90
|
-
const out = {};
|
|
91
|
-
if (o && typeof o === 'object') {
|
|
92
|
-
for (const [k, v] of Object.entries(o)) {
|
|
93
|
-
const n = Number(v);
|
|
94
|
-
if (Number.isFinite(n) && n > 0)
|
|
95
|
-
out[k] = n;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return out;
|
|
99
|
-
};
|
|
100
|
-
const units = {};
|
|
101
|
-
if (raw.units && typeof raw.units === 'object') {
|
|
102
|
-
for (const [u, o] of Object.entries(raw.units))
|
|
103
|
-
units[u] = num(o);
|
|
104
|
-
}
|
|
105
|
-
return { percentile, defaults: num(raw.defaults), units };
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Nearest-rank percentile (ceil), the standard "≥pXX of samples meet the budget"
|
|
109
|
-
* reading: p75 of [a…] is the value at ceil(0.75·n) in the sorted list. One
|
|
110
|
-
* sample → that sample. Deterministic, no interpolation.
|
|
111
|
-
*/
|
|
112
|
-
function percentileOf(p, values) {
|
|
113
|
-
if (values.length === 0)
|
|
114
|
-
return 0;
|
|
115
|
-
const sorted = [...values].sort((a, b) => a - b);
|
|
116
|
-
const rank = Math.min(sorted.length, Math.max(1, Math.ceil((p / 100) * sorted.length)));
|
|
117
|
-
return sorted[rank - 1];
|
|
118
|
-
}
|
|
119
|
-
/** Budget for a metric on a unit: per-unit override, else defaults, else none. */
|
|
120
|
-
function budgetFor(config, unit, metric) {
|
|
121
|
-
return config.units[unit]?.[metric] ?? config.defaults[metric];
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* The scenario_ms verdict for one unit's run. `durations` = per-test wall-clock ms
|
|
125
|
-
* (a @cases scenario contributes one sample per row-test — each is a real run).
|
|
126
|
-
*/
|
|
127
|
-
function perfVerdict(config, unit, samples) {
|
|
128
|
-
const budgetMs = budgetFor(config, unit, 'scenario_ms');
|
|
129
|
-
if (budgetMs === undefined || samples.length === 0)
|
|
130
|
-
return null;
|
|
131
|
-
const measuredMs = percentileOf(config.percentile, samples.map((s) => s.ms));
|
|
132
|
-
const pass = measuredMs <= budgetMs;
|
|
133
|
-
const slowest = pass ? [] : [...samples].sort((a, b) => b.ms - a.ms).slice(0, 3);
|
|
134
|
-
return { unit, metric: 'scenario_ms', percentile: config.percentile, budgetMs, measuredMs, samples: samples.length, pass, slowest };
|
|
135
|
-
}
|
|
136
|
-
//# sourceMappingURL=perf.js.map
|
package/dist/harness/perf.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../../src/harness/perf.ts"],"names":[],"mappings":"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"}
|