specfact-cli 0.14.0__tar.gz → 0.15.0__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.
Files changed (151) hide show
  1. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/PKG-INFO +1 -1
  2. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/pyproject.toml +1 -1
  3. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.01-import.md +8 -5
  4. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.03-review.md +9 -4
  5. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.04-sdd.md +4 -4
  6. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.05-enforce.md +3 -3
  7. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.compare.md +2 -2
  8. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.validate.md +2 -2
  9. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/__init__.py +1 -1
  10. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/__init__.py +1 -1
  11. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/code_analyzer.py +34 -5
  12. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/control_flow_analyzer.py +9 -23
  13. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/cli.py +8 -1
  14. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/enforce.py +10 -9
  15. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/generate.py +16 -12
  16. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/implement.py +3 -3
  17. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/import_cmd.py +52 -65
  18. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/init.py +1 -0
  19. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/migrate.py +456 -0
  20. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/plan.py +34 -5
  21. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/repro.py +12 -5
  22. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/sdd.py +5 -2
  23. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/spec.py +1 -0
  24. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/sync.py +4 -0
  25. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/enrichers/plan_enricher.py +47 -18
  26. specfact_cli-0.15.0/src/specfact_cli/sync/watcher_enhanced.py +493 -0
  27. specfact_cli-0.15.0/src/specfact_cli/templates/__init__.py +8 -0
  28. specfact_cli-0.15.0/src/specfact_cli/templates/specification_templates.py +146 -0
  29. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/bundle_loader.py +3 -2
  30. specfact_cli-0.15.0/src/specfact_cli/utils/context_detection.py +269 -0
  31. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/github_annotations.py +35 -10
  32. specfact_cli-0.15.0/src/specfact_cli/utils/progressive_disclosure.py +326 -0
  33. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/sdd_discovery.py +27 -15
  34. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/structure.py +334 -50
  35. specfact_cli-0.15.0/src/specfact_cli/utils/suggestions.py +155 -0
  36. specfact_cli-0.14.0/src/specfact_cli/templates/__init__.py +0 -13
  37. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/.gitignore +0 -0
  38. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/LICENSE.md +0 -0
  39. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/README.md +0 -0
  40. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/mappings/node-async.yaml +0 -0
  41. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/mappings/python-async.yaml +0 -0
  42. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/mappings/speckit-default.yaml +0 -0
  43. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/shared/cli-enforcement.md +0 -0
  44. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.02-plan.md +0 -0
  45. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.06-sync.md +0 -0
  46. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/prompts/specfact.07-contracts.md +0 -0
  47. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/schemas/deviation.schema.json +0 -0
  48. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/schemas/plan.schema.json +0 -0
  49. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/schemas/protocol.schema.json +0 -0
  50. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/templates/github-action.yml.j2 +0 -0
  51. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/templates/plan.bundle.yaml.j2 +0 -0
  52. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/templates/pr-template.md.j2 +0 -0
  53. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/templates/protocol.yaml.j2 +0 -0
  54. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/resources/templates/telemetry.yaml.example +0 -0
  55. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/agents/__init__.py +0 -0
  56. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/agents/analyze_agent.py +0 -0
  57. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/agents/base.py +0 -0
  58. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/agents/plan_agent.py +0 -0
  59. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/agents/registry.py +0 -0
  60. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/agents/sync_agent.py +0 -0
  61. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/__init__.py +0 -0
  62. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
  63. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
  64. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
  65. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
  66. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
  67. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
  68. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
  69. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/__init__.py +0 -0
  70. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/analyze.py +0 -0
  71. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/bridge.py +0 -0
  72. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/drift.py +0 -0
  73. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/commands/run.py +0 -0
  74. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/common/__init__.py +0 -0
  75. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/common/logger_setup.py +0 -0
  76. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/common/logging_utils.py +0 -0
  77. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/common/text_utils.py +0 -0
  78. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/common/utils.py +0 -0
  79. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/comparators/__init__.py +0 -0
  80. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/comparators/plan_comparator.py +0 -0
  81. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
  82. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/__init__.py +0 -0
  83. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/contract_generator.py +0 -0
  84. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/openapi_extractor.py +0 -0
  85. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/plan_generator.py +0 -0
  86. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/protocol_generator.py +0 -0
  87. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/report_generator.py +0 -0
  88. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/task_generator.py +0 -0
  89. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/test_to_openapi.py +0 -0
  90. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/generators/workflow_generator.py +0 -0
  91. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/importers/__init__.py +0 -0
  92. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/importers/speckit_converter.py +0 -0
  93. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/importers/speckit_scanner.py +0 -0
  94. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/integrations/__init__.py +0 -0
  95. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/integrations/specmatic.py +0 -0
  96. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/migrations/__init__.py +0 -0
  97. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/migrations/plan_migrator.py +0 -0
  98. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/__init__.py +0 -0
  99. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/bridge.py +0 -0
  100. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/deviation.py +0 -0
  101. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/enforcement.py +0 -0
  102. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/plan.py +0 -0
  103. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/project.py +0 -0
  104. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/protocol.py +0 -0
  105. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/quality.py +0 -0
  106. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/sdd.py +0 -0
  107. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/source_tracking.py +0 -0
  108. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/models/task.py +0 -0
  109. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/modes/__init__.py +0 -0
  110. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/modes/detector.py +0 -0
  111. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/modes/router.py +0 -0
  112. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/resources/semgrep/async.yml +0 -0
  113. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
  114. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
  115. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/runtime.py +0 -0
  116. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/__init__.py +0 -0
  117. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/bridge_probe.py +0 -0
  118. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/bridge_sync.py +0 -0
  119. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/bridge_watch.py +0 -0
  120. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/change_detector.py +0 -0
  121. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/code_to_spec.py +0 -0
  122. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/drift_detector.py +0 -0
  123. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/repository_sync.py +0 -0
  124. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/spec_to_code.py +0 -0
  125. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/spec_to_tests.py +0 -0
  126. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/speckit_sync.py +0 -0
  127. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/sync/watcher.py +0 -0
  128. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/telemetry.py +0 -0
  129. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/templates/bridge_templates.py +0 -0
  130. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/__init__.py +0 -0
  131. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
  132. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/console.py +0 -0
  133. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/enrichment_context.py +0 -0
  134. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/enrichment_parser.py +0 -0
  135. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/feature_keys.py +0 -0
  136. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/git.py +0 -0
  137. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/ide_setup.py +0 -0
  138. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/incremental_check.py +0 -0
  139. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/optional_deps.py +0 -0
  140. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/performance.py +0 -0
  141. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/progress.py +0 -0
  142. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/prompts.py +0 -0
  143. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/source_scanner.py +0 -0
  144. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/structured_io.py +0 -0
  145. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/utils/yaml_utils.py +0 -0
  146. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/validators/__init__.py +0 -0
  147. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/validators/cli_first_validator.py +0 -0
  148. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/validators/contract_validator.py +0 -0
  149. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/validators/fsm.py +0 -0
  150. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/src/specfact_cli/validators/repro_checker.py +0 -0
  151. {specfact_cli-0.14.0 → specfact_cli-0.15.0}/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.14.0
