Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Options:
--tests <pattern> Test result files glob pattern (TRX or JUnit)
--matrix <file> Export trace matrix to markdown file
--matrix-depth <depth> Markdown header depth for trace matrix (overrides --depth)
--matrix-titles Include requirement titles as a column in the trace matrix
--justifications <file> Export requirement justifications to markdown file
--justifications-depth <depth> Markdown header depth for justifications (overrides --depth)
--filter <tags> Comma-separated list of tags to filter requirements
Expand Down
2 changes: 1 addition & 1 deletion docs/design/reqstream.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ to produce output.
- *Role*: Consumer (the user provides arguments to the system).
- *Contract*: Defined flag set (`--version`/`-v`, `--help`/`-h`/`-?`, `--silent`, `--validate`,
`--lint`, `--enforce`, `--requirements`, `--tests`, `--report`, `--matrix`, `--justifications`,
`--filter`, `--root-tags`, `--depth`, `--report-depth`, `--matrix-depth`,
`--filter`, `--root-tags`, `--depth`, `--report-depth`, `--matrix-depth`, `--matrix-titles`,
`--justifications-depth`, `--results`/`--result`, `--log`); unknown flags cause
`ArgumentException`.
- *Constraints*: No interactive prompts; all information must be on the command line.
Expand Down
2 changes: 1 addition & 1 deletion docs/design/reqstream/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The `Cli` subsystem contains the following software unit:
**Context properties**: Parsed flags and file lists (`Version`, `Help`, `Silent`, `Validate`,
`Lint`, `Enforce`, `RequirementsFiles`, `TestFiles`, `RequirementsReport`, `Matrix`,
`JustificationsFile`, `ResultsFile`, `FilterTags`, `RootTags`, `Depth`, `ReportDepth`,
`MatrixDepth`, `JustificationsDepth`, `ExitCode`).
`MatrixDepth`, `MatrixTitles`, `JustificationsDepth`, `ExitCode`).

- *Type*: In-process .NET public API (read-only properties).
- *Role*: Provider.
Expand Down
3 changes: 3 additions & 0 deletions docs/design/reqstream/cli/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ not specified.

**`MatrixDepth`**: `int` — Heading depth for trace matrix report; defaults to `Depth`.

**`MatrixTitles`**: `bool` — `true` when `--matrix-titles` was specified; when `true`, the trace
matrix Requirements table includes an additional "Title" column.

**`JustificationsFile`**: `string?` — Destination path for justifications report
(`--justifications`).

Expand Down
3 changes: 2 additions & 1 deletion docs/design/reqstream/program.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ non-lint) run.
- If `context.JustificationsFile` is set, `requirements.ExportJustifications` is called to
produce the justifications report before the trace matrix is constructed.
- Constructs a `TraceMatrix` if `context.TestFiles` is non-empty; exports the matrix if
`context.Matrix` is set.
`context.Matrix` is set, passing `context.MatrixTitles` through to `TraceMatrix.Export` so the
requirement-title column is included when `--matrix-titles` was specified.
- If `context.Matrix` is set and `context.TestFiles` is empty, writes an error via
`context.WriteError` and returns without constructing a `TraceMatrix`.
- Computes the merged root-tag set (`requirements.RootTags` combined with `context.RootTags`).
Expand Down
5 changes: 4 additions & 1 deletion docs/design/reqstream/self-test/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ Prints a header block (version, machine name, OS, .NET runtime, UTC timestamp),
tests sequentially, and prints a multi-line summary. The seven tests:

1. `RunRequirementsProcessingTest` — verifies YAML files are read, merged, and exported.
2. `RunTraceMatrixTest` — verifies test results are loaded and mapped to requirements.
2. `RunTraceMatrixTest` — verifies test results are loaded and mapped to requirements. Before
comparing content, the generated matrix is normalized by stripping U+200B (zero-width space)
characters that `TraceMatrix.Export` inserts after hyphens/underscores for PDF/Markdown line
wrapping, so the test isn't coupled to that cosmetic detail.
3. `RunReportExportTest` — verifies requirements and justifications reports are written.
4. `RunTagsFilteringTest` — verifies tag-based filtering restricts output and coverage.
5. `RunEnforcementModeTest` — verifies `--enforce` produces non-zero exit code on failure.
Expand Down
6 changes: 4 additions & 2 deletions docs/design/reqstream/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ The `Tracing` subsystem contains the following software unit:

