feat: enhance validate command with semantic validation

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 <noreply@anthropic.com>
This commit is contained in:
2026-01-06 03:27:39 +01:00
parent a969c5de47
commit 5264a6083c

View File

@@ -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)