3
+ Version: 0.15.0
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.14.0"
7
+ version = "0.15.0"
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"
@@ -20,7 +20,7 @@ Import codebase → plan bundle. CLI extracts routes/schemas/relationships/contr
20
20
 
21
21
  **Target/Input**: `--bundle NAME` (optional, defaults to active plan), `--repo PATH`, `--entry-point PATH`, `--enrichment PATH`
22
22
  **Output/Results**: `--report PATH`
23
- **Behavior/Options**: `--shadow-only`, `--enrich-for-speckit`
23
+ **Behavior/Options**: `--shadow-only`, `--enrich-for-speckit/--no-enrich-for-speckit` (default: enabled, uses PlanEnricher for consistent enrichment)
24
24
  **Advanced/Configuration**: `--confidence FLOAT` (0.0-1.0), `--key-format FORMAT` (classname|sequential)
25
25
 
26
26
  ## Workflow
@@ -28,12 +28,14 @@ Import codebase → plan bundle. CLI extracts routes/schemas/relationships/contr
28
28
  1. **Execute CLI**: `specfact import from-code [<bundle>] --repo <path> [options]`
29
29
  - CLI extracts: routes (FastAPI/Flask/Django), schemas (Pydantic), relationships, contracts (OpenAPI scaffolds), source tracking
30
30
  - Uses active plan if bundle not specified
31
+ - **Auto-enrichment enabled by default**: Automatically enhances vague acceptance criteria, incomplete requirements, and generic tasks using PlanEnricher (same logic as `plan review --auto-enrich`)
32
+ - Use `--no-enrich-for-speckit` to disable auto-enrichment
31
33
 
32
34
  2. **LLM Enrichment** (if `--enrichment` provided):
33
35
  - Read `.specfact/projects/<bundle>/enrichment_context.md`
34
36
  - Enrich: business context, "why" reasoning, missing acceptance criteria
35
37
  - Validate: contracts vs code, feature/story alignment
36
- - Save enrichment report to `.specfact/reports/enrichment/` (if created)
38
+ - Save enrichment report to `.specfact/projects/<bundle-name>/reports/enrichment/` (bundle-specific, Phase 8.5, if created)
37
39
 
