specfact-cli 0.15.2__tar.gz → 0.15.3__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.15.2 → specfact_cli-0.15.3}/PKG-INFO +1 -1
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/pyproject.toml +1 -1
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.03-review.md +9 -2
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/__init__.py +1 -1
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/__init__.py +1 -1
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/plan.py +30 -5
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/.gitignore +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/LICENSE.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/README.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/mappings/node-async.yaml +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/mappings/python-async.yaml +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/mappings/speckit-default.yaml +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/shared/cli-enforcement.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.01-import.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.02-plan.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.04-sdd.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.05-enforce.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.06-sync.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.07-contracts.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.compare.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/prompts/specfact.validate.md +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/schemas/deviation.schema.json +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/schemas/plan.schema.json +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/schemas/protocol.schema.json +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/templates/github-action.yml.j2 +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/templates/plan.bundle.yaml.j2 +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/templates/pr-template.md.j2 +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/templates/protocol.yaml.j2 +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/resources/templates/telemetry.yaml.example +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/agents/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/agents/analyze_agent.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/agents/base.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/agents/plan_agent.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/agents/registry.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/agents/sync_agent.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/cli.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/analyze.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/bridge.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/drift.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/enforce.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/generate.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/implement.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/import_cmd.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/init.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/migrate.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/repro.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/run.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/sdd.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/spec.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/commands/sync.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/common/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/common/logger_setup.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/common/logging_utils.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/common/text_utils.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/common/utils.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/comparators/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/comparators/plan_comparator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/contract_generator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/openapi_extractor.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/plan_generator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/protocol_generator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/report_generator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/task_generator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/test_to_openapi.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/workflow_generator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/importers/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/importers/speckit_converter.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/importers/speckit_scanner.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/integrations/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/integrations/specmatic.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/migrations/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/migrations/plan_migrator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/bridge.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/deviation.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/enforcement.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/plan.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/project.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/protocol.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/quality.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/sdd.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/source_tracking.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/models/task.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/modes/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/modes/detector.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/modes/router.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/resources/semgrep/async.yml +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/runtime.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/bridge_probe.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/bridge_sync.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/bridge_watch.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/change_detector.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/code_to_spec.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/drift_detector.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/repository_sync.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/spec_to_code.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/spec_to_tests.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/speckit_sync.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/watcher.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/telemetry.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/templates/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/templates/bridge_templates.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/templates/specification_templates.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/bundle_loader.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/console.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/context_detection.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/enrichment_context.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/enrichment_parser.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/feature_keys.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/git.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/github_annotations.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/ide_setup.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/incremental_check.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/optional_deps.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/performance.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/progress.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/prompts.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/sdd_discovery.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/source_scanner.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/structure.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/structured_io.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/suggestions.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/yaml_utils.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/__init__.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/cli_first_validator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/contract_validator.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/fsm.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/repro_checker.py +0 -0
- {specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/schema.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specfact-cli
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.3
|
|
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.15.
|
|
7
|
+
version = "0.15.3"
|
|
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"
|
|
@@ -101,6 +101,7 @@ The recommendation helps less-experienced users make informed decisions.
|
|
|
101
101
|
- `--list-questions` - Output questions in JSON format. Default: False
|
|
102
102
|
- `--output-questions PATH` - Save questions directly to file (JSON format). Use with `--list-questions` to save instead of stdout. Default: None
|
|
103
103
|
- `--list-findings` - Output all findings in structured format. Default: False
|
|
104
|
+
- `--output-findings PATH` - Save findings directly to file (JSON/YAML format). Use with `--list-findings` to save instead of stdout. Default: None
|
|
104
105
|
- `--findings-format FORMAT` - Output format: json, yaml, or table. Default: json for non-interactive, table for interactive
|
|
105
106
|
|
|
106
107
|
### Behavior/Options
|
|
@@ -150,7 +151,11 @@ specfact plan review [<bundle-name>] --list-questions --output-questions /tmp/qu
|
|
|
150
151
|
```bash
|
|
151
152
|
# Get findings (saves to stdout - can redirect to /tmp/)
|
|
152
153
|
# Use /tmp/ to avoid polluting the codebase
|
|
154
|
+
# Option 1: Redirect output (includes CLI banner - not recommended)
|
|
153
155
|
specfact plan review [<bundle-name>] --list-findings --findings-format json --no-interactive > /tmp/findings.json
|
|
156
|
+
|
|
157
|
+
# Option 2: Save directly to file (recommended - clean JSON only)
|
|
158
|
+
specfact plan review [<bundle-name>] --list-findings --output-findings /tmp/findings.json --no-interactive
|
|
154
159
|
```
|
|
155
160
|
|
|
156
161
|
**Note**: The `--output-questions` option saves questions directly to a file, avoiding the need for complex JSON parsing. The ambiguity scanner now recognizes the simplified format (e.g., "Must verify X works correctly (see contract examples)") as valid and will not flag it as vague.
|
|
@@ -362,7 +367,8 @@ When in copilot mode, follow this three-phase workflow:
|
|
|
362
367
|
|
|
363
368
|
```bash
|
|
364
369
|
# Option 1: Get findings (redirect to /tmp/ to avoid polluting codebase)
|
|
365
|
-
|
|
370
|
+
# Option 1: Save findings directly to file (recommended - clean JSON only)
|
|
371
|
+
specfact plan review [<bundle-name>] --list-findings --output-findings /tmp/findings.json --no-interactive
|
|
366
372
|
|
|
367
373
|
# Option 2: Get questions and save directly to /tmp/ (recommended - avoids JSON parsing)
|
|
368
374
|
specfact plan review [<bundle-name>] --list-questions --output-questions /tmp/questions.json --no-interactive
|
|
@@ -513,6 +519,7 @@ Create one with: specfact plan init legacy-api
|
|
|
513
519
|
# Get findings first
|
|
514
520
|
/specfact.03-review --list-findings # List all findings
|
|
515
521
|
/specfact.03-review --list-findings --findings-format json # JSON format for enrichment
|
|
522
|
+
/specfact.03-review --list-findings --output-findings /tmp/findings.json # Save findings to file (clean JSON)
|
|
516
523
|
|
|
517
524
|
# Interactive review
|
|
518
525
|
/specfact.03-review # Uses active plan (default: 5 questions per session)
|
|
@@ -557,7 +564,7 @@ Create one with: specfact plan init legacy-api
|
|
|
557
564
|
2. **Get findings** (optional, for comprehensive analysis - use `/tmp/`):
|
|
558
565
|
|
|
559
566
|
```bash
|
|
560
|
-
specfact plan review [<bundle-name>] --list-findings --findings
|
|
567
|
+
specfact plan review [<bundle-name>] --list-findings --output-findings /tmp/findings.json --no-interactive
|
|
561
568
|
```
|
|
562
569
|
|
|
563
570
|
3. **LLM reasoning and user selection** (REQUIRED for partial findings):
|
|
@@ -2985,6 +2985,7 @@ def _output_findings(
|
|
|
2985
2985
|
report: Any, # AmbiguityReport (imported locally to avoid circular dependency)
|
|
2986
2986
|
findings_format: str | None,
|
|
2987
2987
|
is_non_interactive: bool,
|
|
2988
|
+
output_path: Path | None = None,
|
|
2988
2989
|
) -> None:
|
|
2989
2990
|
"""
|
|
2990
2991
|
Output findings in structured format or table.
|
|
@@ -2993,9 +2994,15 @@ def _output_findings(
|
|
|
2993
2994
|
report: Ambiguity report
|
|
2994
2995
|
findings_format: Output format (json, yaml, table)
|
|
2995
2996
|
is_non_interactive: Whether in non-interactive mode
|
|
2997
|
+
output_path: Optional file path to save findings. If None, outputs to stdout.
|
|
2996
2998
|
"""
|
|
2999
|
+
from rich.console import Console
|
|
3000
|
+
from rich.table import Table
|
|
3001
|
+
|
|
2997
3002
|
from specfact_cli.analyzers.ambiguity_scanner import AmbiguityStatus
|
|
2998
3003
|
|
|
3004
|
+
console = Console()
|
|
3005
|
+
|
|
2999
3006
|
# Determine output format
|
|
3000
3007
|
output_format_str = findings_format
|
|
3001
3008
|
if not output_format_str:
|
|
@@ -3069,7 +3076,7 @@ def _output_findings(
|
|
|
3069
3076
|
import sys
|
|
3070
3077
|
|
|
3071
3078
|
if output_format_str == "json":
|
|
3072
|
-
|
|
3079
|
+
formatted_output = json.dumps(findings_data, indent=2) + "\n"
|
|
3073
3080
|
else: # yaml
|
|
3074
3081
|
from ruamel.yaml import YAML
|
|
3075
3082
|
|
|
@@ -3080,9 +3087,20 @@ def _output_findings(
|
|
|
3080
3087
|
|
|
3081
3088
|
output = StringIO()
|
|
3082
3089
|
yaml.dump(findings_data, output)
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3090
|
+
formatted_output = output.getvalue()
|
|
3091
|
+
|
|
3092
|
+
if output_path:
|
|
3093
|
+
# Save to file
|
|
3094
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
3095
|
+
output_path.write_text(formatted_output, encoding="utf-8")
|
|
3096
|
+
from rich.console import Console
|
|
3097
|
+
|
|
3098
|
+
console = Console()
|
|
3099
|
+
console.print(f"[green]✓[/green] Findings saved to: {output_path}")
|
|
3100
|
+
else:
|
|
3101
|
+
# Output to stdout
|
|
3102
|
+
sys.stdout.write(formatted_output)
|
|
3103
|
+
sys.stdout.flush()
|
|
3086
3104
|
else:
|
|
3087
3105
|
print_error(f"Invalid findings format: {findings_format}. Must be 'json', 'yaml', or 'table'")
|
|
3088
3106
|
raise typer.Exit(1)
|
|
@@ -3987,6 +4005,11 @@ def review(
|
|
|
3987
4005
|
case_sensitive=False,
|
|
3988
4006
|
hidden=True, # Hidden by default, shown with --help-advanced
|
|
3989
4007
|
),
|
|
4008
|
+
output_findings: Path | None = typer.Option(
|
|
4009
|
+
None,
|
|
4010
|
+
"--output-findings",
|
|
4011
|
+
help="Save findings to file (JSON/YAML format). If --list-findings is also set, findings are saved to file instead of stdout. Default: None",
|
|
4012
|
+
),
|
|
3990
4013
|
# Behavior/Options
|
|
3991
4014
|
no_interactive: bool = typer.Option(
|
|
3992
4015
|
False,
|
|
@@ -4031,7 +4054,9 @@ def review(
|
|
|
4031
4054
|
specfact plan review legacy-api
|
|
4032
4055
|
specfact plan review auth-module --max-questions 3 --category "Functional Scope"
|
|
4033
4056
|
specfact plan review legacy-api --list-questions # Output questions as JSON
|
|
4057
|
+
specfact plan review legacy-api --list-questions --output-questions /tmp/questions.json # Save questions to file
|
|
4034
4058
|
specfact plan review legacy-api --list-findings --findings-format json # Output all findings as JSON
|
|
4059
|
+
specfact plan review legacy-api --list-findings --output-findings /tmp/findings.json # Save findings to file
|
|
4035
4060
|
specfact plan review legacy-api --answers '{"Q001": "answer1", "Q002": "answer2"}' # Non-interactive
|
|
4036
4061
|
"""
|
|
4037
4062
|
from rich.console import Console
|
|
@@ -4095,7 +4120,7 @@ def review(
|
|
|
4095
4120
|
|
|
4096
4121
|
# Handle --list-findings mode
|
|
4097
4122
|
if list_findings:
|
|
4098
|
-
_output_findings(report, findings_format, is_non_interactive)
|
|
4123
|
+
_output_findings(report, findings_format, is_non_interactive, output_findings)
|
|
4099
4124
|
raise typer.Exit(0)
|
|
4100
4125
|
|
|
4101
4126
|
# Show initial coverage summary BEFORE questions (so user knows what's missing)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/contract_extractor.py
RENAMED
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/control_flow_analyzer.py
RENAMED
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/relationship_mapper.py
RENAMED
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/requirement_extractor.py
RENAMED
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/analyzers/test_pattern_extractor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/enrichers/constitution_enricher.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/contract_generator.py
RENAMED
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/openapi_extractor.py
RENAMED
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/protocol_generator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/generators/workflow_generator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/resources/semgrep/code-quality.yml
RENAMED
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/resources/semgrep/feature-detection.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/templates/specification_templates.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/utils/progressive_disclosure.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/cli_first_validator.py
RENAMED
|
File without changes
|
{specfact_cli-0.15.2 → specfact_cli-0.15.3}/src/specfact_cli/validators/contract_validator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|