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
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ DEMA Consulting tool for automated file-review evidence management in regulated
- 📋 **Coverage Reporting** - Review plan shows which files are covered and flags uncovered files
- 📊 **Status Reporting** - Review report shows whether each review-set is Current, Stale, Missing, or Failed
- 🔍 **Review Elaboration** - `--elaborate` prints the ID, fingerprint, and file list for a review set
- 🔎 **Configuration Linting** - `--lint` validates the definition file and reports all structural and semantic issues
- 🚦 **Enforcement** - `--enforce` exits non-zero if any review-set is stale or missing, or any file is uncovered
- 🔄 **Re-indexing** - `--index` scans PDF evidence files and writes an up-to-date `index.json`
- ✅ **Self-Validation** - Built-in validation tests with TRX and JUnit output
Expand Down Expand Up @@ -100,6 +101,12 @@ reviewmark --validate
# Save validation results
reviewmark --validate --results results.trx

# Validate definition file
reviewmark --lint

# Validate a specific definition file
reviewmark --lint --definition path/to/definition.yaml

# Silent mode with logging
reviewmark --silent --log output.log
```
Expand All @@ -112,6 +119,7 @@ reviewmark --silent --log output.log
| `-?`, `-h`, `--help` | Display help message |
| `--silent` | Suppress console output |
| `--validate` | Run self-validation |
| `--lint` | Validate the definition file and report issues |
| `--results <file>` | Write validation results to file (TRX or JUnit format) |
| `--log <file>` | Write output to log file |
| `--definition <file>` | Specify the definition YAML file (default: .reviewmark.yaml) |
Expand Down Expand Up @@ -147,9 +155,10 @@ Running self-validation produces a report containing the following information:
✓ ReviewMark_WorkingDirectoryOverride - Passed
✓ ReviewMark_Enforce - Passed
✓ ReviewMark_Elaborate - Passed
✓ ReviewMark_Lint - Passed

Total Tests: 8
Passed: 8
Total Tests: 9
Passed: 9
Failed: 0
```

Expand All @@ -163,6 +172,7 @@ Each test in the report proves:
- **`ReviewMark_WorkingDirectoryOverride`** - `--dir` overrides the working directory for file operations.
- **`ReviewMark_Enforce`** - `--enforce` exits with non-zero code when reviews have issues.
- **`ReviewMark_Elaborate`** - `--elaborate` prints a Markdown elaboration of a review set.
- **`ReviewMark_Lint`** - `--lint` validates a definition file and reports issues.

See the [User Guide][link-guide] for more details on the self-validation tests.

Expand Down
84 changes: 80 additions & 4 deletions docs/guide/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ Example validation report:
✓ ReviewMark_WorkingDirectoryOverride - Passed
✓ ReviewMark_Enforce - Passed
✓ ReviewMark_Elaborate - Passed
✓ ReviewMark_Lint - Passed

Total Tests: 8
Passed: 8
Total Tests: 9
Passed: 9
Failed: 0
```

Expand All @@ -121,6 +122,59 @@ Each test proves specific functionality works correctly:
- **`ReviewMark_WorkingDirectoryOverride`** - `--dir` overrides the working directory for file operations.
- **`ReviewMark_Enforce`** - `--enforce` exits with non-zero code when reviews have issues.
- **`ReviewMark_Elaborate`** - `--elaborate` prints a Markdown elaboration of a review set.
- **`ReviewMark_Lint`** - `--lint` validates a definition file and reports issues.

## Lint Definition File

The `--lint` command validates the definition file (`.reviewmark.yaml`) and reports all
structural and semantic issues in a single pass. Unlike running the full tool, `--lint` never
queries the evidence store — it only checks the definition file itself.

A successful lint exits with code 0; any issue causes a non-zero exit code.

### Running Lint

Lint the default definition file (`.reviewmark.yaml` in the working directory):

```bash
reviewmark --lint
```

Lint a specific definition file:

```bash
reviewmark --lint --definition path/to/definition.yaml
```

### What Lint Checks

Lint checks the following:

- **File readability** — the definition file exists and can be read.
- **YAML syntax** — the file is valid YAML; syntax errors include the filename and line number.
- **`evidence-source` block** — the block is present, has a `type` field (`url` or `fileshare`),
and has a `location` field.
- **Review sets** — each set has an `id`, a `title`, and at least one `paths` entry.
- **Duplicate IDs** — no two review sets share the same `id`.

All detected issues are reported together so you can fix multiple problems in one pass.

### Lint Error Messages

Lint errors follow the standard `[location]: [severity]: [issue]` format. For YAML syntax
errors the location includes the line and column number:

```text
definition.yaml:3:5: error: (yaml parse details)
definition.yaml: error: Configuration is missing required 'evidence-source' block.
definition.yaml: error: reviews[1] has duplicate ID 'core-module' (first defined at reviews[0]).
```

When no issues are found:

```text
definition.yaml: No issues found
```

## Silent Mode

Expand Down Expand Up @@ -163,6 +217,7 @@ The following command-line options are supported:
| `-?`, `-h`, `--help` | Display help message |
| `--silent` | Suppress console output |
| `--validate` | Run self-validation |
| `--lint` | Validate the definition file and report issues |
| `--results <file>` | Write validation results to file (TRX or JUnit format) |
| `--log <file>` | Write output to log file |
| `--definition <file>` | Specify the definition YAML file (default: .reviewmark.yaml) |
Expand Down Expand Up @@ -561,13 +616,34 @@ reviews:
- "!src/Data/Generated/**" # exclude auto-generated entity classes
```

