diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 2e4a0c6..709eaa4 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -19,6 +19,10 @@ jobs:
contents: read
steps:
+ # === INSTALL DEPENDENCIES ===
+ # This section installs all required dependencies for quality checks.
+ # Downstream projects: Add any additional dependency installations here.
+
- name: Checkout
uses: actions/checkout@v6
@@ -34,15 +38,23 @@ jobs:
- name: Capture tool versions
shell: bash
run: |
+ mkdir -p artifacts
echo "Capturing tool versions..."
- dotnet versionmark --capture --job-id "quality" -- dotnet git versionmark
+ dotnet versionmark --capture --job-id "quality" \
+ --output "artifacts/versionmark-quality.json" -- \
+ dotnet git versionmark
echo "✓ Tool versions captured"
- - name: Upload version capture
- uses: actions/upload-artifact@v7
- with:
- name: version-capture-quality
- path: versionmark-quality.json
+ # === CAPTURE OTS SELF-VALIDATION RESULTS ===
+ # This section captures self-validation results from OTS tools.
+ # Downstream projects: Add any additional self-validation steps here.
+
+ - name: Run VersionMark self-validation
+ run: dotnet versionmark --validate --results artifacts/versionmark-self-validation-quality.trx
+
+ # === RUN QUALITY CHECKS ===
+ # This section runs all quality checks for the project.
+ # Downstream projects: Add any additional quality checks here.
- name: Run markdown linter
uses: DavidAnson/markdownlint-cli2-action@v22
@@ -60,6 +72,12 @@ jobs:
with:
config_file: .yamllint.yaml
+ - name: Upload quality artifacts
+ uses: actions/upload-artifact@v7
+ with:
+ name: artifacts-quality
+ path: artifacts/
+
# Builds and unit-tests the project on supported operating systems to ensure
# unit-tests operate on all platforms and to run SonarScanner for generating
# the code quality report.
@@ -78,6 +96,10 @@ jobs:
steps:
+ # === INSTALL DEPENDENCIES ===
+ # This section installs all required dependencies for the build.
+ # Downstream projects: Add any additional dependency installations here.
+
- name: Checkout
uses: actions/checkout@v6
@@ -93,6 +115,34 @@ jobs:
run: >
dotnet tool restore
+ # === CAPTURE TOOL VERSIONS ===
+ # This section captures the versions of all tools used in the build process.
+ # Downstream projects: Add any additional tools to capture here.
+
+ - name: Capture tool versions
+ shell: bash
+ run: |
+ mkdir -p artifacts
+ echo "Capturing tool versions..."
+ # Create short job ID: build-win, build-ubuntu
+ OS_SHORT=$(echo "${{ matrix.os }}" | sed 's/windows-latest/win/;s/ubuntu-latest/ubuntu/')
+ JOB_ID="build-${OS_SHORT}"
+ dotnet versionmark --capture --job-id "${JOB_ID}" \
+ --output "artifacts/versionmark-${JOB_ID}.json" -- \
+ dotnet git dotnet-sonarscanner versionmark
+ echo "✓ Tool versions captured"
+
+ # === CAPTURE OTS SELF-VALIDATION RESULTS ===
+ # This section captures self-validation results from OTS tools.
+ # Downstream projects: Add any additional self-validation steps here.
+
+ - name: Run VersionMark self-validation
+ run: dotnet versionmark --validate --results artifacts/versionmark-self-validation-${{ matrix.os }}.trx
+
+ # === BUILD AND TEST ===
+ # This section builds and tests the project.
+ # Downstream projects: Add any additional build and test steps here.
+
- name: Restore Dependencies
run: >
dotnet restore
@@ -119,9 +169,9 @@ jobs:
dotnet test
--no-build
--configuration Release
- --verbosity normal
--collect "XPlat Code Coverage;Format=opencover"
- --logger "trx;LogFileName=test-results-${{ matrix.os }}.trx"
+ --logger "trx;LogFilePrefix=${{ matrix.os }}"
+ --results-directory artifacts
- name: End Sonar Scanner
run: >
@@ -135,32 +185,17 @@ jobs:
--configuration Release
--property:Version=${{ inputs.version }}
- - name: Capture tool versions
- shell: bash
- run: |
- echo "Capturing tool versions..."
- # Create short job ID: build-win, build-ubuntu
- OS_SHORT=$(echo "${{ matrix.os }}" | sed 's/windows-latest/win/;s/ubuntu-latest/ubuntu/')
- JOB_ID="build-${OS_SHORT}"
- dotnet versionmark --capture --job-id "${JOB_ID}" -- \
- dotnet git dotnet-sonarscanner versionmark
- echo "✓ Tool versions captured"
-
- - name: Upload version capture
- uses: actions/upload-artifact@v7
- with:
- name: version-capture-${{ matrix.os }}
- path: versionmark-build-*.json
+ # === UPLOAD ARTIFACTS ===
+ # This section uploads all build artifacts.
+ # Downstream projects: Add any additional artifact uploads here.
- - name: Upload Test Results
- if: always()
+ - name: Upload build artifacts
uses: actions/upload-artifact@v7
with:
- name: test-results-${{ matrix.os }}
- path: |
- test/**/TestResults/*.trx
+ name: artifacts-build-${{ matrix.os }}
+ path: artifacts/
- - name: Upload Artifacts
+ - name: Upload packages
uses: actions/upload-artifact@v7
with:
name: packages-${{ matrix.os }}
@@ -180,6 +215,10 @@ jobs:
security-events: write
steps:
+ # === INSTALL DEPENDENCIES ===
+ # This section installs all required dependencies for CodeQL analysis.
+ # Downstream projects: Add any additional dependency installations here.
+
- name: Checkout
uses: actions/checkout@v6
with:
@@ -209,6 +248,10 @@ jobs:
run: >
dotnet restore
+ # === BUILD AND ANALYZE ===
+ # This section builds the project and runs CodeQL analysis.
+ # Downstream projects: Add any additional analysis steps here.
+
- name: Build
run: >
dotnet build
@@ -220,14 +263,18 @@ jobs:
uses: github/codeql-action/analyze@v4
with:
category: "/language:csharp"
- output: sarif-results
+ output: artifacts
upload: false
- - name: Upload CodeQL SARIF
+ # === UPLOAD ARTIFACTS ===
+ # This section uploads all CodeQL artifacts.
+ # Downstream projects: Add any additional artifact uploads here.
+
+ - name: Upload CodeQL artifacts
uses: actions/upload-artifact@v7
with:
- name: codeql-sarif
- path: sarif-results/csharp.sarif
+ name: artifacts-codeql
+ path: artifacts/
# Performs integration testing on a matrix of operating systems and .NET runtimes,
# involving basic tool execution and running self-validation to ensure compatibility
@@ -245,6 +292,10 @@ jobs:
dotnet-version: ['8.x', '9.x', '10.x']
steps:
+ # === INSTALL DEPENDENCIES ===
+ # This section installs all required dependencies and tools for integration testing.
+ # Downstream projects: Add any additional dependency installations here.
+
- name: Checkout
uses: actions/checkout@v6
with:
@@ -276,6 +327,28 @@ jobs:
--version ${{ inputs.version }} \
DemaConsulting.ReqStream
+ # === CAPTURE TOOL VERSIONS ===
+ # This section captures the versions of all tools used in the integration tests.
+ # Downstream projects: Add any additional tools to capture here.
+
+ - name: Capture tool versions
+ shell: bash
+ run: |
+ mkdir -p artifacts
+ echo "Capturing tool versions..."
+ # Create short job ID: int-win-8, int-win-9, int-ubuntu-8, etc.
+ OS_SHORT=$(echo "${{ matrix.os }}" | sed 's/windows-latest/win/;s/ubuntu-latest/ubuntu/')
+ DOTNET_SHORT=$(echo "${{ matrix.dotnet-version }}" | sed 's/\.x$//')
+ JOB_ID="int-${OS_SHORT}-${DOTNET_SHORT}"
+ dotnet versionmark --capture --job-id "${JOB_ID}" \
+ --output "artifacts/versionmark-${JOB_ID}.json" -- \
+ dotnet git versionmark
+ echo "✓ Tool versions captured"
+
+ # === RUN INTEGRATION TESTS ===
+ # This section runs the integration tests for the tool.
+ # Downstream projects: Add any additional integration test steps here.
+
- name: Test version display
shell: bash
run: |
@@ -295,33 +368,20 @@ jobs:
run: |
echo "Running self-validation..."
reqstream --validate \
- --results integration-test-${{ matrix.os }}-dotnet${{ matrix.dotnet-version }}.trx \
+ --results artifacts/validation-${{ matrix.os }}-dotnet${{ matrix.dotnet-version }}.trx \
|| { echo "✗ Self-validation failed"; exit 1; }
echo "✓ Self-validation succeeded"
- - name: Capture tool versions
- shell: bash
- run: |
- echo "Capturing tool versions..."
- # Create short job ID: int-win-8, int-win-9, int-ubuntu-8, etc.
- OS_SHORT=$(echo "${{ matrix.os }}" | sed 's/windows-latest/win/;s/ubuntu-latest/ubuntu/')
- DOTNET_SHORT=$(echo "${{ matrix.dotnet-version }}" | sed 's/\.x$//')
- JOB_ID="int-${OS_SHORT}-${DOTNET_SHORT}"
- dotnet versionmark --capture --job-id "${JOB_ID}" -- dotnet git versionmark
- echo "✓ Tool versions captured"
-
- - name: Upload version capture
- uses: actions/upload-artifact@v7
- with:
- name: version-capture-${{ matrix.os }}-dotnet${{ matrix.dotnet-version }}
- path: versionmark-int-*.json
+ # === UPLOAD ARTIFACTS ===
+ # This section uploads all generated artifacts for use by downstream jobs.
+ # Downstream projects: Add any additional artifact uploads here.
- - name: Upload validation test results
+ - name: Upload validation artifacts
if: always()
uses: actions/upload-artifact@v7
with:
- name: integration-test-results-${{ matrix.os }}-dotnet${{ matrix.dotnet-version }}
- path: integration-test-*.trx
+ name: artifacts-validation-${{ matrix.os }}-dotnet${{ matrix.dotnet-version }}
+ path: artifacts/
# Builds the supporting documentation including user guides, requirements,
# trace matrices, code quality reports, and build notes.
@@ -340,32 +400,20 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
- - name: Download all test results
+ - name: Download all job artifacts
uses: actions/download-artifact@v8
with:
- path: test-results
- pattern: '*test-results*'
+ path: artifacts
+ pattern: 'artifacts-*'
+ merge-multiple: true
continue-on-error: true
- - name: Download ReqStream package
+ - name: Download packages artifact
uses: actions/download-artifact@v8
with:
- name: packages-windows-latest
+ name: packages-ubuntu-latest
path: packages
- - name: Download CodeQL SARIF
- uses: actions/download-artifact@v8
- with:
- name: codeql-sarif
- path: codeql-results
-
- - name: Download all version captures
- uses: actions/download-artifact@v8
- with:
- path: version-captures
- pattern: 'version-capture-*'
- continue-on-error: true
-
# === INSTALL DEPENDENCIES ===
# This section installs all required dependencies and tools for document generation.
# Downstream projects: Add any additional dependency installations here.
@@ -402,11 +450,32 @@ jobs:
- name: Capture tool versions for build-docs
shell: bash
run: |
+ mkdir -p artifacts
echo "Capturing tool versions..."
- dotnet versionmark --capture --job-id "build-docs" -- \
+ dotnet versionmark --capture --job-id "build-docs" \
+ --output "artifacts/versionmark-build-docs.json" -- \
dotnet git node npm pandoc weasyprint sarifmark sonarmark reqstream buildmark versionmark
echo "✓ Tool versions captured"
+ # === CAPTURE OTS SELF-VALIDATION RESULTS ===
+ # This section captures self-validation results from OTS tools.
+ # Downstream projects: Add any additional self-validation steps here.
+
+ - name: Run ReqStream self-validation
+ run: reqstream --validate --results artifacts/reqstream-self-validation.trx
+
+ - name: Run BuildMark self-validation
+ run: dotnet buildmark --validate --results artifacts/buildmark-self-validation.trx
+
+ - name: Run VersionMark self-validation
+ run: dotnet versionmark --validate --results artifacts/versionmark-self-validation.trx
+
+ - name: Run SarifMark self-validation
+ run: dotnet sarifmark --validate --results artifacts/sarifmark-self-validation.trx
+
+ - name: Run SonarMark self-validation
+ run: dotnet sonarmark --validate --results artifacts/sonarmark-self-validation.trx
+
# === GENERATE MARKDOWN REPORTS ===
# This section generates all markdown reports from various tools and sources.
# Downstream projects: Add any additional markdown report generation steps here.
@@ -415,7 +484,7 @@ jobs:
run: >
reqstream
--requirements requirements.yaml
- --tests "test-results/**/*.trx"
+ --tests "artifacts/**/*.trx"
--report docs/requirements/requirements.md
--justifications docs/justifications/justifications.md
--matrix docs/tracematrix/tracematrix.md
@@ -425,7 +494,7 @@ jobs:
shell: bash
run: >
dotnet sarifmark
- --sarif codeql-results/csharp.sarif
+ --sarif artifacts/csharp.sarif
--report docs/quality/codeql-quality.md
--heading "ReqStream CodeQL Analysis"
--report-depth 1
@@ -476,7 +545,7 @@ jobs:
run: |
echo "Publishing tool versions..."
dotnet versionmark --publish --report docs/buildnotes/versions.md --report-depth 1 \
- -- "versionmark-*.json" "version-captures/**/versionmark-*.json"
+ -- "artifacts/**/versionmark-*.json"
echo "✓ Tool versions published"
- name: Display Tool Versions Report
diff --git a/AGENTS.md b/AGENTS.md
index 64c1c2e..9676c4d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -19,7 +19,7 @@ written in YAML files.
## Key Files
- **`requirements.yaml`** - All requirements with test linkage (enforced via `dotnet reqstream --enforce`)
-- **`.editorconfig`** - Code style (file-scoped namespaces, 4-space indent, UTF-8+BOM, LF endings)
+- **`.editorconfig`** - Code style (file-scoped namespaces, 4-space indent, UTF-8, LF endings)
- **`.cspell.json`, `.markdownlint-cli2.jsonc`, `.yamllint.yaml`** - Linting configs
## Requirements
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e0460b0..459c02c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -80,7 +80,7 @@ This project follows the coding standards defined in `.editorconfig`. Key conven
- **Indentation**: 4 spaces for C#, 2 spaces for YAML/JSON/XML
- **Line endings**: LF (Unix-style)
-- **Encoding**: UTF-8 with BOM
+- **Encoding**: UTF-8
- **Braces**: Required for all control statements
- **Naming**:
- Interfaces: `IRequirementParser`
diff --git a/README.md b/README.md
index c6bd154..094df63 100644
--- a/README.md
+++ b/README.md
@@ -516,6 +516,8 @@ in this project you agree to abide by its terms.
This project is licensed under the MIT License - see the [LICENSE][license] file for details.
+By contributing to this project, you agree that your contributions will be licensed under the MIT License.
+
## Support
- 🐛 **[Report a Bug][bug-report]** - Found an issue? Let us know
diff --git a/requirements.yaml b/requirements.yaml
index 26a0b54..c16dffb 100644
--- a/requirements.yaml
+++ b/requirements.yaml
@@ -32,7 +32,7 @@ sections:
sections:
- title: Command-Line Interface
requirements:
- - id: CLI-001
+ - id: ReqStream-Cmd-Cli
title: The tool shall provide a command-line interface.
justification: |
A CLI interface enables automation in CI/CD pipelines and allows integration with scripts
@@ -43,7 +43,7 @@ sections:
- Context_Create_NoArguments_ReturnsDefaultContext
- Context_Create_MultipleArguments_ParsesAllCorrectly
- - id: CLI-002
+ - id: ReqStream-Cmd-Version
title: The tool shall display version information when requested.
justification: |
Version information is critical for debugging, support, and ensuring compatibility with
@@ -54,7 +54,7 @@ sections:
- Program_Run_WithVersionFlag_PrintsVersion
- Context_Create_VersionFlag_SetsVersionProperty
- - id: CLI-003
+ - id: ReqStream-Cmd-Help
title: The tool shall display help information when requested.
justification: |
Help information improves user experience and reduces the learning curve for new users by
@@ -65,9 +65,41 @@ sections:
- Program_Run_WithHelpFlag_PrintsHelp
- Context_Create_HelpFlags_SetsHelpProperty
+ - id: ReqStream-Cmd-ErrorOutput
+ title: The tool shall write error messages to stderr.
+ justification: |
+ Error messages must be written to stderr so they remain visible to the user
+ without polluting stdout, which consumers may pipe or redirect for data capture.
+ tags:
+ - cli
+ tests:
+ - Context_WriteError_NormalMode_WritesToConsole
+
+ - id: ReqStream-Cmd-InvalidArgs
+ title: The tool shall reject unknown or malformed command-line arguments with a descriptive error.
+ justification: |
+ Providing clear feedback for invalid arguments helps users quickly correct
+ mistakes and prevents silent misconfiguration.
+ tags:
+ - cli
+ tests:
+ - Context_Create_UnsupportedArgument_ThrowsException
+ - Context_Create_MissingLogFilename_ThrowsException
+ - Context_Create_MissingResultsFilename_ThrowsException
+
+ - id: ReqStream-Cmd-ExitCode
+ title: The tool shall return a non-zero exit code on failure.
+ justification: |
+ Callers (scripts, CI/CD pipelines) must be able to detect failure conditions
+ programmatically via the process exit code.
+ tags:
+ - cli
+ tests:
+ - Context_WriteError_NormalMode_WritesToConsole
+
- title: Requirements File Processing
requirements:
- - id: REQ-001
+ - id: ReqStream-Req-YamlProcessing
title: The tool shall process YAML requirements files.
justification: |
YAML provides a human-readable, version-control-friendly format for managing requirements.
@@ -79,7 +111,7 @@ sections:
- Program_Run_WithRequirementsFiles_ProcessesSuccessfully
- Requirements_Read_ComplexStructure_ParsesCorrectly
- - id: REQ-002
+ - id: ReqStream-Req-GlobPatterns
title: The tool shall support glob patterns for requirements files.
justification: |
Glob patterns enable flexible file selection and reduce the need for explicit file listing,
@@ -89,7 +121,7 @@ sections:
tests:
- Context_Create_WithRequirementsPattern_ExpandsGlobPattern
- - id: REQ-003
+ - id: ReqStream-Req-Validation
title: The tool shall validate requirements file structure.
justification: |
Early validation prevents runtime errors and ensures requirements data integrity, catching
@@ -103,7 +135,7 @@ sections:
- Requirements_Read_DuplicateRequirementId_ThrowsException
- Requirements_Read_DuplicateRequirementId_ExceptionIncludesFileLocation
- - id: REQ-004
+ - id: ReqStream-Req-Hierarchy
title: The tool shall support hierarchical sections and subsections.
justification: |
Hierarchical organization allows requirements to be grouped logically by system components,
@@ -114,7 +146,7 @@ sections:
- Requirements_Read_NestedSections_ParsesHierarchyCorrectly
- Requirements_Export_NestedSections_CreatesHierarchy
- - id: REQ-005
+ - id: ReqStream-Req-Includes
title: The tool shall support file includes in requirements files.
justification: |
File includes enable modular requirements management, allowing teams to organize requirements
@@ -126,7 +158,7 @@ sections:
- Requirements_Read_MultipleFiles_MergesAllFiles
- Requirements_Read_IncludeLoop_DoesNotCauseInfiniteLoop
- - id: REQ-006
+ - id: ReqStream-Req-SectionMerging
title: The tool shall merge sections with the same hierarchy path.
justification: |
Section merging allows multiple files to contribute to the same logical section, supporting
@@ -139,7 +171,7 @@ sections:
- title: Requirements Definition
requirements:
- - id: REQ-007
+ - id: ReqStream-Req-UniqueIds
title: The tool shall require each requirement to have a unique identifier.
justification: |
Unique identifiers enable unambiguous referencing of requirements in documentation, test
@@ -151,7 +183,7 @@ sections:
- Requirements_Read_BlankRequirementId_ThrowsExceptionWithFileLocation
- Requirements_Read_MultipleFilesWithDuplicateIds_ThrowsException
- - id: REQ-008
+ - id: ReqStream-Req-RequiredTitle
title: The tool shall require each requirement to have a title.
justification: |
Titles provide human-readable descriptions of requirements, making them understandable to
@@ -161,7 +193,7 @@ sections:
tests:
- Requirements_Read_BlankRequirementTitle_ThrowsExceptionWithFileLocation
- - id: REQ-009
+ - id: ReqStream-Req-ParentChild
title: The tool shall support parent-child relationships between requirements.
justification: |
Parent-child relationships enable hierarchical requirement decomposition, allowing high-level
@@ -172,7 +204,7 @@ sections:
- Requirements_Read_RequirementWithChildren_ParsesChildrenCorrectly
- TraceMatrix_Export_WithChildRequirements_ConsidersChildTests
- - id: REQ-010
+ - id: ReqStream-Req-TestMappings
title: The tool shall support test mappings for requirements.
justification: |
Test mappings establish traceability between requirements and tests, enabling verification
@@ -188,7 +220,7 @@ sections:
- title: Test Integration
requirements:
- - id: TEST-001
+ - id: ReqStream-Test-ResultFiles
title: The tool shall support processing test result files.
justification: |
Processing test results enables automated verification of requirement satisfaction and
@@ -200,7 +232,7 @@ sections:
- TraceMatrix_MissingFile_ThrowsFileNotFoundException
- TraceMatrix_WithMultipleFiles_AggregatesResults
- - id: TEST-002
+ - id: ReqStream-Test-TrxFormat
title: The tool shall support TRX format test results.
justification: |
TRX is the native test result format for .NET testing frameworks, enabling seamless
@@ -211,7 +243,7 @@ sections:
- TraceMatrix_WithTrxFile_ParsesCorrectly
- TraceMatrix_WithFailedTests_TracksFailures
- - id: TEST-003
+ - id: ReqStream-Test-JUnitFormat
title: The tool shall support JUnit format test results.
justification: |
JUnit format is widely used across multiple programming ecosystems, enabling cross-platform
@@ -222,7 +254,7 @@ sections:
- TraceMatrix_WithJUnitFile_ParsesCorrectly
- TraceMatrix_WithJUnitFailedTests_TracksFailures
- - id: TEST-004
+ - id: ReqStream-Test-GlobPatterns
title: The tool shall support glob patterns for test result files.
justification: |
Glob patterns simplify specification of multiple test result files and enable flexible
@@ -233,7 +265,7 @@ sections:
- Context_Create_WithTestsPattern_ExpandsGlobPattern
- TraceMatrix_WithMixedFormats_ProcessesBoth
- - id: TEST-005
+ - id: ReqStream-Test-SourceFiltering
title: The tool shall support source-specific test matching using filepart@testname pattern.
justification: |
Source-specific matching enables requirements to reference tests from specific test runs
@@ -245,7 +277,7 @@ sections:
- TraceMatrix_WithSourceSpecificTests_DoesNotMatchOtherSources
- TraceMatrix_WithMultipleSourceSpecifiers_MatchesAllRequirements
- - id: TEST-006
+ - id: ReqStream-Test-CaseInsensitive
title: >-
The tool shall perform case-insensitive matching of file parts in source-specific
test names.
@@ -257,7 +289,7 @@ sections:
tests:
- TraceMatrix_WithSourceSpecificTests_IsCaseInsensitive
- - id: TEST-007
+ - id: ReqStream-Test-PartialFilenames
title: The tool shall support partial filename matching for source-specific tests.
justification: |
Partial matching simplifies test specification by allowing short, memorable identifiers
@@ -267,7 +299,7 @@ sections:
tests:
- TraceMatrix_WithSourceSpecificTests_MatchesPartialFilename
- - id: TEST-008
+ - id: ReqStream-Test-PlainTestNames
title: The tool shall support plain test names that aggregate from all sources.
justification: |
Plain test names enable requirements to aggregate test results across all platforms and
@@ -277,7 +309,7 @@ sections:
tests:
- TraceMatrix_WithPlainTestNames_MatchesAllSources
- - id: TEST-009
+ - id: ReqStream-Test-MixedTestNames
title: >-
The tool shall support mixing plain and source-specific test names in the same
requirement.
@@ -289,7 +321,7 @@ sections:
tests:
- TraceMatrix_WithMixedTestNames_MatchesAppropriately
- - id: TEST-010
+ - id: ReqStream-Test-MultipleRequirements
title: >-
The tool shall match tests to multiple requirements with mixed filter
references.
@@ -303,7 +335,7 @@ sections:
- title: Reporting
requirements:
- - id: RPT-001
+ - id: ReqStream-Rpt-MarkdownExport
title: The tool shall export requirements to markdown format.
justification: |
Markdown export enables requirements to be included in documentation, wikis, and other
@@ -316,7 +348,7 @@ sections:
- Requirements_Export_MultipleSections_ExportsAll
- Requirements_Export_EmptyRequirements_CreatesEmptyFile
- - id: RPT-002
+ - id: ReqStream-Rpt-HeaderDepth
title: The tool shall support configurable markdown header depth for requirements reports.
justification: |
Configurable header depth allows requirements reports to be embedded in larger documents
@@ -327,7 +359,7 @@ sections:
- Context_Create_ReportDepth_SetsReportDepthProperty
- Requirements_Export_WithCustomDepth_UsesCorrectHeaderLevel
- - id: RPT-003
+ - id: ReqStream-Rpt-TraceMatrix
title: The tool shall export trace matrices to markdown format.
justification: |
Trace matrix export provides visibility into test coverage and requirement satisfaction,
@@ -341,7 +373,7 @@ sections:
- TraceMatrix_Export_WithNoTests_ShowsNotSatisfied
- TraceMatrix_Export_WithNotExecutedTests_ShowsNotExecuted
- - id: RPT-004
+ - id: ReqStream-Rpt-TraceMatrixDepth
title: The tool shall support configurable markdown header depth for trace matrices.
justification: |
Configurable header depth allows trace matrices to be embedded in larger documents while
@@ -352,7 +384,7 @@ sections:
- Context_Create_MatrixDepth_SetsMatrixDepthProperty
- Requirements_Export_WithCustomDepth_UsesCorrectHeaderLevel
- - id: RPT-005
+ - id: ReqStream-Rpt-TagFiltering
title: The tool shall support filtering requirements by tags.
justification: |
Tag-based filtering enables selective export of requirement subsets for focused reports,
@@ -370,7 +402,7 @@ sections:
- TraceMatrix_CalculateSatisfiedRequirements_WithFilterTags_CountsOnlyMatchingRequirements
- TraceMatrix_GetUnsatisfiedRequirements_WithFilterTags_ReturnsOnlyMatchingRequirements
- - id: RPT-006
+ - id: ReqStream-Rpt-Justifications
title: The tool shall export requirement justifications to markdown format.
justification: |
Justification export enables stakeholders to understand the rationale behind
@@ -382,7 +414,7 @@ sections:
- Requirements_ExportJustifications_WithoutJustifications_CreatesHeadersOnly
- Requirements_ExportJustifications_NestedSections_CreatesHierarchy
- - id: RPT-007
+ - id: ReqStream-Rpt-JustificationsDepth
title: >-
The tool shall support configurable markdown header depth for justification
reports.
@@ -396,7 +428,7 @@ sections:
- title: Logging
requirements:
- - id: LOG-001
+ - id: ReqStream-Log-FileOutput
title: The tool shall support writing output to a log file.
justification: |
Log file support enables capturing tool output for debugging, audit trails, and CI/CD
@@ -410,7 +442,7 @@ sections:
- title: Validation
requirements:
- - id: VAL-001
+ - id: ReqStream-Val-SelfValidation
title: The tool shall support self-validation mode.
justification: |
Self-validation ensures the tool's own integrity and serves as a smoke test for
@@ -421,7 +453,7 @@ sections:
- Program_Run_WithValidateFlag_RunsValidation
- Context_Create_ValidateFlag_SetsValidateProperty
- - id: VAL-002
+ - id: ReqStream-Val-EnforcementMode
title: >-
The tool shall support enforcement mode to fail when requirements are
not fully tested.
@@ -440,7 +472,7 @@ sections:
- title: Platform Support
requirements:
- - id: PLT-001
+ - id: ReqStream-Plt-Windows
title: The tool shall run on Windows operating systems.
justification: |
Windows support is essential for .NET developers who primarily work in Windows environments
@@ -454,7 +486,7 @@ sections:
- "windows@ReqStream_TagsFiltering"
- "windows@ReqStream_EnforcementMode"
- - id: PLT-002
+ - id: ReqStream-Plt-Linux
title: The tool shall run on Linux operating systems.
justification: |
Linux support enables use in containerized CI/CD environments and cloud-based build systems
@@ -468,7 +500,7 @@ sections:
- "ubuntu@ReqStream_TagsFiltering"
- "ubuntu@ReqStream_EnforcementMode"
- - id: PLT-004
+ - id: ReqStream-Plt-Net8
title: The tool shall support .NET 8.0 runtime.
justification: |
.NET 8.0 is an LTS release, providing long-term stability and support for enterprise users.
@@ -481,7 +513,7 @@ sections:
- "dotnet8.x@ReqStream_TagsFiltering"
- "dotnet8.x@ReqStream_EnforcementMode"
- - id: PLT-005
+ - id: ReqStream-Plt-Net9
title: The tool shall support .NET 9.0 runtime.
justification: |
.NET 9.0 support enables users to leverage the latest .NET features and performance
@@ -495,7 +527,7 @@ sections:
- "dotnet9.x@ReqStream_TagsFiltering"
- "dotnet9.x@ReqStream_EnforcementMode"
- - id: PLT-006
+ - id: ReqStream-Plt-Net10
title: The tool shall support .NET 10.0 runtime.
justification: |
.NET 10.0 support ensures the tool remains compatible with the latest .NET ecosystem and
@@ -508,3 +540,84 @@ sections:
- "dotnet10.x@ReqStream_ReportExport"
- "dotnet10.x@ReqStream_TagsFiltering"
- "dotnet10.x@ReqStream_EnforcementMode"
+
+ - title: OTS Software
+ requirements:
+ - id: ReqStream-OTS-MSTest
+ title: MSTest shall execute unit tests and report results.
+ justification: |
+ MSTest (MSTest.TestFramework and MSTest.TestAdapter) is the unit-testing framework used
+ by the project. It discovers and runs all test methods and writes TRX result files that
+ feed into coverage reporting and requirements traceability. Passing tests confirm the
+ framework is functioning correctly.
+ tags: [ots]
+ tests:
+ - Context_Create_NoArguments_ReturnsDefaultContext
+ - Context_Create_VersionFlag_SetsVersionProperty
+ - Context_Create_HelpFlags_SetsHelpProperty
+ - Context_Create_ValidateFlag_SetsValidateProperty
+ - Context_Create_EnforceFlag_SetsEnforceProperty
+ - Requirements_Read_SimpleRequirement_ParsesCorrectly
+ - Program_Run_WithVersionFlag_PrintsVersion
+ - Program_Run_WithHelpFlag_PrintsHelp
+
+ - id: ReqStream-OTS-ReqStream
+ title: ReqStream shall enforce that every requirement is linked to passing test evidence.
+ justification: |
+ DemaConsulting.ReqStream processes requirements.yaml and the TRX test-result files to
+ produce a requirements report, justifications document, and traceability matrix. When
+ run with --enforce, it exits with a non-zero code if any requirement lacks test evidence,
+ making unproven requirements a build-breaking condition. A successful pipeline run with
+ --enforce proves all requirements are covered and that ReqStream is functioning.
+ tags: [ots]
+ tests:
+ - ReqStream_EnforcementMode
+
+ - id: ReqStream-OTS-BuildMark
+ title: BuildMark shall generate build-notes documentation from GitHub Actions metadata.
+ justification: |
+ DemaConsulting.BuildMark queries the GitHub API to capture workflow run details and
+ renders them as a markdown build-notes document included in the release artifacts.
+ It runs as part of the same CI pipeline that produces the TRX test results, so a
+ successful pipeline run is evidence that BuildMark executed without error.
+ tags: [ots]
+ tests:
+ - BuildMark_MarkdownReportGeneration
+
+ - id: ReqStream-OTS-VersionMark
+ title: VersionMark shall publish captured tool-version information.
+ justification: |
+ DemaConsulting.VersionMark reads version metadata for each dotnet tool used in the
+ pipeline and writes a versions markdown document included in the release artifacts.
+ It runs in the same CI pipeline that produces the TRX test results, so a successful
+ pipeline run is evidence that VersionMark executed without error.
+ tags: [ots]
+ tests:
+ - VersionMark_CapturesVersions
+ - VersionMark_GeneratesMarkdownReport
+
+ - id: ReqStream-OTS-SarifMark
+ title: SarifMark shall convert CodeQL SARIF results into a markdown report.
+ justification: |
+ DemaConsulting.SarifMark reads the SARIF output produced by CodeQL code scanning and
+ renders it as a human-readable markdown document included in the release artifacts.
+ It runs in the same CI pipeline that produces the TRX test results, so a successful
+ pipeline run is evidence that SarifMark executed without error.
+ tags: [ots]
+ tests:
+ - SarifMark_SarifReading
+ - SarifMark_MarkdownReportGeneration
+
+ - id: ReqStream-OTS-SonarMark
+ title: SonarMark shall generate a SonarCloud quality report.
+ justification: |
+ DemaConsulting.SonarMark retrieves quality-gate and metrics data from SonarCloud and
+ renders it as a markdown document included in the release artifacts. It runs in the
+ same CI pipeline that produces the TRX test results, so a successful pipeline run is
+ evidence that SonarMark executed without error.
+ tags: [ots]
+ tests:
+ - SonarMark_QualityGateRetrieval
+ - SonarMark_IssuesRetrieval
+ - SonarMark_HotSpotsRetrieval
+ - SonarMark_MarkdownReportGeneration
diff --git a/src/DemaConsulting.ReqStream/Context.cs b/src/DemaConsulting.ReqStream/Context.cs
index a216a2a..a3551c2 100644
--- a/src/DemaConsulting.ReqStream/Context.cs
+++ b/src/DemaConsulting.ReqStream/Context.cs
@@ -353,7 +353,7 @@ public static Context Create(string[] args)
{
try
{
- result._logWriter = new StreamWriter(logFile, append: false);
+ result._logWriter = new StreamWriter(logFile, append: false) { AutoFlush = true };
}
catch (Exception ex)
{
@@ -415,7 +415,7 @@ public void WriteError(string message)
{
var previousColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine(message);
+ Console.Error.WriteLine(message);
Console.ForegroundColor = previousColor;
}
diff --git a/src/DemaConsulting.ReqStream/DemaConsulting.ReqStream.csproj b/src/DemaConsulting.ReqStream/DemaConsulting.ReqStream.csproj
index 9c61e99..c58abe8 100644
--- a/src/DemaConsulting.ReqStream/DemaConsulting.ReqStream.csproj
+++ b/src/DemaConsulting.ReqStream/DemaConsulting.ReqStream.csproj
@@ -46,19 +46,27 @@
Organization: $(Company)
+
-
+
+
+
+
-
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -67,11 +75,6 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
diff --git a/src/DemaConsulting.ReqStream/Program.cs b/src/DemaConsulting.ReqStream/Program.cs
index b84ce08..4e1067e 100644
--- a/src/DemaConsulting.ReqStream/Program.cs
+++ b/src/DemaConsulting.ReqStream/Program.cs
@@ -62,19 +62,19 @@ private static int Main(string[] args)
catch (ArgumentException ex)
{
// Print expected argument exceptions and return error code
- Console.WriteLine($"Error: {ex.Message}");
+ Console.Error.WriteLine($"Error: {ex.Message}");
return 1;
}
catch (InvalidOperationException ex)
{
// Print expected operation exceptions and return error code
- Console.WriteLine($"Error: {ex.Message}");
+ Console.Error.WriteLine($"Error: {ex.Message}");
return 1;
}
catch (Exception ex)
{
// Print unexpected exceptions and re-throw to generate event logs
- Console.WriteLine($"Unexpected error: {ex.Message}");
+ Console.Error.WriteLine($"Unexpected error: {ex.Message}");
throw;
}
}
diff --git a/test/DemaConsulting.ReqStream.Tests/ContextTests.cs b/test/DemaConsulting.ReqStream.Tests/ContextTests.cs
index f61fd43..1a47407 100644
--- a/test/DemaConsulting.ReqStream.Tests/ContextTests.cs
+++ b/test/DemaConsulting.ReqStream.Tests/ContextTests.cs
@@ -353,9 +353,9 @@ public void Context_WriteLine_SilentMode_DoesNotWriteToConsole()
[TestMethod]
public void Context_WriteError_NormalMode_WritesToConsole()
{
- var originalOut = Console.Out;
+ var originalError = Console.Error;
using var output = new StringWriter();
- Console.SetOut(output);
+ Console.SetError(output);
try
{
@@ -367,7 +367,7 @@ public void Context_WriteError_NormalMode_WritesToConsole()
}
finally
{
- Console.SetOut(originalOut);
+ Console.SetError(originalError);
}
}
@@ -377,9 +377,9 @@ public void Context_WriteError_NormalMode_WritesToConsole()
[TestMethod]
public void Context_WriteError_SilentMode_DoesNotWriteToConsole()
{
- var originalOut = Console.Out;
+ var originalError = Console.Error;
using var output = new StringWriter();
- Console.SetOut(output);
+ Console.SetError(output);
try
{
@@ -391,7 +391,7 @@ public void Context_WriteError_SilentMode_DoesNotWriteToConsole()
}
finally
{
- Console.SetOut(originalOut);
+ Console.SetError(originalError);
}
}
diff --git a/test/DemaConsulting.ReqStream.Tests/DemaConsulting.ReqStream.Tests.csproj b/test/DemaConsulting.ReqStream.Tests/DemaConsulting.ReqStream.Tests.csproj
index 5f26690..ca0eef7 100644
--- a/test/DemaConsulting.ReqStream.Tests/DemaConsulting.ReqStream.Tests.csproj
+++ b/test/DemaConsulting.ReqStream.Tests/DemaConsulting.ReqStream.Tests.csproj
@@ -3,7 +3,7 @@
net8.0;net9.0;net10.0
- 12
+ latest
enable
enable
diff --git a/test/DemaConsulting.ReqStream.Tests/ProgramTests.cs b/test/DemaConsulting.ReqStream.Tests/ProgramTests.cs
index 4815102..5e34bf8 100644
--- a/test/DemaConsulting.ReqStream.Tests/ProgramTests.cs
+++ b/test/DemaConsulting.ReqStream.Tests/ProgramTests.cs
@@ -489,32 +489,35 @@ public void Program_Run_WithEnforcementAndUnsatisfiedRequirements_Fails()
// Save current directory and change to test directory
var originalDir = Directory.GetCurrentDirectory();
- var originalOut = Console.Out;
- using var output = new StringWriter();
- Console.SetOut(output);
+ var logFile = Path.Combine(_testDirectory, "enforcement-test.log");
try
{
Directory.SetCurrentDirectory(_testDirectory);
- using var context = Context.Create([
+ int exitCode;
+ using (var context = Context.Create([
"--requirements", "*.yaml",
"--tests", "*.trx",
- "--enforce"
- ]);
- Program.Run(context);
-
- Assert.AreEqual(1, context.ExitCode);
-
- // Verify error message includes the unsatisfied requirement
- var outputText = output.ToString();
- Assert.Contains("Only 1 of 2 requirements are satisfied", outputText);
- Assert.Contains("Unsatisfied requirements:", outputText);
- Assert.Contains("REQ-002", outputText);
+ "--enforce",
+ "--silent",
+ "--log", logFile
+ ]))
+ {
+ Program.Run(context);
+ exitCode = context.ExitCode;
+ }
+
+ Assert.AreEqual(1, exitCode);
+
+ // Verify error message includes the unsatisfied requirement via log file
+ var logContent = File.ReadAllText(logFile);
+ Assert.Contains("Only 1 of 2 requirements are satisfied", logContent);
+ Assert.Contains("Unsatisfied requirements:", logContent);
+ Assert.Contains("REQ-002", logContent);
}
finally
{
- Console.SetOut(originalOut);
Directory.SetCurrentDirectory(originalDir);
}
}