From 5264a6083c9697185faa66ce0445d60142975188 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 6 Jan 2026 03:27:39 +0100 Subject: [PATCH] feat: enhance validate command with semantic validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrates SemanticValidator into CLI validate command: New Options: - --semantic/--no-semantic (default: True) - Enable/disable semantic validation - --check-links - Enable link validation (requires semantic validation) - --strict - Treat warnings as errors (fail on WARNING-level issues) Features: - Automatically detects x-markitect extensions in schema - Runs semantic validation alongside structural validation - Combines results with clear separation in output - Maintains full backward compatibility (--no-semantic for classic mode) - Supports .md schema files with embedded JSON - Graceful degradation: semantic validation errors don't crash command Example Usage: # Full validation (structural + semantic) markitect validate doc.md --schema manpage-schema-v1.0.md # Strict mode (warnings = errors) markitect validate doc.md --schema schema.md --strict # Classic mode (structural only) markitect validate doc.md --schema schema.json --no-semantic Output Format: - Shows structural validation results first - Then semantic validation results (sections, content) - Clear summary with error/warning counts - Exit codes: 0=pass, 1=fail (respects --strict flag) Integration: cli.py:1493-1668 šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- markitect/cli.py | 71 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/markitect/cli.py b/markitect/cli.py index 93c69c14..39d769c2 100644 --- a/markitect/cli.py +++ b/markitect/cli.py @@ -1493,7 +1493,7 @@ def generate_schema(config, file_path, max_depth, output, outfile, output_format @cli.command('validate') @click.argument('file_path', type=click.Path(exists=True, path_type=Path)) @click.option('--schema', '-s', type=click.Path(exists=True, path_type=Path), - help='Path to JSON schema file') + help='Path to JSON schema file (.json or .md)') @click.option('--schema-json', type=str, help='JSON schema provided as a string') @click.option('--quiet', '-q', is_flag=True, @@ -1502,21 +1502,38 @@ def generate_schema(config, file_path, max_depth, output, outfile, output_format help='Show detailed validation errors (Issue #8)') @click.option('--error-format', type=click.Choice(['text', 'json', 'markdown']), default='text', help='Format for detailed error output') +@click.option('--semantic/--no-semantic', default=True, + help='Enable/disable semantic validation (sections, patterns, quality)') +@click.option('--check-links', is_flag=True, + help='Enable link validation (may be slow, requires --semantic)') +@click.option('--strict', is_flag=True, + help='Treat warnings as errors') @pass_config -def validate(config, file_path, schema, schema_json, quiet, detailed_errors, error_format): +def validate(config, file_path, schema, schema_json, quiet, detailed_errors, error_format, + semantic, check_links, strict): """ Validate a markdown file against a JSON schema. + ENHANCED: Now includes semantic validation of x-markitect extensions: + - Section classifications (required, recommended, optional, discouraged, improper) + - Content patterns (required_patterns, forbidden_patterns) + - Quality metrics (min_words, max_words, min_sentences) + Checks if a markdown document strictly adheres to the structure defined by a specified schema. Returns boolean result (True/False). - Issue #8: Enhanced with detailed error reporting for failed validations. - Examples: - markitect validate doc.md --schema schema.json - markitect validate doc.md --schema-json '{"$schema": "...", "type": "object"}' + # Structural + semantic validation (default) + markitect validate doc.md --schema manpage-schema-v1.0.md + + # Only structural validation + markitect validate doc.md --schema schema.json --no-semantic + + # Strict mode (warnings become errors) + markitect validate doc.md --schema schema.json --strict + + # Legacy detailed errors markitect validate doc.md --schema schema.json --detailed-errors - markitect validate doc.md --schema schema.json --errors --error-format json """ try: validator = SchemaValidator() @@ -1594,6 +1611,46 @@ def validate(config, file_path, schema, schema_json, quiet, detailed_errors, err click.echo("āŒ Document structure does not match schema requirements") click.echo("šŸ’” Use --detailed-errors to see specific validation issues") + # Semantic validation (if enabled and schema has x-markitect extensions) + semantic_report = None + if semantic and schema: + try: + from .semantic_validator import SemanticValidator, load_schema_from_path + + # Load schema (supports .md and .json) + schema_dict = load_schema_from_path(schema) + + # Check if schema has x-markitect extensions + has_extensions = ('x-markitect-sections' in schema_dict or + 'x-markitect-content-control' in schema_dict) + + if has_extensions: + sem_validator = SemanticValidator(schema_dict) + semantic_report = sem_validator.validate(file_path, check_links=check_links) + + # Combine with structural validation result + if semantic_report and not quiet: + click.echo("") + click.echo("=" * 60) + click.echo("Semantic Validation Results:") + click.echo("=" * 60) + click.echo(semantic_report.format_text()) + + # Update validity based on semantic validation + if semantic_report: + if semantic_report.has_errors(): + is_valid = False + elif strict and semantic_report.has_warnings(): + is_valid = False + + except Exception as e: + # Semantic validation failure doesn't fail the whole command + # unless strict mode is enabled + if not quiet: + click.echo(f"\nāš ļø Semantic validation error: {e}", err=True) + if strict: + is_valid = False + # Exit with appropriate code sys.exit(0 if is_valid else 1)