feat: implement Phase 3 - Schema-for-Schemas Metaschema
Some checks failed
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / code-quality (push) Has been cancelled
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
Some checks failed
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / code-quality (push) Has been cancelled
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
Completed Phase 3 of the schema-of-schemas implementation with a comprehensive metaschema that validates all MarkiTect schema files against conventions and standards. Metaschema Implementation (schema-schema-v1.0.md - 650+ lines): - Validates core JSON Schema fields ($schema, $id, title, description) - Validates MarkiTect version field (SemVer: major.minor.patch) - Validates $id URL format (HTTPS with version path) - Validates MarkiTect extensions: - x-markitect-sections: section classifications and content rules - x-markitect-content-control: pattern and quality validation - x-markitect-metadata: status, authors, tags - x-markitect-source: loader metadata (auto-added) - Section classification validation (required, recommended, optional, discouraged, improper) - Content control pattern validation - Comprehensive documentation with examples and usage guides CLI Command (markitect schema-validate): - Validates schema files against metaschema - Supports both markdown and JSON schema files - Detailed error reporting with schema paths - Structure validation recommendations - Exit codes for CI/CD integration Test Coverage (tests/test_schema_metaschema.py - 12 tests, 100% passing): - Metaschema self-validation - Manpage schema validation - Required fields enforcement - Version format validation (valid and invalid cases) - $id format validation (valid and invalid cases) - Section classification validation - Complete schema with all extensions Validation Results: - ✅ Metaschema validates itself successfully - ✅ Manpage schema (v1.0.md) validates successfully - ⚠️ Terminology schema needs migration (missing version, incorrect $id) Progress Tracking: - Updated TODO.md with Phase 3 completion - Updated CHANGELOG.md with implementation details - Next: Phase 4 - Schema Migration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
104
markitect/cli.py
104
markitect/cli.py
@@ -1903,6 +1903,110 @@ def schema_delete(config, schema_name, confirm):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@cli.command('schema-validate')
|
||||
@click.argument('schema_file', type=click.Path(exists=True, path_type=Path))
|
||||
@click.option('--detailed-errors', is_flag=True, help='Show detailed validation errors')
|
||||
@pass_config
|
||||
def schema_validate_cmd(config, schema_file, detailed_errors):
|
||||
"""
|
||||
Validate a schema file against the schema-for-schemas metaschema.
|
||||
|
||||
Ensures schema files follow MarkiTect conventions and standards:
|
||||
- Required fields ($schema, $id, title, description, version)
|
||||
- Version format (SemVer: major.minor.patch)
|
||||
- $id URL format (HTTPS with version)
|
||||
- MarkiTect extensions (x-markitect-*)
|
||||
- Section classification structures
|
||||
|
||||
SCHEMA_FILE: Path to the schema file to validate (markdown or JSON)
|
||||
|
||||
Examples:
|
||||
markitect schema-validate manpage-schema-v1.0.md
|
||||
markitect schema-validate my-schema-v2.0.md --detailed-errors
|
||||
"""
|
||||
try:
|
||||
from .schema_loader import MarkdownSchemaLoader
|
||||
try:
|
||||
import jsonschema
|
||||
from jsonschema import Draft7Validator, ValidationError
|
||||
except ImportError:
|
||||
click.echo("❌ Error: jsonschema package not installed", err=True)
|
||||
click.echo("Install it with: pip install jsonschema", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
loader = MarkdownSchemaLoader()
|
||||
|
||||
# Load the schema to validate
|
||||
click.echo(f"Loading schema: {schema_file.name}")
|
||||
try:
|
||||
if schema_file.suffix == '.md':
|
||||
schema_data = loader.load_schema(schema_file)
|
||||
schema = schema_data['schema']
|
||||
else:
|
||||
# Assume JSON
|
||||
schema = json.loads(schema_file.read_text())
|
||||
except Exception as e:
|
||||
click.echo(f"❌ Failed to load schema: {e}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
# Load metaschema
|
||||
metaschema_path = Path(__file__).parent / 'schemas' / 'schema-schema-v1.0.md'
|
||||
if not metaschema_path.exists():
|
||||
click.echo(f"❌ Metaschema not found: {metaschema_path}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
metaschema_data = loader.load_schema(metaschema_path)
|
||||
metaschema = metaschema_data['schema']
|
||||
except Exception as e:
|
||||
click.echo(f"❌ Failed to load metaschema: {e}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
# Validate schema against metaschema
|
||||
validator = Draft7Validator(metaschema)
|
||||
errors = list(validator.iter_errors(schema))
|
||||
|
||||
if not errors:
|
||||
click.echo(f"✅ Schema is valid: {schema_file.name}")
|
||||
click.echo(f" Title: {schema.get('title', 'N/A')}")
|
||||
click.echo(f" Version: {schema.get('version', 'N/A')}")
|
||||
click.echo(f" $id: {schema.get('$id', 'N/A')}")
|
||||
|
||||
# Additional structure validation
|
||||
issues = loader.validate_schema_structure(schema)
|
||||
if issues:
|
||||
click.echo(f"\n⚠️ Structure recommendations:")
|
||||
for issue in issues:
|
||||
click.echo(f" - {issue}")
|
||||
else:
|
||||
click.echo(f"❌ Schema validation failed: {schema_file.name}", err=True)
|
||||
click.echo(f"\nFound {len(errors)} validation error(s):\n", err=True)
|
||||
|
||||
for i, error in enumerate(errors, 1):
|
||||
path = ' → '.join(str(p) for p in error.path) if error.path else 'root'
|
||||
click.echo(f"{i}. At {path}:", err=True)
|
||||
click.echo(f" {error.message}", err=True)
|
||||
|
||||
if detailed_errors and error.context:
|
||||
click.echo(f" Context:", err=True)
|
||||
for ctx_error in error.context:
|
||||
click.echo(f" - {ctx_error.message}", err=True)
|
||||
|
||||
if detailed_errors:
|
||||
click.echo(f" Schema path: {' → '.join(str(p) for p in error.schema_path)}", err=True)
|
||||
|
||||
click.echo()
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
except Exception as e:
|
||||
click.echo(f"❌ Schema validation error: {e}", err=True)
|
||||
if config and config.get('verbose'):
|
||||
import traceback
|
||||
click.echo(traceback.format_exc(), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@cli.command('schema-analyze')
|
||||
@click.argument('schema_file', type=click.Path(exists=True))
|
||||
@click.option('--verbose', '-v', is_flag=True, help='Show detailed analysis')
|
||||
|
||||
Reference in New Issue
Block a user