diff --git a/artifacts/linux/requirements-summary.md b/artifacts/linux/requirements-summary.md
index 9e7c3061..358d63ed 100644
--- a/artifacts/linux/requirements-summary.md
+++ b/artifacts/linux/requirements-summary.md
@@ -12,7 +12,7 @@
| REQ-031 | Parsing logic validates presence of required fields and reports missing or malformed data. | | 1 | 1 | 0 | 0 | 100.00 |
| REQ-032 | Parser tolerates and retains unknown attributes for future extensibility. | | 1 | 1 | 0 | 0 | 100.00 |
| REQ-033 | Tests ending with SelfHosted.Workflow.Tests.ps1 execute only in dry run mode unless the workflow targets a self-hosted Windows runner labeled self-hosted-windows-lv. | | 1 | 1 | 0 | 0 | 100.00 |
-| Unmapped | | | 48 | 48 | 0 | 0 | 100.00 |
+| Unmapped | | | 49 | 49 | 0 | 0 | 100.00 |
### Requirement Testcases
| Requirement ID | Test ID | Status |
@@ -49,6 +49,7 @@
| Unmapped | fails-when-requirement-lacks-test-coverage | Passed |
| Unmapped | fails-when-tests-are-unmapped | Passed |
| Unmapped | fails-when-tests-reference-unknown-requirements | Passed |
+| Unmapped | fails-without-runner-metadata | Passed |
| Unmapped | formaterror-handles-plain-objects | Passed |
| Unmapped | formaterror-handles-primitives | Passed |
| Unmapped | formaterror-handles-real-error-objects | Passed |
diff --git a/artifacts/linux/summary-standard.md b/artifacts/linux/summary-standard.md
index ba8667be..dea79ac3 100644
--- a/artifacts/linux/summary-standard.md
+++ b/artifacts/linux/summary-standard.md
@@ -1,7 +1,7 @@
### Test Summary
| OS | Passed | Failed | Skipped | Duration (s) | Pass Rate (%) |
| --- | --- | --- | --- | --- | --- |
-| overall | 59 | 0 | 0 | 15.06 | 100.00 |
-| linux | 59 | 0 | 0 | 15.06 | 100.00 |
+| overall | 60 | 0 | 0 | 23.74 | 100.00 |
+| linux | 60 | 0 | 0 | 23.74 | 100.00 |
_For detailed per-test information, see [traceability-standard.md](traceability-standard.md)._
\ No newline at end of file
diff --git a/artifacts/linux/summary.md b/artifacts/linux/summary.md
index 843d3c3b..848d78d4 100644
--- a/artifacts/linux/summary.md
+++ b/artifacts/linux/summary.md
@@ -1,8 +1,8 @@
### Test Summary
| OS | Passed | Failed | Skipped | Duration (s) | Pass Rate (%) |
| --- | --- | --- | --- | --- | --- |
-| overall | 59 | 0 | 0 | 15.06 | 100.00 |
-| linux | 59 | 0 | 0 | 15.06 | 100.00 |
+| overall | 60 | 0 | 0 | 23.74 | 100.00 |
+| linux | 60 | 0 | 0 | 23.74 | 100.00 |
### Requirement Summary
| Requirement ID | Description | Owner | Total Tests | Passed | Failed | Skipped | Pass Rate (%) |
@@ -18,6 +18,6 @@
| REQ-031 | Parsing logic validates presence of required fields and reports missing or malformed data. | | 1 | 1 | 0 | 0 | 100.00 |
| REQ-032 | Parser tolerates and retains unknown attributes for future extensibility. | | 1 | 1 | 0 | 0 | 100.00 |
| REQ-033 | Tests ending with SelfHosted.Workflow.Tests.ps1 execute only in dry run mode unless the workflow targets a self-hosted Windows runner labeled self-hosted-windows-lv. | | 1 | 1 | 0 | 0 | 100.00 |
-| Unmapped | | | 48 | 48 | 0 | 0 | 100.00 |
+| Unmapped | | | 49 | 49 | 0 | 0 | 100.00 |
_For detailed per-test information, see [traceability.md](traceability.md)._
\ No newline at end of file
diff --git a/artifacts/linux/traceability-standard.md b/artifacts/linux/traceability-standard.md
index 8cb2d138..6dd24a87 100644
--- a/artifacts/linux/traceability-standard.md
+++ b/artifacts/linux/traceability-standard.md
@@ -4,37 +4,37 @@
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-023 | parses-nested-junit-structures | Passed | 0.006 | | |
+| REQ-023 | parses-nested-junit-structures | Passed | 0.011 | | |
#### REQ-024 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-024 | captures-root-testsuites-attributes | Passed | 0.005 | | |
+| REQ-024 | captures-root-testsuites-attributes | Passed | 0.003 | | |
#### REQ-025 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-025 | captures-testsuite-attributes | Passed | 0.001 | | |
+| REQ-025 | captures-testsuite-attributes | Passed | 0.006 | | |
#### REQ-026 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-026 | captures-suite-properties | Passed | 0.001 | | |
+| REQ-026 | captures-suite-properties | Passed | 0.002 | | |
#### REQ-027 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-027 | captures-testcase-attributes-and-skipped-message | Passed | 0.008 | | |
+| REQ-027 | captures-testcase-attributes-and-skipped-message | Passed | 0.001 | | |
#### REQ-028 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-028 | extracts-requirement-identifiers | Passed | 0.002 | | |
+| REQ-028 | extracts-requirement-identifiers | Passed | 0.003 | | |
#### REQ-029 (100% passed)
@@ -46,7 +46,7 @@
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-030 | builds-traceability-matrix-with-skipped-reasons | Passed | 0.001 | | |
+| REQ-030 | builds-traceability-matrix-with-skipped-reasons | Passed | 0.002 | | |
#### REQ-031 (100% passed)
@@ -64,59 +64,60 @@
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-033 | throws-error-for-malformed-xml | Passed | 0.001 | | |
+| REQ-033 | throws-error-for-malformed-xml | Passed | 0.004 | | |
Unmapped (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| Unmapped | associates-classname-with-requirement | Passed | 0.012 | | |
-| Unmapped | buildissuebranchname-formats-branch-name | Passed | 0.001 | | |
-| Unmapped | buildissuebranchname-rejects-non-numeric-input | Passed | 0.001 | | |
+| Unmapped | associates-classname-with-requirement | Passed | 0.016 | | |
+| Unmapped | buildissuebranchname-formats-branch-name | Passed | 0.003 | | |
+| Unmapped | buildissuebranchname-rejects-non-numeric-input | Passed | 0.002 | | |
| Unmapped | buildprofile1.iconeditor.addtokentolabview.dispatcher.dry-runs-add-token-to-labview-with-expected-arguments- | Passed | 0.482 | | |
| Unmapped | buildprofile1.iconeditor.applyvipc.dispatcher.dry-runs-apply-vipc-with-expected-arguments- | Passed | 0.042 | | |
| Unmapped | buildprofile1.iconeditor.buildvipackage.dispatcher.dry-runs-build-vi-package-with-expected-arguments- | Passed | 0.106 | | |
| Unmapped | buildprofile1.iconeditor.closelabview.dispatcher.dry-runs-close-labview-with-expected-arguments- | Passed | 0.036 | | |
-| Unmapped | buildsummary-splits-totals-by-os | Passed | 0.000 | | |
-| Unmapped | collecttestcases-captures-requirement-property | Passed | 0.009 | | |
-| Unmapped | collecttestcases-uses-evidence-property-and-falls-back-to-directory-scan | Passed | 0.009 | | |
-| Unmapped | collecttestcases-uses-machine-name-property-for-owner | Passed | 0.003 | | |
+| Unmapped | buildsummary-splits-totals-by-os | Passed | 0.001 | | |
+| Unmapped | collecttestcases-captures-requirement-property | Passed | 0.020 | | |
+| Unmapped | collecttestcases-uses-evidence-property-and-falls-back-to-directory-scan | Passed | 0.008 | | |
+| Unmapped | collecttestcases-uses-machine-name-property-for-owner | Passed | 0.008 | | |
| Unmapped | computestatuscounts-tallies-test-statuses | Passed | 0.000 | | |
-| Unmapped | detects-downloaded-artifacts-path | Passed | 0.894 | | |
-| Unmapped | dispatchers-and-parameters-include-descriptions | Passed | 0.002 | | |
-| Unmapped | errors-when-strict-unmapped-mode-enabled | Passed | 0.952 | | |
-| Unmapped | escapemarkdown-escapes-special-characters | Passed | 0.002 | | |
+| Unmapped | detects-downloaded-artifacts-path | Passed | 1.285 | | |
+| Unmapped | dispatchers-and-parameters-include-descriptions | Passed | 0.009 | | |
+| Unmapped | errors-when-strict-unmapped-mode-enabled | Passed | 1.270 | | |
+| Unmapped | escapemarkdown-escapes-special-characters | Passed | 0.001 | | |
| Unmapped | escapemarkdown-leaves-plain-text-untouched | Passed | 0.000 | | |
-| Unmapped | fails-when-commit-lacks-requirement-reference | Passed | 0.759 | | |
-| Unmapped | fails-when-requirement-lacks-test-coverage | Passed | 0.749 | | |
-| Unmapped | fails-when-tests-are-unmapped | Passed | 0.766 | | |
-| Unmapped | fails-when-tests-reference-unknown-requirements | Passed | 0.813 | | |
+| Unmapped | fails-when-commit-lacks-requirement-reference | Passed | 1.298 | | |
+| Unmapped | fails-when-requirement-lacks-test-coverage | Passed | 1.526 | | |
+| Unmapped | fails-when-tests-are-unmapped | Passed | 1.205 | | |
+| Unmapped | fails-when-tests-reference-unknown-requirements | Passed | 1.266 | | |
+| Unmapped | fails-without-runner-metadata | Passed | 0.825 | | |
| Unmapped | formaterror-handles-plain-objects | Passed | 0.000 | | |
| Unmapped | formaterror-handles-primitives | Passed | 0.000 | | |
-| Unmapped | formaterror-handles-real-error-objects | Passed | 0.001 | | |
-| Unmapped | formaterror-handles-unstringifiable-values | Passed | 0.000 | | |
-| Unmapped | generate-ci-summary-features | Passed | 0.021 | | |
-| Unmapped | groups-owners-and-includes-requirements-and-evidence | Passed | 0.856 | | |
-| Unmapped | grouptomarkdown-omits-numeric-identifiers | Passed | 0.001 | | |
+| Unmapped | formaterror-handles-real-error-objects | Passed | 0.003 | | |
+| Unmapped | formaterror-handles-unstringifiable-values | Passed | 0.001 | | |
+| Unmapped | generate-ci-summary-features | Passed | 0.026 | | |
+| Unmapped | groups-owners-and-includes-requirements-and-evidence | Passed | 1.361 | | |
+| Unmapped | grouptomarkdown-omits-numeric-identifiers | Passed | 0.003 | | |
| Unmapped | grouptomarkdown-supports-optional-limit-for-truncation | Passed | 0.001 | | |
| Unmapped | handles-root-level-testcases | Passed | 0.001 | | |
-| Unmapped | handles-zipped-junit-artifacts | Passed | 0.721 | | |
-| Unmapped | ignores-stale-junit-files-outside-artifacts-path | Passed | 0.804 | | |
-| Unmapped | loadrequirements-logs-warning-on-invalid-json | Passed | 0.017 | | |
-| Unmapped | loadrequirements-merges-multiple-files | Passed | 0.003 | | |
-| Unmapped | loadrequirements-warns-and-skips-invalid-entries | Passed | 0.004 | | |
-| Unmapped | logs-a-warning-when-no-junit-files-are-found | Passed | 0.845 | | |
-| Unmapped | partitions-requirement-groups-by-runner\_type | Passed | 0.763 | | |
-| Unmapped | passes-with-coverage-and-requirement-reference | Passed | 0.818 | | |
-| Unmapped | requirementssummarytomarkdown-escapes-pipes-in-description | Passed | 0.000 | | |
-| Unmapped | skips-invalid-junit-files-and-still-generates-summary | Passed | 0.994 | | |
+| Unmapped | handles-zipped-junit-artifacts | Passed | 1.055 | | |
+| Unmapped | ignores-stale-junit-files-outside-artifacts-path | Passed | 1.161 | | |
+| Unmapped | loadrequirements-logs-warning-on-invalid-json | Passed | 0.045 | | |
+| Unmapped | loadrequirements-merges-multiple-files | Passed | 0.012 | | |
+| Unmapped | loadrequirements-warns-and-skips-invalid-entries | Passed | 0.015 | | |
+| Unmapped | logs-a-warning-when-no-junit-files-are-found | Passed | 1.294 | | |
+| Unmapped | partitions-requirement-groups-by-runner\_type | Passed | 1.050 | | |
+| Unmapped | passes-with-coverage-and-requirement-reference | Passed | 1.298 | | |
+| Unmapped | requirementssummarytomarkdown-escapes-pipes-in-description | Passed | 0.001 | | |
+| Unmapped | skips-invalid-junit-files-and-still-generates-summary | Passed | 1.517 | | |
| Unmapped | summarytomarkdown-handles-no-tests | Passed | 0.000 | | |
-| Unmapped | summarytomarkdown-sorts-os-alphabetically-and-escapes-special-characters | Passed | 0.000 | | |
-| Unmapped | throws-when-no-junit-files-found-and-strict-mode-enabled | Passed | 0.671 | | |
-| Unmapped | uses-latest-artifact-directory-when-multiple-are-present | Passed | 0.866 | | |
-| Unmapped | warns-when-all-tests-are-unmapped | Passed | 1.048 | | |
-| Unmapped | writeerrorsummary-appends-error-details-to-summary-file | Passed | 0.006 | | |
-| Unmapped | writeerrorsummary-skips-summary-file-for-non-error-throws | Passed | 0.003 | | |
-| Unmapped | writes-outputs-to-os-specific-directory | Passed | 0.946 | | |
+| Unmapped | summarytomarkdown-sorts-os-alphabetically-and-escapes-special-characters | Passed | 0.001 | | |
+| Unmapped | throws-when-no-junit-files-found-and-strict-mode-enabled | Passed | 0.849 | | |
+| Unmapped | uses-latest-artifact-directory-when-multiple-are-present | Passed | 1.241 | | |
+| Unmapped | warns-when-all-tests-are-unmapped | Passed | 1.603 | | |
+| Unmapped | writeerrorsummary-appends-error-details-to-summary-file | Passed | 0.005 | | |
+| Unmapped | writeerrorsummary-skips-summary-file-for-non-error-throws | Passed | 0.004 | | |
+| Unmapped | writes-outputs-to-os-specific-directory | Passed | 1.750 | | |
\ No newline at end of file
diff --git a/artifacts/linux/traceability.json b/artifacts/linux/traceability.json
index 168158df..847c286d 100644
--- a/artifacts/linux/traceability.json
+++ b/artifacts/linux/traceability.json
@@ -9,7 +9,7 @@
"name": "[REQ-023] parses nested JUnit structures",
"className": "test",
"status": "Passed",
- "duration": 0.006212,
+ "duration": 0.010802,
"requirements": [
"REQ-023"
],
@@ -26,7 +26,7 @@
"name": "[REQ-024] captures root testsuites attributes",
"className": "test",
"status": "Passed",
- "duration": 0.005192,
+ "duration": 0.002729,
"requirements": [
"REQ-024"
],
@@ -43,7 +43,7 @@
"name": "[REQ-025] captures testsuite attributes",
"className": "test",
"status": "Passed",
- "duration": 0.000669,
+ "duration": 0.006149,
"requirements": [
"REQ-025"
],
@@ -60,7 +60,7 @@
"name": "[REQ-026] captures suite properties",
"className": "test",
"status": "Passed",
- "duration": 0.000506,
+ "duration": 0.001994,
"requirements": [
"REQ-026"
],
@@ -77,7 +77,7 @@
"name": "[REQ-027] captures testcase attributes and skipped message",
"className": "test",
"status": "Passed",
- "duration": 0.007769,
+ "duration": 0.001389,
"requirements": [
"REQ-027"
],
@@ -94,7 +94,7 @@
"name": "[REQ-028] extracts requirement identifiers",
"className": "test",
"status": "Passed",
- "duration": 0.001575,
+ "duration": 0.003376,
"requirements": [
"REQ-028"
],
@@ -111,7 +111,7 @@
"name": "[REQ-029] aggregates status by requirement and suite",
"className": "test",
"status": "Passed",
- "duration": 0.001939,
+ "duration": 0.002179,
"requirements": [
"REQ-029"
],
@@ -128,7 +128,7 @@
"name": "[REQ-030] builds traceability matrix with skipped reasons",
"className": "test",
"status": "Passed",
- "duration": 0.001094,
+ "duration": 0.002123,
"requirements": [
"REQ-030"
],
@@ -145,7 +145,7 @@
"name": "[REQ-031] validates missing fields",
"className": "test",
"status": "Passed",
- "duration": 0.000691,
+ "duration": 0.001122,
"requirements": [
"REQ-031"
],
@@ -162,7 +162,7 @@
"name": "[REQ-032] preserves unknown attributes",
"className": "test",
"status": "Passed",
- "duration": 0.000569,
+ "duration": 0.000799,
"requirements": [
"REQ-032"
],
@@ -179,7 +179,7 @@
"name": "[REQ-033] throws error for malformed XML",
"className": "test",
"status": "Passed",
- "duration": 0.001253,
+ "duration": 0.00418,
"requirements": [
"REQ-033"
],
@@ -195,7 +195,7 @@
"name": "associates classname with requirement",
"className": "test",
"status": "Passed",
- "duration": 0.011747,
+ "duration": 0.015669,
"requirements": [],
"os": "linux"
},
@@ -204,7 +204,7 @@
"name": "buildIssueBranchName formats branch name",
"className": "test",
"status": "Passed",
- "duration": 0.001276,
+ "duration": 0.003472,
"requirements": [],
"os": "linux"
},
@@ -213,7 +213,7 @@
"name": "buildIssueBranchName rejects non-numeric input",
"className": "test",
"status": "Passed",
- "duration": 0.001038,
+ "duration": 0.001627,
"requirements": [],
"os": "linux"
},
@@ -258,7 +258,7 @@
"name": "buildSummary splits totals by OS",
"className": "test",
"status": "Passed",
- "duration": 0.000311,
+ "duration": 0.000891,
"requirements": [],
"os": "linux"
},
@@ -267,7 +267,7 @@
"name": "collectTestCases captures requirement property",
"className": "test",
"status": "Passed",
- "duration": 0.008665,
+ "duration": 0.019617,
"requirements": [],
"os": "linux"
},
@@ -276,7 +276,7 @@
"name": "collectTestCases uses evidence property and falls back to directory scan",
"className": "test",
"status": "Passed",
- "duration": 0.008942,
+ "duration": 0.008364,
"requirements": [],
"os": "linux"
},
@@ -285,7 +285,7 @@
"name": "collectTestCases uses machine-name property for owner",
"className": "test",
"status": "Passed",
- "duration": 0.0032,
+ "duration": 0.008127,
"requirements": [],
"os": "linux"
},
@@ -294,7 +294,7 @@
"name": "computeStatusCounts tallies test statuses",
"className": "test",
"status": "Passed",
- "duration": 0.00031,
+ "duration": 0.00049,
"requirements": [],
"os": "linux"
},
@@ -303,7 +303,7 @@
"name": "detects downloaded artifacts path",
"className": "test",
"status": "Passed",
- "duration": 0.894465,
+ "duration": 1.285456,
"requirements": [],
"os": "linux"
},
@@ -312,7 +312,7 @@
"name": "Dispatchers and parameters include descriptions",
"className": "test",
"status": "Passed",
- "duration": 0.00239,
+ "duration": 0.008556,
"requirements": [],
"os": "linux"
},
@@ -321,7 +321,7 @@
"name": "errors when strict unmapped mode enabled",
"className": "test",
"status": "Passed",
- "duration": 0.951951,
+ "duration": 1.270083,
"requirements": [],
"os": "linux"
},
@@ -330,7 +330,7 @@
"name": "escapeMarkdown escapes special characters",
"className": "test",
"status": "Passed",
- "duration": 0.0022,
+ "duration": 0.001408,
"requirements": [],
"os": "linux"
},
@@ -339,7 +339,7 @@
"name": "escapeMarkdown leaves plain text untouched",
"className": "test",
"status": "Passed",
- "duration": 0.000172,
+ "duration": 0.000199,
"requirements": [],
"os": "linux"
},
@@ -348,7 +348,7 @@
"name": "fails when commit lacks requirement reference",
"className": "test",
"status": "Passed",
- "duration": 0.759453,
+ "duration": 1.297728,
"requirements": [],
"os": "linux"
},
@@ -357,7 +357,7 @@
"name": "fails when requirement lacks test coverage",
"className": "test",
"status": "Passed",
- "duration": 0.748901,
+ "duration": 1.525556,
"requirements": [],
"os": "linux"
},
@@ -366,7 +366,7 @@
"name": "fails when tests are unmapped",
"className": "test",
"status": "Passed",
- "duration": 0.765915,
+ "duration": 1.204814,
"requirements": [],
"os": "linux"
},
@@ -375,7 +375,16 @@
"name": "fails when tests reference unknown requirements",
"className": "test",
"status": "Passed",
- "duration": 0.81344,
+ "duration": 1.266281,
+ "requirements": [],
+ "os": "linux"
+ },
+ {
+ "id": "fails-without-runner-metadata",
+ "name": "fails without runner metadata",
+ "className": "test",
+ "status": "Passed",
+ "duration": 0.8252,
"requirements": [],
"os": "linux"
},
@@ -384,7 +393,7 @@
"name": "formatError handles plain objects",
"className": "test",
"status": "Passed",
- "duration": 0.000229,
+ "duration": 0.000455,
"requirements": [],
"os": "linux"
},
@@ -393,7 +402,7 @@
"name": "formatError handles primitives",
"className": "test",
"status": "Passed",
- "duration": 0.000106,
+ "duration": 0.000323,
"requirements": [],
"os": "linux"
},
@@ -402,7 +411,7 @@
"name": "formatError handles real Error objects",
"className": "test",
"status": "Passed",
- "duration": 0.001221,
+ "duration": 0.00265,
"requirements": [],
"os": "linux"
},
@@ -411,7 +420,7 @@
"name": "formatError handles unstringifiable values",
"className": "test",
"status": "Passed",
- "duration": 0.000187,
+ "duration": 0.00055,
"requirements": [],
"os": "linux"
},
@@ -420,7 +429,7 @@
"name": "generate-ci-summary features",
"className": "test",
"status": "Passed",
- "duration": 0.020691,
+ "duration": 0.026061,
"requirements": [],
"os": "linux"
},
@@ -429,7 +438,7 @@
"name": "groups owners and includes requirements and evidence",
"className": "test",
"status": "Passed",
- "duration": 0.855927,
+ "duration": 1.361341,
"requirements": [],
"os": "linux"
},
@@ -438,7 +447,7 @@
"name": "groupToMarkdown omits numeric identifiers",
"className": "test",
"status": "Passed",
- "duration": 0.001157,
+ "duration": 0.002602,
"requirements": [],
"os": "linux"
},
@@ -447,7 +456,7 @@
"name": "groupToMarkdown supports optional limit for truncation",
"className": "test",
"status": "Passed",
- "duration": 0.000608,
+ "duration": 0.000886,
"requirements": [],
"os": "linux"
},
@@ -456,7 +465,7 @@
"name": "handles root-level testcases",
"className": "test",
"status": "Passed",
- "duration": 0.000832,
+ "duration": 0.000869,
"requirements": [],
"os": "linux"
},
@@ -465,7 +474,7 @@
"name": "handles zipped JUnit artifacts",
"className": "test",
"status": "Passed",
- "duration": 0.720984,
+ "duration": 1.054579,
"requirements": [],
"os": "linux"
},
@@ -474,7 +483,7 @@
"name": "ignores stale JUnit files outside artifacts path",
"className": "test",
"status": "Passed",
- "duration": 0.804072,
+ "duration": 1.160572,
"requirements": [],
"os": "linux"
},
@@ -483,7 +492,7 @@
"name": "loadRequirements logs warning on invalid JSON",
"className": "test",
"status": "Passed",
- "duration": 0.016972,
+ "duration": 0.045129,
"requirements": [],
"os": "linux"
},
@@ -492,7 +501,7 @@
"name": "loadRequirements merges multiple files",
"className": "test",
"status": "Passed",
- "duration": 0.002667,
+ "duration": 0.011535,
"requirements": [],
"os": "linux"
},
@@ -501,7 +510,7 @@
"name": "loadRequirements warns and skips invalid entries",
"className": "test",
"status": "Passed",
- "duration": 0.003562,
+ "duration": 0.015018,
"requirements": [],
"os": "linux"
},
@@ -510,7 +519,7 @@
"name": "logs a warning when no JUnit files are found",
"className": "test",
"status": "Passed",
- "duration": 0.845258,
+ "duration": 1.294323,
"requirements": [],
"os": "linux"
},
@@ -519,7 +528,7 @@
"name": "partitions requirement groups by runner_type",
"className": "test",
"status": "Passed",
- "duration": 0.762931,
+ "duration": 1.050325,
"requirements": [],
"os": "linux"
},
@@ -528,7 +537,7 @@
"name": "passes with coverage and requirement reference",
"className": "test",
"status": "Passed",
- "duration": 0.818483,
+ "duration": 1.297657,
"requirements": [],
"os": "linux"
},
@@ -537,7 +546,7 @@
"name": "requirementsSummaryToMarkdown escapes pipes in description",
"className": "test",
"status": "Passed",
- "duration": 0.000342,
+ "duration": 0.000956,
"requirements": [],
"os": "linux"
},
@@ -546,7 +555,7 @@
"name": "skips invalid JUnit files and still generates summary",
"className": "test",
"status": "Passed",
- "duration": 0.99408,
+ "duration": 1.517327,
"requirements": [],
"os": "linux"
},
@@ -555,7 +564,7 @@
"name": "summaryToMarkdown handles no tests",
"className": "test",
"status": "Passed",
- "duration": 0.000204,
+ "duration": 0.000396,
"requirements": [],
"os": "linux"
},
@@ -564,7 +573,7 @@
"name": "summaryToMarkdown sorts OS alphabetically and escapes special characters",
"className": "test",
"status": "Passed",
- "duration": 0.000471,
+ "duration": 0.000721,
"requirements": [],
"os": "linux"
},
@@ -573,7 +582,7 @@
"name": "throws when no JUnit files found and strict mode enabled",
"className": "test",
"status": "Passed",
- "duration": 0.670756,
+ "duration": 0.849162,
"requirements": [],
"os": "linux"
},
@@ -582,7 +591,7 @@
"name": "uses latest artifact directory when multiple are present",
"className": "test",
"status": "Passed",
- "duration": 0.865636,
+ "duration": 1.240923,
"requirements": [],
"os": "linux"
},
@@ -591,7 +600,7 @@
"name": "warns when all tests are unmapped",
"className": "test",
"status": "Passed",
- "duration": 1.048228,
+ "duration": 1.603055,
"requirements": [],
"os": "linux"
},
@@ -600,7 +609,7 @@
"name": "writeErrorSummary appends error details to summary file",
"className": "test",
"status": "Passed",
- "duration": 0.005534,
+ "duration": 0.005131,
"requirements": [],
"os": "linux"
},
@@ -609,7 +618,7 @@
"name": "writeErrorSummary skips summary file for non-Error throws",
"className": "test",
"status": "Passed",
- "duration": 0.002942,
+ "duration": 0.004137,
"requirements": [],
"os": "linux"
},
@@ -618,7 +627,7 @@
"name": "writes outputs to OS-specific directory",
"className": "test",
"status": "Passed",
- "duration": 0.945781,
+ "duration": 1.750139,
"requirements": [],
"os": "linux"
}
@@ -627,18 +636,18 @@
],
"totals": {
"overall": {
- "passed": 59,
+ "passed": 60,
"failed": 0,
"skipped": 0,
- "duration": 15.057706000000003,
+ "duration": 23.743201999999997,
"rate": 100
},
"byOs": {
"linux": {
- "passed": 59,
+ "passed": 60,
"failed": 0,
"skipped": 0,
- "duration": 15.057706000000003,
+ "duration": 23.743201999999997,
"rate": 100
}
}
diff --git a/artifacts/linux/traceability.md b/artifacts/linux/traceability.md
index 8cb2d138..6dd24a87 100644
--- a/artifacts/linux/traceability.md
+++ b/artifacts/linux/traceability.md
@@ -4,37 +4,37 @@
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-023 | parses-nested-junit-structures | Passed | 0.006 | | |
+| REQ-023 | parses-nested-junit-structures | Passed | 0.011 | | |
#### REQ-024 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-024 | captures-root-testsuites-attributes | Passed | 0.005 | | |
+| REQ-024 | captures-root-testsuites-attributes | Passed | 0.003 | | |
#### REQ-025 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-025 | captures-testsuite-attributes | Passed | 0.001 | | |
+| REQ-025 | captures-testsuite-attributes | Passed | 0.006 | | |
#### REQ-026 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-026 | captures-suite-properties | Passed | 0.001 | | |
+| REQ-026 | captures-suite-properties | Passed | 0.002 | | |
#### REQ-027 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-027 | captures-testcase-attributes-and-skipped-message | Passed | 0.008 | | |
+| REQ-027 | captures-testcase-attributes-and-skipped-message | Passed | 0.001 | | |
#### REQ-028 (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-028 | extracts-requirement-identifiers | Passed | 0.002 | | |
+| REQ-028 | extracts-requirement-identifiers | Passed | 0.003 | | |
#### REQ-029 (100% passed)
@@ -46,7 +46,7 @@
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-030 | builds-traceability-matrix-with-skipped-reasons | Passed | 0.001 | | |
+| REQ-030 | builds-traceability-matrix-with-skipped-reasons | Passed | 0.002 | | |
#### REQ-031 (100% passed)
@@ -64,59 +64,60 @@
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| REQ-033 | throws-error-for-malformed-xml | Passed | 0.001 | | |
+| REQ-033 | throws-error-for-malformed-xml | Passed | 0.004 | | |
Unmapped (100% passed)
| Requirement | Test ID | Status | Duration (s) | Owner | Evidence |
| --- | --- | --- | --- | --- | --- |
-| Unmapped | associates-classname-with-requirement | Passed | 0.012 | | |
-| Unmapped | buildissuebranchname-formats-branch-name | Passed | 0.001 | | |
-| Unmapped | buildissuebranchname-rejects-non-numeric-input | Passed | 0.001 | | |
+| Unmapped | associates-classname-with-requirement | Passed | 0.016 | | |
+| Unmapped | buildissuebranchname-formats-branch-name | Passed | 0.003 | | |
+| Unmapped | buildissuebranchname-rejects-non-numeric-input | Passed | 0.002 | | |
| Unmapped | buildprofile1.iconeditor.addtokentolabview.dispatcher.dry-runs-add-token-to-labview-with-expected-arguments- | Passed | 0.482 | | |
| Unmapped | buildprofile1.iconeditor.applyvipc.dispatcher.dry-runs-apply-vipc-with-expected-arguments- | Passed | 0.042 | | |
| Unmapped | buildprofile1.iconeditor.buildvipackage.dispatcher.dry-runs-build-vi-package-with-expected-arguments- | Passed | 0.106 | | |
| Unmapped | buildprofile1.iconeditor.closelabview.dispatcher.dry-runs-close-labview-with-expected-arguments- | Passed | 0.036 | | |
-| Unmapped | buildsummary-splits-totals-by-os | Passed | 0.000 | | |
-| Unmapped | collecttestcases-captures-requirement-property | Passed | 0.009 | | |
-| Unmapped | collecttestcases-uses-evidence-property-and-falls-back-to-directory-scan | Passed | 0.009 | | |
-| Unmapped | collecttestcases-uses-machine-name-property-for-owner | Passed | 0.003 | | |
+| Unmapped | buildsummary-splits-totals-by-os | Passed | 0.001 | | |
+| Unmapped | collecttestcases-captures-requirement-property | Passed | 0.020 | | |
+| Unmapped | collecttestcases-uses-evidence-property-and-falls-back-to-directory-scan | Passed | 0.008 | | |
+| Unmapped | collecttestcases-uses-machine-name-property-for-owner | Passed | 0.008 | | |
| Unmapped | computestatuscounts-tallies-test-statuses | Passed | 0.000 | | |
-| Unmapped | detects-downloaded-artifacts-path | Passed | 0.894 | | |
-| Unmapped | dispatchers-and-parameters-include-descriptions | Passed | 0.002 | | |
-| Unmapped | errors-when-strict-unmapped-mode-enabled | Passed | 0.952 | | |
-| Unmapped | escapemarkdown-escapes-special-characters | Passed | 0.002 | | |
+| Unmapped | detects-downloaded-artifacts-path | Passed | 1.285 | | |
+| Unmapped | dispatchers-and-parameters-include-descriptions | Passed | 0.009 | | |
+| Unmapped | errors-when-strict-unmapped-mode-enabled | Passed | 1.270 | | |
+| Unmapped | escapemarkdown-escapes-special-characters | Passed | 0.001 | | |
| Unmapped | escapemarkdown-leaves-plain-text-untouched | Passed | 0.000 | | |
-| Unmapped | fails-when-commit-lacks-requirement-reference | Passed | 0.759 | | |
-| Unmapped | fails-when-requirement-lacks-test-coverage | Passed | 0.749 | | |
-| Unmapped | fails-when-tests-are-unmapped | Passed | 0.766 | | |
-| Unmapped | fails-when-tests-reference-unknown-requirements | Passed | 0.813 | | |
+| Unmapped | fails-when-commit-lacks-requirement-reference | Passed | 1.298 | | |
+| Unmapped | fails-when-requirement-lacks-test-coverage | Passed | 1.526 | | |
+| Unmapped | fails-when-tests-are-unmapped | Passed | 1.205 | | |
+| Unmapped | fails-when-tests-reference-unknown-requirements | Passed | 1.266 | | |
+| Unmapped | fails-without-runner-metadata | Passed | 0.825 | | |
| Unmapped | formaterror-handles-plain-objects | Passed | 0.000 | | |
| Unmapped | formaterror-handles-primitives | Passed | 0.000 | | |
-| Unmapped | formaterror-handles-real-error-objects | Passed | 0.001 | | |
-| Unmapped | formaterror-handles-unstringifiable-values | Passed | 0.000 | | |
-| Unmapped | generate-ci-summary-features | Passed | 0.021 | | |
-| Unmapped | groups-owners-and-includes-requirements-and-evidence | Passed | 0.856 | | |
-| Unmapped | grouptomarkdown-omits-numeric-identifiers | Passed | 0.001 | | |
+| Unmapped | formaterror-handles-real-error-objects | Passed | 0.003 | | |
+| Unmapped | formaterror-handles-unstringifiable-values | Passed | 0.001 | | |
+| Unmapped | generate-ci-summary-features | Passed | 0.026 | | |
+| Unmapped | groups-owners-and-includes-requirements-and-evidence | Passed | 1.361 | | |
+| Unmapped | grouptomarkdown-omits-numeric-identifiers | Passed | 0.003 | | |
| Unmapped | grouptomarkdown-supports-optional-limit-for-truncation | Passed | 0.001 | | |
| Unmapped | handles-root-level-testcases | Passed | 0.001 | | |
-| Unmapped | handles-zipped-junit-artifacts | Passed | 0.721 | | |
-| Unmapped | ignores-stale-junit-files-outside-artifacts-path | Passed | 0.804 | | |
-| Unmapped | loadrequirements-logs-warning-on-invalid-json | Passed | 0.017 | | |
-| Unmapped | loadrequirements-merges-multiple-files | Passed | 0.003 | | |
-| Unmapped | loadrequirements-warns-and-skips-invalid-entries | Passed | 0.004 | | |
-| Unmapped | logs-a-warning-when-no-junit-files-are-found | Passed | 0.845 | | |
-| Unmapped | partitions-requirement-groups-by-runner\_type | Passed | 0.763 | | |
-| Unmapped | passes-with-coverage-and-requirement-reference | Passed | 0.818 | | |
-| Unmapped | requirementssummarytomarkdown-escapes-pipes-in-description | Passed | 0.000 | | |
-| Unmapped | skips-invalid-junit-files-and-still-generates-summary | Passed | 0.994 | | |
+| Unmapped | handles-zipped-junit-artifacts | Passed | 1.055 | | |
+| Unmapped | ignores-stale-junit-files-outside-artifacts-path | Passed | 1.161 | | |
+| Unmapped | loadrequirements-logs-warning-on-invalid-json | Passed | 0.045 | | |
+| Unmapped | loadrequirements-merges-multiple-files | Passed | 0.012 | | |
+| Unmapped | loadrequirements-warns-and-skips-invalid-entries | Passed | 0.015 | | |
+| Unmapped | logs-a-warning-when-no-junit-files-are-found | Passed | 1.294 | | |
+| Unmapped | partitions-requirement-groups-by-runner\_type | Passed | 1.050 | | |
+| Unmapped | passes-with-coverage-and-requirement-reference | Passed | 1.298 | | |
+| Unmapped | requirementssummarytomarkdown-escapes-pipes-in-description | Passed | 0.001 | | |
+| Unmapped | skips-invalid-junit-files-and-still-generates-summary | Passed | 1.517 | | |
| Unmapped | summarytomarkdown-handles-no-tests | Passed | 0.000 | | |
-| Unmapped | summarytomarkdown-sorts-os-alphabetically-and-escapes-special-characters | Passed | 0.000 | | |
-| Unmapped | throws-when-no-junit-files-found-and-strict-mode-enabled | Passed | 0.671 | | |
-| Unmapped | uses-latest-artifact-directory-when-multiple-are-present | Passed | 0.866 | | |
-| Unmapped | warns-when-all-tests-are-unmapped | Passed | 1.048 | | |
-| Unmapped | writeerrorsummary-appends-error-details-to-summary-file | Passed | 0.006 | | |
-| Unmapped | writeerrorsummary-skips-summary-file-for-non-error-throws | Passed | 0.003 | | |
-| Unmapped | writes-outputs-to-os-specific-directory | Passed | 0.946 | | |
+| Unmapped | summarytomarkdown-sorts-os-alphabetically-and-escapes-special-characters | Passed | 0.001 | | |
+| Unmapped | throws-when-no-junit-files-found-and-strict-mode-enabled | Passed | 0.849 | | |
+| Unmapped | uses-latest-artifact-directory-when-multiple-are-present | Passed | 1.241 | | |
+| Unmapped | warns-when-all-tests-are-unmapped | Passed | 1.603 | | |
+| Unmapped | writeerrorsummary-appends-error-details-to-summary-file | Passed | 0.005 | | |
+| Unmapped | writeerrorsummary-skips-summary-file-for-non-error-throws | Passed | 0.004 | | |
+| Unmapped | writes-outputs-to-os-specific-directory | Passed | 1.750 | | |
\ No newline at end of file
diff --git a/ci_evidence.txt b/ci_evidence.txt
index 0999005d..6b3faf4a 100644
--- a/ci_evidence.txt
+++ b/ci_evidence.txt
@@ -1 +1 @@
-{"pipeline":"Unknown","git_sha":"18df35a724af7429bac01805085922dddf3b9b85","req_status":{"REQ-023":"PASS","REQ-024":"PASS","REQ-025":"PASS","REQ-026":"PASS","REQ-027":"PASS","REQ-028":"PASS","REQ-029":"PASS","REQ-030":"PASS","REQ-031":"PASS","REQ-032":"PASS","REQ-033":"PASS"}}
\ No newline at end of file
+{"pipeline":"Unknown","git_sha":"74b28b12cf04f046cf9f89dfedf9a33e093d7e34","req_status":{"REQ-023":"PASS","REQ-024":"PASS","REQ-025":"PASS","REQ-026":"PASS","REQ-027":"PASS","REQ-028":"PASS","REQ-029":"PASS","REQ-030":"PASS","REQ-031":"PASS","REQ-032":"PASS","REQ-033":"PASS"}}
\ No newline at end of file
diff --git a/scripts/__tests__/generate-ci-summary.test.js b/scripts/__tests__/generate-ci-summary.test.js
index ed205bde..a75898a5 100644
--- a/scripts/__tests__/generate-ci-summary.test.js
+++ b/scripts/__tests__/generate-ci-summary.test.js
@@ -277,6 +277,7 @@ test('writes outputs to OS-specific directory', async () => {
TEST_RESULTS_GLOBS: junitPath,
EVIDENCE_DIR: tmp,
RUNNER_OS: 'Windows',
+ RUNNER_LABEL: 'ubuntu-latest',
};
await execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env });
@@ -312,6 +313,7 @@ test('skips invalid JUnit files and still generates summary', async () => {
TEST_RESULTS_GLOBS: `${goodPath} ${badPath}`,
EVIDENCE_DIR: dir,
RUNNER_OS: 'Linux',
+ RUNNER_LABEL: 'ubuntu-latest',
};
const { stderr } = await execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env });
@@ -343,6 +345,7 @@ test('warns when all tests are unmapped', async () => {
EVIDENCE_DIR: dir,
REQ_MAPPING_FILE: reqPath,
RUNNER_OS: 'Linux',
+ RUNNER_LABEL: 'ubuntu-latest',
};
const { stderr } = await execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env });
@@ -368,6 +371,7 @@ test('errors when strict unmapped mode enabled', async () => {
REQ_MAPPING_FILE: reqPath,
RUNNER_OS: 'Linux',
REQUIRE_REQUIREMENTS_MAPPING: '1',
+ RUNNER_LABEL: 'ubuntu-latest',
};
await assert.rejects(
@@ -389,6 +393,7 @@ test('ignores stale JUnit files outside artifacts path', async () => {
await fs.writeFile(stalePath, '');
const env = { ...process.env, RUNNER_OS: 'Linux' };
+ env.RUNNER_LABEL = 'ubuntu-latest';
await execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env });
const trace = await fs.readFile(path.join('artifacts', 'linux', 'traceability.md'), 'utf8');
@@ -401,7 +406,7 @@ test('ignores stale JUnit files outside artifacts path', async () => {
test('throws when no JUnit files found and strict mode enabled', async () => {
await fs.rm('artifacts', { recursive: true, force: true });
- const env = { ...process.env, REQUIRE_TEST_RESULTS: '1', RUNNER_OS: 'Linux' };
+ const env = { ...process.env, REQUIRE_TEST_RESULTS: '1', RUNNER_OS: 'Linux', RUNNER_LABEL: 'ubuntu-latest' };
await assert.rejects(
execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env }),
/No JUnit files found/,
@@ -431,6 +436,7 @@ test('partitions requirement groups by runner_type', async () => {
EVIDENCE_DIR: dir,
REQ_MAPPING_FILE: reqPath,
RUNNER_OS: 'Linux',
+ RUNNER_LABEL: 'ubuntu-latest',
};
await execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env });
@@ -469,6 +475,7 @@ test('handles zipped JUnit artifacts', async () => {
REQ_MAPPING_FILE: reqPath,
DISPATCHER_REGISTRY: dispPath,
RUNNER_OS: 'Linux',
+ RUNNER_LABEL: 'ubuntu-latest',
};
await execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env });
@@ -479,3 +486,12 @@ test('handles zipped JUnit artifacts', async () => {
await fs.rm('artifacts', { recursive: true, force: true });
await fs.rm(tmp, { recursive: true, force: true });
});
+
+test('fails without runner metadata', async () => {
+ await fs.rm('artifacts', { recursive: true, force: true });
+ const env = { ...process.env, RUNNER_OS: 'Linux' };
+ await assert.rejects(
+ execFileP('node_modules/.bin/tsx', ['scripts/generate-ci-summary.ts'], { env }),
+ /RUNNER_LABEL, RUNNER_TYPE, or SKIP_DRY_RUN must be set/,
+ );
+});
diff --git a/scripts/generate-ci-summary.ts b/scripts/generate-ci-summary.ts
index 56f403db..608c2eb9 100644
--- a/scripts/generate-ci-summary.ts
+++ b/scripts/generate-ci-summary.ts
@@ -23,6 +23,17 @@ import { collectTestCases } from './summary/tests.ts';
import { loadRequirements, mapToRequirements, redact } from './summary/requirements.ts';
async function main() {
+ const hasRunnerMeta = Boolean(
+ process.env.RUNNER_LABEL ||
+ process.env.RUNNER_TYPE ||
+ process.env.SKIP_DRY_RUN,
+ );
+ if (!hasRunnerMeta) {
+ console.error(
+ 'At least one of RUNNER_LABEL, RUNNER_TYPE, or SKIP_DRY_RUN must be set',
+ );
+ process.exit(1);
+ }
const mappingFiles = (process.env.REQ_MAPPING_FILE || 'requirements.json')
.split(',')
.map((s) => s.trim())
diff --git a/test-results/node-junit.xml b/test-results/node-junit.xml
index a2a81f29..02ff843e 100644
--- a/test-results/node-junit.xml
+++ b/test-results/node-junit.xml
@@ -1,66 +1,67 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+