- *Type*: In-process .NET public API.
- *Role*: Provider.
- *Contract*: Accepts `filePath`, `depth`, and optional `filterTags`; writes a Markdown report
with Summary, Requirements, and Testing sections. The `depth` parameter sets the starting
- *Contract*: Accepts `filePath`, `depth`, optional `filterTags`, and an optional
`includeTitles` flag (default `false`); writes a Markdown report with Summary, Requirements,
and Testing sections. When `includeTitles` is `true`, the Requirements table includes an
additional "Title" column. The `depth` parameter sets the starting
Markdown heading level (ATX `#` count) for the report; when omitted the default is 1
(top-level `#` headings). Only a lower bound of 1 is enforced — nested requirement sections
increase the heading level further for each level of nesting and are not capped at the
Expand Down
39 changes: 35 additions & 4 deletions docs/design/reqstream/tracing/trace-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,44 @@ case-insensitively against each `TestExecution.FileBaseName` for source-specific
- *Preconditions*: None.
- *Postconditions*: None (read-only).

**Export(filePath, depth, filterTags)**: Writes the trace matrix to a Markdown file with three
sections: Summary, Requirements, and Testing.

- *Parameters*: `string filePath`; `int depth` (minimum value: 1); `HashSet<string>? filterTags`.
**Export(filePath, depth, filterTags)** / **Export(filePath, depth, filterTags, includeTitles)**:
Writes the trace matrix to a Markdown file with three sections: Summary, Requirements, and
Testing. Exposed as two public overloads:

- `Export(string filePath, int depth = 1, HashSet<string>? filterTags = null)` — the original,
binary-compatibility-preserving overload. Delegates directly to the four-parameter overload
with `includeTitles: false`, reproducing the exact original behavior (no "Title" column).
- `Export(string filePath, int depth, HashSet<string>? filterTags, bool includeTitles)` — the
implementation overload. `depth` and `filterTags` are required (no defaults) on this overload
specifically to avoid overload-resolution ambiguity with the three-parameter overload; callers
needing the `includeTitles` behavior must supply all four arguments, exactly as `Program` does.

