@sun-asterisk/sungen 3.2.25 → 3.2.26

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 (58) hide show
  1. package/dist/cli/commands/audit.d.ts.map +1 -1
  2. package/dist/cli/commands/audit.js +23 -4
  3. package/dist/cli/commands/audit.js.map +1 -1
  4. package/dist/exporters/matrix/build.d.ts.map +1 -1
  5. package/dist/exporters/matrix/build.js +4 -1
  6. package/dist/exporters/matrix/build.js.map +1 -1
  7. package/dist/exporters/matrix/map-loader.d.ts.map +1 -1
  8. package/dist/exporters/matrix/map-loader.js +5 -0
  9. package/dist/exporters/matrix/map-loader.js.map +1 -1
  10. package/dist/exporters/matrix/types.d.ts +11 -0
  11. package/dist/exporters/matrix/types.d.ts.map +1 -1
  12. package/dist/exporters/matrix/types.js.map +1 -1
  13. package/dist/harness/audit.d.ts +7 -0
  14. package/dist/harness/audit.d.ts.map +1 -1
  15. package/dist/harness/audit.js +74 -6
  16. package/dist/harness/audit.js.map +1 -1
  17. package/dist/harness/flow-contract.d.ts +18 -1
  18. package/dist/harness/flow-contract.d.ts.map +1 -1
  19. package/dist/harness/flow-contract.js +72 -9
  20. package/dist/harness/flow-contract.js.map +1 -1
  21. package/dist/harness/quality-gates.d.ts +12 -1
  22. package/dist/harness/quality-gates.d.ts.map +1 -1
  23. package/dist/harness/quality-gates.js +62 -7
  24. package/dist/harness/quality-gates.js.map +1 -1
  25. package/dist/harness/spec-branches.d.ts +88 -0
  26. package/dist/harness/spec-branches.d.ts.map +1 -0
  27. package/dist/harness/spec-branches.js +280 -0
  28. package/dist/harness/spec-branches.js.map +1 -0
  29. package/dist/harness/spec-coverage.d.ts +1 -1
  30. package/dist/harness/spec-coverage.js +4 -4
  31. package/dist/harness/spec-coverage.js.map +1 -1
  32. package/dist/harness/viewpoint-baseline.d.ts +9 -0
  33. package/dist/harness/viewpoint-baseline.d.ts.map +1 -1
  34. package/dist/harness/viewpoint-baseline.js +33 -3
  35. package/dist/harness/viewpoint-baseline.js.map +1 -1
  36. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  37. package/dist/harness/viewpoint-ledger.js +63 -5
  38. package/dist/harness/viewpoint-ledger.js.map +1 -1
  39. package/dist/orchestrator/templates/ai-src/commands/add-flow.md +16 -0
  40. package/dist/orchestrator/templates/ai-src/commands/create-test.md +9 -0
  41. package/dist/orchestrator/templates/ai-src/commands/delivery.md +9 -2
  42. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +31 -1
  43. package/package.json +3 -3
  44. package/src/cli/commands/audit.ts +22 -3
  45. package/src/exporters/matrix/build.ts +4 -1
  46. package/src/exporters/matrix/map-loader.ts +5 -0
  47. package/src/exporters/matrix/types.ts +11 -0
  48. package/src/harness/audit.ts +78 -8
  49. package/src/harness/flow-contract.ts +87 -9
  50. package/src/harness/quality-gates.ts +64 -6
  51. package/src/harness/spec-branches.ts +346 -0
  52. package/src/harness/spec-coverage.ts +4 -4
  53. package/src/harness/viewpoint-baseline.ts +41 -6
  54. package/src/harness/viewpoint-ledger.ts +56 -4
  55. package/src/orchestrator/templates/ai-src/commands/add-flow.md +16 -0
  56. package/src/orchestrator/templates/ai-src/commands/create-test.md +9 -0
  57. package/src/orchestrator/templates/ai-src/commands/delivery.md +9 -2
  58. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +31 -1
@@ -56,20 +56,41 @@ const read_text_1 = require("./read-text");
56
56
  function downstreamRoutes(specText) {
57
57
  const ownRoute = (specText.match(/\*\*Route\*\*\s*:\s*`?(\/[^\s`]+)/) || [])[1] || '';
58
58
  const routes = new Set();
