@sun-asterisk/sungen 3.2.21 → 3.2.22-beta.1
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 +8 -0
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/delivery.d.ts +3 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +15 -0
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/inspect.d.ts +41 -0
- package/dist/cli/commands/inspect.d.ts.map +1 -0
- package/dist/cli/commands/inspect.js +134 -0
- package/dist/cli/commands/inspect.js.map +1 -0
- package/dist/cli/commands/trace.d.ts.map +1 -1
- package/dist/cli/commands/trace.js +9 -0
- package/dist/cli/commands/trace.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/exporters/matrix/build.d.ts +10 -0
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +38 -0
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +11 -0
- 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 +44 -1
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +10 -0
- 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 +1 -0
- package/dist/exporters/playwright-report-parser.js.map +1 -1
- package/dist/exporters/types.d.ts +2 -0
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +6 -1
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +5 -0
- 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 +27 -19
- 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 +22 -0
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/harness/audit.d.ts +2 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +101 -10
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/flow-contract.d.ts +87 -0
- package/dist/harness/flow-contract.d.ts.map +1 -0
- package/dist/harness/flow-contract.js +259 -0
- package/dist/harness/flow-contract.js.map +1 -0
- package/dist/harness/flow-plan.d.ts +3 -0
- package/dist/harness/flow-plan.d.ts.map +1 -1
- package/dist/harness/flow-plan.js +6 -2
- package/dist/harness/flow-plan.js.map +1 -1
- package/dist/harness/parse.d.ts +5 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +29 -1
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/perf.d.ts +40 -0
- package/dist/harness/perf.d.ts.map +1 -0
- package/dist/harness/perf.js +136 -0
- package/dist/harness/perf.js.map +1 -0
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +13 -1
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/spec-coverage.d.ts +8 -0
- package/dist/harness/spec-coverage.d.ts.map +1 -1
- package/dist/harness/spec-coverage.js +60 -6
- package/dist/harness/spec-coverage.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/commands/add-flow.md +51 -3
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +10 -0
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +23 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +60 -16
- package/dist/orchestrator/templates/qa-context.md +14 -1
- package/package.json +3 -3
- package/src/cli/commands/audit.ts +8 -0
- package/src/cli/commands/delivery.ts +14 -2
- package/src/cli/commands/inspect.ts +128 -0
- package/src/cli/commands/trace.ts +9 -0
- package/src/cli/index.ts +2 -0
- package/src/exporters/matrix/build.ts +40 -0
- package/src/exporters/matrix/export.ts +11 -0
- package/src/exporters/matrix/render-xlsx.ts +45 -1
- package/src/exporters/matrix/types.ts +10 -0
- package/src/exporters/playwright-report-parser.ts +2 -0
- package/src/exporters/types.ts +2 -0
- package/src/generators/test-generator/diagnostics.ts +6 -1
- package/src/generators/test-generator/patterns/index.ts +30 -24
- package/src/generators/test-generator/step-mapper.ts +22 -0
- package/src/harness/audit.ts +104 -11
- package/src/harness/flow-contract.ts +261 -0
- package/src/harness/flow-plan.ts +10 -3
- package/src/harness/parse.ts +31 -1
- package/src/harness/perf.ts +112 -0
- package/src/harness/sensors.ts +13 -1
- package/src/harness/spec-coverage.ts +55 -5
- package/src/orchestrator/templates/ai-src/commands/add-flow.md +51 -3
- package/src/orchestrator/templates/ai-src/commands/create-test.md +10 -0
- package/src/orchestrator/templates/ai-src/commands/run-test.md +23 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +60 -16
- package/src/orchestrator/templates/qa-context.md +14 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { ScenarioInfo } from './parse';
|
|
2
|
+
export interface FlowContract {
|
|
3
|
+
goal: string;
|
|
4
|
+
actor?: string;
|
|
5
|
+
trigger?: string;
|
|
6
|
+
precondition?: string;
|
|
7
|
+
outcome: {
|
|
8
|
+
screen: string;
|
|
9
|
+
assertion?: string;
|
|
10
|
+
};
|
|
11
|
+
value?: string;
|
|
12
|
+
/** Journey phases this flow declares. Default [HP, ER, EH]; UI is allowed but
|
|
13
|
+
* never demanded (presentation is the balance axis's business, not coverage's). */
|
|
14
|
+
phases: string[];
|
|
15
|
+
/** The mutated collection (cart, order, application …) — enables regression dims. */
|
|
16
|
+
stateful?: string;
|
|
17
|
+
budgets?: Record<string, number>;
|
|
18
|
+
/** External-system legs (owned by another team/vendor) — ISTQB System INTEGRATION Testing
|
|
19
|
+
* scope (#580 P10). Scenarios touching these namespaces are classified SIT. */
|
|
20
|
+
external?: Array<{
|
|
21
|
+
name: string;
|
|
22
|
+
owner?: string;
|
|
23
|
+
screens: string[];
|
|
24
|
+
}>;
|
|
25
|
+
/** This flow is release-critical: Final Inspection expects a @golden scenario here (P9). */
|
|
26
|
+
golden?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface FlowQualityResult {
|
|
29
|
+
hasContract: boolean;
|
|
30
|
+
contract?: FlowContract;
|
|
31
|
+
/** Parse/shape errors — a broken contract is reported, never silently ignored. */
|
|
32
|
+
errors: string[];
|
|
33
|
+
outcomeProven: boolean;
|
|
34
|
+
/** Manual-only proof: the goal is covered but not by automation. */
|
|
35
|
+
outcomeManualOnly: boolean;
|
|
36
|
+
/** Scenario names that never touch the outcome screen (guard/error phases excluded). */
|
|
37
|
+
offGoal: string[];
|
|
38
|
+
offGoalRatio: number;
|
|
39
|
+
/** Off-goal categories, for the split suggestion ("VP-FILTER-* looks like its own flow"). */
|
|
40
|
+
offGoalCategories: string[];
|
|
41
|
+
phases: {
|
|
42
|
+
phase: string;
|
|
43
|
+
covered: boolean;
|
|
44
|
+
automated: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
/** Covered-and-automated phases / declared phases (UI excluded) — the flow coverage axis. */
|
|
47
|
+
phaseRatio: number;
|
|
48
|
+
/** Cross-namespace transitions followed by an assertion / all transitions. */
|
|
49
|
+
handoffs: {
|
|
50
|
+
total: number;
|
|
51
|
+
asserted: number;
|
|
52
|
+
ratio: number;
|
|
53
|
+
};
|
|
54
|
+
/** ISTQB SIT classification (#580 P10): scenarios whose steps touch an external-system
|
|
55
|
+
* namespace declared in the contract's `external:` block. */
|
|
56
|
+
sit: Array<{
|
|
57
|
+
name: string;
|
|
58
|
+
external: string;
|
|
59
|
+
mockOnly: boolean;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
export declare function flowContractPath(unitDir: string): string;
|
|
63
|
+
/** Load + validate. Returns null when absent; a present-but-broken file returns errors. */
|
|
64
|
+
export declare function loadFlowContract(unitDir: string): {
|
|
65
|
+
contract: FlowContract | null;
|
|
66
|
+
errors: string[];
|
|
67
|
+
};
|
|
68
|
+
/** Phase of a scenario: its declared phase token (FL-HP-001 / VP-FLOW-ER-02 / MS-EH-005)
|
|
69
|
+
* when present, else vocabulary detection. */
|
|
70
|
+
export declare function phaseOf(s: ScenarioInfo, declared: string[]): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Verify the suite against the contract. Deterministic; a flow without a contract
|
|
73
|
+
* returns hasContract:false and neutral values (the audit reports the checklist).
|
|
74
|
+
*/
|
|
75
|
+
export declare function flowQuality(unitDir: string, scenarios: ScenarioInfo[]): FlowQualityResult;
|
|
76
|
+
/**
|
|
77
|
+
* Generalized stateful regression depth: the contract names the mutated collection,
|
|
78
|
+
* so the three dims (count-proof · teardown · multi-source) stop being cart-only.
|
|
79
|
+
*/
|
|
80
|
+
export declare function statefulDepthFor(collection: string, scenarios: ScenarioInfo[]): {
|
|
81
|
+
countProof: boolean;
|
|
82
|
+
teardown: boolean;
|
|
83
|
+
multiSource: boolean;
|
|
84
|
+
missing: string[];
|
|
85
|
+
ratio: number;
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=flow-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-contract.d.ts","sourceRoot":"","sources":["../../src/harness/flow-contract.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;wFACoF;IACpF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;oFACgF;IAChF,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACtE,4FAA4F;IAC5F,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kFAAkF;IAClF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,iBAAiB,EAAE,OAAO,CAAC;IAC3B,wFAAwF;IACxF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAClE,6FAA6F;IAC7F,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D;kEAC8D;IAC9D,GAAG,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACnE;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CA4CrG;AAaD;+CAC+C;AAC/C,wBAAgB,OAAO,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAU1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,iBAAiB,CAyFzF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAWlL"}
|
|
@@ -0,0 +1,259 @@
|
|
|
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
|
+
external: Array.isArray(raw.external)
|
|
110
|
+
? raw.external
|
|
111
|
+
.filter((e) => e && typeof e === 'object' && e.name)
|
|
112
|
+
.map((e) => ({
|
|
113
|
+
name: String(e.name),
|
|
114
|
+
owner: e.owner !== undefined ? String(e.owner) : undefined,
|
|
115
|
+
screens: Array.isArray(e.screens) ? e.screens.map((x) => String(x).toLowerCase()) : [],
|
|
116
|
+
}))
|
|
117
|
+
: undefined,
|
|
118
|
+
golden: raw.golden === true,
|
|
119
|
+
},
|
|
120
|
+
errors: [],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/** `[screen:element]` namespaces referenced by a scenario's steps, in step order. */
|
|
124
|
+
function namespacesInOrder(s) {
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const m of s.stepsText.matchAll(/\[([a-z0-9_.-]+):/g))
|
|
127
|
+
out.push(m[1]);
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
function touchesOutcome(s, outcomeScreen) {
|
|
131
|
+
return namespacesInOrder(s).includes(outcomeScreen);
|
|
132
|
+
}
|
|
133
|
+
/** Phase of a scenario: its declared phase token (FL-HP-001 / VP-FLOW-ER-02 / MS-EH-005)
|
|
134
|
+
* when present, else vocabulary detection. */
|
|
135
|
+
function phaseOf(s, declared) {
|
|
136
|
+
const id = (s.vpId ?? '').toUpperCase();
|
|
137
|
+
for (const ph of declared) {
|
|
138
|
+
if (new RegExp(`(^|-)${ph}(-|$)`).test(id))
|
|
139
|
+
return ph;
|
|
140
|
+
}
|
|
141
|
+
const hay = s.haystack;
|
|
142
|
+
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))
|
|
143
|
+
return 'EH';
|
|
144
|
+
if (declared.includes('ER') && /\b(invalid|error|required|validation|malformed|blocked|then correct|recover)\b/.test(hay))
|
|
145
|
+
return 'ER';
|
|
146
|
+
if (declared.includes('HP') && s.hasDataAssertion)
|
|
147
|
+
return 'HP';
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Verify the suite against the contract. Deterministic; a flow without a contract
|
|
152
|
+
* returns hasContract:false and neutral values (the audit reports the checklist).
|
|
153
|
+
*/
|
|
154
|
+
function flowQuality(unitDir, scenarios) {
|
|
155
|
+
const { contract, errors } = loadFlowContract(unitDir);
|
|
156
|
+
const neutral = {
|
|
157
|
+
hasContract: false, errors, outcomeProven: false, outcomeManualOnly: false,
|
|
158
|
+
offGoal: [], offGoalRatio: 0, offGoalCategories: [],
|
|
159
|
+
phases: [], phaseRatio: 1, handoffs: { total: 0, asserted: 0, ratio: 1 }, sit: [],
|
|
160
|
+
};
|
|
161
|
+
if (!contract)
|
|
162
|
+
return neutral;
|
|
163
|
+
const outcomeScreen = contract.outcome.screen;
|
|
164
|
+
// --- Outcome proof: the flow proves its own goal, by automation -------------
|
|
165
|
+
const proofs = scenarios.filter((s) => touchesOutcome(s, outcomeScreen) && s.hasDataAssertion);
|
|
166
|
+
const outcomeProven = proofs.some((s) => !s.manual);
|
|
167
|
+
const outcomeManualOnly = !outcomeProven && proofs.length > 0;
|
|
168
|
+
// --- Scope creep: a scenario that never touches the outcome and is not a ----
|
|
169
|
+
// guard/error phase is evidence of a SECOND business goal in this flow.
|
|
170
|
+
const declaredPhases = contract.phases;
|
|
171
|
+
const offGoalScenarios = scenarios.filter((s) => {
|
|
172
|
+
if (touchesOutcome(s, outcomeScreen))
|
|
173
|
+
return false;
|
|
174
|
+
const ph = phaseOf(s, declaredPhases);
|
|
175
|
+
return ph !== 'EH' && ph !== 'ER'; // guards/error-recovery legitimately stop early
|
|
176
|
+
});
|
|
177
|
+
const offGoalRatio = scenarios.length ? offGoalScenarios.length / scenarios.length : 0;
|
|
178
|
+
const offGoalCategories = Array.from(new Set(offGoalScenarios.map((s) => s.category ?? s.vpId?.replace(/-\d+.*$/, '') ?? '?')));
|
|
179
|
+
// --- Phase coverage: the flow's coverage axis (UI never demanded) -----------
|
|
180
|
+
const demanded = declaredPhases.filter((p) => p !== 'UI');
|
|
181
|
+
const phases = demanded.map((phase) => {
|
|
182
|
+
const inPhase = scenarios.filter((s) => phaseOf(s, declaredPhases) === phase);
|
|
183
|
+
// HP must additionally prove the outcome — a data assertion elsewhere is not the goal.
|
|
184
|
+
const relevant = phase === 'HP' ? inPhase.filter((s) => touchesOutcome(s, outcomeScreen)) : inPhase;
|
|
185
|
+
return {
|
|
186
|
+
phase,
|
|
187
|
+
covered: relevant.length > 0,
|
|
188
|
+
automated: relevant.some((s) => !s.manual),
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
const phaseRatio = demanded.length
|
|
192
|
+
? phases.filter((p) => p.covered && p.automated).length / demanded.length
|
|
193
|
+
: 1;
|
|
194
|
+
// --- Handoff integrity: no blind tail after a cross-namespace transition. ---
|
|
195
|
+
// A transition counts as asserted when ANY assertion follows it — in the entered
|
|
196
|
+
// namespace or later. Demanding the assertion in the entered namespace itself
|
|
197
|
+
// flagged two legitimate shapes: a guard that asserts the REDIRECT target
|
|
198
|
+
// ("go to [Checkout] → see [Home] page"), and a passthrough click en route
|
|
199
|
+
// ("click [Cart:Checkout]" asserting on the next screen). What the sensor
|
|
200
|
+
// actually guards against is a flow that clicks through screens and ends blind.
|
|
201
|
+
let total = 0;
|
|
202
|
+
let asserted = 0;
|
|
203
|
+
for (const s of scenarios) {
|
|
204
|
+
if (s.manual)
|
|
205
|
+
continue;
|
|
206
|
+
const steps = s.steps ?? [];
|
|
207
|
+
let current = null;
|
|
208
|
+
for (let i = 0; i < steps.length; i++) {
|
|
209
|
+
const ns = (steps[i].text.match(/\[([A-Za-z0-9_.-]+):/) || [])[1]?.toLowerCase() ?? null;
|
|
210
|
+
if (!ns)
|
|
211
|
+
continue;
|
|
212
|
+
if (current !== null && ns !== current) {
|
|
213
|
+
total++;
|
|
214
|
+
if (steps.slice(i).some((st) => st.bucket === 'then'))
|
|
215
|
+
asserted++;
|
|
216
|
+
}
|
|
217
|
+
current = ns;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const handoffs = { total, asserted, ratio: total ? asserted / total : 1 };
|
|
221
|
+
// --- SIT classification (#580 P10): a scenario whose steps touch an external-system
|
|
222
|
+
// namespace belongs to the System INTEGRATION group the QA matrix keeps separate. When
|
|
223
|
+
// that scenario is also verified only against mocks, its pass says nothing about the
|
|
224
|
+
// real vendor behaviour — the exit criteria the QA doc holds open (Pass (Mocked)).
|
|
225
|
+
const MOCK_STEP = /\[[^\]]+\]\s+mock\s+(?:is\s+active|called)\b/i;
|
|
226
|
+
const sit = [];
|
|
227
|
+
for (const leg of contract.external ?? []) {
|
|
228
|
+
const legScreens = new Set(leg.screens);
|
|
229
|
+
for (const s of scenarios) {
|
|
230
|
+
if (!namespacesInOrder(s).some((ns) => legScreens.has(ns)))
|
|
231
|
+
continue;
|
|
232
|
+
sit.push({ name: s.name.slice(0, 80), external: leg.name, mockOnly: MOCK_STEP.test(s.stepsText) });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
hasContract: true, contract, errors: [],
|
|
237
|
+
outcomeProven, outcomeManualOnly,
|
|
238
|
+
offGoal: offGoalScenarios.map((s) => s.name.slice(0, 80)),
|
|
239
|
+
offGoalRatio, offGoalCategories,
|
|
240
|
+
phases, phaseRatio, handoffs, sit,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Generalized stateful regression depth: the contract names the mutated collection,
|
|
245
|
+
* so the three dims (count-proof · teardown · multi-source) stop being cart-only.
|
|
246
|
+
*/
|
|
247
|
+
function statefulDepthFor(collection, scenarios) {
|
|
248
|
+
const hay = scenarios.map((s) => s.haystack);
|
|
249
|
+
const any = (re) => hay.some((h) => re.test(h));
|
|
250
|
+
const noun = collection.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
251
|
+
const countProof = any(new RegExp(`\\b(quantity|qty|row count|count|number of|two (rows|lines|items)|\\d+ (rows|lines|items))\\b`));
|
|
252
|
+
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}`));
|
|
253
|
+
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));
|
|
254
|
+
const multiSource = any(/\b(recommended|related|you may also|another source|both sources|second (list|source))\b/) && adds.length > 0;
|
|
255
|
+
const dims = [['count-proof', countProof], ['teardown', teardown], ['multi-source', multiSource]];
|
|
256
|
+
const missing = dims.filter(([, v]) => !v).map(([k]) => k);
|
|
257
|
+
return { countProof, teardown, multiSource, missing, ratio: (dims.length - missing.length) / dims.length };
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=flow-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-contract.js","sourceRoot":"","sources":["../../src/harness/flow-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,9 @@ export interface FlowPlan {
|
|
|
13
13
|
legs: LegPlan[];
|
|
14
14
|
byReason: Record<string, number>;
|
|
15
15
|
capabilityManual: number;
|
|
16
|
+
/** @manual whose reason is "cross-screen → automate via flow" (class XS) — inside a flow this
|
|
17
|
+
* usually means the scenario should simply BE automated here. (#569) */
|
|
18
|
+
crossScreenManual: number;
|
|
16
19
|
judgmentManual: number;
|
|
17
20
|
contracts: Contract[];
|
|
18
21
|
readiness: 'ready' | 'not-ready';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-plan.d.ts","sourceRoot":"","sources":["../../src/harness/flow-plan.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkB,QAAQ,EAAE,MAAM,cAAc,CAAC;AA6CxD,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AACD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,SAAS,EAAE,OAAO,GAAG,WAAW,CAAC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"flow-plan.d.ts","sourceRoot":"","sources":["../../src/harness/flow-plan.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkB,QAAQ,EAAE,MAAM,cAAc,CAAC;AA6CxD,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AACD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB;6EACyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,SAAS,EAAE,OAAO,GAAG,WAAW,CAAC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CA4DjE"}
|
|
@@ -113,16 +113,20 @@ function buildFlowPlan(cwd, flow) {
|
|
|
113
113
|
// Legs = distinct screen namespaces.
|
|
114
114
|
const legMap = new Map();
|
|
115
115
|
const byReason = {};
|
|
116
|
-
let capabilityManual = 0, judgmentManual = 0;
|
|
116
|
+
let capabilityManual = 0, judgmentManual = 0, crossScreenManual = 0;
|
|
117
117
|
for (const sc of scenarios) {
|
|
118
118
|
if (sc.manual) {
|
|
119
119
|
const { code } = (0, capability_plan_1.inferReasonCode)(sc.tags, sc.reason);
|
|
120
120
|
byReason[code] = (byReason[code] || 0) + 1;
|
|
121
121
|
const cls = capability_plan_1.MANUAL_REASONS[code]?.cls;
|
|
122
|
+
// XS ("cross-screen → automate via flow") is a THIRD class; it used to be silently
|
|
123
|
+
// dropped from both counters, understating the plan's manual load. (#569)
|
|
122
124
|
if (cls === 'capability')
|
|
123
125
|
capabilityManual++;
|
|
124
126
|
else if (cls === 'keep')
|
|
125
127
|
judgmentManual++;
|
|
128
|
+
else if (cls === 'flow')
|
|
129
|
+
crossScreenManual++;
|
|
126
130
|
}
|
|
127
131
|
for (const r of sc.refs) {
|
|
128
132
|
const leg = r.screen.toLowerCase();
|
|
@@ -163,6 +167,6 @@ function buildFlowPlan(cwd, flow) {
|
|
|
163
167
|
}
|
|
164
168
|
if (readiness === 'ready')
|
|
165
169
|
plan.unshift('Selectors present for every automated leg — ready to compile + run.');
|
|
166
|
-
return { flow, total: scenarios.length, legs, byReason, capabilityManual, judgmentManual, contracts, readiness, missingLegs, plan };
|
|
170
|
+
return { flow, total: scenarios.length, legs, byReason, capabilityManual, judgmentManual, crossScreenManual, contracts, readiness, missingLegs, plan };
|
|
167
171
|
}
|
|
168
172
|
//# sourceMappingURL=flow-plan.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-plan.js","sourceRoot":"","sources":["../../src/harness/flow-plan.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"flow-plan.js","sourceRoot":"","sources":["../../src/harness/flow-plan.ts"],"names":[],"mappings":"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"}
|
package/dist/harness/parse.d.ts
CHANGED
|
@@ -24,6 +24,11 @@ export interface ScenarioInfo {
|
|
|
24
24
|
requiresCaps?: string[];
|
|
25
25
|
deferredToFlow?: boolean;
|
|
26
26
|
ownedByFlow?: string;
|
|
27
|
+
/** Ordered steps with their resolved bucket (And/But inherit) — flow handoff analysis (#569). */
|
|
28
|
+
steps?: Array<{
|
|
29
|
+
bucket: 'given' | 'when' | 'then';
|
|
30
|
+
text: string;
|
|
31
|
+
}>;
|
|
27
32
|
}
|
|
28
33
|
/** Format-tolerant: is this token an ID (project's scheme), not a prose word?
|
|
29
34
|
* Accepts VP0, VP0-001, MS-HP-001, TV-01, VP-LIST-001 — requires a digit + uppercase start. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/harness/parse.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC;CACjD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/harness/parse.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC;CACjD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED;+FAC+F;AAC/F,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE3C;AAED,yFAAyF;AACzF,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAiBD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAmEzE;AAwGD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,EAAE,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAE/E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKzE"}
|
package/dist/harness/parse.js
CHANGED
|
@@ -100,6 +100,29 @@ function parseViewpointOverview(filePath) {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
// 1b) Flow-style declarations (#569). Flow viewpoint files commonly declare per-item
|
|
104
|
+
// ids at the END of a bullet ("… → **FL-HP-001**") under phase section headers
|
|
105
|
+
// ("## FL-HP — Happy Path"). Neither matched the table/group passes, so every flow
|
|
106
|
+
// audit collapsed to taxonomy=0% / traceability n-a — scenarios correctly tagged
|
|
107
|
+
// FL-HP-001 were reported as unmapped. Both forms are additive here.
|
|
108
|
+
for (const raw of lines) {
|
|
109
|
+
const line = raw.trim();
|
|
110
|
+
const section = line.match(/^##\s+([A-Z]{2,}(?:-[A-Z0-9]{2,})*)\s+[—–-]\s*(.*)$/);
|
|
111
|
+
if (section && isViewpointId(section[1] + '-0')) {
|
|
112
|
+
const id = section[1].toUpperCase();
|
|
113
|
+
if (!entries.has(id))
|
|
114
|
+
entries.set(id, { id, priority: 'Unknown', reason: section[2] ?? '' });
|
|
115
|
+
}
|
|
116
|
+
if (/^[-*+]\s/.test(line)) {
|
|
117
|
+
const arrow = line.match(/(?:→|->)\s*\*{0,2}([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*-\d+[a-zA-Z]?)\*{0,2}\s*$/);
|
|
118
|
+
if (arrow) {
|
|
119
|
+
const id = arrow[1].toUpperCase();
|
|
120
|
+
if (!entries.has(id)) {
|
|
121
|
+
entries.set(id, { id, priority: 'Unknown', reason: line.replace(/\s*(?:→|->).*$/, '').replace(/^[-*+]\s+/, '') });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
103
126
|
// 2) Viewpoint Grouping: ### Required / ### Recommended / ### Optional → bullet list
|
|
104
127
|
let group;
|
|
105
128
|
for (const raw of lines) {
|
|
@@ -168,7 +191,9 @@ function classifyScenario(sc) {
|
|
|
168
191
|
// Category is everything between `VP-` and the final `-<sequence>` — INCLUDING hyphens, so
|
|
169
192
|
// compound categories (VP-LIST-DISPLAY-01, VP-ADD-TO-CART-03, VP-PRODUCT-DISCOVERY-02) parse,
|
|
170
193
|
// not just single-word ones. A single-word category (VP-CART-001) still works. (H1)
|
|
171
|
-
|
|
194
|
+
// Flows use journey-phase ids (FL-HP-001 / FL-ER-002) — the VP- anchor rejected them, so every
|
|
195
|
+
// flow scenario had NO category and the whole suite bucketed `other` (taxonomy=0%, #569).
|
|
196
|
+
const codeMatch = sc.name.match(/\b(?:VP|FL)-([A-Z]+(?:-[A-Z]+)*)-\d+/i);
|
|
172
197
|
const vpCode = codeMatch ? codeMatch[0].toUpperCase() : undefined;
|
|
173
198
|
const category = codeMatch ? codeMatch[1].toUpperCase() : undefined;
|
|
174
199
|
// Project-scheme ID: the leading token of the title (VP0-001 / MS-HP-001 / VP-LIST-001).
|
|
@@ -181,12 +206,14 @@ function classifyScenario(sc) {
|
|
|
181
206
|
const skeletonParts = [];
|
|
182
207
|
const textParts = [sc.name];
|
|
183
208
|
const stepTextParts = [];
|
|
209
|
+
const orderedSteps = [];
|
|
184
210
|
for (const step of sc.steps) {
|
|
185
211
|
const kw = step.keyword.trim();
|
|
186
212
|
if (kw === 'Given' || kw === 'When' || kw === 'Then')
|
|
187
213
|
last = kw;
|
|
188
214
|
textParts.push(step.text);
|
|
189
215
|
stepTextParts.push(step.text);
|
|
216
|
+
orderedSteps.push({ bucket: (kw === 'And' || kw === 'But' ? last : kw).toLowerCase(), text: step.text });
|
|
190
217
|
// normalized skeleton: keep [refs] (distinct targets = distinct tests),
|
|
191
218
|
// but neutralize {{vars}} and quoted values so EP/data families collapse.
|
|
192
219
|
const skel = step.text
|
|
@@ -220,6 +247,7 @@ function classifyScenario(sc) {
|
|
|
220
247
|
stepSkeleton: skeletonParts.join(' | '),
|
|
221
248
|
haystack: textParts.join(' ').toLowerCase(),
|
|
222
249
|
stepsText: stepTextParts.join(' ').toLowerCase(),
|
|
250
|
+
steps: orderedSteps,
|
|
223
251
|
vpId,
|
|
224
252
|
casesDataset,
|
|
225
253
|
queryRefs: queryRefs.size ? [...queryRefs] : undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/harness/parse.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/harness/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|