@elisra-devops/docgen-data-provider 1.100.0 → 1.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,6 +26,8 @@ export default class ResultDataProvider {
26
26
  private static readonly MEWP_INTERNAL_VALIDATION_TRACE_TAG;
27
27
  private static readonly MEWP_INTERNAL_VALIDATION_DIAGNOSTICS_TAG;
28
28
  private static readonly MEWP_INTERNAL_VALIDATION_SUMMARY_TAG;
29
+ private static readonly MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_REF;
30
+ private static readonly MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_HEADER_PATTERN;
29
31
  private static readonly MEWP_L2_COVERAGE_COLUMNS;
30
32
  private static readonly INTERNAL_VALIDATION_COLUMNS;
31
33
  orgUrl: string;
@@ -104,6 +106,15 @@ export default class ResultDataProvider {
104
106
  private isExternalStateInScope;
105
107
  private invertBaseRequirementLinks;
106
108
  private buildMewpTestCaseTitleMap;
109
+ /**
110
+ * Builds a lookup of test case id -> test case description using suite payload data.
111
+ *
112
+ * Resolution order:
113
+ * 1) direct description fields on test-case payload (`testCase.description` / `workItem.description`)
114
+ * 2) `System.Description` / `Description` in work-item fields map
115
+ * 3) `System.Description` / `Description` from work-item field list (`workItemFields`)
116
+ */
117
+ private buildMewpTestCaseDescriptionMap;
107
118
  private extractMewpTestCaseId;
108
119
  private buildTestCaseStepsXmlMap;
109
120
  private extractStepsXmlFromTestCaseItem;
@@ -115,6 +126,27 @@ export default class ResultDataProvider {
115
126
  private resolveRequirementStatusForWindow;
116
127
  private extractRequirementCodesFromText;
117
128
  private extractRequirementMentionsFromExpectedSteps;
129
+ /**
130
+ * Extracts SR requirement mentions from the "assumptions" section inside a test-case description.
131
+ *
132
+ * Notes:
133
+ * - Heading detection is case-insensitive and keyed by "assumptions".
134
+ * - Parsing is scoped to that section only and stops when a likely next section heading is reached
135
+ * after at least one requirement-bearing line was collected.
136
+ * - Returned stepRef is a synthetic marker ("Assumptions") so downstream discrepancy output can
137
+ * clearly attribute source to description-level assumptions.
138
+ */
139
+ private extractRequirementMentionsFromAssumptionsDescription;
140
+ /**
141
+ * Normalizes raw HTML/plain description content into comparable text lines.
142
+ * This makes section/title heuristics resilient to formatting differences.
143
+ */
144
+ private normalizeMewpDescriptionLines;
145
+ /**
146
+ * Heuristic detector for description section headings used to stop assumptions parsing.
147
+ * A line is considered a heading when it is short/title-like and does not itself contain SR codes.
148
+ */
149
+ private isLikelyMewpDescriptionSectionHeading;
118
150
  private extractRequirementCodesFromExpectedText;
119
151
  private extractRequirementCandidatesFromToken;
120
152
  private expandRequirementTokenByComma;
@@ -227,7 +259,14 @@ export default class ResultDataProvider {
227
259
  * Returns true when the snapshot includes a non-empty test steps XML payload.
228
260
  */
229
261
  private hasStepsInWorkItemSnapshot;
230
- private logRunlessSnapshotDecision;
262
+ /**
263
+ * Resolves the suite-aware revision for a test point.
264
+ */
265
+ private resolvePointRevision;
266
+ /**
267
+ * Builds ordered keys used to match a point with fetched iteration payloads.
268
+ */
269
+ private buildIterationLookupCandidates;
231
270
  /**
232
271
  * Resolves runless test case data using ordered fallbacks:
233
272
  * 1) point-based `asOf` snapshot, 2) explicit revision, 3) suite payload snapshot, 4) latest WI.
@@ -517,6 +517,7 @@ class ResultDataProvider {
517
517
  const rows = [];
518
518
  const stepsXmlByTestCase = this.buildTestCaseStepsXmlMap(testData);
519
519
  const testCaseTitleMap = this.buildMewpTestCaseTitleMap(testData);
520
+ const testCaseDescriptionMap = this.buildMewpTestCaseDescriptionMap(testData);
520
521
  const allTestCaseIds = new Set();
521
522
  for (const suite of testData || []) {
522
523
  const testCasesItems = Array.isArray(suite === null || suite === void 0 ? void 0 : suite.testCasesItems) ? suite.testCasesItems : [];
@@ -562,7 +563,13 @@ class ResultDataProvider {
562
563
  : [];
563
564
  const executableSteps = parsedSteps.filter((step) => !(step === null || step === void 0 ? void 0 : step.isSharedStepTitle));
564
565
  diagnostics.totalParsedSteps += executableSteps.length;
565
- const mentionEntries = this.extractRequirementMentionsFromExpectedSteps(parsedSteps, true);
566
+ // Direction A/B mentions can come from two sources:
567
+ // 1) Expected Result in executable steps.
568
+ // 2) "Assumptions" section in the test-case description.
569
+ const stepMentionEntries = this.extractRequirementMentionsFromExpectedSteps(parsedSteps, true);
570
+ const descriptionText = testCaseDescriptionMap.get(testCaseId) || '';
571
+ const assumptionsMentionEntries = this.extractRequirementMentionsFromAssumptionsDescription(descriptionText, true);
572
+ const mentionEntries = [...stepMentionEntries, ...assumptionsMentionEntries];
566
573
  diagnostics.totalStepsWithMentions += mentionEntries.length;
567
574
  const mentionedL2Only = new Set();
568
575
  const mentionedCodeFirstStep = new Map();
@@ -1289,6 +1296,48 @@ class ResultDataProvider {
1289
1296
  }
1290
1297
  return map;
1291
1298
  }
1299
+ /**
1300
+ * Builds a lookup of test case id -> test case description using suite payload data.
1301
+ *
1302
+ * Resolution order:
1303
+ * 1) direct description fields on test-case payload (`testCase.description` / `workItem.description`)
1304
+ * 2) `System.Description` / `Description` in work-item fields map
1305
+ * 3) `System.Description` / `Description` from work-item field list (`workItemFields`)
1306
+ */
1307
+ buildMewpTestCaseDescriptionMap(testData) {
1308
+ var _a, _b, _c, _d;
1309
+ const map = new Map();
1310
+ const readDescriptionFromFields = (fields) => {
1311
+ var _a;
1312
+ const value = (_a = this.getFieldValueByName(fields, 'System.Description')) !== null && _a !== void 0 ? _a : this.getFieldValueByName(fields, 'Description');
1313
+ return this.toMewpComparableText(value);
1314
+ };
1315
+ for (const suite of testData || []) {
1316
+ const testCasesItems = Array.isArray(suite === null || suite === void 0 ? void 0 : suite.testCasesItems) ? suite.testCasesItems : [];
1317
+ for (const testCase of testCasesItems) {
1318
+ const id = Number(((_a = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _a === void 0 ? void 0 : _a.id) || (testCase === null || testCase === void 0 ? void 0 : testCase.testCaseId) || (testCase === null || testCase === void 0 ? void 0 : testCase.id));
1319
+ if (!Number.isFinite(id) || id <= 0 || map.has(id))
1320
+ continue;
1321
+ const fromDirect = this.toMewpComparableText((testCase === null || testCase === void 0 ? void 0 : testCase.description) || ((_b = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _b === void 0 ? void 0 : _b.description));
1322
+ if (fromDirect) {
1323
+ map.set(id, fromDirect);
1324
+ continue;
1325
+ }
1326
+ const fieldsFromMap = ((_c = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _c === void 0 ? void 0 : _c.fields) || {};
1327
+ const fromFieldsMap = readDescriptionFromFields(fieldsFromMap);
1328
+ if (fromFieldsMap) {
1329
+ map.set(id, fromFieldsMap);
1330
+ continue;
1331
+ }
1332
+ const fieldsFromList = this.extractWorkItemFieldsMap((_d = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _d === void 0 ? void 0 : _d.workItemFields);
1333
+ const fromFieldsList = readDescriptionFromFields(fieldsFromList);
1334
+ if (fromFieldsList) {
1335
+ map.set(id, fromFieldsList);
1336
+ }
1337
+ }
1338
+ }
1339
+ return map;
1340
+ }
1292
1341
  extractMewpTestCaseId(runResult) {
1293
1342
  var _a;
1294
1343
  const testCaseId = Number((runResult === null || runResult === void 0 ? void 0 : runResult.testCaseId) || ((_a = runResult === null || runResult === void 0 ? void 0 : runResult.testCase) === null || _a === void 0 ? void 0 : _a.id) || 0);
@@ -1479,6 +1528,102 @@ class ResultDataProvider {
1479
1528
  }
1480
1529
  return out;
1481
1530
  }
1531
+ /**
1532
+ * Extracts SR requirement mentions from the "assumptions" section inside a test-case description.
1533
+ *
1534
+ * Notes:
1535
+ * - Heading detection is case-insensitive and keyed by "assumptions".
1536
+ * - Parsing is scoped to that section only and stops when a likely next section heading is reached
1537
+ * after at least one requirement-bearing line was collected.
1538
+ * - Returned stepRef is a synthetic marker ("Assumptions") so downstream discrepancy output can
1539
+ * clearly attribute source to description-level assumptions.
1540
+ */
1541
+ extractRequirementMentionsFromAssumptionsDescription(description, includeSuffix) {
1542
+ const lines = this.normalizeMewpDescriptionLines(description);
1543
+ if (lines.length === 0)
1544
+ return [];
1545
+ const assumptionsHeaderIndex = lines.findIndex((line) => ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_HEADER_PATTERN.test(line));
1546
+ if (assumptionsHeaderIndex < 0)
1547
+ return [];
1548
+ const assumptionCodes = new Set();
1549
+ let hasCollectedRequirementCodes = false;
1550
+ for (let index = assumptionsHeaderIndex + 1; index < lines.length; index += 1) {
1551
+ const rawLine = String(lines[index] || '').trim();
1552
+ if (!rawLine)
1553
+ continue;
1554
+ const line = rawLine.replace(/^[-*•]+\s*/, '').trim();
1555
+ if (!line)
1556
+ continue;
1557
+ const lineCodes = this.extractRequirementCodesFromExpectedText(line, includeSuffix);
1558
+ if (lineCodes.size > 0) {
1559
+ for (const code of lineCodes)
1560
+ assumptionCodes.add(code);
1561
+ hasCollectedRequirementCodes = true;
1562
+ continue;
1563
+ }
1564
+ if (hasCollectedRequirementCodes && this.isLikelyMewpDescriptionSectionHeading(line)) {
1565
+ break;
1566
+ }
1567
+ }
1568
+ if (assumptionCodes.size === 0)
1569
+ return [];
1570
+ return [{ stepRef: ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_REF, codes: assumptionCodes }];
1571
+ }
1572
+ /**
1573
+ * Normalizes raw HTML/plain description content into comparable text lines.
1574
+ * This makes section/title heuristics resilient to formatting differences.
1575
+ */
1576
+ normalizeMewpDescriptionLines(description) {
1577
+ const raw = String(description || '');
1578
+ if (!raw)
1579
+ return [];
1580
+ const normalized = raw
1581
+ .replace(/\r\n?/g, '\n')
1582
+ .replace(/<\s*br\s*\/?>/gi, '\n')
1583
+ // Underlined sections are commonly used as inline HTML titles in MEWP test-case descriptions.
1584
+ // Treat underline tags as boundaries so compact forms like <u><b>Title</b></u><p>... preserve section split.
1585
+ .replace(/<\s*u\b[^>]*>/gi, '\n')
1586
+ .replace(/<\/\s*u\s*>/gi, '\n')
1587
+ .replace(/<\s*li\b[^>]*>/gi, '\n- ')
1588
+ .replace(/<\/\s*(p|div|li|ul|ol|tr|td|h[1-6])\s*>/gi, '\n')
1589
+ .replace(/&nbsp;|&#160;|&#xA0;/gi, ' ')
1590
+ .replace(/&lt;/gi, '<')
1591
+ .replace(/&gt;/gi, '>')
1592
+ .replace(/&amp;/gi, '&')
1593
+ .replace(/&quot;/gi, '"')
1594
+ .replace(/&#39;|&apos;/gi, "'")
1595
+ .replace(/<[^>]*>/g, ' ')
1596
+ .replace(/[\u200B-\u200D\uFEFF]/g, '')
1597
+ .replace(/[ \t]+/g, ' ');
1598
+ return normalized
1599
+ .split('\n')
1600
+ .map((line) => String(line || '').trim())
1601
+ .filter((line) => !!line);
1602
+ }
1603
+ /**
1604
+ * Heuristic detector for description section headings used to stop assumptions parsing.
1605
+ * A line is considered a heading when it is short/title-like and does not itself contain SR codes.
1606
+ */
1607
+ isLikelyMewpDescriptionSectionHeading(line) {
1608
+ const normalized = String(line || '')
1609
+ .replace(/^[-*•]+\s*/, '')
1610
+ .trim();
1611
+ if (!normalized)
1612
+ return false;
1613
+ if (ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_HEADER_PATTERN.test(normalized))
1614
+ return false;
1615
+ if (this.extractRequirementCodesFromExpectedText(normalized, true).size > 0)
1616
+ return false;
1617
+ const compact = normalized.replace(/[.:;,\-–—]+$/, '').trim();
1618
+ if (!compact)
1619
+ return false;
1620
+ const wordCount = compact.split(/\s+/).filter((item) => !!item).length;
1621
+ if (wordCount === 0 || wordCount > 12)
1622
+ return false;
1623
+ if (/[.;!?]/.test(compact))
1624
+ return false;
1625
+ return /^[a-z0-9\s()&/+_'-]+$/i.test(compact);
1626
+ }
1482
1627
  extractRequirementCodesFromExpectedText(text, includeSuffix) {
1483
1628
  const out = new Set();
1484
1629
  const source = this.normalizeRequirementStepText(text);
@@ -2764,7 +2909,6 @@ class ResultDataProvider {
2764
2909
  const parsedAsOf = new Date(String(asOfTimestamp || '').trim());
2765
2910
  if (!Number.isFinite(id) || id <= 0 || Number.isNaN(parsedAsOf.getTime()))
2766
2911
  return null;
2767
- logger_1.default.debug(`[RunlessResolver] Fetching work item ${id} by asOf (raw="${String(asOfTimestamp || '')}", normalized="${parsedAsOf.toISOString()}", expandAll=${String(expandAll)})`);
2768
2912
  const query = [`asOf=${encodeURIComponent(parsedAsOf.toISOString())}`];
2769
2913
  if (expandAll) {
2770
2914
  query.push(`$expand=all`);
@@ -2799,15 +2943,34 @@ class ResultDataProvider {
2799
2943
  const stepsXml = this.extractStepsXmlFromFieldsMap((workItemData === null || workItemData === void 0 ? void 0 : workItemData.fields) || {});
2800
2944
  return String(stepsXml || '').trim() !== '';
2801
2945
  }
2802
- logRunlessSnapshotDecision(testCaseId, source, snapshot) {
2803
- var _a;
2804
- if (!snapshot) {
2805
- logger_1.default.debug(`[RunlessResolver] TC ${testCaseId}: source=${source}, snapshot=none`);
2806
- return;
2946
+ /**
2947
+ * Resolves the suite-aware revision for a test point.
2948
+ */
2949
+ resolvePointRevision(testCase, point) {
2950
+ return Number(this.resolveSuiteTestCaseRevision(testCase) ||
2951
+ this.resolveSuiteTestCaseRevision(point === null || point === void 0 ? void 0 : point.suiteTestCase) ||
2952
+ 0);
2953
+ }
2954
+ /**
2955
+ * Builds ordered keys used to match a point with fetched iteration payloads.
2956
+ */
2957
+ buildIterationLookupCandidates(input) {
2958
+ const candidates = [];
2959
+ const addCandidate = (key) => {
2960
+ if (key && !candidates.includes(key)) {
2961
+ candidates.push(key);
2962
+ }
2963
+ };
2964
+ addCandidate(this.buildIterationLookupKey(input));
2965
+ const revision = Number((input === null || input === void 0 ? void 0 : input.testCaseRevision) || 0);
2966
+ if (Number.isFinite(revision) && revision > 0) {
2967
+ addCandidate(this.buildIterationLookupKey({
2968
+ testCaseId: input === null || input === void 0 ? void 0 : input.testCaseId,
2969
+ testCaseRevision: revision,
2970
+ }));
2807
2971
  }
2808
- const stepsXml = this.extractStepsXmlFromFieldsMap((snapshot === null || snapshot === void 0 ? void 0 : snapshot.fields) || {});
2809
- const stepsLength = String(stepsXml || '').trim().length;
2810
- logger_1.default.debug(`[RunlessResolver] TC ${testCaseId}: source=${source}, rev=${String((_a = snapshot === null || snapshot === void 0 ? void 0 : snapshot.rev) !== null && _a !== void 0 ? _a : '')}, hasSteps=${String(stepsLength > 0)}, stepsLength=${String(stepsLength)}`);
2972
+ addCandidate(`${Number((input === null || input === void 0 ? void 0 : input.testCaseId) || 0)}`);
2973
+ return candidates;
2811
2974
  }
2812
2975
  /**
2813
2976
  * Resolves runless test case data using ordered fallbacks:
@@ -2817,31 +2980,24 @@ class ResultDataProvider {
2817
2980
  let bestSnapshotWithoutSteps = null;
2818
2981
  if (pointAsOfTimestamp) {
2819
2982
  const asOfSnapshot = await this.fetchWorkItemByAsOf(projectName, testCaseId, pointAsOfTimestamp, expandAll);
2820
- this.logRunlessSnapshotDecision(testCaseId, 'asOf', asOfSnapshot);
2821
2983
  if (asOfSnapshot) {
2822
2984
  if (this.hasStepsInWorkItemSnapshot(asOfSnapshot))
2823
2985
  return asOfSnapshot;
2824
2986
  bestSnapshotWithoutSteps = asOfSnapshot;
2825
2987
  }
2826
2988
  }
2827
- else {
2828
- logger_1.default.debug(`[RunlessResolver] TC ${testCaseId}: asOf timestamp is empty, skipping asOf fetch`);
2829
- }
2830
2989
  const revisionSnapshot = await this.fetchWorkItemByRevision(projectName, testCaseId, suiteTestCaseRevision, expandAll);
2831
- this.logRunlessSnapshotDecision(testCaseId, `revision:${String(suiteTestCaseRevision)}`, revisionSnapshot);
2832
2990
  if (revisionSnapshot) {
2833
2991
  if (this.hasStepsInWorkItemSnapshot(revisionSnapshot))
2834
2992
  return revisionSnapshot;
2835
2993
  bestSnapshotWithoutSteps = bestSnapshotWithoutSteps || revisionSnapshot;
2836
2994
  }
2837
- this.logRunlessSnapshotDecision(testCaseId, 'suiteSnapshot', fallbackSnapshot);
2838
2995
  if (fallbackSnapshot) {
2839
2996
  if (this.hasStepsInWorkItemSnapshot(fallbackSnapshot))
2840
2997
  return fallbackSnapshot;
2841
2998
  bestSnapshotWithoutSteps = bestSnapshotWithoutSteps || fallbackSnapshot;
2842
2999
  }
2843
3000
  const latestSnapshot = await this.fetchWorkItemLatest(projectName, testCaseId, expandAll);
2844
- this.logRunlessSnapshotDecision(testCaseId, 'latest', latestSnapshot);
2845
3001
  if (latestSnapshot) {
2846
3002
  if (this.hasStepsInWorkItemSnapshot(latestSnapshot))
2847
3003
  return latestSnapshot;
@@ -2881,7 +3037,6 @@ class ResultDataProvider {
2881
3037
  const pointAsOfTimestamp = useRunlessAsOf
2882
3038
  ? String((point === null || point === void 0 ? void 0 : point.pointAsOfTimestamp) || '').trim()
2883
3039
  : '';
2884
- logger_1.default.debug(`[RunlessResolver] Start TC ${String(testCaseId)}: useRunlessAsOf=${String(useRunlessAsOf)}, pointAsOfTimestamp="${pointAsOfTimestamp}", suiteRevision=${String(suiteTestCaseRevision)}, pointOutcome="${String((point === null || point === void 0 ? void 0 : point.outcome) || '')}"`);
2885
3040
  const fallbackSnapshot = this.buildWorkItemSnapshotFromSuiteTestCase(suiteTestCaseItem, testCaseId, String((point === null || point === void 0 ? void 0 : point.testCaseName) || ''));
2886
3041
  const testCaseData = await this.resolveRunlessTestCaseData(projectName, testCaseId, suiteTestCaseRevision, pointAsOfTimestamp, fallbackSnapshot, isTestReporter);
2887
3042
  if (!testCaseData) {
@@ -3522,9 +3677,6 @@ class ResultDataProvider {
3522
3677
  };
3523
3678
  if (!Number.isFinite(pointTestCaseId) || pointTestCaseId <= 0)
3524
3679
  continue;
3525
- if (!testCaseById.has(pointTestCaseId) && isTestReporter) {
3526
- logger_1.default.debug(`[RunlessResolver] Missing suite testCase payload for point testCaseId=${String(pointTestCaseId)}; using point fallback for alignment`);
3527
- }
3528
3680
  const testCaseWorkItemFields = Array.isArray((_d = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _d === void 0 ? void 0 : _d.workItemFields)
3529
3681
  ? testCase.workItem.workItemFields
3530
3682
  : [];
@@ -3534,29 +3686,15 @@ class ResultDataProvider {
3534
3686
  continue;
3535
3687
  }
3536
3688
  }
3537
- const iterationKey = this.buildIterationLookupKey({
3689
+ const iterationLookupKeys = this.buildIterationLookupCandidates({
3538
3690
  testCaseId: testCase.workItem.id,
3539
3691
  lastRunId: point === null || point === void 0 ? void 0 : point.lastRunId,
3540
3692
  lastResultId: point === null || point === void 0 ? void 0 : point.lastResultId,
3541
3693
  testPointId: point === null || point === void 0 ? void 0 : point.testPointId,
3542
- testCaseRevision: this.resolveSuiteTestCaseRevision(testCase) ||
3543
- this.resolveSuiteTestCaseRevision(point === null || point === void 0 ? void 0 : point.suiteTestCase),
3694
+ testCaseRevision: this.resolvePointRevision(testCase, point),
3544
3695
  });
3545
- const fallbackRevision = Number(this.resolveSuiteTestCaseRevision(testCase) ||
3546
- this.resolveSuiteTestCaseRevision(point === null || point === void 0 ? void 0 : point.suiteTestCase) ||
3547
- 0);
3548
- const fallbackRevisionKey = Number.isFinite(fallbackRevision) && fallbackRevision > 0
3549
- ? this.buildIterationLookupKey({
3550
- testCaseId: testCase.workItem.id,
3551
- testCaseRevision: fallbackRevision,
3552
- })
3553
- : '';
3554
- const fallbackCaseOnlyKey = `${testCase.workItem.id}`;
3555
- const fetchedTestCase = iterationsMap[iterationKey] ||
3556
- (fallbackRevisionKey && fallbackRevisionKey !== iterationKey
3557
- ? iterationsMap[fallbackRevisionKey]
3558
- : undefined) ||
3559
- (iterationKey !== fallbackCaseOnlyKey ? iterationsMap[fallbackCaseOnlyKey] : undefined) ||
3696
+ const fetchedTestCaseFromMap = iterationLookupKeys.find((key) => iterationsMap[key]) || '';
3697
+ const fetchedTestCase = (fetchedTestCaseFromMap ? iterationsMap[fetchedTestCaseFromMap] : undefined) ||
3560
3698
  (includeNotRunTestCases ? testCase : undefined);
3561
3699
  // First check if fetchedTestCase exists
3562
3700
  if (!fetchedTestCase)
@@ -3610,7 +3748,6 @@ class ResultDataProvider {
3610
3748
  detailedResults.push(...resultObjectsToAdd);
3611
3749
  }
3612
3750
  else {
3613
- logger_1.default.debug(`[RunlessResolver] No step rows generated for testCaseId=${String((point === null || point === void 0 ? void 0 : point.testCaseId) || '')}; falling back to test-level row`);
3614
3751
  detailedResults.push(options.createResultObject({
3615
3752
  testItem,
3616
3753
  point,
@@ -3687,9 +3824,6 @@ class ResultDataProvider {
3687
3824
  testCaseRevision: iterationItem === null || iterationItem === void 0 ? void 0 : iterationItem.testCaseRevision,
3688
3825
  });
3689
3826
  map[key] = iterationItem;
3690
- if (isTestReporter && (iterationItem === null || iterationItem === void 0 ? void 0 : iterationItem.iteration)) {
3691
- logger_1.default.debug(`[RunlessResolver] createIterationsMap: mapped runless testCaseId=${String(iterationItem === null || iterationItem === void 0 ? void 0 : iterationItem.testCaseId)} to key=${key}`);
3692
- }
3693
3827
  }
3694
3828
  else if ((iterationItem === null || iterationItem === void 0 ? void 0 : iterationItem.iteration) && !isTestReporter) {
3695
3829
  const key = this.buildIterationLookupKey({
@@ -3819,7 +3953,7 @@ class ResultDataProvider {
3819
3953
  * Fetches result Data for a specific test point
3820
3954
  */
3821
3955
  async fetchResultDataBase(projectName, testSuiteId, point, fetchResultMethod, createResponseObject, additionalArgs = []) {
3822
- var _a, _b, _c, _d, _e, _f;
3956
+ var _a;
3823
3957
  try {
3824
3958
  const { lastRunId, lastResultId } = point;
3825
3959
  const resultData = await fetchResultMethod(projectName, (lastRunId === null || lastRunId === void 0 ? void 0 : lastRunId.toString()) || '0', (lastResultId === null || lastResultId === void 0 ? void 0 : lastResultId.toString()) || '0', ...additionalArgs);
@@ -3844,7 +3978,6 @@ class ResultDataProvider {
3844
3978
  });
3845
3979
  }
3846
3980
  const stepsList = await this.testStepParserHelper.parseTestSteps(resultData.stepsResultXml, sharedStepIdToRevisionLookupMap);
3847
- logger_1.default.debug(`[RunlessResolver] TC ${String((point === null || point === void 0 ? void 0 : point.testCaseId) || ((_b = resultData === null || resultData === void 0 ? void 0 : resultData.testCase) === null || _b === void 0 ? void 0 : _b.id) || '')}: parseTestSteps xmlLength=${String(String(resultData.stepsResultXml || '').length)}, parsedSteps=${String(stepsList.length)}, actionResultsBeforeMap=${String(actionResults.length)}`);
3848
3981
  sharedStepIdToRevisionLookupMap.clear();
3849
3982
  const stepMap = new Map();
3850
3983
  for (const step of stepsList) {
@@ -3864,7 +3997,6 @@ class ResultDataProvider {
3864
3997
  iteration.actionResults = actionResults
3865
3998
  .filter((result) => result.stepPosition)
3866
3999
  .sort((a, b) => this.compareActionResults(a.stepPosition, b.stepPosition));
3867
- logger_1.default.debug(`[RunlessResolver] TC ${String((point === null || point === void 0 ? void 0 : point.testCaseId) || ((_c = resultData === null || resultData === void 0 ? void 0 : resultData.testCase) === null || _c === void 0 ? void 0 : _c.id) || '')}: mappedActionResults=${String(((_d = iteration.actionResults) === null || _d === void 0 ? void 0 : _d.length) || 0)} (from existing iteration actionResults)`);
3868
4000
  }
3869
4001
  else {
3870
4002
  // Fallback for runs that have no action results: emit test definition steps as Not Run.
@@ -3884,7 +4016,6 @@ class ResultDataProvider {
3884
4016
  });
3885
4017
  })
3886
4018
  .sort((a, b) => this.compareActionResults(a.stepPosition, b.stepPosition));
3887
- logger_1.default.debug(`[RunlessResolver] TC ${String((point === null || point === void 0 ? void 0 : point.testCaseId) || ((_e = resultData === null || resultData === void 0 ? void 0 : resultData.testCase) === null || _e === void 0 ? void 0 : _e.id) || '')}: fallbackActionResults=${String(((_f = iteration.actionResults) === null || _f === void 0 ? void 0 : _f.length) || 0)} (from parsed steps)`);
3888
4019
  }
3889
4020
  }
3890
4021
  return (resultData === null || resultData === void 0 ? void 0 : resultData.testCase)
@@ -4525,6 +4656,8 @@ class ResultDataProvider {
4525
4656
  ResultDataProvider.MEWP_INTERNAL_VALIDATION_TRACE_TAG = '[MEWP][InternalValidation][Trace]';
4526
4657
  ResultDataProvider.MEWP_INTERNAL_VALIDATION_DIAGNOSTICS_TAG = '[MEWP][InternalValidation][Diagnostics]';
4527
4658
  ResultDataProvider.MEWP_INTERNAL_VALIDATION_SUMMARY_TAG = '[MEWP][InternalValidation][Summary]';
4659
+ ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_REF = 'Assumptions';
4660
+ ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_HEADER_PATTERN = /assumptions/i;
4528
4661
  ResultDataProvider.MEWP_L2_COVERAGE_COLUMNS = [
4529
4662
  'L2 REQ ID',
4530
4663
  'L2 REQ Title',