Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion docs/design/cli/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ arguments:
| `IndexPaths` | string[]? | Paths to scan when building an evidence index |
| `WorkingDirectory` | string | Base directory for resolving relative paths |
Comment thread
Malcolmnixon marked this conversation as resolved.
Outdated
| `Enforce` | bool | Fail if any review-set is not Current |
| `Elaborate` | bool | Expand file lists in generated documents |
| `ElaborateId` | string? | Review-set ID to elaborate, or null if `--elaborate` was not specified |

## Argument Parsing

Expand Down
21 changes: 14 additions & 7 deletions docs/design/program.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,24 @@ than by `Program.Main` explicitly returning a non-zero value.
executing the first matching action and returning:

1. If `--version` — print version and return
2. If `--help` — print banner and return
3. If `--validate` — run self-validation and return
4. If `--lint` — run configuration lint and return
5. If `--index` paths provided — scan and write evidence index, then return
6. Otherwise — generate Review Plan and/or Review Report and return
2. Print application banner
3. If `--help` — print help and return
4. If `--validate` — run self-validation and return
5. If `--lint` — run configuration lint and return
6. Otherwise — run main tool logic (index scanning and/or Review Plan/Report/Elaborate)

The application banner (step 2) is always printed unless `--version` is specified.
Only one top-level action is performed per invocation. Actions later in the priority
order are not reached if an earlier flag is set.

## PrintBanner()

`Program.PrintBanner(Context)` writes the help text to the console via
`Context.WriteLine()`. The banner lists all supported flags and arguments with brief
`Program.PrintBanner(Context)` writes the application name, version, and copyright
notice to the console via `Context.WriteLine()`. The banner is printed for every
invocation except `--version`.

## PrintHelp()

`Program.PrintHelp(Context)` writes usage information to the console via
`Context.WriteLine()`. The help text lists all supported flags and arguments with brief
descriptions.
26 changes: 13 additions & 13 deletions test/DemaConsulting.ReviewMark.Tests/Cli/ContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public void Context_Create_LogFlag_OpensLogFile()
public void Context_Create_UnknownArgument_ThrowsArgumentException()
{
// Act & Assert
var exception = Assert.Throws<ArgumentException>(() => Context.Create(["--unknown"]));
var exception = Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--unknown"]));
Assert.Contains("Unsupported argument", exception.Message);
}

Expand All @@ -211,7 +211,7 @@ public void Context_Create_UnknownArgument_ThrowsArgumentException()
public void Context_Create_LogFlag_WithoutValue_ThrowsArgumentException()
{
// Act & Assert
var exception = Assert.Throws<ArgumentException>(() => Context.Create(["--log"]));
var exception = Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--log"]));
Assert.Contains("--log", exception.Message);
}

Expand All @@ -222,7 +222,7 @@ public void Context_Create_LogFlag_WithoutValue_ThrowsArgumentException()
public void Context_Create_ResultsFlag_WithoutValue_ThrowsArgumentException()
{
// Act & Assert
var exception = Assert.Throws<ArgumentException>(() => Context.Create(["--results"]));
var exception = Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--results"]));
Assert.Contains("--results", exception.Message);
}

Expand Down Expand Up @@ -412,7 +412,7 @@ public void Context_Create_DefinitionFlag_SetsDefinitionFile()
public void Context_Create_DefinitionFlag_WithoutValue_ThrowsArgumentException()
{
// Act & Assert - --definition with no following value should throw and include the flag name in the message
var exception = Assert.Throws<ArgumentException>(() => Context.Create(["--definition"]));
var exception = Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--definition"]));
Assert.Contains("--definition", exception.Message);
}