## Example 4: Self-Validation with Results
## Example 4: Lint a Definition File

Lint the default definition file (`.reviewmark.yaml`) to catch all configuration errors before
running the full tool:

```bash
reviewmark --lint
```

Lint a specific definition file:

```bash
reviewmark --lint --definition path/to/.reviewmark.yaml
```

With silent mode and logging (useful in CI pipelines):

```bash
reviewmark --silent --log lint.log --lint
```

## Example 5: Self-Validation with Results

```bash
reviewmark --validate --results validation-results.trx
```

## Example 5: Silent Mode with Logging
## Example 6: Silent Mode with Logging

```bash
reviewmark --silent --log tool-output.log
Expand Down
28 changes: 28 additions & 0 deletions requirements.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,28 @@ sections:
- Program_Run_WithElaborateFlag_UnknownId_ReportsError
- ReviewMark_Elaborate

- id: ReviewMark-Cmd-Lint
title: The tool shall support --lint flag to validate the definition file and report issues.
justification: |
Users need a way to verify that the .reviewmark.yaml configuration file is valid
before running the main tool, providing clear error messages about the cause and
location of any issues.
tests:
- Context_Create_LintFlag_SetsLintTrue
- Context_Create_NoArguments_LintIsFalse
- Program_Run_WithHelpFlag_IncludesLintOption
- Program_Run_WithLintFlag_ValidConfig_ReportsSuccess
- Program_Run_WithLintFlag_MissingConfig_ReportsError
- Program_Run_WithLintFlag_DuplicateIds_ReportsError
- Program_Run_WithLintFlag_UnknownSourceType_ReportsError
- Program_Run_WithLintFlag_CorruptedYaml_ReportsError
- Program_Run_WithLintFlag_MissingEvidenceSource_ReportsError
- Program_Run_WithLintFlag_MultipleErrors_ReportsAll
- ReviewMarkConfiguration_Load_InvalidYaml_ErrorIncludesFilenameAndLine
- ReviewMarkConfiguration_Load_MissingEvidenceSource_ErrorIncludesFilename
- ReviewMarkConfiguration_Lint_MultipleErrors_ReturnsAll
- ReviewMark_Lint

- title: Configuration Reading
requirements:
- id: ReviewMark-Config-Reading
Expand Down Expand Up @@ -321,6 +343,7 @@ sections:
- "windows@ReviewMark_Enforce"
- "windows@ReviewMark_WorkingDirectoryOverride"
- "windows@ReviewMark_Elaborate"
- "windows@ReviewMark_Lint"

- id: ReviewMark-Platform-Linux
title: The tool shall build and run on Linux platforms.
Expand All @@ -336,6 +359,7 @@ sections:
- "ubuntu@ReviewMark_Enforce"
- "ubuntu@ReviewMark_WorkingDirectoryOverride"
- "ubuntu@ReviewMark_Elaborate"
- "ubuntu@ReviewMark_Lint"

- id: ReviewMark-Platform-MacOS
title: The tool shall build and run on macOS platforms.
Expand All @@ -351,6 +375,7 @@ sections:
- "macos@ReviewMark_Enforce"
- "macos@ReviewMark_WorkingDirectoryOverride"
- "macos@ReviewMark_Elaborate"
- "macos@ReviewMark_Lint"

- id: ReviewMark-Platform-Net8
title: The tool shall support .NET 8 runtime.
Expand All @@ -365,6 +390,7 @@ sections:
- "dotnet8.x@ReviewMark_Enforce"
- "dotnet8.x@ReviewMark_WorkingDirectoryOverride"
- "dotnet8.x@ReviewMark_Elaborate"
- "dotnet8.x@ReviewMark_Lint"

- id: ReviewMark-Platform-Net9
title: The tool shall support .NET 9 runtime.
Expand All @@ -379,6 +405,7 @@ sections:
- "dotnet9.x@ReviewMark_Enforce"
- "dotnet9.x@ReviewMark_WorkingDirectoryOverride"
- "dotnet9.x@ReviewMark_Elaborate"
- "dotnet9.x@ReviewMark_Lint"

- id: ReviewMark-Platform-Net10
title: The tool shall support .NET 10 runtime.
Expand All @@ -393,6 +420,7 @@ sections:
- "dotnet10.x@ReviewMark_Enforce"
- "dotnet10.x@ReviewMark_WorkingDirectoryOverride"
- "dotnet10.x@ReviewMark_Elaborate"
- "dotnet10.x@ReviewMark_Lint"

- title: OTS Software
requirements:
Expand Down
15 changes: 15 additions & 0 deletions src/DemaConsulting.ReviewMark/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ internal sealed class Context : IDisposable
/// </summary>
public bool Validate { get; private init; }

/// <summary>
/// Gets a value indicating whether the lint flag was specified.
/// </summary>
public bool Lint { get; private init; }

/// <summary>
/// Gets the validation results file path.
/// </summary>
Expand Down Expand Up @@ -159,6 +164,7 @@ public static Context Create(string[] args)
Help = parser.Help,
Silent = parser.Silent,
Validate = parser.Validate,
Lint = parser.Lint,
ResultsFile = parser.ResultsFile,
DefinitionFile = parser.DefinitionFile,
PlanFile = parser.PlanFile,
Expand Down Expand Up @@ -226,6 +232,11 @@ private sealed class ArgumentParser
/// </summary>
public bool Validate { get; private set; }

/// <summary>
/// Gets a value indicating whether the lint flag was specified.
/// </summary>
public bool Lint { get; private set; }

/// <summary>
/// Gets the log file path.
/// </summary>
Expand Down Expand Up @@ -328,6 +339,10 @@ private int ParseArgument(string arg, string[] args, int index)
Validate = true;
return index;

case "--lint":
Lint = true;
return index;

case "--log":
LogFile = GetRequiredStringArgument(arg, args, index, FilenameArgument);
return index + 1;
Expand Down
34 changes: 33 additions & 1 deletion src/DemaConsulting.ReviewMark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,14 @@ public static void Run(Context context)
return;
}

// Priority 4: Main tool functionality
// Priority 4: Lint
if (context.Lint)
{
RunLintLogic(context);
return;
}

// Priority 5: Main tool functionality
RunToolLogic(context);
}

Expand Down Expand Up @@ -140,6 +147,7 @@ private static void PrintHelp(Context context)
context.WriteLine(" -?, -h, --help Display this help message");
context.WriteLine(" --silent Suppress console output");
context.WriteLine(" --validate Run self-validation");
context.WriteLine(" --lint Lint the definition file and report issues");
context.WriteLine(" --results <file> Write validation results to file (.trx or .xml)");
context.WriteLine(" --log <file> Write output to log file");
context.WriteLine(" --definition <file> Specify the definition YAML file (default: .reviewmark.yaml)");
Expand All @@ -154,6 +162,30 @@ private static void PrintHelp(Context context)
context.WriteLine(" --elaborate <id> Print a Markdown elaboration of the specified review set");
}

/// <summary>
/// Runs the lint logic to validate the definition file.
/// </summary>
/// <param name="context">The context containing command line arguments and program state.</param>
private static void RunLintLogic(Context context)
{
// Determine the definition file path (explicit or default)
var directory = context.WorkingDirectory ?? Directory.GetCurrentDirectory();
var definitionFile = context.DefinitionFile ?? PathHelpers.SafePathCombine(directory, ".reviewmark.yaml");

// Lint the file, collecting all detectable errors in one pass.
var errors = ReviewMarkConfiguration.Lint(definitionFile);
foreach (var error in errors)
{
context.WriteError(error);
}

// Report overall result
if (errors.Count == 0)
{
context.WriteLine($"{definitionFile}: No issues found");
}
}

/// <summary>
/// Runs the main tool logic.
/// </summary>
Expand Down
Loading