- *Parameters*: `string filePath`; `int depth` (minimum value: 1); `HashSet<string>? filterTags`;
`bool includeTitles` (four-parameter overload only).
- *Returns*: `void`.
- *Preconditions*: `filePath` must not be null or empty; `depth` must be at least 1.
- *Postconditions*: Markdown file written.
- *Note — Title column*: When `includeTitles` is `true`, the Requirements table gains an
additional "Title" column (between ID and Tests Linked) showing each requirement's
`Title` value. When `false` (the default), the table is emitted with its original column
structure unchanged.
- *Note — soft-break insertion is unconditional*: `Export` applies the private
`InsertSoftBreaks` helper, which inserts a zero-width space (`'\u200B'`) immediately after
every `-` and `_` character, to `requirement.Id` in the Requirements table and to
`testName`/`reqId` in the Testing table **unconditionally** — regardless of the
`includeTitles` value — and to `requirement.Title` only when `includeTitles` is `true`. This
is a deliberate, permanent design decision, not a defect: long underscore-joined test names
and hyphenated requirement IDs can overflow the rendered table width in generated PDFs even
when no Title column is present at all, so the soft-break insertion on IDs/test names must
not be gated behind `includeTitles`. The zero-width space gives PDF renderers a valid
line-break opportunity for long identifier-like values without altering the visible text.
- *Note — `EscapeTableCell` contract*: Requirement titles are passed through the private
`EscapeTableCell` helper before being written into the Title column. It (1) escapes a literal
backslash (`\`) as `\\` **before** escaping a literal pipe (`|`) as `\|` — this order is
mandatory so that a pre-existing literal `\|` sequence round-trips correctly as `\\\|` instead
of being corrupted — and (2) normalizes embedded line breaks (`\r\n`, `\r`, `\n`) to a single
space each, so a multi-line title (for example from a YAML block-scalar) cannot split a
Markdown table row across multiple lines.
- *Note — Summary vs. Requirements asymmetry*: The **Summary** section counts satisfied
requirements by calling `CalculateSatisfiedRequirements`, which delegates to
`IsRequirementSatisfied`. That method recurses through the full descendant subtree via
Expand Down
1 change: 1 addition & 0 deletions docs/reqstream/reqstream/cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ sections:
- ReqStream-Command-ReportDepth
- ReqStream-Command-Matrix
- ReqStream-Command-MatrixDepth
- ReqStream-Command-MatrixTitles
- ReqStream-Command-Justifications
- ReqStream-Command-JustificationsDepth
- ReqStream-Command-Depth
Expand Down
10 changes: 10 additions & 0 deletions docs/reqstream/reqstream/cli/context.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,16 @@ sections:
tests:
- Context_Create_MatrixDepth_SetsMatrixDepthProperty

- id: ReqStream-Command-MatrixTitles
title: The tool shall accept a `--matrix-titles` flag to include requirement titles as a column in the trace
matrix.
justification: |
An opt-in title column lets readers identify requirements by their title text directly
from the trace matrix without cross-referencing the requirements report.
tags: [cli]
tests:
- Context_Create_MatrixTitlesFlag_SetsMatrixTitlesProperty

- id: ReqStream-Command-Depth
title: The tool shall support a default markdown header depth that applies to all reports.
justification: |
Expand Down
1 change: 1 addition & 0 deletions docs/reqstream/reqstream/program.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ sections:
- Program_Run_WithRequirementsFiles_ProcessesSuccessfully
- Program_Run_WithRequirementsExport_GeneratesReport
- Program_Run_WithTraceMatrixExport_GeneratesMatrix
- Program_Run_WithMatrixTitlesFlag_IncludesTitleColumn
- Program_Run_WithJustificationsExport_GeneratesJustificationsReport

- id: ReqStream-Program-Enforce
Expand Down
1 change: 1 addition & 0 deletions docs/reqstream/reqstream/tracing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ sections:
children:
- ReqStream-Report-TraceMatrix
- ReqStream-Report-TraceMatrixDepth
- ReqStream-Report-TraceMatrixTitles
- ReqStream-Report-TagFiltering
11 changes: 11 additions & 0 deletions docs/reqstream/reqstream/tracing/trace-matrix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ sections:
tests:
- TraceMatrix_Export_WithCustomDepth_UsesCorrectHeaderLevel

- id: ReqStream-Report-TraceMatrixTitles
title: The tool shall support including requirement titles as an optional column in the trace matrix Requirements
table.
justification: |
An opt-in title column lets readers identify requirements by their title text directly
from the trace matrix without cross-referencing the requirements report.
tags: [reporting]
tests:
- TraceMatrix_Export_WithIncludeTitlesTrue_AddsTitleColumn
- TraceMatrix_Export_WithIncludeTitlesFalse_OmitsTitleColumn

- id: ReqStream-Report-TagFiltering
title: The tool shall support filtering trace matrix output by requirement tags.
justification: |
Expand Down
5 changes: 5 additions & 0 deletions docs/user_guide/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ ReqStream supports the following command-line options:
| `--tests <pattern>` | Glob pattern for test result files (TRX or JUnit format) |
| `--matrix <file>` | Export trace matrix to markdown file |
| `--matrix-depth <depth>` | Starting header depth for trace matrix (overrides `--depth`) |
| `--matrix-titles` | Include requirement titles as a column in the trace matrix |
| `--justifications <file>` | Export justifications to markdown file |
| `--justifications-depth <depth>` | Starting header depth for justifications (overrides `--depth`) |
| `--enforce` | Fail if requirements are not fully tested or are orphaned (when root tags are configured) |
Expand Down Expand Up @@ -835,6 +836,10 @@ The trace matrix includes:
- Test status (Passed, Failed, Skipped) from test results
- Coverage analysis

By default, the Requirements table lists each requirement's ID alongside its test statistics. Pass
`--matrix-titles` to add an additional "Title" column showing each requirement's title text
directly in the table, without needing to cross-reference a separate requirements report.

**Example trace matrix output:**

```markdown
Expand Down
2 changes: 2 additions & 0 deletions docs/verification/reqstream/cli/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ flags set the corresponding properties. This scenario is tested by
`Context_Create_ResultsFlag_SetsResultsFileProperty`, `Context_Create_ResultFlag_SetsResultsFileProperty`,
`Context_Create_ReportFile_SetsReportProperty`, `Context_Create_MissingReportFilename_ThrowsException`,
`Context_Create_MatrixFile_SetsMatrixProperty`, `Context_Create_MissingMatrixFilename_ThrowsException`,
`Context_Create_MatrixTitlesFlag_SetsMatrixTitlesProperty`,
`Context_Create_JustificationsFile_SetsJustificationsFileProperty`, and
`Context_Create_MissingJustificationsFilename_ThrowsException`.

Expand Down Expand Up @@ -138,6 +139,7 @@ coverage:
| `ReqStream-Command-Report` | Results and Report Flags Scenario | `Context_Create_MissingReportFilename_ThrowsException` |
| `ReqStream-Command-Matrix` | Results and Report Flags Scenario | `Context_Create_MatrixFile_SetsMatrixProperty` |
| `ReqStream-Command-Matrix` | Results and Report Flags Scenario | `Context_Create_MissingMatrixFilename_ThrowsException` |
| `ReqStream-Command-MatrixTitles` | Results and Report Flags Scenario | `Context_Create_MatrixTitlesFlag_SetsMatrixTitlesProperty` |
| `ReqStream-Command-Justifications` | Results and Report Flags Scenario | `Context_Create_JustificationsFile_SetsJustificationsFileProperty` |
| `ReqStream-Command-Justifications` | Results and Report Flags Scenario | `Context_Create_MissingJustificationsFilename_ThrowsException` |
| `ReqStream-Command-JustificationsDepth` | Depth Flags Scenario | `Context_Create_JustificationsDepth_SetsJustificationsDepthProperty` |
Expand Down
8 changes: 5 additions & 3 deletions docs/verification/reqstream/program.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ which asserts an informational message when no files are provided;
`Program_Run_WithRequirementsFiles_ProcessesSuccessfully`, which asserts processing succeeds;
`Program_Run_WithRequirementsExport_GeneratesReport`, which asserts a requirements report is
generated; `Program_Run_WithTraceMatrixExport_GeneratesMatrix`, which asserts a trace matrix is
generated; and `Program_Run_WithJustificationsExport_GeneratesJustificationsReport`, which
asserts a justifications report.
generated; `Program_Run_WithMatrixTitlesFlag_IncludesTitleColumn`, which asserts the
`--matrix-titles` flag produces a Title column in the generated trace matrix end-to-end; and
`Program_Run_WithJustificationsExport_GeneratesJustificationsReport`, which asserts a
justifications report.

**Matrix Without Tests**: Tests verify that requesting `--matrix` without providing test files
produces an error. This scenario is tested by
Expand Down Expand Up @@ -98,7 +100,7 @@ regression). This scenario is tested by
| `ReqStream-Program-Version` | `Program_Run_WithVersionFlag_PrintsVersion` |
| `ReqStream-Program-Help` | `Program_Run_WithHelpFlag_PrintsHelp` |
| `ReqStream-Program-Validate` | `Program_Run_WithValidateFlag_RunsValidation`, `Program_Run_WithValidateAndResults_WritesResultsFile` |
| `ReqStream-Program-Requirements` | `Program_Run_WithNoRequirementsFiles_ShowsMessage`, `Program_Run_WithRequirementsFiles_ProcessesSuccessfully`, `Program_Run_WithRequirementsExport_GeneratesReport`, `Program_Run_WithTraceMatrixExport_GeneratesMatrix`, `Program_Run_WithJustificationsExport_GeneratesJustificationsReport` |
| `ReqStream-Program-Requirements` | `Program_Run_WithNoRequirementsFiles_ShowsMessage`, `Program_Run_WithRequirementsFiles_ProcessesSuccessfully`, `Program_Run_WithRequirementsExport_GeneratesReport`, `Program_Run_WithTraceMatrixExport_GeneratesMatrix`, `Program_Run_WithMatrixTitlesFlag_IncludesTitleColumn`, `Program_Run_WithJustificationsExport_GeneratesJustificationsReport` |
| `ReqStream-Program-MatrixNoTests` | `Program_Run_WithMatrixButNoTestFiles_ReportsError`, `Program_Run_WithMatrixAndUnmatchedTestsPattern_ReportsError` |
| `ReqStream-Program-Enforce` | `Program_Run_WithEnforcementAndFullySatisfiedRequirements_Succeeds`, `Program_Run_WithEnforcementAndUnsatisfiedRequirements_Fails`, `Program_Run_WithEnforcementAndNoTests_Fails`, `Program_Run_WithEnforcementAndFailedTests_Fails` |
| `ReqStream-Program-Lint` | `Program_Run_WithLintFlag_RunsLinter` |
Expand Down
21 changes: 18 additions & 3 deletions docs/verification/reqstream/tracing/trace-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,29 @@ mixed filter and plain references. This scenario is tested by