59
+ const negated = new Set();
59
60
  for (const line of specText.split('\n')) {
60
61
  if (!/success|navigat|to \(|→/i.test(line))
61
62
  continue;
62
63
  // A real route's leading `/` sits at a path boundary (start, whitespace, backtick, quote, paren),
63
64
  // NOT after a letter/digit. The lookbehind rejects prose slashes like "text/icon" or
64
65
  // "category/brand" that aren't routes at all (H2 — they produced /icon, /button, /brand).
66
+ let negRun = false; // inside a "…, not `/a`/`/b`" list
67
+ let prevEnd = 0;
65
68
  for (const m of line.matchAll(/(?<![A-Za-z0-9])(\/[a-z][a-z0-9/_-]+)`?/gi)) {
66
69
  const r = m[1];
70
+ // "the destination is `/a/b` (singular, not `/a/bs` as this spec assumed)" declares ONE
71
+ // target and CORRECTS another. A spec that says where a route is NOT is doing the reader a
72
+ // service; extracting the disowned one and demanding a test for it punishes the correction.
73
+ // The negation carries across a LIST — "not `/x`/`/y`" disowns both, not just the first.
74
+ const before = line.slice(Math.max(0, m.index - 24), m.index);
75
+ const gap = line.slice(prevEnd, m.index);
76
+ prevEnd = m.index + m[0].length;
77
+ if (/\b(?:not|instead of|rather than|no longer|never|không)\s*[`'"(\[]*\s*$/i.test(before))
78
+ negRun = true;
79
+ else if (negRun && !/^[`'"\s)\]]*[/,]?\s*(?:or|hoặc)?\s*[`'"(\[]*$/i.test(gap))
80
+ negRun = false;
81
+ if (negRun) {
82
+ negated.add(r);
83
+ continue;
84
+ }
67
85
  if (r !== ownRoute && r.split('/').length > ownRoute.split('/').length - 0)
68
86
  routes.add(r);
69
87
  }
70
88
  }
89
+ for (const n of negated)
90
+ if (!routes.has(n))
91
+ routes.delete(n);
71
92
  // keep only routes that extend beyond the own route (a distinct downstream surface)
72
- return [...routes].filter((r) => r !== ownRoute && (!ownRoute || r.startsWith(ownRoute + '/') || r.split('/').length >= 3));
93
+ return [...routes].filter((r) => !negated.has(r) && r !== ownRoute && (!ownRoute || r.startsWith(ownRoute + '/') || r.split('/').length >= 3));
73
94
  }
74
95
  /**
75
96
  * H5 — a @parallel stateful (cart-mutating) flow with NO per-scenario isolation is flaky: scenarios
@@ -140,9 +161,25 @@ function sameScreenName(slug, label) {
140
161
  i++;
141
162
  return i >= 5 && i / Math.min(a.length, b.length) >= 0.6;
142
163
  }
143
- function downstreamScope(specText, scenarios) {
144
- const routes = downstreamRoutes(specText);
164
+ function downstreamScope(specText, scenarios, featureText = '') {
165
+ const all = downstreamRoutes(specText);
166
+ // A one-segment route that other declared routes are BUILT ON is a prefix, not a destination:
167
+ // a spec noting that "every route is served under a `/xx/` locale prefix (e.g. `/xx/register`)"
168
+ // was read as declaring `/xx/` a navigation target, and no suite will ever "navigate to" it.
169
+ // Structural, so it catches any mount point — locale, tenant, api version — without a list.
170
+ const mounts = all.filter((r) => {
171
+ const segs = r.split('/').filter(Boolean);
172
+ return segs.length === 1 && all.some((o) => o !== r && o.startsWith(r.endsWith('/') ? r : `${r}/`));
173
+ });
174
+ // The same destination written twice — once bare, once under the mount the spec documents —
175
+ // is one navigation target, and reporting both doubles the work it asks for.
176
+ const routes = all.filter((r) => !mounts.includes(r)
177
+ && !mounts.some((m) => {
178
+ const bare = r.slice(m.replace(/\/$/, '').length);
179
+ return bare.startsWith('/') && all.includes(bare);
180
+ }));
145
181
  const underCovered = [];
182
+ const absent = [];
146
183
  for (const route of routes) {
147
184
  const slug = (route.split('/').filter(Boolean).pop() || route).toLowerCase();
148
185
  // Referenced when the route/slug appears literally, OR when any `[Ref]` in the suite
@@ -150,17 +187,35 @@ function downstreamScope(specText, scenarios) {
150
187
  const labelsOf = (s) => [...s.haystack.matchAll(/\[([^\]]+)\]/g)].map((m) => m[1].split(':')[0]);
151
188
  const refs = scenarios.filter((s) => s.haystack.includes(slug) || s.haystack.includes(route.toLowerCase()) ||
152
189
  labelsOf(s).some((l) => sameScreenName(slug, l)));
153
- if (!refs.length)
154
- continue; // not referenced at all out of this screen's scope entirely
190
+ if (!refs.length) {
191
+ // A scenario's haystack is its name + steps, so a route documented in a @manual scenario's
192
+ // tester procedure — a COMMENT — looks like nothing at all. That route is accounted for: a
193
+ // person has been told to check it. Reporting "no scenario mentions it, add one" over a
194
+ // deliberate manual deferral is the false positive this whole round is about, so absence is
195
+ // measured against the feature TEXT, comments included (#651 follow-up).
196
+ if (!featureText.toLowerCase().includes(route.toLowerCase()))
197
+ absent.push({ route, slug });
198
+ continue;
199
+ }
155
200
  // Substantively covered only if some scenario OPERATES on the downstream — i.e. it
156
201
  // starts there (`is on [<downstream>]`) — not merely navigates to it as a terminal
157
202
  // `see [<downstream>] page` assertion. The latter just proves the transition.
203
+ // Two shapes prove the screen's CONTENT was checked, not just its route:
204
+ // - the suite OPENS ON it (`is on [Registration] page`), and
205
+ // - it asserts an element NAMESPACED to it (`see [Registration:Submit] button`) — the
206
+ // namespace names the screen, so the assertion is about that screen by construction.
207
+ // Only the first counted, so a scenario that navigated there and then asserted the screen's
208
+ // own elements was still reported "covered only by a page-nav assertion" (#630). The field
209
+ // report's hypothesis — that the parser reads one line after the nav and stops — is still not
210
+ // what happens: there is no line window, and both shapes are matched over the whole scenario.
158
211
  const contentCovered = refs.some((s) => [...s.haystack.matchAll(/\bis on \[([^\]]+)\]/g)]
159
- .some((m) => sameScreenName(slug, m[1].split(':')[0])));
212
+ .some((m) => sameScreenName(slug, m[1].split(':')[0]))
213
+ || [...s.haystack.matchAll(/\bsee \[([^\]:]+):[^\]]+\]/g)]
214
+ .some((m) => sameScreenName(slug, m[1])));
160
215
  if (!contentCovered)
161
216
  underCovered.push({ route, slug });
162
217
  }
163
- return { downstreamRoutes: routes, underCovered };
218
+ return { downstreamRoutes: routes, underCovered, absent };
164
219
  }
165
220
  function blocks(featureText) {
166
221
  return featureText.split(/\n\s*\n/).filter((b) => /\bScenario:/.test(b));
@@ -1 +1 @@
1
- {"version":3,"file":"quality-gates.js","sourceRoot":"","sources":["../../src/harness/quality-gates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"quality-gates.js","sourceRoot":"","sources":["../../src/harness/quality-gates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Mutually-exclusive branches declared in the spec, and whether each one has a scenario (#630).
3
+ *
4
+ * A field report hit the same gap three times in three different flows, in three different
5
+ * shapes: an `### Exception Flow A` heading left entirely blank; a decision table
6
+ * (`DEC-003_EmptyStateCascade`) whose three arms produced ONE covered arm and two
7
+ * scenarios verifying that same arm under different names; and a pseudocode block with two
8
+ * attention-hint branches where only the first got a case.
9
+ *
10
+ * The narrative rule already existed — "AND condition → test each branch failing independently",
11
+ * "business rule → 1 behavioural TC per rule". It was missed anyway, three times. So the
12
+ * reviewers' own conclusion is the design here: what works is an ENFORCED enumeration, the way
13
+ * `Viewpoint items` are enumerated and completeness-checked, not another sentence of guidance.
14
+ *
15
+ * Deliberately conservative. A branch is only claimed when the spec makes the enumeration
16
+ * explicit — a named heading, a table that declares conditions and outcomes, or an if/else
17
+ * cascade — because a false "you missed a branch" costs more trust than it buys coverage.
18
+ */
19
+ import { ScenarioInfo } from './parse';
20
+ export interface SpecBranch {
21
+ /** Stable id for the message: the block name plus the arm. */
22
+ id: string;
23
+ /** The distinctive token the suite is expected to cite. */
24
+ label: string;
25
+ kind: 'exception-flow' | 'alternative-flow' | 'decision-arm' | 'pseudocode-arm';
26
+ /** Where it was found, so the author can go and read it. */
27
+ source: string;
28
+ }
29
+ export declare function specBranches(specText: string): SpecBranch[];
30
+ export declare function unenumeratedBranches(branches: SpecBranch[], featureText: string): SpecBranch[];
31
+ /**
32
+ * Scenarios whose assertions are IDENTICAL — "N cases" in a coverage sheet that verify one arm N
33
+ * times. The field report's decision table produced exactly this: two cases under different
34
+ * names, both asserting the same message, reported as two covered branches.
35
+ *
36
+ * Compares only the assertion side: two scenarios may legitimately share setup and differ in
37
+ * what they prove, but if what they PROVE is identical they are one test.
38
+ */
39
+ export declare function sameOracleClusters(scenarios: ScenarioInfo[]): Array<{
40
+ oracle: string;
41
+ scenarios: string[];
42
+ }>;
43
+ export declare function permissionPairGaps(scenarios: ScenarioInfo[]): Array<{
44
+ scenario: string;
45
+ subject: string[];
46
+ }>;
47
+ export declare function awaitingSeedData(testDataText: string, scenarios: ScenarioInfo[]): Array<{
48
+ key: string;
49
+ scenarios: string[];
50
+ }>;
51
+ /**
52
+ * The fixed risk catalog for a multi-screen journey, reconciled against the flow (#651 F1-7).
53
+ *
54
+ * `SPEC-BRANCH-UNCOVERED` enforces the branches a spec DECLARES. This is the other half, and the
55
+ * one a field report asked for explicitly: the risks a spec is often SILENT about, which a
56
+ * reviewer notices and a generator does not. Their words — *"cả 2 flow đều thiếu 2-3 nhóm trong
57
+ * danh sách này, không phải vì không áp dụng mà vì không có bước bắt buộc rà lại checklist đó
58
+ * trước khi coi flow 'đủ'"*.
59
+ *
60
+ * The same families as the step × risk matrix in `sungen-tc-generation`, so guidance and gate
61
+ * cannot drift apart. A family counts as CONSIDERED when it is mentioned anywhere the author
62
+ * reasons: a declared flow's branch point, outcome or reason; a scenario; or the viewpoint. That
63
+ * makes "we thought about it and it does not apply" a one-line answer — the accounting the flow
64
+ * inventory already asks for — rather than a scenario nobody needs.
65
+ */
66
+ export interface RiskFamily {
67
+ id: string;
68
+ label: string;
69
+ /** What the author writes when they HAVE considered it. */
70
+ re: RegExp;
71
+ /** Why it bites on a multi-screen journey specifically. */
72
+ why: string;
73
+ }
74
+ export declare const MULTI_SCREEN_RISKS: RiskFamily[];
75
+ export declare function unconsideredRisks(contract: FlowContractLike, scenarios: ScenarioInfo[], viewpointText: string): RiskFamily[];
76
+ /** The slice of the contract this needs — kept structural so the module stays import-light. */
77
+ export interface FlowContractLike {
78
+ flows?: Array<{
79
+ id: string;
80
+ branchFrom?: string;
81
+ outcome?: string;
82
+ reason?: string;
83
+ }>;
84
+ minimalGuarantee?: string;
85
+ successGuarantee?: string;
86
+ precondition?: string;
87
+ }
88
+ //# sourceMappingURL=spec-branches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-branches.d.ts","sourceRoot":"","sources":["../../src/harness/spec-branches.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,cAAc,GAAG,gBAAgB,CAAC;IAChF,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;CAChB;AA6DD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CA8D3D;AAYD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,EAAE,CAc9F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAgB5G;AAgBD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,YAAY,EAAE,GACxB,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAmBhD;AAWD,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAC9C,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAgB7C;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,kBAAkB,EAAE,UAAU,EA4B1C,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,aAAa,EAAE,MAAM,GAC3E,UAAU,EAAE,CAUd;AAED,+FAA+F;AAC/F,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MULTI_SCREEN_RISKS = void 0;
4
+ exports.specBranches = specBranches;
5
+ exports.unenumeratedBranches = unenumeratedBranches;
6
+ exports.sameOracleClusters = sameOracleClusters;
7
+ exports.permissionPairGaps = permissionPairGaps;
8
+ exports.awaitingSeedData = awaitingSeedData;
9
+ exports.unconsideredRisks = unconsideredRisks;
10
+ /**
11
+ * CamelCase identifiers only — an outcome LABEL (`StateNoItems`, `HintPrimary`).
12
+ *
13
+ * SCREAMING_SNAKE was in this pattern and produced two false branches on a real spec:
14
+ * `DEFAULT_FILTER` from `conditions !== DEFAULT_FILTER` and `MESSAGE_READ` from a permission check.
15
+ * Those are OPERANDS inside a condition, not arms of it — a constant names a value, an outcome
16
+ * names a result. Shape alone cannot tell them apart, so the shape that only outcomes use is the
17
+ * one to match (#651 follow-up).
18
+ */
19
+ const IDENTIFIER = /\b([A-Z][a-z0-9]+(?:[A-Z][a-z0-9]+)+)\b/g;
20
+ /**
21
+ * Code references are not branch labels. A table cell citing
22
+ * `src/components/molecules/HomeBoard/AlertPanel.tsx` yielded four "branches" —
23
+ * AlertPanel, TaskPanel, FeaturedList, HomeBoard — none of which is a branch at all.
24
+ * Backticked spans and anything path-shaped go before identifiers are read.
25
+ */
26
+ function withoutCodeRefs(text) {
27
+ return text
28
+ .replace(/`[^`]*`/g, ' ') // inline code spans
29
+ .replace(/\[[^\]]*\]\([^)]*\)/g, ' ') // markdown links
30
+ .replace(/\S*\/\S*/g, ' ') // any path-like token
31
+ .replace(/\b\w+\.(?:tsx?|jsx?|vue|py|rb|go|java|kt|swift|md|ya?ml|json)\b/gi, ' ');
32
+ }
33
+ /** A named decision/rule block: `DEC-003_Foo`, `BR-001_Bar`, `ALG-002`. */
34
+ const NAMED_BLOCK = /\b((?:DEC|BR|ALG|RULE|DISC)-\d+)(?:_([A-Za-z0-9]+))?\b/;
35
+ const HEADING = /^(#{1,6})\s+(.*)$/;
36
+ /**
37
+ * Split a markdown document into `{ heading, lines }` sections, so a table or fence can be
38
+ * attributed to the block that names it.
39
+ */
40
+ function sections(text) {
41
+ const out = [{ heading: '', lines: [] }];
42
+ for (const raw of text.split('\n')) {
43
+ const h = raw.match(HEADING);
44
+ if (h)
45
+ out.push({ heading: h[2].replace(/[*`]/g, '').trim(), lines: [] });
46
+ else
47
+ out[out.length - 1].lines.push(raw);
48
+ }
49
+ return out;
50
+ }
51
+ /** Does this table declare CONDITIONS mapping to OUTCOMES (a decision table)? */
52
+ function isDecisionTable(header, sectionHeading) {
53
+ const cells = header.map((c) => c.toLowerCase());
54
+ // A Given/When/Then table is a list of TEST CASES, not a decision to enumerate — each row is
55
+ // already a case. It matched on `when`+`then` and turned a real spec's test-case table into
56
+ // five phantom branches (#651 follow-up).
57
+ const isGherkinTable = cells.some((c) => /\bgiven\b/.test(c)) && cells.some((c) => /\bwhen\b/.test(c))
58
+ && cells.some((c) => /\bthen\b/.test(c));
59
+ const isTestCaseTable = cells.some((c) => /test[- ]?id|tc[- ]?id|case[- ]?id/.test(c));
60
+ if (isGherkinTable || isTestCaseTable)
61
+ return false;
62
+ const hasCondition = cells.some((c) => /condition|case|when|input|state|flag|criteria|nhánh|điều kiện/.test(c));
63
+ const hasOutcome = cells.some((c) => /outcome|result|then|display|shows?|expected|action|behaviou?r|kết quả/.test(c));
64
+ // A block the spec itself NAMES as a decision counts even if its columns are worded oddly.
65
+ return (hasCondition && hasOutcome) || /\b(?:DEC|decision|cascade|matrix)\b/i.test(sectionHeading);
66
+ }
67
+ function specBranches(specText) {
68
+ const out = [];
69
+ const seen = new Set();
70
+ const push = (b) => {
71
+ const k = `${b.id}|${b.label}`;
72
+ if (seen.has(k))
73
+ return;
74
+ seen.add(k);
75
+ out.push(b);
76
+ };
77
+ for (const sec of sections(specText)) {
78
+ // 1. An `### Exception Flow A` / `### Alternative Flow 2` heading IS one branch. Unambiguous.
79
+ const flowH = sec.heading.match(/^(exception|alternative|alternate)\s+flow\s*([A-Z0-9][\w-]*)?/i);
80
+ if (flowH) {
81
+ const label = sec.heading;
82
+ push({
83
+ id: label, label,
84
+ kind: /^exception/i.test(flowH[1]) ? 'exception-flow' : 'alternative-flow',
85
+ source: `heading "${sec.heading}"`,
86
+ });
87
+ continue;
88
+ }
89
+ const named = sec.heading.match(NAMED_BLOCK);
90
+ const blockName = named ? named[0] : sec.heading;
91
+ // 2. A decision table: each data row is one arm. Matched on the identifier the row names.
92
+ const rows = sec.lines.filter((l) => l.trim().startsWith('|') && !/^\|[\s|:-]+\|?$/.test(l.trim()));
93
+ if (rows.length >= 3) { // header + at least two arms
94
+ const header = rows[0].split('|').map((c) => c.trim()).filter(Boolean);
95
+ if (isDecisionTable(header, sec.heading)) {
96
+ for (const row of rows.slice(1)) {
97
+ const ids = [...withoutCodeRefs(row).matchAll(IDENTIFIER)].map((m) => m[1]);
98
+ // Only an identifier is distinctive enough to look for in a suite; a prose condition
99
+ // would match half the feature file.
100
+ for (const id of ids)
101
+ push({ id: `${blockName}:${id}`, label: id, kind: 'decision-arm', source: `decision table under "${sec.heading}"` });
102
+ }
103
+ }
104
+ }
105
+ // 3. An if/elif/else cascade in a fenced block: each arm that NAMES an outcome identifier.
106
+ let inFence = false;
107
+ let fence = [];
108
+ for (const l of sec.lines) {
109
+ if (l.trim().startsWith('```')) {
110
+ if (inFence) {
111
+ const body = fence.join('\n');
112
+ const arms = (body.match(/\b(?:else\s+if|elif|if|else)\b/g) ?? []).length;
113
+ if (arms >= 2) {
114
+ for (const m of withoutCodeRefs(body).matchAll(IDENTIFIER)) {
115
+ push({ id: `${blockName}:${m[1]}`, label: m[1], kind: 'pseudocode-arm', source: `pseudocode under "${sec.heading}"` });
116
+ }
117
+ }
118
+ fence = [];
119
+ }
120
+ inFence = !inFence;
121
+ continue;
122
+ }
123
+ if (inFence)
124
+ fence.push(l);
125
+ }
126
+ }
127
+ return out;
128
+ }
129
+ /**
130
+ * Branches with no scenario citing them. A citation counts anywhere in the feature text —
131
+ * title, steps or a comment — because an author who deliberately excludes a branch writes the
132
+ * reason as a comment, and that is an accounting, not a gap.
133
+ */
134
+ const GENERIC_WORD = new Set([
135
+ 'flow', 'exception', 'alternative', 'alternate', 'the', 'and', 'with', 'without', 'when', 'then',
136
+ 'user', 'visitor', 'screen', 'page', 'from', 'that', 'this', 'case', 'gate', 'step',
137
+ ]);
138
+ function unenumeratedBranches(branches, featureText) {
139
+ const hay = featureText.toLowerCase();
140
+ return branches.filter((b) => {
141
+ // An IDENTIFIER is precise — require it verbatim. A HEADING is prose the author will
142
+ // rephrase ("Exception Flow A — drawer confirm gate" becomes "closing the drawer without
143
+ // confirming"), so match on its distinctive words instead: demanding the heading verbatim
144
+ // would report a branch that is covered under a better name.
145
+ if (b.kind === 'decision-arm' || b.kind === 'pseudocode-arm')
146
+ return !hay.includes(b.label.toLowerCase());
147
+ const words = [...new Set((b.label.toLowerCase().match(/[a-z][a-z-]{3,}/g) ?? []))]
148
+ .filter((w) => !GENERIC_WORD.has(w));
149
+ if (words.length === 0)
150
+ return !hay.includes(b.label.toLowerCase());
151
+ const hits = words.filter((w) => hay.includes(w)).length;
152
+ return hits < Math.min(2, words.length);
153
+ });
154
+ }
155
+ /**
156
+ * Scenarios whose assertions are IDENTICAL — "N cases" in a coverage sheet that verify one arm N
157
+ * times. The field report's decision table produced exactly this: two cases under different
158
+ * names, both asserting the same message, reported as two covered branches.
159
+ *
160
+ * Compares only the assertion side: two scenarios may legitimately share setup and differ in
161
+ * what they prove, but if what they PROVE is identical they are one test.
162
+ */
163
+ function sameOracleClusters(scenarios) {
164
+ const byOracle = new Map();
165
+ for (const s of scenarios) {
166
+ if (s.manual)
167
+ continue; // a procedure's oracle is prose
168
+ const asserts = [...(s.steps ?? [])]
169
+ .filter((st) => st.bucket === 'then')
170
+ .map((st) => st.text.toLowerCase().replace(/\s+/g, ' ').trim())
171
+ .sort();
172
+ if (asserts.length === 0)
173
+ continue;
174
+ const key = asserts.join(' ; ');
175
+ byOracle.set(key, [...(byOracle.get(key) ?? []), s.name]);
176
+ }
177
+ return [...byOracle.entries()]
178
+ .filter(([, names]) => names.length > 1)
179
+ .map(([oracle, names]) => ({ oracle: oracle.slice(0, 100), scenarios: names }))
180
+ .sort((a, b) => b.scenarios.length - a.scenarios.length);
181
+ }
182
+ /**
183
+ * A "denied → hidden" scenario with no "allowed → shown" counterpart (#630).
184
+ *
185
+ * Two security cases proved that chat content is hidden when `MESSAGE_READ` is denied. If the code
186
+ * hid it unconditionally — ignoring the permission entirely — both still pass. The deny side alone
187
+ * cannot distinguish "the guard works" from "the feature is broken for everyone", so the pair is
188
+ * the test, exactly as `min-1 / min / max / max+1` is the test for a boundary.
189
+ *
190
+ * The mirror of the negative-claim rule the skill already has, on the other side.
191
+ */
192
+ const DENY_SHAPE = /\b(?:denied|deny|denies|forbidden|not authoriz\w*|unauthoriz\w*|no permission|without (?:the )?(?:permission|right|access|flag)|permission (?:is )?off|flag (?:is )?off|revoked|restricted)\b/i;
193
+ const HIDDEN_SHAPE = /\b(?:is hidden|are hidden|not (?:visible|shown|displayed)|blocked|masked|redacted|does not (?:show|render|appear))\b/i;
194
+ const ALLOW_SHAPE = /\b(?:granted|allowed|permitted|authoriz\w*|has (?:the )?(?:permission|right|access)|permission (?:is )?on|flag (?:is )?on|with (?:the )?(?:permission|right|access))\b/i;
195
+ function permissionPairGaps(scenarios) {
196
+ const denies = scenarios.filter((s) => DENY_SHAPE.test(s.haystack) && HIDDEN_SHAPE.test(s.haystack));
197
+ if (denies.length === 0)
198
+ return [];
199
+ const allows = scenarios.filter((s) => ALLOW_SHAPE.test(s.haystack) && !HIDDEN_SHAPE.test(s.stepsText));
200
+ // Words only — the scenario ID is stripped first, because `[a-z][a-z-]{4,}` happily matches
201
+ // `fl-er-` and an id fragment can never appear in the counterpart's title, so demanding it made
202
+ // the pair impossible to find.
203
+ const distinctive = (s) => [...new Set((s.name.replace(/^\S+\s*/, '').toLowerCase().match(/[a-z]{5,}/g) ?? []))]
204
+ .filter((w) => !GENERIC_WORD.has(w) && !/denied|denies|hidden|permission|scenario/.test(w));
205
+ const out = [];
206
+ for (const d of denies) {
207
+ const subject = distinctive(d);
208
+ // The counterpart has to be about the SAME thing — two shared distinctive words, the same
209
+ // bar the ledger's prose matching uses.
210
+ const paired = allows.some((a) => subject.filter((w) => a.haystack.includes(w)).length >= Math.min(2, subject.length));
211
+ if (!paired)
212
+ out.push({ scenario: d.name, subject: subject.slice(0, 4) });
213
+ }
214
+ return out;
215
+ }
216
+ /**
217
+ * Scenarios blocked on test data that is still a placeholder (#630).
218
+ *
219
+ * A deliverable reported "Pending" for a case whose design was finished and whose only blocker was
220
+ * an unseeded ENV-BOUND value — indistinguishable, on the report, from a case with an unresolved
221
+ * design problem. One is a data task, the other is test work; they should not read the same.
222
+ */
223
+ const SEED_PLACEHOLDER = /^(?:TODO[_-]?SEED\w*|TODO|TBD|<[^>]+>|REPLACE[_-]?ME|FILL[_-]?ME|CHANGE[_-]?ME|XXX+)$/i;
224
+ function awaitingSeedData(testDataText, scenarios) {
225
+ // One placeholder key is ONE data task, however many files or lines mention it — a real project
226
+ // reported the same key three times because its overlays each declare it (#651 follow-up).
227
+ const placeholders = [...new Set([...testDataText.matchAll(/^\s*([A-Za-z0-9_.-]+)\s*:\s*["']?([^"'\n#]+?)["']?\s*(?:#.*)?$/gm)]
228
+ .filter((m) => SEED_PLACEHOLDER.test(m[2].trim()))
229
+ .map((m) => m[1]))];
230
+ if (placeholders.length === 0)
231
+ return [];
232
+ return placeholders
233
+ .map((key) => ({
234
+ key,
235
+ scenarios: scenarios.filter((s) => s.stepsText.includes(`{{${key.toLowerCase()}`)
236
+ || new RegExp(`\\{\\{[a-z0-9_.-]*\\.${key.toLowerCase()}\\}\\}`).test(s.stepsText)).map((s) => s.name),
237
+ }))
238
+ .filter((p) => p.scenarios.length > 0);
239
+ }
240
+ exports.MULTI_SCREEN_RISKS = [
241
+ { id: 'double-submit', label: 'double submit / double activation',
242
+ re: /\b(?:double[- ]?(?:submit|click|tap|activation)|twice|two taps?|idempoten\w*|re-?submit|duplicate request)\b/i,
243
+ why: 'a second activation before the first response is the classic way one journey creates two records' },
244
+ { id: 'concurrency', label: 'two tabs / two devices at once',
245
+ re: /\b(?:two tabs?|second tab|another tab|multi[- ]?tab|two devices|second device|concurrent\w*|simultaneous\w*|race)\b/i,
246
+ why: 'a journey that buffers state client-side behaves differently when two of it run at once' },
247
+ { id: 'client-buffer', label: 'client-side buffer kept / lost',
248
+ re: /\b(?:session ?storage|local ?storage|buffer\w*|draft|unsaved|re-?hydrat\w*|restore[sd]?)\b/i,
249
+ why: 'state held between two steps must be proved BOTH ways — it survives a legitimate return, and it is lost when the spec says it is' },
250
+ { id: 'server-error', label: 'a mid-journey server error',
251
+ re: /\b(?:server error|5\d{2}\b|network (?:error|drop|failure)|offline|timeout|unavailable|fails? server-?side|retry)\b/i,
252
+ why: 'the interesting question is what survives the failure, not that an error appeared' },
253
+ { id: 'abandonment', label: 'abandonment / TTL of partial state',
254
+ re: /\b(?:abandon\w*|lapse[sd]?|expir\w*|ttl\b|stale|cleanup|24 ?h|dormant|never (?:completed|finished))\b/i,
255
+ why: 'a journey stopped halfway leaves state somebody owns; a flow test is where that becomes visible' },
256
+ { id: 'direct-access', label: 'direct URL access to a later step',
257
+ re: /\b(?:direct(?:ly)? access|deep[- ]?link|without (?:a |an |the )?(?:context|session|prior)|guard|not skippable|redirect\w*)\b/i,
258
+ why: 'every step after the first is reachable by URL, and only a journey test can check the guard' },
259
+ { id: 'auth-transition', label: 'where the session begins',
260
+ re: /\b(?:authenticat\w*|unauthenticat\w*|signed[- ]in|logged[- ]in|session (?:is )?(?:established|created|begins)|auto[- ]?login)\b/i,
261
+ why: 'the step where an actor stops being anonymous is a boundary no single screen owns' },
262
+ { id: 'escape-hatch', label: 'a documented way out of the journey',
263
+ re: /\b(?:cancel|back to top|exit|leave[sd]? the (?:journey|flow)|opt[- ]?out|skip|dismiss)\b/i,
264
+ why: 'a designed-for exit is an alternate flow with its own outcome, not an error' },
265
+ { id: 'side-effect-order', label: 'ordering of a delayed side effect',
266
+ re: /\b(?:mail|email|notification|webhook|queue|async|delayed|eventual\w*|dispatch\w*|side[- ]effect)\b/i,
267
+ why: 'a journey that triggers an out-of-band effect is where its ordering and its absence both matter' },
268
+ ];
269
+ function unconsideredRisks(contract, scenarios, viewpointText) {
270
+ // Everywhere the author reasons about the journey. A mention in ANY of them is consideration —
271
+ // the check asks "did you think about this?", not "did you write a scenario for it?".
272
+ const corpus = [
273
+ viewpointText,
274
+ ...scenarios.map((s) => s.haystack),
275
+ ...(contract.flows ?? []).flatMap((f) => [f.id, f.branchFrom ?? '', f.outcome ?? '', f.reason ?? '']),
276
+ contract.minimalGuarantee ?? '', contract.successGuarantee ?? '', contract.precondition ?? '',
277
+ ].join('\n').toLowerCase();
278
+ return exports.MULTI_SCREEN_RISKS.filter((r) => !r.re.test(corpus));
279
+ }
280
+ //# sourceMappingURL=spec-branches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-branches.js","sourceRoot":"","sources":["../../src/harness/spec-branches.ts"],"names":[],"mappings":"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"}
@@ -49,7 +49,7 @@ export declare function specCoverage(specPath: string, scenarios: ScenarioInfo[]
49
49
  /**
50
50
  * A flow's requirement list that is a HAND RESTATEMENT of the screen specs it traverses.
51
51
  *
52
- * A flow spec typically cites its requirements as belonging elsewhere — "ST_AUTH_002 FR-001",
52
+ * A flow spec typically cites its requirements as belonging elsewhere — "SCREEN_A_002 FR-001",
53
53
  * "restated here in flow terms". That restatement is lossy by construction, and nothing checked
54
54
  * it: on a real run the flow spec restated two of the screens' FRs, `specFR` read **2/2 = 100%**,
55
55
  * and the guard clause the flow most needed (a double-submit rule in one of those screen specs)
@@ -224,7 +224,7 @@ function specCoverage(specPath, scenarios, featureText) {
224
224
  /**
225
225
  * A flow's requirement list that is a HAND RESTATEMENT of the screen specs it traverses.
226
226
  *
227
- * A flow spec typically cites its requirements as belonging elsewhere — "ST_AUTH_002 FR-001",
227
+ * A flow spec typically cites its requirements as belonging elsewhere — "SCREEN_A_002 FR-001",
228
228
  * "restated here in flow terms". That restatement is lossy by construction, and nothing checked
229
229
  * it: on a real run the flow spec restated two of the screens' FRs, `specFR` read **2/2 = 100%**,
230
230
  * and the guard clause the flow most needed (a double-submit rule in one of those screen specs)
@@ -237,12 +237,12 @@ function specCoverage(specPath, scenarios, featureText) {
237
237
  * someone can answer, instead of one nothing was asking.
238
238
  */
239
239
  function restatedRequirementSources(specText, availableUnits) {
240
- // "these ... originate in the SCREEN specs", "restated here", "per ST_AUTH_002 FR-001".
240
+ // "these ... originate in the SCREEN specs", "restated here", "per SCREEN_A_002 FR-001".
241
241
  const restated = /\brestate[sd]?\b|\boriginate[sd]? in\b|\bderived from the (?:screen|per-screen) spec/i.test(specText);
242
- // External document ids carrying their own requirement number: `ST_AUTH_002 FR-001`,
242
+ // External document ids carrying their own requirement number: `SCREEN_A_002 FR-001`,
243
243
  // `SCR-1-SYS-0001.FR-3`. Two+ segments and an uppercase head, so a bare `FR-001` (the flow's
244
244
  // own) never matches.
245
- // A citation may name SEVERAL documents at once — "ST_AUTH_002/ST_AUTH_004 FR-001" — so match
245
+ // A citation may name SEVERAL documents at once — "SCREEN_A_002/SCREEN_A_004 FR-001" — so match
246
246
  // the whole slash/comma-joined run and split it. Capturing only the token adjacent to the
247
247
  // requirement number silently dropped every sibling.
248
248
  const DOC = '[A-Z][A-Z0-9]*(?:[_-][A-Z0-9]+)+';