specfact-cli 0.20.0__tar.gz → 0.20.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/PKG-INFO +1 -1
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/pyproject.toml +1 -1
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/shared/cli-enforcement.md +6 -0
- specfact_cli-0.20.5/resources/prompts/specfact.01-import.md +263 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.02-plan.md +3 -1
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.03-review.md +104 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.04-sdd.md +1 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.05-enforce.md +1 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.06-sync.md +1 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.compare.md +1 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.validate.md +1 -0
- specfact_cli-0.20.5/resources/templates/sidecar/README.md +187 -0
- specfact_cli-0.20.5/resources/templates/sidecar/__init__.py +0 -0
- specfact_cli-0.20.5/resources/templates/sidecar/adapters.py +632 -0
- specfact_cli-0.20.5/resources/templates/sidecar/bindings.yaml +26 -0
- specfact_cli-0.20.5/resources/templates/sidecar/bindings.yaml.example +42 -0
- specfact_cli-0.20.5/resources/templates/sidecar/crosshair_django_wrapper.py +140 -0
- specfact_cli-0.20.5/resources/templates/sidecar/crosshair_plugin.py +34 -0
- specfact_cli-0.20.5/resources/templates/sidecar/django_form_extractor.py +440 -0
- specfact_cli-0.20.5/resources/templates/sidecar/django_url_extractor.py +304 -0
- specfact_cli-0.20.5/resources/templates/sidecar/generate_harness.py +561 -0
- specfact_cli-0.20.5/resources/templates/sidecar/harness_contracts.py +26 -0
- specfact_cli-0.20.5/resources/templates/sidecar/populate_contracts.py +278 -0
- specfact_cli-0.20.5/resources/templates/sidecar/run_sidecar.sh +410 -0
- specfact_cli-0.20.5/resources/templates/sidecar/sidecar-init.sh +107 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/__init__.py +1 -1
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/__init__.py +1 -1
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/generate.py +63 -68
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/init.py +95 -9
- specfact_cli-0.20.5/src/specfact_cli/commands/repro.py +468 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/enrichment_parser.py +97 -24
- specfact_cli-0.20.5/src/specfact_cli/utils/env_manager.py +443 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/repro_checker.py +233 -73
- specfact_cli-0.20.0/resources/prompts/specfact.01-import.md +0 -121
- specfact_cli-0.20.0/src/specfact_cli/commands/repro.py +0 -226
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/.gitignore +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/LICENSE.md +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/README.md +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/mappings/node-async.yaml +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/mappings/python-async.yaml +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/mappings/speckit-default.yaml +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/prompts/specfact.07-contracts.md +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/schemas/deviation.schema.json +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/schemas/plan.schema.json +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/schemas/protocol.schema.json +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/github-action.yml.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/persona/architect.md.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/persona/developer.md.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/persona/product-owner.md.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/plan.bundle.yaml.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/pr-template.md.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/protocol.yaml.j2 +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/resources/templates/telemetry.yaml.example +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/agents/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/agents/analyze_agent.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/agents/base.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/agents/plan_agent.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/agents/registry.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/agents/sync_agent.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/cli.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/analyze.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/bridge.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/contract_cmd.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/drift.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/enforce.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/implement.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/import_cmd.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/migrate.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/plan.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/project_cmd.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/sdd.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/spec.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/commands/sync.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/common/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/common/logger_setup.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/common/logging_utils.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/common/text_utils.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/common/utils.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/comparators/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/comparators/plan_comparator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/contract_generator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/openapi_extractor.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/persona_exporter.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/plan_generator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/protocol_generator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/report_generator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/task_generator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/test_to_openapi.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/generators/workflow_generator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/importers/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/importers/speckit_converter.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/importers/speckit_scanner.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/integrations/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/integrations/specmatic.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/merge/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/merge/resolver.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/migrations/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/migrations/plan_migrator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/bridge.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/contract.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/deviation.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/enforcement.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/persona_template.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/plan.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/project.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/protocol.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/quality.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/sdd.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/source_tracking.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/models/task.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/modes/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/modes/detector.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/modes/router.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/parsers/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/parsers/persona_importer.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/resources/semgrep/async.yml +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/runtime.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/bridge_probe.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/bridge_sync.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/bridge_watch.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/change_detector.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/code_to_spec.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/drift_detector.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/repository_sync.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/spec_to_code.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/spec_to_tests.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/speckit_sync.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/watcher.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/telemetry.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/templates/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/templates/bridge_templates.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/templates/specification_templates.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/bundle_loader.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/console.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/context_detection.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/enrichment_context.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/feature_keys.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/git.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/github_annotations.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/ide_setup.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/incremental_check.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/optional_deps.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/performance.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/progress.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/prompts.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/sdd_discovery.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/source_scanner.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/structure.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/structured_io.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/suggestions.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/utils/yaml_utils.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/agile_validation.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/cli_first_validator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/contract_validator.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/fsm.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/validators/schema.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/versioning/__init__.py +0 -0
- {specfact_cli-0.20.0 → specfact_cli-0.20.5}/src/specfact_cli/versioning/analyzer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specfact-cli
|
|
3
|
-
Version: 0.20.
|
|
3
|
+
Version: 0.20.5
|
|
4
4
|
Summary: Brownfield-first CLI: Reverse engineer legacy Python → specs → enforced contracts. Automate legacy code documentation and prevent modernization regressions.
|
|
5
5
|
Project-URL: Homepage, https://github.com/nold-ai/specfact-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/nold-ai/specfact-cli.git
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specfact-cli"
|
|
7
|
-
version = "0.20.
|
|
7
|
+
version = "0.20.5"
|
|
8
8
|
description = "Brownfield-first CLI: Reverse engineer legacy Python → specs → enforced contracts. Automate legacy code documentation and prevent modernization regressions."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -37,6 +37,12 @@ These operations **require LLM** and are only available via AI IDE slash prompts
|
|
|
37
37
|
**Access**: Only available via AI IDE slash prompts (Cursor, CoPilot, etc.)
|
|
38
38
|
**Pattern**: Slash prompt → LLM generates → CLI validates → Apply if valid
|
|
39
39
|
|
|
40
|
+
## LLM Grounding Rules
|
|
41
|
+
|
|
42
|
+
- Treat CLI artifacts as the source of truth for keys, structure, and metadata.
|
|
43
|
+
- Scan the codebase only when asked to infer missing behavior/context or explain deviations; respect `--entry-point` scope when provided.
|
|
44
|
+
- Use codebase findings to propose updates via CLI (enrichment report, plan update commands), never to rewrite artifacts directly.
|
|
45
|
+
|
|
40
46
|
## Rules
|
|
41
47
|
|
|
42
48
|
1. **Execute CLI First**: Always run CLI commands before any analysis
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Import codebase → plan bundle. CLI extracts routes/schemas/relationships. LLM enriches with context.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# SpecFact Import Command
|
|
6
|
+
|
|
7
|
+
## User Input
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
$ARGUMENTS
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
You **MUST** consider the user input before proceeding (if not empty).
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
|
|
17
|
+
Import codebase → plan bundle. CLI extracts routes/schemas/relationships/contracts. LLM enriches context/"why"/completeness.
|
|
18
|
+
|
|
19
|
+
## Parameters
|
|
20
|
+
|
|
21
|
+
**Target/Input**: `--bundle NAME` (optional, defaults to active plan), `--repo PATH`, `--entry-point PATH`, `--enrichment PATH`
|
|
22
|
+
**Output/Results**: `--report PATH`
|
|
23
|
+
**Behavior/Options**: `--shadow-only`, `--enrich-for-speckit/--no-enrich-for-speckit` (default: enabled, uses PlanEnricher for consistent enrichment)
|
|
24
|
+
**Advanced/Configuration**: `--confidence FLOAT` (0.0-1.0), `--key-format FORMAT` (classname|sequential)
|
|
25
|
+
|
|
26
|
+
## Workflow
|
|
27
|
+
|
|
28
|
+
1. **Execute CLI**: `specfact [GLOBAL OPTIONS] import from-code [<bundle>] --repo <path> [options]`
|
|
29
|
+
- CLI extracts: routes (FastAPI/Flask/Django), schemas (Pydantic), relationships, contracts (OpenAPI scaffolds), source tracking
|
|
30
|
+
- Uses active plan if bundle not specified
|
|
31
|
+
- Note: `--no-interactive` is a global option and must appear before the subcommand (e.g., `specfact --no-interactive import from-code ...`).
|
|
32
|
+
- **Auto-enrichment enabled by default**: Automatically enhances vague acceptance criteria, incomplete requirements, and generic tasks using PlanEnricher (same logic as `plan review --auto-enrich`)
|
|
33
|
+
- Use `--no-enrich-for-speckit` to disable auto-enrichment
|
|
34
|
+
- **Contract extraction**: OpenAPI contracts are extracted automatically **only** for features with `source_tracking.implementation_files` and detectable API endpoints (FastAPI/Flask patterns). For enrichment-added features or Django apps, use `specfact contract init` after enrichment (see Phase 4)
|
|
35
|
+
|
|
36
|
+
2. **LLM Enrichment** (Copilot-only, before applying `--enrichment`):
|
|
37
|
+
- Read CLI artifacts: `.specfact/projects/<bundle>/enrichment_context.md`, feature YAMLs, contract scaffolds, and brownfield reports
|
|
38
|
+
- Scan the codebase within `--entry-point` (and adjacent modules) to identify missing features, dependencies, and behavior; do **not** rely solely on AST-derived YAML
|
|
39
|
+
- Compare code findings vs CLI artifacts, then add missing features/stories, reasoning, and acceptance criteria (each added feature must include at least one story)
|
|
40
|
+
- Save the enrichment report to `.specfact/projects/<bundle-name>/reports/enrichment/<bundle-name>-<timestamp>.enrichment.md` (bundle-specific, Phase 8.5)
|
|
41
|
+
- **CRITICAL**: Follow the exact enrichment report format (see "Enrichment Report Format" section below) to ensure successful parsing
|
|
42
|
+
|
|
43
|
+
3. **Present**: Bundle location, report path, summary (features/stories/contracts/relationships)
|
|
44
|
+
|
|
45
|
+
## CLI Enforcement
|
|
46
|
+
|
|
47
|
+
**CRITICAL**: Always use SpecFact CLI commands. See [CLI Enforcement Rules](./shared/cli-enforcement.md) for details.
|
|
48
|
+
|
|
49
|
+
**Rules:**
|
|
50
|
+
|
|
51
|
+
- Execute CLI first - never create artifacts directly
|
|
52
|
+
- Use the global `--no-interactive` flag in CI/CD environments (must appear before the subcommand)
|
|
53
|
+
- Never modify `.specfact/` directly
|
|
54
|
+
- Use CLI output as grounding for validation
|
|
55
|
+
- Code generation requires LLM (only via AI IDE slash prompts, not CLI-only)
|
|
56
|
+
|
|
57
|
+
## Dual-Stack Workflow (Copilot Mode)
|
|
58
|
+
|
|
59
|
+
When in copilot mode, follow this three-phase workflow:
|
|
60
|
+
|
|
61
|
+
### Phase 1: CLI Grounding (REQUIRED)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Execute CLI to get structured output
|
|
65
|
+
specfact --no-interactive import from-code [<bundle>] --repo <path>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Capture**:
|
|
69
|
+
|
|
70
|
+
- CLI-generated artifacts (plan bundles, reports)
|
|
71
|
+
- Metadata (timestamps, confidence scores)
|
|
72
|
+
- Telemetry (execution time, file counts)
|
|
73
|
+
|
|
74
|
+
### Phase 2: LLM Enrichment (OPTIONAL, Copilot Only)
|
|
75
|
+
|
|
76
|
+
**Purpose**: Add semantic understanding to CLI output
|
|
77
|
+
|
|
78
|
+
**What to do**:
|
|
79
|
+
|
|
80
|
+
- Read CLI-generated artifacts (use file reading tools for display only)
|
|
81
|
+
- Scan the codebase within `--entry-point` for missing features/behavior and compare against CLI artifacts
|
|
82
|
+
- Identify missing features/stories and add reasoning/acceptance criteria (no direct edits to `.specfact/`)
|
|
83
|
+
- Suggest confidence adjustments and extract business context
|
|
84
|
+
- **CRITICAL**: Generate enrichment report in the exact format specified below (see "Enrichment Report Format" section)
|
|
85
|
+
|
|
86
|
+
**What NOT to do**:
|
|
87
|
+
|
|
88
|
+
- ❌ Create YAML/JSON artifacts directly
|
|
89
|
+
- ❌ Modify CLI artifacts directly (use CLI commands to update)
|
|
90
|
+
- ❌ Bypass CLI validation
|
|
91
|
+
- ❌ Write to `.specfact/` folder directly (always use CLI)
|
|
92
|
+
- ❌ Use direct file manipulation tools for writing (use CLI commands)
|
|
93
|
+
- ❌ Deviate from the enrichment report format (will cause parsing failures)
|
|
94
|
+
|
|
95
|
+
**Output**: Generate enrichment report (Markdown) saved to `.specfact/projects/<bundle-name>/reports/enrichment/` (bundle-specific, Phase 8.5)
|
|
96
|
+
|
|
97
|
+
**Enrichment Report Format** (REQUIRED for successful parsing):
|
|
98
|
+
|
|
99
|
+
The enrichment parser expects a specific Markdown format. Follow this structure exactly:
|
|
100
|
+
|
|
101
|
+
```markdown
|
|
102
|
+
# [Bundle Name] Enrichment Report
|
|
103
|
+
|
|
104
|
+
**Date**: YYYY-MM-DDTHH:MM:SS
|
|
105
|
+
**Bundle**: <bundle-name>
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Missing Features
|
|
110
|
+
|
|
111
|
+
1. **Feature Title** (Key: FEATURE-XXX)
|
|
112
|
+
- Confidence: 0.85
|
|
113
|
+
- Outcomes: outcome1, outcome2, outcome3
|
|
114
|
+
- Stories:
|
|
115
|
+
1. Story title here
|
|
116
|
+
- Acceptance: criterion1, criterion2, criterion3
|
|
117
|
+
2. Another story title
|
|
118
|
+
- Acceptance: criterion1, criterion2
|
|
119
|
+
|
|
120
|
+
2. **Another Feature** (Key: FEATURE-YYY)
|
|
121
|
+
- Confidence: 0.80
|
|
122
|
+
- Outcomes: outcome1, outcome2
|
|
123
|
+
- Stories:
|
|
124
|
+
1. Story title
|
|
125
|
+
- Acceptance: criterion1, criterion2, criterion3
|
|
126
|
+
|
|
127
|
+
## Confidence Adjustments
|
|
128
|
+
|
|
129
|
+
- FEATURE-EXISTING-KEY: 0.90 (reason: improved understanding after code review)
|
|
130
|
+
|
|
131
|
+
## Business Context
|
|
132
|
+
|
|
133
|
+
- Priority: High priority feature for core functionality
|
|
134
|
+
- Constraint: Must support both REST and GraphQL APIs
|
|
135
|
+
- Risk: Potential performance issues with large datasets
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Format Requirements**:
|
|
139
|
+
|
|
140
|
+
1. **Section Header**: Must use `## Missing Features` (case-insensitive, but prefer this exact format)
|
|
141
|
+
2. **Feature Format**:
|
|
142
|
+
- Numbered list: `1. **Feature Title** (Key: FEATURE-XXX)`
|
|
143
|
+
- **Bold title** is required (use `**Title**`)
|
|
144
|
+
- **Key in parentheses**: `(Key: FEATURE-XXX)` - must be uppercase, alphanumeric with hyphens/underscores
|
|
145
|
+
- Fields on separate lines with `-` prefix:
|
|
146
|
+
- `- Confidence: 0.85` (float between 0.0-1.0)
|
|
147
|
+
- `- Outcomes: comma-separated or line-separated list`
|
|
148
|
+
- `- Stories:` (required - each feature must have at least one story)
|
|
149
|
+
3. **Stories Format**:
|
|
150
|
+
- Numbered list under `Stories:` section: `1. Story title`
|
|
151
|
+
- **Indentation**: Stories must be indented (2-4 spaces) under the feature
|
|
152
|
+
- **Acceptance Criteria**: `- Acceptance: criterion1, criterion2, criterion3`
|
|
153
|
+
- Can be comma-separated on one line
|
|
154
|
+
- Or multi-line (each criterion on new line)
|
|
155
|
+
- Must start with `- Acceptance:`
|
|
156
|
+
4. **Optional Sections**:
|
|
157
|
+
- `## Confidence Adjustments`: List existing features with confidence updates
|
|
158
|
+
- `## Business Context`: Priorities, constraints, risks (bullet points)
|
|
159
|
+
5. **File Naming**: `<bundle-name>-<timestamp>.enrichment.md` (e.g., `djangogoat-2025-12-23T23-50-00.enrichment.md`)
|
|
160
|
+
|
|
161
|
+
**Example** (working format):
|
|
162
|
+
|
|
163
|
+
```markdown
|
|
164
|
+
## Missing Features
|
|
165
|
+
|
|
166
|
+
1. **User Authentication** (Key: FEATURE-USER-AUTHENTICATION)
|
|
167
|
+
- Confidence: 0.85
|
|
168
|
+
- Outcomes: User registration, login, profile management
|
|
169
|
+
- Stories:
|
|
170
|
+
1. User can sign up for new account
|
|
171
|
+
- Acceptance: sign_up view processes POST requests, creates User automatically, user is logged in after signup, redirects to profile page
|
|
172
|
+
2. User can log in with credentials
|
|
173
|
+
- Acceptance: log_in view authenticates username/password, on success user is logged in and redirected, on failure error message is displayed
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Common Mistakes to Avoid**:
|
|
177
|
+
|
|
178
|
+
- ❌ Missing `(Key: FEATURE-XXX)` - parser needs this to identify features
|
|
179
|
+
- ❌ Missing `Stories:` section - every feature must have at least one story
|
|
180
|
+
- ❌ Stories not indented - parser expects indented numbered lists
|
|
181
|
+
- ❌ Missing `- Acceptance:` prefix - acceptance criteria won't be parsed
|
|
182
|
+
- ❌ Using bullet points (`-`) instead of numbers (`1.`) for stories
|
|
183
|
+
- ❌ Feature title not in bold (`**Title**`) - parser may not extract title correctly
|
|
184
|
+
|
|
185
|
+
### Phase 3: CLI Artifact Creation (REQUIRED)
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# Use enrichment to update plan via CLI
|
|
189
|
+
specfact --no-interactive import from-code [<bundle>] --repo <path> --enrichment <enrichment-report>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Result**: Final artifacts are CLI-generated with validated enrichments
|
|
193
|
+
|
|
194
|
+
**Note**: If code generation is needed, use the validation loop pattern (see [CLI Enforcement Rules](./shared/cli-enforcement.md#standard-validation-loop-pattern-for-llm-generated-code))
|
|
195
|
+
|
|
196
|
+
### Phase 4: OpenAPI Contract Generation (REQUIRED for Sidecar Validation)
|
|
197
|
+
|
|
198
|
+
**When contracts are generated automatically:**
|
|
199
|
+
|
|
200
|
+
The `import from-code` command attempts to extract OpenAPI contracts automatically, but **only if**:
|
|
201
|
+
|
|
202
|
+
1. Features have `source_tracking.implementation_files` (AST-detected features)
|
|
203
|
+
2. The OpenAPI extractor finds API endpoints (FastAPI/Flask patterns like `@app.get`, `@router.post`, `@app.route`)
|
|
204
|
+
|
|
205
|
+
**When contracts are NOT generated:**
|
|
206
|
+
|
|
207
|
+
Contracts are **NOT** generated automatically when:
|
|
208
|
+
|
|
209
|
+
- Features were added via enrichment (no `source_tracking.implementation_files`)
|
|
210
|
+
- Django applications (Django `path()` patterns are not detected by the extractor)
|
|
211
|
+
- Features without API endpoints (models, utilities, middleware, etc.)
|
|
212
|
+
- Framework SDKs or libraries without web endpoints
|
|
213
|
+
|
|
214
|
+
**How to generate contracts manually:**
|
|
215
|
+
|
|
216
|
+
For features that need OpenAPI contracts (e.g., for sidecar validation with CrossHair), use:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Generate contract for a single feature
|
|
220
|
+
specfact --no-interactive contract init --bundle <bundle-name> --feature <FEATURE_KEY> --repo <path>
|
|
221
|
+
|
|
222
|
+
# Example: Generate contracts for all enrichment-added features
|
|
223
|
+
specfact --no-interactive contract init --bundle djangogoat-validation --feature FEATURE-USER-AUTHENTICATION --repo .
|
|
224
|
+
specfact --no-interactive contract init --bundle djangogoat-validation --feature FEATURE-NOTES-MANAGEMENT --repo .
|
|
225
|
+
# ... repeat for each feature that needs a contract
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**When to apply contract generation:**
|
|
229
|
+
|
|
230
|
+
- **After Phase 3** (enrichment applied): Check which features have contracts in `.specfact/projects/<bundle>/contracts/`
|
|
231
|
+
- **Before sidecar validation**: All features that will be analyzed by CrossHair/Specmatic need OpenAPI contracts
|
|
232
|
+
- **For Django apps**: Always generate contracts manually after enrichment, as Django URL patterns are not auto-detected
|
|
233
|
+
|
|
234
|
+
**Verification:**
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Check which features have contracts
|
|
238
|
+
ls .specfact/projects/<bundle>/contracts/*.yaml
|
|
239
|
+
|
|
240
|
+
# Compare with total features
|
|
241
|
+
ls .specfact/projects/<bundle>/features/*.yaml
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
If the contract count is less than the feature count, generate missing contracts using `contract init`.
|
|
245
|
+
|
|
246
|
+
## Expected Output
|
|
247
|
+
|
|
248
|
+
**Success**: Bundle location, report path, summary (features/stories/contracts/relationships)
|
|
249
|
+
**Error**: Missing bundle name or bundle already exists
|
|
250
|
+
|
|
251
|
+
## Common Patterns
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
/specfact.01-import --repo . # Uses active plan, auto-enrichment enabled by default
|
|
255
|
+
/specfact.01-import --bundle legacy-api --repo . # Auto-enrichment enabled
|
|
256
|
+
/specfact.01-import --repo . --no-enrich-for-speckit # Disable auto-enrichment
|
|
257
|
+
/specfact.01-import --repo . --entry-point src/auth/
|
|
258
|
+
/specfact.01-import --repo . --enrichment report.md
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Context
|
|
262
|
+
|
|
263
|
+
{ARGS}
|
|
@@ -107,7 +107,9 @@ specfact plan <operation> [--bundle <name>] [options] --no-interactive
|
|
|
107
107
|
**What to do**:
|
|
108
108
|
|
|
109
109
|
- Read CLI-generated artifacts (use file reading tools for display only)
|
|
110
|
-
-
|
|
110
|
+
- Use CLI artifacts as the source of truth for keys/structure/metadata
|
|
111
|
+
- Scan codebase only if asked to align the plan with implementation or to add missing features
|
|
112
|
+
- When scanning, compare findings against CLI artifacts and propose updates via CLI commands
|
|
111
113
|
- Identify missing features/stories
|
|
112
114
|
- Suggest confidence adjustments
|
|
113
115
|
- Extract business context
|
|
@@ -135,6 +135,9 @@ For these cases, use the **export-to-file → LLM reasoning → import-from-file
|
|
|
135
135
|
|
|
136
136
|
**CRITICAL**: Always use `/tmp/` for temporary artifacts to avoid polluting the codebase. Never create temporary files in the project root.
|
|
137
137
|
|
|
138
|
+
**CRITICAL**: Question IDs are generated per run and can change if you re-run review.
|
|
139
|
+
**Do not** re-run `plan review` between exporting questions and applying answers. Always answer using the exact exported questions file for that session.
|
|
140
|
+
|
|
138
141
|
**Note**: The `--max-questions` parameter (default: 5) limits the number of questions per session, not the total number of available questions. If there are more questions available, you may need to run the review multiple times to answer all questions. Each session will ask different questions (avoiding duplicates from previous sessions).
|
|
139
142
|
|
|
140
143
|
**Export questions to file for LLM reasoning:**
|
|
@@ -397,6 +400,11 @@ specfact plan review [<bundle-name>] --list-questions --output-questions /tmp/qu
|
|
|
397
400
|
|
|
398
401
|
**What to do**:
|
|
399
402
|
|
|
403
|
+
0. **Grounding rule**:
|
|
404
|
+
- Treat CLI-exported questions as the source of truth; consult codebase/docs only to answer them (do not invent new artifacts)
|
|
405
|
+
- **Feature/Story Completeness note**: Answers here are clarifications only. They do **NOT** create stories.
|
|
406
|
+
For missing stories, use `specfact plan add-story` (or `plan update-story --batch-updates` if stories already exist).
|
|
407
|
+
|
|
400
408
|
1. **Read exported questions file** (`/tmp/questions.json`):
|
|
401
409
|
- Review all questions and their categories
|
|
402
410
|
- Identify questions requiring code/feature analysis
|
|
@@ -605,6 +613,102 @@ Create one with: specfact plan init legacy-api
|
|
|
605
613
|
- Use `plan update-idea` to update idea fields directly
|
|
606
614
|
- If bundle needs regeneration, use `import from-code --enrichment`
|
|
607
615
|
|
|
616
|
+
**Note on OpenAPI Contracts:**
|
|
617
|
+
|
|
618
|
+
After applying enrichment or review updates, check if features need OpenAPI contracts for sidecar validation:
|
|
619
|
+
|
|
620
|
+
- Features added via enrichment typically don't have contracts (no `source_tracking`)
|
|
621
|
+
- Django applications require manual contract generation (Django URL patterns not auto-detected)
|
|
622
|
+
- Use `specfact contract init --bundle <bundle> --feature <FEATURE_KEY>` to generate contracts for features that need them
|
|
623
|
+
|
|
624
|
+
**Enrichment Report Format** (for `import from-code --enrichment`):
|
|
625
|
+
|
|
626
|
+
When generating enrichment reports for use with `import from-code --enrichment`, follow this exact format:
|
|
627
|
+
|
|
628
|
+
```markdown
|
|
629
|
+
# [Bundle Name] Enrichment Report
|
|
630
|
+
|
|
631
|
+
**Date**: YYYY-MM-DDTHH:MM:SS
|
|
632
|
+
**Bundle**: <bundle-name>
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## Missing Features
|
|
637
|
+
|
|
638
|
+
1. **Feature Title** (Key: FEATURE-XXX)
|
|
639
|
+
- Confidence: 0.85
|
|
640
|
+
- Outcomes: outcome1, outcome2, outcome3
|
|
641
|
+
- Stories:
|
|
642
|
+
1. Story title here
|
|
643
|
+
- Acceptance: criterion1, criterion2, criterion3
|
|
644
|
+
2. Another story title
|
|
645
|
+
- Acceptance: criterion1, criterion2
|
|
646
|
+
|
|
647
|
+
2. **Another Feature** (Key: FEATURE-YYY)
|
|
648
|
+
- Confidence: 0.80
|
|
649
|
+
- Outcomes: outcome1, outcome2
|
|
650
|
+
- Stories:
|
|
651
|
+
1. Story title
|
|
652
|
+
- Acceptance: criterion1, criterion2, criterion3
|
|
653
|
+
|
|
654
|
+
## Confidence Adjustments
|
|
655
|
+
|
|
656
|
+
- FEATURE-EXISTING-KEY: 0.90 (reason: improved understanding after code review)
|
|
657
|
+
|
|
658
|
+
## Business Context
|
|
659
|
+
|
|
660
|
+
- Priority: High priority feature for core functionality
|
|
661
|
+
- Constraint: Must support both REST and GraphQL APIs
|
|
662
|
+
- Risk: Potential performance issues with large datasets
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
**Format Requirements**:
|
|
666
|
+
|
|
667
|
+
1. **Section Header**: Must use `## Missing Features` (case-insensitive, but prefer this exact format)
|
|
668
|
+
2. **Feature Format**:
|
|
669
|
+
- Numbered list: `1. **Feature Title** (Key: FEATURE-XXX)`
|
|
670
|
+
- **Bold title** is required (use `**Title**`)
|
|
671
|
+
- **Key in parentheses**: `(Key: FEATURE-XXX)` - must be uppercase, alphanumeric with hyphens/underscores
|
|
672
|
+
- Fields on separate lines with `-` prefix:
|
|
673
|
+
- `- Confidence: 0.85` (float between 0.0-1.0)
|
|
674
|
+
- `- Outcomes: comma-separated or line-separated list`
|
|
675
|
+
- `- Stories:` (required - each feature must have at least one story)
|
|
676
|
+
3. **Stories Format**:
|
|
677
|
+
- Numbered list under `Stories:` section: `1. Story title`
|
|
678
|
+
- **Indentation**: Stories must be indented (2-4 spaces) under the feature
|
|
679
|
+
- **Acceptance Criteria**: `- Acceptance: criterion1, criterion2, criterion3`
|
|
680
|
+
- Can be comma-separated on one line
|
|
681
|
+
- Or multi-line (each criterion on new line)
|
|
682
|
+
- Must start with `- Acceptance:`
|
|
683
|
+
4. **Optional Sections**:
|
|
684
|
+
- `## Confidence Adjustments`: List existing features with confidence updates
|
|
685
|
+
- `## Business Context`: Priorities, constraints, risks (bullet points)
|
|
686
|
+
5. **File Naming**: `<bundle-name>-<timestamp>.enrichment.md` (e.g., `djangogoat-2025-12-23T23-50-00.enrichment.md`)
|
|
687
|
+
|
|
688
|
+
**Example** (working format):
|
|
689
|
+
|
|
690
|
+
```markdown
|
|
691
|
+
## Missing Features
|
|
692
|
+
|
|
693
|
+
1. **User Authentication** (Key: FEATURE-USER-AUTHENTICATION)
|
|
694
|
+
- Confidence: 0.85
|
|
695
|
+
- Outcomes: User registration, login, profile management
|
|
696
|
+
- Stories:
|
|
697
|
+
1. User can sign up for new account
|
|
698
|
+
- Acceptance: sign_up view processes POST requests, creates User automatically, user is logged in after signup, redirects to profile page
|
|
699
|
+
2. User can log in with credentials
|
|
700
|
+
- Acceptance: log_in view authenticates username/password, on success user is logged in and redirected, on failure error message is displayed
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
**Common Mistakes to Avoid**:
|
|
704
|
+
|
|
705
|
+
- ❌ Missing `(Key: FEATURE-XXX)` - parser needs this to identify features
|
|
706
|
+
- ❌ Missing `Stories:` section - every feature must have at least one story
|
|
707
|
+
- ❌ Stories not indented - parser expects indented numbered lists
|
|
708
|
+
- ❌ Missing `- Acceptance:` prefix - acceptance criteria won't be parsed
|
|
709
|
+
- ❌ Using bullet points (`-`) instead of numbers (`1.`) for stories
|
|
710
|
+
- ❌ Feature title not in bold (`**Title**`) - parser may not extract title correctly
|
|
711
|
+
|
|
608
712
|
## Context
|
|
609
713
|
|
|
610
714
|
{ARGS}
|
|
@@ -90,6 +90,7 @@ specfact plan harden [<bundle-name>] [--sdd <path>] --no-interactive
|
|
|
90
90
|
**What to do**:
|
|
91
91
|
|
|
92
92
|
- Read CLI-generated SDD (use file reading tools for display only)
|
|
93
|
+
- Treat CLI SDD as the source of truth; scan codebase only to enrich WHY/WHAT/HOW context
|
|
93
94
|
- Research codebase for additional context
|
|
94
95
|
- Suggest improvements to WHY/WHAT/HOW sections
|
|
95
96
|
|
|
@@ -94,6 +94,7 @@ specfact enforce sdd [<bundle-name>] [--sdd <path>] --no-interactive
|
|
|
94
94
|
**What to do**:
|
|
95
95
|
|
|
96
96
|
- Read CLI-generated validation report (use file reading tools for display only)
|
|
97
|
+
- Treat the CLI report as the source of truth; scan codebase only to explain deviations or propose fixes
|
|
97
98
|
- Research codebase for context on deviations
|
|
98
99
|
- Suggest fixes for validation failures
|
|
99
100
|
|
|
@@ -97,6 +97,7 @@ specfact sync bridge --adapter <adapter> --repo <path> [options] --no-interactiv
|
|
|
97
97
|
**What to do**:
|
|
98
98
|
|
|
99
99
|
- Read CLI-generated sync results (use file reading tools for display only)
|
|
100
|
+
- Treat CLI sync output as the source of truth; scan codebase only to explain conflicts
|
|
100
101
|
- Research codebase for context on conflicts
|
|
101
102
|
- Suggest resolution strategies
|
|
102
103
|
|
|
@@ -94,6 +94,7 @@ specfact plan compare [--bundle <name>] [options] --no-interactive
|
|
|
94
94
|
**What to do**:
|
|
95
95
|
|
|
96
96
|
- Read CLI-generated comparison report (use file reading tools for display only)
|
|
97
|
+
- Treat the comparison report as the source of truth; scan codebase only to explain or confirm deviations
|
|
97
98
|
- Research codebase for context on deviations
|
|
98
99
|
- Suggest fixes for missing features or mismatches
|
|
99
100
|
|
|
@@ -96,6 +96,7 @@ specfact repro --repo <path> [options] --no-interactive
|
|
|
96
96
|
**What to do**:
|
|
97
97
|
|
|
98
98
|
- Read CLI-generated validation report (use file reading tools for display only)
|
|
99
|
+
- Treat the validation report as the source of truth; scan codebase only to explain failures
|
|
99
100
|
- Research codebase for context on failures
|
|
100
101
|
- Suggest fixes for validation failures
|
|
101
102
|
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Sidecar Validation Templates
|
|
2
|
+
|
|
3
|
+
Purpose: Run validation tools against a target repository without modifying its source.
|
|
4
|
+
|
|
5
|
+
This template set is intended for Phase B validation and can be copied into a
|
|
6
|
+
separate sidecar workspace. Use `.specfact/projects/<bundle>/contracts/` as the
|
|
7
|
+
source of truth for API contracts (specmatic/OpenAPI).
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
1. Copy this folder into a sidecar workspace, or run:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
./sidecar-init.sh /path/to/sidecar /path/to/target/repo bundle-name
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
1. Export environment variables (or use the `.env` file created by `sidecar-init.sh`):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
export REPO_PATH=/path/to/target/repo
|
|
21
|
+
export BUNDLE_NAME=bundle-name
|
|
22
|
+
export SEMGREP_CONFIG=/path/to/semgrep.yml # optional
|
|
23
|
+
export REPO_PYTHONPATH="/path/to/target/repo/src:/path/to/target/repo"
|
|
24
|
+
export SIDECAR_SOURCE_DIRS="/path/to/target/repo/src" # optional (defaults to src/)
|
|
25
|
+
export PYTHON_CMD=python3 # optional (auto-detects venv if .venv/ or venv/ exists)
|
|
26
|
+
export DJANGO_SETTINGS_MODULE=project.settings # optional (auto-detected for Django projects)
|
|
27
|
+
export SPECMATIC_CMD=/path/to/specmatic # optional (CLI binary, or: "npx --yes specmatic")
|
|
28
|
+
export SPECMATIC_JAR=/path/to/specmatic.jar # optional (java -jar fallback)
|
|
29
|
+
export SPECMATIC_CONFIG=/path/to/specmatic.yaml # optional config file
|
|
30
|
+
export SPECMATIC_TEST_BASE_URL=http://localhost:5000 # optional target
|
|
31
|
+
export SPECMATIC_HOST=localhost # optional target host
|
|
32
|
+
export SPECMATIC_PORT=5000 # optional target port
|
|
33
|
+
export SPECMATIC_TIMEOUT=30 # optional request timeout (seconds)
|
|
34
|
+
export SPECMATIC_AUTO_STUB=1 # optional (default: 1) run stub when no target configured
|
|
35
|
+
export SPECMATIC_STUB_HOST=127.0.0.1 # optional stub host
|
|
36
|
+
export SPECMATIC_STUB_PORT=19000 # optional stub port
|
|
37
|
+
export SPECMATIC_STUB_WAIT=15 # optional stub startup wait (seconds)
|
|
38
|
+
export SIDECAR_APP_CMD="python -m your_app" # optional app command to run
|
|
39
|
+
export SIDECAR_APP_HOST=127.0.0.1 # optional app host
|
|
40
|
+
export SIDECAR_APP_PORT=5000 # optional app port
|
|
41
|
+
export SIDECAR_APP_WAIT=15 # optional app startup wait (seconds)
|
|
42
|
+
export BINDINGS_PATH=/path/to/bindings.yaml # optional bindings map
|
|
43
|
+
export FEATURES_DIR=/path/to/features # optional features dir (FEATURE-*.yaml)
|
|
44
|
+
export CROSSHAIR_VERBOSE=1 # optional CrossHair debug output
|
|
45
|
+
export CROSSHAIR_REPORT_ALL=1 # optional report all postconditions
|
|
46
|
+
export CROSSHAIR_REPORT_VERBOSE=1 # optional report stack traces
|
|
47
|
+
export CROSSHAIR_MAX_UNINTERESTING_ITERATIONS=50 # optional iteration budget
|
|
48
|
+
export CROSSHAIR_PER_PATH_TIMEOUT=2 # optional per-path timeout
|
|
49
|
+
export CROSSHAIR_PER_CONDITION_TIMEOUT=10 # optional per-condition timeout
|
|
50
|
+
export CROSSHAIR_ANALYSIS_KIND=icontract # optional kinds (comma-separated)
|
|
51
|
+
export CROSSHAIR_EXTRA_PLUGIN=/path/to/plugin.py # optional extra plugins
|
|
52
|
+
export RUN_BASEDPYRIGHT=0 # optional toggle per tool (default: 0)
|
|
53
|
+
export TIMEOUT_BASEDPYRIGHT=30 # optional per-tool timeout
|
|
54
|
+
export GENERATE_HARNESS=1 # optional (default: 1)
|
|
55
|
+
export HARNESS_PATH=harness_contracts.py # optional
|
|
56
|
+
export INPUTS_PATH=inputs.json # optional
|
|
57
|
+
export SIDECAR_REPORTS_DIR=/path/to/repo/.specfact/projects/bundle/reports/sidecar # optional
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
1. Run the sidecar script:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
./run_sidecar.sh
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Refreshing the Sidecar Workspace
|
|
67
|
+
|
|
68
|
+
If you update templates (for example `adapters.py`, `run_sidecar.sh`, or the
|
|
69
|
+
harness generator), re-initialize the sidecar workspace so the new templates
|
|
70
|
+
are copied over:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
./sidecar-init.sh /path/to/sidecar /path/to/target/repo bundle-name
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Notes:
|
|
77
|
+
|
|
78
|
+
- This overwrites existing template files in the sidecar workspace.
|
|
79
|
+
- Preserve local changes (for example `bindings.yaml` or `.env`) before
|
|
80
|
+
re-running if you have custom edits.
|
|
81
|
+
- Re-run `./run_sidecar.sh` with `GENERATE_HARNESS=1` if you want a fresh
|
|
82
|
+
`harness_contracts.py` and `inputs.json` after template updates.
|
|
83
|
+
|
|
84
|
+
## Notes
|
|
85
|
+
|
|
86
|
+
- CrossHair requires contracts (icontract/PEP316/deal) or registered contracts.
|
|
87
|
+
Use `harness_contracts.py` or `crosshair_plugin.py` to attach contracts
|
|
88
|
+
externally without touching production code.
|
|
89
|
+
|
|
90
|
+
- **Dual CrossHair Analysis**: The sidecar runs CrossHair in two modes:
|
|
91
|
+
1. **Source code analysis**: Analyzes source directories directly to catch existing decorators
|
|
92
|
+
(beartype, icontract, PEP316, deal) already present in the codebase (e.g., SpecFact CLI dogfooding).
|
|
93
|
+
2. **Harness analysis**: Analyzes generated harness files to catch contracts added externally
|
|
94
|
+
for code without decorators (e.g., DjangoGoat, Flask, Requests).
|
|
95
|
+
|
|
96
|
+
Both analyses are necessary for complete coverage:
|
|
97
|
+
- **Case A**: Code with existing decorators → CrossHair analyzes source directly
|
|
98
|
+
- **Case B**: Code without decorators → CrossHair analyzes harness with externally-added contracts
|
|
99
|
+
- Specmatic contracts are expected in:
|
|
100
|
+
`<REPO_PATH>/.specfact/projects/<BUNDLE_NAME>/contracts/`
|
|
101
|
+
- If you only have the Python `specmatic` package installed, note it does not
|
|
102
|
+
expose a CLI or module runner. Provide a CLI path (`SPECMATIC_CMD`), use `npx`,
|
|
103
|
+
or supply a jar (`SPECMATIC_JAR`) to execute Specmatic in the sidecar.
|
|
104
|
+
- For contract tests that hit a running service, set `SPECMATIC_TEST_BASE_URL`
|
|
105
|
+
(or `SPECMATIC_HOST`/`SPECMATIC_PORT`) so Specmatic knows where to send requests.
|
|
106
|
+
- If you don't have a target service, the sidecar can auto-start a Specmatic
|
|
107
|
+
stub (`SPECMATIC_AUTO_STUB=1`) or launch a real service with `SIDECAR_APP_CMD`.
|
|
108
|
+
- All reports/logs should be written to SpecFact bundle reports, not into the
|
|
109
|
+
target repo.
|
|
110
|
+
|
|
111
|
+
## CrossHair Defaults (Suggested)
|
|
112
|
+
|
|
113
|
+
These defaults provide stable results for most repositories; tune them if your
|
|
114
|
+
codebase is large or has heavy initialization.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
export CROSSHAIR_ANALYSIS_KIND=icontract
|
|
118
|
+
export CROSSHAIR_PER_PATH_TIMEOUT=2
|
|
119
|
+
export CROSSHAIR_PER_CONDITION_TIMEOUT=10
|
|
120
|
+
export CROSSHAIR_MAX_UNINTERESTING_ITERATIONS=50
|
|
121
|
+
export CROSSHAIR_REPORT_ALL=1
|
|
122
|
+
export CROSSHAIR_REPORT_VERBOSE=0
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Tool Toggles & Timeouts
|
|
126
|
+
|
|
127
|
+
The sidecar runner supports basic toggles (set to `0` to skip):
|
|
128
|
+
|
|
129
|
+
- `RUN_SEMGREP`, `RUN_BASEDPYRIGHT`, `RUN_SPECMATIC`, `RUN_CROSSHAIR`
|
|
130
|
+
- `GENERATE_HARNESS` (generate `harness_contracts.py` and `inputs.json` from OpenAPI)
|
|
131
|
+
|
|
132
|
+
And per-tool timeouts in seconds:
|
|
133
|
+
|
|
134
|
+
- `TIMEOUT_SEMGREP`, `TIMEOUT_BASEDPYRIGHT`, `TIMEOUT_SPECMATIC`, `TIMEOUT_CROSSHAIR`
|
|
135
|
+
|
|
136
|
+
## Harness Generation
|
|
137
|
+
|
|
138
|
+
The harness is auto-generated from OpenAPI contracts in:
|
|
139
|
+
`<REPO_PATH>/.specfact/projects/<BUNDLE_NAME>/contracts/`
|
|
140
|
+
|
|
141
|
+
Generated outputs (in the sidecar workspace):
|
|
142
|
+
|
|
143
|
+
- `harness_contracts.py` (CrossHair harness)
|
|
144
|
+
- `inputs.json` (deterministic example requests/responses)
|
|
145
|
+
- `bindings.yaml` (optional mapping to real code)
|
|
146
|
+
|
|
147
|
+
Bindings let you attach harness functions to real code without editing the repo.
|
|
148
|
+
If `bindings.yaml` is present, the harness will call the bound function instead
|
|
149
|
+
of returning a fixed example.
|
|
150
|
+
|
|
151
|
+
Binding schema (minimal):
|
|
152
|
+
|
|
153
|
+
```yaml
|
|
154
|
+
bindings:
|
|
155
|
+
- operation_id: create_item
|
|
156
|
+
target: your_package.factory:ItemFactory
|
|
157
|
+
method: create
|
|
158
|
+
factory:
|
|
159
|
+
args: ["$request.item_type"]
|
|
160
|
+
call_style: kwargs
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Optional keys:
|
|
164
|
+
|
|
165
|
+
- `adapter`: name of a function in `adapters.py` to handle complex setup.
|
|
166
|
+
- `factory.target`: alternate factory callable (module:func) to create instance.
|
|
167
|
+
- `factory.args` / `factory.kwargs`: supports `$request.<key>` or `$env.<VAR>` values.
|
|
168
|
+
|
|
169
|
+
Available adapters (see `adapters.py` for config fields):
|
|
170
|
+
|
|
171
|
+
- `call_method_with_factory`: construct instance then call method.
|
|
172
|
+
- `call_constructor_then_method`: construct instance via `init` and call method.
|
|
173
|
+
- `call_classmethod`: call a classmethod/staticmethod on a class target.
|
|
174
|
+
- `call_with_context_manager`: create resource in `with` block then call method.
|
|
175
|
+
- `call_async`: call async function and run the coroutine.
|
|
176
|
+
- `call_with_setup_teardown`: run setup/teardown around a target call.
|
|
177
|
+
- `call_with_request_transform`: rename/drop/set/coerce request fields before call.
|
|
178
|
+
- `call_generator`: consume a generator/iterator and return list/last/count.
|
|
179
|
+
- `call_from_registry`: resolve a callable from a registry/entrypoint map.
|
|
180
|
+
- `call_with_overrides`: temporarily override module attributes during a call.
|
|
181
|
+
- `call_with_contextvars`: set context variables for the call duration.
|
|
182
|
+
- `call_with_session`: create a session/transaction around the call.
|
|
183
|
+
- `call_with_callbacks`: inject callbacks into the request payload.
|
|
184
|
+
|
|
185
|
+
Logs are written to:
|
|
186
|
+
|
|
187
|
+
- `<REPO_PATH>/.specfact/projects/<BUNDLE_NAME>/reports/sidecar/`
|
|
File without changes
|