38
40
  3. **Present**: Bundle location, report path, summary (features/stories/contracts/relationships)
39
41
 
@@ -86,7 +88,7 @@ specfact import from-code [<bundle>] --repo <path> --no-interactive
86
88
  - ❌ Write to `.specfact/` folder directly (always use CLI)
87
89
  - ❌ Use direct file manipulation tools for writing (use CLI commands)
88
90
 
89
- **Output**: Generate enrichment report (Markdown) saved to `.specfact/reports/enrichment/`
91
+ **Output**: Generate enrichment report (Markdown) saved to `.specfact/projects/<bundle-name>/reports/enrichment/` (bundle-specific, Phase 8.5)
90
92
 
91
93
  ### Phase 3: CLI Artifact Creation (REQUIRED)
92
94
 
@@ -107,8 +109,9 @@ specfact import from-code [<bundle>] --repo <path> --enrichment <enrichment-repo
107
109
  ## Common Patterns
108
110
 
109
111
  ```bash
110
- /specfact.01-import --repo . # Uses active plan
111
- /specfact.01-import --bundle legacy-api --repo .
112
+ /specfact.01-import --repo . # Uses active plan, auto-enrichment enabled by default
113
+ /specfact.01-import --bundle legacy-api --repo . # Auto-enrichment enabled
114
+ /specfact.01-import --repo . --no-enrich-for-speckit # Disable auto-enrichment
112
115
  /specfact.01-import --repo . --entry-point src/auth/
113
116
  /specfact.01-import --repo . --enrichment report.md
114
117
  ```
@@ -37,7 +37,7 @@ Review project bundle to identify/resolve ambiguities and missing information. A
37
37
 
38
38
  - `--no-interactive` - Non-interactive mode (for CI/CD). Default: False (interactive mode)
39
39
  - `--answers JSON` - JSON object with question_id -> answer mappings. Default: None
40
- - `--auto-enrich` - Automatically enrich vague acceptance criteria. Default: False
40
+ - `--auto-enrich` - Automatically enrich vague acceptance criteria using PlanEnricher (same enrichment logic as `import from-code`). Default: False (opt-in for review, but import has auto-enrichment enabled by default)
41
41
 
42
42
  ### Advanced/Configuration
43
43
 
@@ -260,16 +260,21 @@ Create one with: specfact plan init legacy-api
260
260
 
261
261
  ## Enrichment Workflow
262
262
 
263
+ **Note**: Import command (`specfact import from-code`) has **auto-enrichment enabled by default** using PlanEnricher. Review command requires explicit `--auto-enrich` flag.
264
+
263
265
  **Typical workflow when enrichment is needed:**
264
266
 
265
267
  1. **Get findings**: `specfact plan review --list-findings --findings-format json`
266
268
  2. **Analyze findings**: Review missing information (target_users, value_hypothesis, etc.)
267
- 3. **Create enrichment report**: Write Markdown file addressing findings
268
- 4. **Apply enrichment**:
269
+ 3. **Apply automatic enrichment** (if needed):
270
+ - **During import**: Auto-enrichment happens automatically (enabled by default)
271
+ - **After import**: Use `specfact plan review --auto-enrich` to enhance vague criteria
272
+ 4. **Create enrichment report** (for business context, confidence adjustments, missing features): Write Markdown file addressing findings
273
+ 5. **Apply manual enrichment**:
269
274
  - **Preferred**: Use enrichment to create `--answers` JSON and run `plan review --answers`
270
275
  - **Alternative**: Use `plan update-idea` to update idea fields directly
271
276
  - **Last resort**: If bundle needs regeneration, use `import from-code --enrichment`
272
- 5. **Verify**: Run `plan review` again to confirm improvements
277
+ 6. **Verify**: Run `plan review` again to confirm improvements
273
278
 
274
279
  ## Context
275
280
 