**Export**: Tests verify Markdown trace matrix export for simple matrices, matrices with failed
tests, matrices with no tests, matrices with not-executed tests, custom heading depth, tag
filtering, child requirements, and tag-filtered counts and unsatisfied requirement retrieval.
filtering, child requirements, tag-filtered counts and unsatisfied requirement retrieval, the
optional Title column, and zero-width-space soft-break insertion for identifier-like values.
This scenario is tested by `TraceMatrix_Export_SimpleTraceMatrix_CreatesMarkdownFile`,
`TraceMatrix_Export_WithFailedTests_ShowsFailures`,
`TraceMatrix_Export_WithNoTests_ShowsNotSatisfied`,
`TraceMatrix_Export_WithNotExecutedTests_ShowsNotExecuted`,
`TraceMatrix_Export_WithCustomDepth_UsesCorrectHeaderLevel`,
`TraceMatrix_Export_WithFilterTags_ExportsOnlyMatchingRequirements`,
`TraceMatrix_Export_WithChildRequirements_ConsidersChildTests`,
`TraceMatrix_CalculateSatisfiedRequirements_WithFilterTags_CountsOnlyMatchingRequirements`, and
`TraceMatrix_GetUnsatisfiedRequirements_WithFilterTags_ReturnsOnlyMatchingRequirements`.
`TraceMatrix_CalculateSatisfiedRequirements_WithFilterTags_CountsOnlyMatchingRequirements`,
`TraceMatrix_GetUnsatisfiedRequirements_WithFilterTags_ReturnsOnlyMatchingRequirements`,
`TraceMatrix_Export_WithIncludeTitlesFalse_OmitsTitleColumn`,
`TraceMatrix_Export_WithIncludeTitlesTrue_AddsTitleColumn`,
`TraceMatrix_Export_IdentifierWithHyphensAndUnderscores_InsertsSoftBreaks`,
`TraceMatrix_Export_TitleWithHyphensAndUnderscores_InsertsSoftBreaksInTitleColumn`,
`TraceMatrix_Export_TitleWithPipeCharacter_EscapesPipeInTitleColumn`, which asserts a literal
pipe character in a requirement title is escaped so it does not corrupt the Title column;
`TraceMatrix_Export_TitleWithEmbeddedLineBreaks_NormalizesToSingleLineCell`, which asserts an
embedded line break in a requirement title is normalized to a single space so the Markdown
table row is not split across multiple lines; and
`TraceMatrix_Export_TitleWithLiteralBackslashPipe_EscapesBackslashBeforePipe`, which asserts a
literal backslash-then-pipe sequence in a requirement title is escaped with the backslash
doubled before the pipe is escaped, so the original sequence round-trips correctly.

#### Requirements Coverage

Expand Down Expand Up @@ -89,3 +102,5 @@ This scenario is tested by `TraceMatrix_Export_SimpleTraceMatrix_CreatesMarkdown
| `ReqStream-Report-TagFiltering` | Export Scenario | `TraceMatrix_Export_WithFilterTags_ExportsOnlyMatchingRequirements` |
| `ReqStream-Report-TagFiltering` | Export Scenario | `TraceMatrix_CalculateSatisfiedRequirements_WithFilterTags_CountsOnlyMatchingRequirements` |
| `ReqStream-Report-TagFiltering` | Export Scenario | `TraceMatrix_GetUnsatisfiedRequirements_WithFilterTags_ReturnsOnlyMatchingRequirements` |
| `ReqStream-Report-TraceMatrixTitles` | Export Scenario | `TraceMatrix_Export_WithIncludeTitlesTrue_AddsTitleColumn` |
| `ReqStream-Report-TraceMatrixTitles` | Export Scenario | `TraceMatrix_Export_WithIncludeTitlesFalse_OmitsTitleColumn` |
Loading
Loading