From 4d2bc9e6ab5a778f1baed3a3f951b2d35aeacd3e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 00:03:48 +0000 Subject: [PATCH 1/8] Initial plan From c1999487bafeb7d5997ef6b8800e0acf0ac090ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 00:16:06 +0000 Subject: [PATCH 2/8] fix: address VersionMark-CommandLine-Review failures - Add missing justification and tags to Cmd-ErrorOutput, Cmd-InvalidArgs, Cmd-ExitCode requirements - Fix stale test reference VersionMark_GeneratesMarkdownReport -> VersionMark_PublishCommand_GeneratesMarkdownReport in publish.yaml - Remove non-existent VersionMark_CapturesVersions test reference from capture.yaml - Align priority table in command-line.md with Program.cs priority comments Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> --- docs/design/command-line.md | 12 ++++++------ docs/reqstream/capture.yaml | 1 - docs/reqstream/command-line.yaml | 15 +++++++++++++++ docs/reqstream/publish.yaml | 8 ++++---- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/docs/design/command-line.md b/docs/design/command-line.md index 22e9d47..705bda2 100644 --- a/docs/design/command-line.md +++ b/docs/design/command-line.md @@ -34,12 +34,12 @@ generate event-log entries. This satisfies requirements `VersionMark-Cmd-ExitCod | Priority | Condition | Action | |----------|------------------------|---------------------------------| | 1 | `context.Version` | Print version string and return | -| 2 | Print banner | Always executed after priority 1| -| 3 | `context.Help` | Print usage and return | -| 4 | `context.Validate` | Run self-validation and return | -| 5 | `context.Capture` | Run capture mode and return | -| 5.5 | `context.Publish` | Run publish mode and return | -| 6 | Default | Run placeholder tool logic | +| — | Print banner | Always executed after priority 1| +| 2 | `context.Help` | Print usage and return | +| 3 | `context.Validate` | Run self-validation and return | +| 4 | `context.Capture` | Run capture mode and return | +| 4.5 | `context.Publish` | Run publish mode and return | +| 5 | Default | Run placeholder tool logic | This dispatch order satisfies requirements `VersionMark-Cmd-Version`, `VersionMark-Cmd-Help`, `VersionMark-Cmd-Validate`, `VersionMark-Cap-Capture`, and `VersionMark-Pub-Publish`. diff --git a/docs/reqstream/capture.yaml b/docs/reqstream/capture.yaml index c27dc77..84cd1a7 100644 --- a/docs/reqstream/capture.yaml +++ b/docs/reqstream/capture.yaml @@ -12,7 +12,6 @@ sections: tags: - capture tests: - - VersionMark_CapturesVersions - Program_Run_WithCaptureCommand_CapturesToolVersions - IntegrationTest_CaptureCommand_CapturesToolVersions diff --git a/docs/reqstream/command-line.yaml b/docs/reqstream/command-line.yaml index eec1292..a240bee 100644 --- a/docs/reqstream/command-line.yaml +++ b/docs/reqstream/command-line.yaml @@ -94,12 +94,22 @@ sections: - id: VersionMark-Cmd-ErrorOutput title: The tool shall write error messages to stderr. + justification: | + Separating error output from standard output allows callers and CI/CD + pipelines to distinguish normal output from failure diagnostics. + tags: + - cli tests: - Context_WriteError_NotSilent_WritesToConsole - IntegrationTest_UnknownArgument_ReturnsError - id: VersionMark-Cmd-InvalidArgs title: The tool shall reject unknown or malformed command-line arguments with a descriptive error. + justification: | + Clear rejection of invalid arguments prevents silent misconfiguration and + guides users toward correct usage without requiring external documentation. + tags: + - cli tests: - Context_Create_UnknownArgument_ThrowsArgumentException - Context_Create_LogFlag_WithoutValue_ThrowsArgumentException @@ -108,6 +118,11 @@ sections: - id: VersionMark-Cmd-ExitCode title: The tool shall return a non-zero exit code on failure. + justification: | + A non-zero exit code on failure enables CI/CD pipelines and scripts to + detect and respond to tool failures automatically. + tags: + - cli tests: - Context_WriteError_SetsErrorExitCode - IntegrationTest_UnknownArgument_ReturnsError diff --git a/docs/reqstream/publish.yaml b/docs/reqstream/publish.yaml index 6f761c6..ab40a7a 100644 --- a/docs/reqstream/publish.yaml +++ b/docs/reqstream/publish.yaml @@ -12,7 +12,7 @@ sections: tags: - publish tests: - - VersionMark_GeneratesMarkdownReport + - VersionMark_PublishCommand_GeneratesMarkdownReport - id: VersionMark-Pub-Report title: The tool shall support --report parameter to specify the output markdown file path in publish mode. @@ -22,7 +22,7 @@ sections: tags: - publish tests: - - VersionMark_GeneratesMarkdownReport + - VersionMark_PublishCommand_GeneratesMarkdownReport - id: VersionMark-Pub-ReportDepth title: The tool shall support --report-depth parameter to control heading depth in generated markdown. @@ -52,7 +52,7 @@ sections: tags: - publish tests: - - VersionMark_GeneratesMarkdownReport + - VersionMark_PublishCommand_GeneratesMarkdownReport - id: VersionMark-Pub-Consolidate title: The tool shall read and parse JSON files matching the specified glob patterns in publish mode. @@ -62,7 +62,7 @@ sections: tags: - publish tests: - - VersionMark_GeneratesMarkdownReport + - VersionMark_PublishCommand_GeneratesMarkdownReport - id: VersionMark-Pub-ConflictReport title: The tool shall report errors when no JSON files match the specified glob patterns. From 75c385c2f075a0fb2c3c8a5a39fbac82eb2dae5b Mon Sep 17 00:00:00 2001 From: Malcolm Nixon Date: Sat, 14 Mar 2026 10:26:01 -0400 Subject: [PATCH 3/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/reqstream/publish.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reqstream/publish.yaml b/docs/reqstream/publish.yaml index ab40a7a..27ce6f7 100644 --- a/docs/reqstream/publish.yaml +++ b/docs/reqstream/publish.yaml @@ -52,7 +52,8 @@ sections: tags: - publish tests: - - VersionMark_PublishCommand_GeneratesMarkdownReport + - VersionMark_PublishCommandWithCustomGlobPatterns_FiltersFiles + - Context_Create_GlobPatternsAfterSeparator_CapturesPatterns - id: VersionMark-Pub-Consolidate title: The tool shall read and parse JSON files matching the specified glob patterns in publish mode. From 915c35b14c2900ecefb7914371bcb30451ac2755 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:57:23 +0000 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20correct=20VersionMark-Fmt-MarkdownLi?= =?UTF-8?q?st=20requirement=20wording=20(subscript=20=E2=86=92=20bold)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> --- docs/reqstream/formatter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reqstream/formatter.yaml b/docs/reqstream/formatter.yaml index 56f6ba2..7d3671b 100644 --- a/docs/reqstream/formatter.yaml +++ b/docs/reqstream/formatter.yaml @@ -41,7 +41,7 @@ sections: - id: VersionMark-Fmt-MarkdownList title: >- - The tool shall use subscript formatting and parenthesized job IDs to indicate which + The tool shall use bold formatting and parenthesized job IDs to indicate which jobs had which versions. justification: | Provides clear visual distinction between different job executions and their From a2528e00977e523325fa5d0bab570cf662f03880 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:08:37 +0000 Subject: [PATCH 5/8] fix: correct stale remarks on RunCommand in VersionMarkConfig.cs Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> --- src/DemaConsulting.VersionMark/VersionMarkConfig.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/DemaConsulting.VersionMark/VersionMarkConfig.cs b/src/DemaConsulting.VersionMark/VersionMarkConfig.cs index fa69c35..7be6e78 100644 --- a/src/DemaConsulting.VersionMark/VersionMarkConfig.cs +++ b/src/DemaConsulting.VersionMark/VersionMarkConfig.cs @@ -331,8 +331,9 @@ public VersionInfo FindVersions(IEnumerable toolNames, string jobId) /// The combined stdout and stderr output. /// Thrown when the command fails to execute. /// - /// Commands are split on the first space character to separate executable from arguments. - /// This does not handle quoted arguments containing spaces. + /// Commands are delegated to the OS shell (cmd.exe /c on Windows, /bin/sh -c + /// elsewhere) via ArgumentList to avoid escaping issues. This supports .cmd/.bat + /// files on Windows and shell features (pipes, redirects, built-ins) on all platforms. /// private static string RunCommand(string command) { From 059b670da796e661b47447468380ecddbb4d8951 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:29:26 +0000 Subject: [PATCH 6/8] fix: resolve VersionMark-VersionInfo-Review failures Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> --- docs/design/version-info.md | 3 ++- .../VersionInfoTests.cs | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/design/version-info.md b/docs/design/version-info.md index d2d9844..dff325c 100644 --- a/docs/design/version-info.md +++ b/docs/design/version-info.md @@ -20,7 +20,8 @@ The `VersionInfo` record (`VersionInfo.cs`) is a positional record with two prop `SaveToFile` serializes the record to indented JSON using `JsonSerializer.Serialize` with `WriteIndented = true` and writes it to the specified path using UTF-8 encoding. Non-`InvalidOperationException` errors are wrapped and re-thrown as `InvalidOperationException` with context. This satisfies -requirements `VersionMark-Cap-JsonOutput` and `VersionMark-Cap-DefaultOutput`. +requirement `VersionMark-Cap-JsonOutput`. The default output filename (`versionmark-.json`) +is determined by the CLI layer and contributes to satisfying `VersionMark-Cap-DefaultOutput`. ### LoadFromFile Method diff --git a/test/DemaConsulting.VersionMark.Tests/VersionInfoTests.cs b/test/DemaConsulting.VersionMark.Tests/VersionInfoTests.cs index c3a461f..c61569b 100644 --- a/test/DemaConsulting.VersionMark.Tests/VersionInfoTests.cs +++ b/test/DemaConsulting.VersionMark.Tests/VersionInfoTests.cs @@ -278,6 +278,31 @@ public void VersionInfo_EmptyVersions_SavesAndLoadsCorrectly() } } + /// + /// Test LoadFromFile throws ArgumentException when JSON deserializes to null (e.g., literal "null"). + /// + [TestMethod] + public void VersionInfo_LoadFromFile_NullJson_ThrowsArgumentException() + { + // Arrange + var tempFile = Path.GetTempFileName(); + try + { + File.WriteAllText(tempFile, "null"); + + // Act & Assert + var exception = Assert.Throws(() => VersionInfo.LoadFromFile(tempFile)); + Assert.Contains("deserialize", exception.Message, StringComparison.OrdinalIgnoreCase); + } + finally + { + if (File.Exists(tempFile)) + { + File.Delete(tempFile); + } + } + } + /// /// Test VersionInfo with special characters in values. /// From 5a5e641c57aa21262b269a1190a9bdd9afbc5ef0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 16:27:12 +0000 Subject: [PATCH 7/8] fix: resolve VersionMark-Validation-Review failures Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> --- docs/design/validation.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/design/validation.md b/docs/design/validation.md index 83dfdbc..b5a78b7 100644 --- a/docs/design/validation.md +++ b/docs/design/validation.md @@ -30,7 +30,8 @@ organizes all test execution internally. 1. Creates a `TemporaryDirectory` (see below). 2. Writes a minimal `.versionmark.yaml` containing only the `dotnet` tool. -3. Constructs a `Context` with `--capture`, `--job-id test-job`, and `--output `. +3. Constructs a `Context` with `--silent`, `--log `, `--capture`, `--job-id test-job`, + and `--output `. 4. Changes the current directory to the temp directory and calls `Program.Run`. 5. Verifies exit code is 0, output file exists, `JobId` equals `"test-job"`, and `dotnet` version was captured and is non-empty. @@ -43,7 +44,8 @@ The test name is `VersionMark_CapturesVersions`, satisfying `VersionMark-Cap-Cap 1. Creates a `TemporaryDirectory`. 2. Writes two `VersionInfo` JSON files with known content. -3. Constructs a `Context` with `--publish`, `--report `, and `-- versionmark-*.json`. +3. Constructs a `Context` with `--silent`, `--log `, `--publish`, `--report `, + `--report-depth 2`, and `-- versionmark-*.json`. 4. Changes the current directory to the temp directory and calls `Program.Run`. 5. Verifies exit code is 0, report file exists, and contains `## Tool Versions`, `**dotnet**`, `**node**`, `8.0.0`, and `20.0.0`. From 0c41e4d1c9736ca1616d95f35e138740a594f038 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:04:42 +0000 Subject: [PATCH 8/8] fix: strengthen two weak test assertions in CommandLine test files TEST-01 fix 1 - Program_Run_WithVersionFlag_DisplaysVersionOnly (ProgramTests.cs): Added positive assertion that a version string IS printed, in addition to the existing negative assertions that the banner is NOT shown. Without this, the test would pass even if nothing was printed at all. TEST-01 fix 2 - IntegrationTest_SilentFlag_SuppressesOutput (IntegrationTests.cs): Captured the output instead of discarding it and added DoesNotContain assertions for the tool's normal banner content. The prior test only checked exit code and had a comment 'Output check removed', making the test name misleading. All 57 ContextTests/ProgramTests/IntegrationTests pass on net8.0/net9.0/net10.0. --- test/DemaConsulting.VersionMark.Tests/IntegrationTests.cs | 6 ++++-- test/DemaConsulting.VersionMark.Tests/ProgramTests.cs | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/DemaConsulting.VersionMark.Tests/IntegrationTests.cs b/test/DemaConsulting.VersionMark.Tests/IntegrationTests.cs index 3e5cff7..9495840 100644 --- a/test/DemaConsulting.VersionMark.Tests/IntegrationTests.cs +++ b/test/DemaConsulting.VersionMark.Tests/IntegrationTests.cs @@ -196,7 +196,7 @@ public void IntegrationTest_SilentFlag_SuppressesOutput() { // Arrange & Act - Run the application with --silent flag var exitCode = Runner.Run( - out var _, + out var output, "dotnet", _dllPath, "--silent"); @@ -204,7 +204,9 @@ public void IntegrationTest_SilentFlag_SuppressesOutput() // Assert - Verify success Assert.AreEqual(0, exitCode); - // Output check removed since silent mode may still produce some output + // Verify the tool's normal output is suppressed + Assert.DoesNotContain("VersionMark version", output); + Assert.DoesNotContain("Copyright (c) DEMA Consulting", output); } /// diff --git a/test/DemaConsulting.VersionMark.Tests/ProgramTests.cs b/test/DemaConsulting.VersionMark.Tests/ProgramTests.cs index 05115cf..fa66a1d 100644 --- a/test/DemaConsulting.VersionMark.Tests/ProgramTests.cs +++ b/test/DemaConsulting.VersionMark.Tests/ProgramTests.cs @@ -45,6 +45,7 @@ public void Program_Run_WithVersionFlag_DisplaysVersionOnly() // Assert - Verify version-only output var output = outWriter.ToString(); + Assert.IsFalse(string.IsNullOrWhiteSpace(output), "Version string should be printed"); Assert.DoesNotContain("Copyright", output); Assert.DoesNotContain("VersionMark version", output); }