@@ -25,7 +25,7 @@ Create/update SDD manifest from project bundle. Captures WHY (intent/constraints
25
25
  ### Target/Input
26
26
 
27
27
  - `bundle NAME` (optional argument) - Project bundle name (e.g., legacy-api, auth-module). Default: active plan (set via `plan select`)
28
- - `--sdd PATH` - Output SDD manifest path. Default: .specfact/sdd/<bundle-name>.<format>
28
+ - `--sdd PATH` - Output SDD manifest path. Default: bundle-specific .specfact/projects/<bundle-name>/sdd.<format> (Phase 8.5)
29
29
 
30
30
  ### Output/Results
31
31
 
@@ -119,12 +119,12 @@ specfact plan harden [<bundle-name>] --no-interactive
119
119
  ### Success
120
120
 
121
121
  ```text
122
- ✓ SDD manifest created: .specfact/sdd/legacy-api.yaml
122
+ ✓ SDD manifest created: .specfact/projects/legacy-api/sdd.yaml
123
123
 
124
124
  SDD Manifest Summary:
125
125
  Project Bundle: .specfact/projects/legacy-api/
126
126
  Bundle Hash: abc123def456...
127
- SDD Path: .specfact/sdd/legacy-api.yaml
127
+ SDD Path: .specfact/projects/legacy-api/sdd.yaml
128
128
 
129
129
  WHY (Intent):
130
130
  Build secure authentication system
@@ -151,7 +151,7 @@ Create one with: specfact plan init legacy-api
151
151
  /specfact.04-sdd # Uses active plan
152
152
  /specfact.04-sdd legacy-api # Specific bundle
153
153
  /specfact.04-sdd --output-format json # JSON format
154
- /specfact.04-sdd --sdd .specfact/sdd/custom.yaml
154
+ /specfact.04-sdd --sdd .specfact/projects/custom-bundle/sdd.yaml
155
155
  ```
156
156
 
157
157
  ## Context
@@ -25,12 +25,12 @@ Validate SDD manifest against project bundle and contracts. Checks hash matching
25
25
  ### Target/Input
26
26
 
27
27
  - `bundle NAME` (optional argument) - Project bundle name (e.g., legacy-api, auth-module). Default: active plan (set via `plan select`)
28
- - `--sdd PATH` - Path to SDD manifest. Default: .specfact/sdd/<bundle-name>.<format>
28
+ - `--sdd PATH` - Path to SDD manifest. Default: bundle-specific .specfact/projects/<bundle-name>/sdd.<format> (Phase 8.5), with fallback to legacy .specfact/sdd/<bundle-name>.<format>
29
29
 
30
30
  ### Output/Results
31
31
 
32
32
  - `--output-format FORMAT` - Output format (yaml, json, markdown). Default: yaml
33
- - `--out PATH` - Output file path. Default: .specfact/reports/sdd/validation-<timestamp>.<format>
33
+ - `--out PATH` - Output file path. Default: bundle-specific .specfact/projects/<bundle-name>/reports/enforcement/report-<timestamp>.<format> (Phase 8.5)
34
34
 
35
35
  ### Behavior/Options
36
36
 
@@ -131,7 +131,7 @@ Total deviations: 0
131
131
  Medium: 0
132
132
  Low: 0
133
133
 
134
- Report saved to: .specfact/reports/sdd/validation-2025-11-26T10-30-00.yaml
134
+ Report saved to: .specfact/projects/<bundle-name>/reports/enforcement/report-2025-11-26T10-30-00.yaml
135
135
  ```
136
136
 
137
137
  ### Failure (Hash Mismatch)
@@ -31,7 +31,7 @@ Compare two project bundles (or legacy plan bundles) to detect deviations, misma
31
31
  ### Output/Results
32
32
 
33
33
  - `--output-format FORMAT` - Output format (markdown, json, yaml). Default: markdown
34
- - `--out PATH` - Output file path. Default: .specfact/reports/comparison/deviations-<timestamp>.md
34
+ - `--out PATH` - Output file path. Default: bundle-specific .specfact/projects/<bundle-name>/reports/comparison/report-<timestamp>.md (Phase 8.5), or global .specfact/reports/comparison/ if no bundle context
35
35
 
36
36
  ### Behavior/Options
37
37
 
@@ -125,7 +125,7 @@ specfact plan compare [--bundle <name>] --no-interactive
125
125
  ```text
126
126
  ✓ Comparison complete
127
127
 
128
- Comparison Report: .specfact/reports/comparison/deviations-2025-11-26T10-30-00.md
128
+ Comparison Report: .specfact/projects/<bundle-name>/reports/comparison/report-2025-11-26T10-30-00.md
129
129
 
130
130
  Deviations Summary:
131
131
  Total: 5
@@ -28,7 +28,7 @@ Run full validation suite for reproducibility and contract compliance. Executes
28
28
 
29
29
  ### Output/Results
30
30
 
31
- - `--out PATH` - Output report path. Default: .specfact/reports/enforcement/report-<timestamp>.yaml
31
+ - `--out PATH` - Output report path. Default: bundle-specific .specfact/projects/<bundle-name>/reports/enforcement/report-<timestamp>.yaml (Phase 8.5), or global .specfact/reports/enforcement/ if no bundle context
32
32
 
33
33
  ### Behavior/Options
34
34
 
@@ -135,7 +135,7 @@ Check Summary:
135
135
  Property Tests ✓ Passed
136
136
  Smoke Tests ✓ Passed
137
137
 
138
- Report saved to: .specfact/reports/enforcement/report-2025-11-26T10-30-00.yaml
138
+ Report saved to: .specfact/projects/<bundle-name>/reports/enforcement/report-2025-11-26T10-30-00.yaml
139
139
  ```
140
140
 
141
141
  ### Failure
@@ -3,4 +3,4 @@ SpecFact CLI - Spec→Contract→Sentinel tool for contract-driven development.
3
3
  """
4
4
 
5
5
  # Define the package version (kept in sync with pyproject.toml and setup.py)
6
- __version__ = "0.14.0"
6
+ __version__ = "0.14.2"
@@ -9,6 +9,6 @@ This package provides command-line tools for:
9
9
  - Validating reproducibility
10
10
  """
11
11
 
12
- __version__ = "0.14.0"
12
+ __version__ = "0.15.0"
13
13
 
14
14
  __all__ = ["__version__"]
@@ -144,6 +144,8 @@ class CodeAnalyzer:
144
144
  SpinnerColumn(),
145
145
  TextColumn("[progress.description]{task.description}"),
146
146
  BarColumn(),
147
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
148
+ TextColumn("({task.completed}/{task.total})"),
147
149
  TimeElapsedColumn(),
148
150
  console=console,
149
151
  ) as progress:
@@ -202,7 +204,13 @@ class CodeAnalyzer:
202
204
  prev_features_count = len(self.features)
203
205
  self._merge_analysis_results(results)
204
206
  completed_count += 1
205
- progress.update(task3, completed=completed_count)
207
+ # Update progress with feature count in description
208
+ features_count = len(self.features)
209
+ progress.update(
210
+ task3,
211
+ completed=completed_count,
212
+ description=f"[cyan]Phase 3: Analyzing files and extracting features... ({features_count} features discovered)",
213
+ )
206
214
 
207
215
  # Phase 4.9: Report incremental results for quick first value
208
216
  if self.incremental_callback and len(self.features) > prev_features_count:
@@ -211,7 +219,12 @@ class CodeAnalyzer:
211
219
  except Exception as e:
212
220
  console.print(f"[dim]⚠ Warning: Failed to analyze {file_path}: {e}[/dim]")
213
221
  completed_count += 1
214
- progress.update(task3, completed=completed_count)
222
+ features_count = len(self.features)
223
+ progress.update(
224
+ task3,
225
+ completed=completed_count,
226
+ description=f"[cyan]Phase 3: Analyzing files and extracting features... ({features_count} features discovered)",
227
+ )
215
228
  else:
216
229
  executor = ThreadPoolExecutor(max_workers=max_workers)
217
230
  interrupted = False
@@ -230,7 +243,13 @@ class CodeAnalyzer:
230
243
  prev_features_count = len(self.features)
231
244
  self._merge_analysis_results(results)
232
245
  completed_count += 1
233
- progress.update(task3, completed=completed_count)
246
+ # Update progress with feature count in description
247
+ features_count = len(self.features)
248
+ progress.update(
249
+ task3,
250
+ completed=completed_count,
251
+ description=f"[cyan]Phase 3: Analyzing files and extracting features... ({features_count} features discovered)",
252
+ )
234
253
 
235
254
  # Phase 4.9: Report incremental results for quick first value
236
255
  if self.incremental_callback and len(self.features) > prev_features_count:
@@ -248,7 +267,12 @@ class CodeAnalyzer:
248
267
  file_path = future_to_file[future]
249
268
  console.print(f"[dim]⚠ Warning: Failed to analyze {file_path}: {e}[/dim]")
250
269
  completed_count += 1
251
- progress.update(task3, completed=completed_count)
270
+ features_count = len(self.features)
271
+ progress.update(
272
+ task3,
273
+ completed=completed_count,
274
+ description=f"[cyan]Phase 3: Analyzing files and extracting features... ({features_count} features discovered)",
275
+ )
252
276
  except KeyboardInterrupt:
253
277
  # Also catch KeyboardInterrupt from as_completed() itself
254
278
  interrupted = True
@@ -278,7 +302,12 @@ class CodeAnalyzer:
278
302
  # Update progress for skipped files
279
303
  skipped_count = len(python_files) - len(files_to_analyze)
280
304
  if skipped_count > 0:
281
- progress.update(task3, completed=len(python_files))
305
+ features_count = len(self.features)
306
+ progress.update(
307
+ task3,
308
+ completed=len(python_files),
309
+ description=f"[cyan]Phase 3: Analyzing files and extracting features... ({features_count} features discovered)",
310
+ )
282
311
 
283
312
  progress.update(
284
313
  task3,
@@ -53,7 +53,7 @@ class ControlFlowAnalyzer:
53
53
  method_name: Name of the method
54
54
 
55
55
  Returns:
56
- Dictionary with scenario types as keys and lists of Given/When/Then scenarios as values
56
+ Dictionary with scenario types as keys and lists of scenario descriptions as values
57
57
  """
58
58
  scenarios: dict[str, list[str]] = {
59
59
  "primary": [],
@@ -67,9 +67,7 @@ class ControlFlowAnalyzer:
67
67
 
68
68
  # If no scenarios found, generate default primary scenario
69
69
  if not any(scenarios.values()):
70
- scenarios["primary"].append(
71
- f"Given {class_name} instance, When {method_name} is called, Then method executes successfully"
72
- )
70
+ scenarios["primary"].append(f"{method_name} executes successfully")
73
71
 
74
72
  return scenarios
75
73
 
@@ -103,15 +101,13 @@ class ControlFlowAnalyzer:
103
101
  # Primary scenario: if branch (happy path)
104
102
  if if_node.body:
105
103
  primary_action = self._extract_action_from_body(if_node.body)
106
- scenarios["primary"].append(
107
- f"Given {class_name} instance, When {method_name} is called with {condition}, Then {primary_action}"
108
- )
104
+ scenarios["primary"].append(f"{method_name} called with {condition}: {primary_action}")
109
105
 
110
106
  # Alternate scenario: else branch
111
107
  if if_node.orelse:
112
108
  alternate_action = self._extract_action_from_body(if_node.orelse)
113
109
  scenarios["alternate"].append(
114
- f"Given {class_name} instance, When {method_name} is called with {self._negate_condition(condition)}, Then {alternate_action}"
110
+ f"{method_name} called with {self._negate_condition(condition)}: {alternate_action}"
115
111
  )
116
112
 
117
113
  @beartype
@@ -122,9 +118,7 @@ class ControlFlowAnalyzer:
122
118
  # Primary scenario: try block (happy path)
123
119
  if try_node.body:
124
120
  primary_action = self._extract_action_from_body(try_node.body)
125
- scenarios["primary"].append(
126
- f"Given {class_name} instance, When {method_name} is called, Then {primary_action}"
127
- )
121
+ scenarios["primary"].append(f"{method_name} executes: {primary_action}")
128
122
 
129
123
  # Exception scenarios: except blocks
130
124
  for handler in try_node.handlers:
@@ -133,22 +127,16 @@ class ControlFlowAnalyzer:
133
127
  exception_type = self._extract_exception_type(handler.type)
134
128
 
135
129
  exception_action = self._extract_action_from_body(handler.body) if handler.body else "error is handled"
136
- scenarios["exception"].append(
137
- f"Given {class_name} instance, When {method_name} is called and {exception_type} occurs, Then {exception_action}"
138
- )
130
+ scenarios["exception"].append(f"{method_name} raises {exception_type}: {exception_action}")
139
131
 
140
132
  # Check for retry/recovery logic in exception handler
141
133
  if self._has_retry_logic(handler.body):
142
- scenarios["recovery"].append(
143
- f"Given {class_name} instance, When {method_name} fails with {exception_type}, Then system retries and recovers"
144
- )
134
+ scenarios["recovery"].append(f"{method_name} retries and recovers after {exception_type}")
145
135
 
146
136
  # Recovery scenario: finally block or retry logic
147
137
  if try_node.finalbody:
148
138
  recovery_action = self._extract_action_from_body(try_node.finalbody)
149
- scenarios["recovery"].append(
150
- f"Given {class_name} instance, When {method_name} completes or fails, Then {recovery_action}"
151
- )
139
+ scenarios["recovery"].append(f"{method_name} cleanup: {recovery_action}")
152
140
 
153
141
  @beartype
154
142
  def _extract_loop_scenario(
@@ -157,9 +145,7 @@ class ControlFlowAnalyzer:
157
145
  """Extract scenario from loop (might indicate retry logic)."""
158
146
  # Check if loop contains retry/retry logic
159
147
  if self._has_retry_logic(loop_node.body):
160
- scenarios["recovery"].append(
161
- f"Given {class_name} instance, When {method_name} is called, Then system retries on failure until success"
162
- )
148
+ scenarios["recovery"].append(f"{method_name} retries on failure until success")
163
149
 
164
150
  @beartype
165
151
  def _extract_condition(self, test_node: ast.AST) -> str:
@@ -72,6 +72,7 @@ from specfact_cli.commands import (
72
72
  sync,
73
73
  )
74
74
  from specfact_cli.modes import OperationalMode, detect_mode
75
+ from specfact_cli.utils.progressive_disclosure import ProgressiveDisclosureGroup
75
76
  from specfact_cli.utils.structured_io import StructuredFormat
76
77
 
77
78
 
@@ -120,7 +121,8 @@ app = typer.Typer(
120
121
  help="SpecFact CLI - Spec → Contract → Sentinel for Contract-Driven Development",
121
122
  add_completion=True, # Enable Typer's built-in completion (works natively for bash/zsh/fish without extensions)
122
123
  rich_markup_mode="rich",
123
- context_settings={"help_option_names": ["-h", "--help"]}, # Add -h as alias for --help
124
+ context_settings={"help_option_names": ["-h", "--help", "--help-advanced", "-ha"]}, # Add aliases for help
125
+ cls=ProgressiveDisclosureGroup, # Use custom group for progressive disclosure
124
126
  )
125
127
 
126
128
  console = Console()
@@ -352,6 +354,11 @@ app.add_typer(
352
354
 
353
355
  def cli_main() -> None:
354
356
  """Entry point for the CLI application."""
357
+ # Intercept --help-advanced before Typer processes it
358
+ from specfact_cli.utils.progressive_disclosure import intercept_help_advanced
359
+
360
+ intercept_help_advanced()
361
+
355
362
  # Normalize shell names in argv for Typer's built-in completion commands
356
363
  normalize_shell_in_argv()
357
364
 
@@ -129,7 +129,7 @@ def enforce_sdd(
129
129
  sdd: Path | None = typer.Option(
130
130
  None,
131
131
  "--sdd",
132
- help="Path to SDD manifest. Default: .specfact/sdd/<bundle-name>.<format>",
132
+ help="Path to SDD manifest. Default: bundle-specific .specfact/projects/<bundle-name>/sdd.<format> (Phase 8.5), with fallback to legacy .specfact/sdd/<bundle-name>.<format>",
133
133
  ),
134
134
  # Output/Results
135
135
  output_format: str = typer.Option(
@@ -140,7 +140,7 @@ def enforce_sdd(
140
140
  out: Path | None = typer.Option(
141
141
  None,
142
142
  "--out",
143
- help="Output file path. Default: .specfact/reports/sdd/validation-<timestamp>.<format>",
143
+ help="Output file path. Default: bundle-specific .specfact/projects/<bundle-name>/reports/enforcement/report-<timestamp>.<format> (Phase 8.5)",
144
144
  ),
145
145
  # Behavior/Options
146
146
  no_interactive: bool = typer.Option(
@@ -213,7 +213,8 @@ def enforce_sdd(
213
213
  discovered_sdd = find_sdd_for_bundle(bundle, base_path, sdd)
214
214
  if discovered_sdd is None:
215
215
  console.print("[bold red]✗[/bold red] SDD manifest not found")
216
- console.print(f"[dim]Searched for: .specfact/sdd/{bundle}.yaml or .specfact/sdd/{bundle}.json[/dim]")
216
+ console.print(f"[dim]Searched for: .specfact/projects/{bundle}/sdd.yaml (bundle-specific, Phase 8.5)[/dim]")
217
+ console.print(f"[dim]Fallback: .specfact/sdd/{bundle}.yaml or .specfact/sdd/{bundle}.json[/dim]")
217
218
  console.print("[dim]Legacy fallback: .specfact/sdd.yaml or .specfact/sdd.json[/dim]")
218
219
  console.print(f"[dim]Create one with: specfact plan harden {bundle}[/dim]")
219
220
  raise typer.Exit(1)
@@ -382,15 +383,15 @@ def enforce_sdd(
382
383
  else:
383
384
  console.print("[dim]No API contracts found in bundle[/dim]")
384
385
 
385
- # Generate output report
386
+ # Generate output report (Phase 8.5: bundle-specific location)
386
387
  output_format_str = output_format.lower()
387
388
  if out is None:
388
- SpecFactStructure.ensure_structure()
389
- reports_dir = Path(".") / SpecFactStructure.ROOT / "reports" / "sdd"
390
- reports_dir.mkdir(parents=True, exist_ok=True)
391
- timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
389
+ # Use bundle-specific enforcement report path
392
390
  extension = "md" if output_format_str == "markdown" else output_format_str
393
- out = reports_dir / f"validation-{timestamp}.{extension}"
391
+ out = SpecFactStructure.get_bundle_enforcement_report_path(bundle_name=bundle, base_path=base_path)
392
+ # Update extension if needed
393
+ if extension != "yaml" and out.suffix != f".{extension}":
394
+ out = out.with_suffix(f".{extension}")
394
395
 
395
396
  # Save report
396
397
  if output_format_str == "markdown":
@@ -59,7 +59,7 @@ def generate_contracts(
59
59
  sdd: Path | None = typer.Option(
60
60
  None,
61
61
  "--sdd",
62
- help="Path to SDD manifest. Default: .specfact/sdd/<bundle-name>.yaml if --bundle specified, else .specfact/sdd.yaml. Ignored if --bundle is specified.",
62
+ help="Path to SDD manifest. Default: bundle-specific .specfact/projects/<bundle-name>/sdd.yaml if --bundle specified (Phase 8.5), else .specfact/sdd.yaml. Ignored if --bundle is specified.",
63
63
  ),
64
64
  plan: Path | None = typer.Option(
65
65
  None,
@@ -149,7 +149,7 @@ def generate_contracts(
149
149
  # Detect bundle format to determine SDD path
150
150
  format_type, _ = detect_bundle_format(plan_path)
151
151
  if format_type == BundleFormat.MODULAR:
152
- # Modular bundle: SDD is at .specfact/sdd/<bundle-name>.yaml
152
+ # Modular bundle: SDD is at .specfact/projects/<bundle-name>/sdd.yaml (Phase 8.5)
153
153
  if plan_path.is_dir():
154
154
  bundle_name = plan_path.name
155
155
  else:
@@ -321,6 +321,7 @@ def generate_contracts_prompt(
321
321
  None,
322
322
  "--output",
323
323
  help=("Output file path (currently unused, prompt saved to .specfact/prompts/)"),
324
+ hidden=True, # Hidden by default, shown with --help-advanced
324
325
  ),
325
326
  ) -> None:
326
327
  """
@@ -1360,7 +1361,7 @@ def generate_tasks(
1360
1361
  out: Path | None = typer.Option(
1361
1362
  None,
1362
1363
  "--out",
1363
- help="Output file path. Default: .specfact/tasks/<bundle-name>-<hash>.tasks.<format>",
1364
+ help="Output file path. Default: bundle-specific .specfact/projects/<bundle-name>/tasks.yaml (Phase 8.5)",
1364
1365
  ),
1365
1366
  # Behavior/Options
1366
1367
  no_interactive: bool = typer.Option(
@@ -1452,17 +1453,20 @@ def generate_tasks(
1452
1453
  print_info("Generating task breakdown...")
1453
1454
  task_list = generate_tasks_func(project_bundle, sdd_manifest, bundle)
1454
1455
 
1455
- # Determine output path
1456
+ # Determine output path (Phase 8.5: bundle-specific location)
1456
1457
  if out is None:
1457
- tasks_dir = base_path / SpecFactStructure.TASKS
1458
- tasks_dir.mkdir(parents=True, exist_ok=True)
1458
+ # Use bundle-specific tasks path (Phase 8.5)
1459
+ out = SpecFactStructure.get_bundle_tasks_path(bundle_name=bundle, base_path=base_path)
1460
+ # Ensure parent directory exists
1461
+ out.parent.mkdir(parents=True, exist_ok=True)
1462
+ # Update extension if needed
1459
1463
  format_ext = output_format.lower()
1460
- hash_short = (
1461
- task_list.plan_bundle_hash[:16]
1462
- if len(task_list.plan_bundle_hash) > 16
1463
- else task_list.plan_bundle_hash
1464
- )
1465
- out = tasks_dir / f"{bundle}-{hash_short}.tasks.{format_ext}"
1464
+ if format_ext == "yaml":
1465
+ out = out.with_suffix(".yaml")
1466
+ elif format_ext == "json":
1467
+ out = out.with_suffix(".json")
1468
+ else:
1469
+ out = out.with_suffix(".md")
1466
1470
  else:
1467
1471
  # Ensure correct extension
1468
1472
  if output_format.lower() == "yaml":
@@ -70,9 +70,9 @@ def implement_tasks(
70
70
  - **Behavior/Options**: --dry-run, --skip-validation, --no-interactive
71
71
 
72
72
  **Examples:**
73
- specfact implement tasks .specfact/tasks/bundle-abc123.tasks.yaml
74
- specfact implement tasks .specfact/tasks/bundle-abc123.tasks.yaml --phase setup
75
- specfact implement tasks .specfact/tasks/bundle-abc123.tasks.yaml --task TASK-001 --dry-run
73
+ specfact implement tasks .specfact/projects/bundle-name/tasks.yaml
74
+ specfact implement tasks .specfact/projects/bundle-name/tasks.yaml --phase setup
75
+ specfact implement tasks .specfact/projects/bundle-name/tasks.yaml --task TASK-001 --dry-run
76
76
  """
77
77
  from specfact_cli.telemetry import telemetry
78
78