Expand Down Expand Up @@ -452,7 +452,7 @@ public void Context_Create_PlanDepthFlag_SetsPlanDepth()
public void Context_Create_PlanDepthFlag_WithInvalidValue_ThrowsArgumentException()
{
// Act & Assert - --plan-depth with a non-numeric value should throw
Assert.Throws<ArgumentException>(() => Context.Create(["--plan-depth", "not-a-number"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--plan-depth", "not-a-number"]));
}

/// <summary>
Expand All @@ -463,7 +463,7 @@ public void Context_Create_PlanDepthFlag_WithInvalidValue_ThrowsArgumentExceptio
public void Context_Create_PlanDepthFlag_WithZeroValue_ThrowsArgumentException()
{
// Act & Assert - --plan-depth requires a positive integer; zero is not valid
Assert.Throws<ArgumentException>(() => Context.Create(["--plan-depth", "0"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--plan-depth", "0"]));
}

/// <summary>
Expand Down Expand Up @@ -501,7 +501,7 @@ public void Context_Create_ReportDepthFlag_SetsReportDepth()
public void Context_Create_ReportDepthFlag_NonNumeric_ThrowsArgumentException()
{
// Act & Assert - creating a context with a non-numeric report depth should fail validation
Assert.Throws<ArgumentException>(() => Context.Create(["--report-depth", "abc"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--report-depth", "abc"]));
}

/// <summary>
Expand All @@ -511,7 +511,7 @@ public void Context_Create_ReportDepthFlag_NonNumeric_ThrowsArgumentException()
public void Context_Create_ReportDepthFlag_Zero_ThrowsArgumentException()
{
// Act & Assert - creating a context with a report depth of 0 should fail validation
Assert.Throws<ArgumentException>(() => Context.Create(["--report-depth", "0"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--report-depth", "0"]));
}

/// <summary>
Expand All @@ -521,7 +521,7 @@ public void Context_Create_ReportDepthFlag_Zero_ThrowsArgumentException()
public void Context_Create_ReportDepthFlag_MissingValue_ThrowsArgumentException()
{
// Act & Assert - creating a context with --report-depth but no value should fail validation
Assert.Throws<ArgumentException>(() => Context.Create(["--report-depth"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--report-depth"]));
}

/// <summary>
Expand Down Expand Up @@ -628,7 +628,7 @@ public void Context_Create_NoArguments_EnforceFalse()
public void Context_Create_PlanDepthFlag_WithValueGreaterThanFive_ThrowsArgumentException()
{
// Act & Assert - --plan-depth cannot exceed 5 (max heading depth supported)
Assert.Throws<ArgumentException>(() => Context.Create(["--plan-depth", "6"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--plan-depth", "6"]));
}

/// <summary>
Expand All @@ -638,7 +638,7 @@ public void Context_Create_PlanDepthFlag_WithValueGreaterThanFive_ThrowsArgument
public void Context_Create_ReportDepthFlag_WithValueGreaterThanFive_ThrowsArgumentException()
{
// Act & Assert - --report-depth cannot exceed 5 (max heading depth supported)
Assert.Throws<ArgumentException>(() => Context.Create(["--report-depth", "6"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--report-depth", "6"]));
}

/// <summary>
Expand Down Expand Up @@ -675,7 +675,7 @@ public void Context_Create_NoArguments_WorkingDirectoryIsNull()
public void Context_Create_DirFlag_MissingValue_ThrowsArgumentException()
{
// Act & Assert - --dir without a path value should throw
Assert.Throws<ArgumentException>(() => Context.Create(["--dir"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--dir"]));
}

/// <summary>
Expand Down Expand Up @@ -712,7 +712,7 @@ public void Context_Create_NoArguments_ElaborateIdIsNull()
public void Context_Create_ElaborateFlag_WithoutValue_ThrowsArgumentException()
{
// Act & Assert - --elaborate without an ID argument should throw
Assert.Throws<ArgumentException>(() => Context.Create(["--elaborate"]));
Assert.ThrowsExactly<ArgumentException>(() => Context.Create(["--elaborate"]));
}

/// <summary>
Expand Down