specfact-cli 0.40.0__tar.gz → 0.40.2__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.40.0 → specfact_cli-0.40.2}/PKG-INFO +3 -1
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/README.md +2 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/pyproject.toml +3 -3
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/__init__.py +1 -1
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/__init__.py +1 -1
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/ado.py +15 -0
- specfact_cli-0.40.2/src/specfact_cli/backlog/__init__.py +14 -0
- specfact_cli-0.40.2/src/specfact_cli/backlog/adapters/__init__.py +8 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/__init__.py +1 -3
- specfact_cli-0.40.2/src/specfact_cli/groups/member_group.py +60 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_discovery.py +7 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_packages.py +22 -18
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/ide_setup.py +0 -4
- specfact_cli-0.40.2/src/specfact_cli/validation/__init__.py +14 -0
- specfact_cli-0.40.2/src/specfact_cli/validation/command_audit.py +165 -0
- specfact_cli-0.40.0/resources/prompts/specfact.backlog-add.md +0 -90
- specfact_cli-0.40.0/resources/prompts/specfact.backlog-daily.md +0 -125
- specfact_cli-0.40.0/resources/prompts/specfact.backlog-refine.md +0 -557
- specfact_cli-0.40.0/resources/prompts/specfact.sync-backlog.md +0 -557
- specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_agile.yaml +0 -24
- specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_default.yaml +0 -24
- specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_kanban.yaml +0 -26
- specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_safe.yaml +0 -29
- specfact_cli-0.40.0/resources/templates/backlog/field_mappings/ado_scrum.yaml +0 -24
- specfact_cli-0.40.0/resources/templates/backlog/frameworks/safe/safe_feature_v1.yaml +0 -26
- specfact_cli-0.40.0/resources/templates/backlog/personas/developer/developer_task_v1.yaml +0 -28
- specfact_cli-0.40.0/src/specfact_cli/backlog/__init__.py +0 -24
- specfact_cli-0.40.0/src/specfact_cli/backlog/adapters/__init__.py +0 -13
- specfact_cli-0.40.0/src/specfact_cli/backlog/adapters/local_yaml_adapter.py +0 -177
- specfact_cli-0.40.0/src/specfact_cli/backlog/ai_refiner.py +0 -523
- specfact_cli-0.40.0/src/specfact_cli/backlog/format_detector.py +0 -50
- specfact_cli-0.40.0/src/specfact_cli/backlog/formats/__init__.py +0 -14
- specfact_cli-0.40.0/src/specfact_cli/backlog/formats/base.py +0 -98
- specfact_cli-0.40.0/src/specfact_cli/backlog/formats/markdown_format.py +0 -130
- specfact_cli-0.40.0/src/specfact_cli/backlog/formats/structured_format.py +0 -97
- specfact_cli-0.40.0/src/specfact_cli/backlog/template_detector.py +0 -288
- specfact_cli-0.40.0/src/specfact_cli/commands/backlog_commands.py +0 -18
- specfact_cli-0.40.0/src/specfact_cli/groups/backlog_group.py +0 -63
- specfact_cli-0.40.0/src/specfact_cli/templates/defaults/defect_v1.yaml +0 -22
- specfact_cli-0.40.0/src/specfact_cli/templates/defaults/enabler_v1.yaml +0 -21
- specfact_cli-0.40.0/src/specfact_cli/templates/defaults/spike_v1.yaml +0 -20
- specfact_cli-0.40.0/src/specfact_cli/templates/defaults/user_story_v1.yaml +0 -19
- specfact_cli-0.40.0/src/specfact_cli/templates/frameworks/scrum/user_story_v1.yaml +0 -23
- specfact_cli-0.40.0/src/specfact_cli/templates/personas/product-owner/user_story_v1.yaml +0 -24
- specfact_cli-0.40.0/src/specfact_cli/templates/providers/ado/work_item_v1.yaml +0 -21
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/.gitignore +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/LICENSE +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/keys/README.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/keys/module-signing-public.pem +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/mappings/node-async.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/mappings/python-async.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/mappings/speckit-default.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/shared/cli-enforcement.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.01-import.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.02-plan.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.03-review.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.04-sdd.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.05-enforce.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.06-sync.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.07-contracts.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.compare.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/prompts/specfact.validate.md +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/schemas/deviation.schema.json +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/schemas/plan.schema.json +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/schemas/protocol.schema.json +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/github-action.yml.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/persona/architect.md.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/persona/developer.md.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/persona/product-owner.md.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/plan.bundle.yaml.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/kanban.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/mixed.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/safe.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/policies/scrum.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/pr-template.md.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/protocol.yaml.j2 +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/resources/templates/telemetry.yaml.example +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/__main__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/backlog_base.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/base.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/github.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/openspec.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/openspec_parser.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/registry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/adapters/speckit.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/analyze_agent.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/base.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/plan_agent.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/registry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/agents/sync_agent.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/adapters/base.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/converter.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/filters.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/ado_mapper.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/base.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/github_mapper.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/backlog/mappers/template_config.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/cli.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/_bundle_shim.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/analyze.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/contract_cmd.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/drift.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/enforce.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/generate.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/import_cmd.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/init.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/migrate.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/plan.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/project_cmd.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/repro.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/sdd.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/spec.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/sync.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/update.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/commands/validate.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/bundle_factory.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/logger_setup.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/logging_utils.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/text_utils.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/common/utils.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/comparators/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/comparators/plan_comparator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/contracts/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/contracts/crosshair_props.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/contracts/module_interface.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/contract_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/openapi_extractor.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/persona_exporter.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/plan_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/protocol_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/report_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/task_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/test_to_openapi.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/generators/workflow_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/codebase_group.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/govern_group.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/project_group.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/groups/spec_group.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/importers/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/importers/speckit_converter.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/importers/speckit_scanner.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/integrations/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/integrations/specmatic.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/merge/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/merge/resolver.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/migrations/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/migrations/plan_migrator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/backlog_item.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/bridge.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/capabilities.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/change.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/contract.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/deviation.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/dor_config.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/enforcement.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/module_package.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/persona_template.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/plan.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/project.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/protocol.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/quality.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/sdd.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/source_tracking.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/task.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/models/validation.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modes/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modes/detector.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modes/router.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/_bundle_import.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/module-package.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/app.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/commands.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/init/src/first_run_selection.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_io_shim.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/module-package.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/src/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/src/app.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/module_registry/src/commands.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/module-package.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/src/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/src/app.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/modules/upgrade/src/commands.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/parsers/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/parsers/persona_importer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/alias_manager.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/bootstrap.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/bridge_registry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/crypto_validator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/custom_registries.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/dependency_resolver.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/extension_registry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/help_cache.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/marketplace_client.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/metadata.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_grouping.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_installer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_lifecycle.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_security.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/module_state.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/registry/registry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/resources/semgrep/async.yml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/runtime.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/bridge_probe.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/bridge_sync.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/bridge_watch.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/change_detector.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/code_to_spec.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/drift_detector.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/repository_sync.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/spec_to_code.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/spec_to_tests.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/watcher.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/telemetry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/templates/__init__.py +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/defect_v1.yaml +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/enabler_v1.yaml +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/spike_v1.yaml +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/defaults/user_story_v1.yaml +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/frameworks/scrum/user_story_v1.yaml +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/personas/product-owner/user_story_v1.yaml +0 -0
- {specfact_cli-0.40.0/resources/templates/backlog → specfact_cli-0.40.2/src/specfact_cli/templates}/providers/ado/work_item_v1.yaml +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/templates/registry.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/templates/specification_templates.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/auth_tokens.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/bundle_converters.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/bundle_loader.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/code_change_detector.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/console.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/content_sanitizer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/context_detection.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/enrichment_context.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/enrichment_parser.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/env_manager.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/feature_keys.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/git.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/github_annotations.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/incremental_check.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/metadata.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/optional_deps.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/performance.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/persona_ownership.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/progress.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/prompts.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/sdd_discovery.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/source_scanner.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/startup_checks.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/structure.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/structured_io.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/suggestions.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/terminal.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/utils/yaml_utils.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/agile_validation.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/change_proposal_integration.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/cli_first_validator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/contract_validator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/fsm.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/repro_checker.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/schema.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/contract_populator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/crosshair_runner.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/crosshair_summary.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/dependency_installer.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/framework_detector.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/base.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/django.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/drf.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/frameworks/flask.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/harness_generator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/models.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/orchestrator.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/specmatic_runner.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/validators/sidecar/unannotated_detector.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/src/specfact_cli/versioning/__init__.py +0 -0
- {specfact_cli-0.40.0 → specfact_cli-0.40.2}/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.40.
|
|
3
|
+
Version: 0.40.2
|
|
4
4
|
Summary: The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with validation and contract enforcement for new projects and long-lived codebases.
|
|
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
|
|
@@ -353,6 +353,8 @@ As of `0.40.0`, flat root commands are removed. Use grouped commands:
|
|
|
353
353
|
### Backlog Bridge (60 seconds)
|
|
354
354
|
|
|
355
355
|
SpecFact's USP is closing the drift gap between **backlog -> specs -> code**.
|
|
356
|
+
These commands require the backlog bundle to be installed first, for example via
|
|
357
|
+
`specfact init --profile backlog-team` or `specfact init --install backlog`.
|
|
356
358
|
|
|
357
359
|
```bash
|
|
358
360
|
# 1) Initialize backlog config + field mapping
|
|
@@ -74,6 +74,8 @@ As of `0.40.0`, flat root commands are removed. Use grouped commands:
|
|
|
74
74
|
### Backlog Bridge (60 seconds)
|
|
75
75
|
|
|
76
76
|
SpecFact's USP is closing the drift gap between **backlog -> specs -> code**.
|
|
77
|
+
These commands require the backlog bundle to be installed first, for example via
|
|
78
|
+
`specfact init --profile backlog-team` or `specfact init --install backlog`.
|
|
77
79
|
|
|
78
80
|
```bash
|
|
79
81
|
# 1) Initialize backlog config + field mapping
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specfact-cli"
|
|
7
|
-
version = "0.40.
|
|
7
|
+
version = "0.40.2"
|
|
8
8
|
description = "The swiss knife CLI for agile DevOps teams. Keep backlog, specs, tests, and code in sync with validation and contract enforcement for new projects and long-lived codebases."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -377,9 +377,10 @@ method = "thread"
|
|
|
377
377
|
dev-mode-dirs = ["src","tools"]
|
|
378
378
|
|
|
379
379
|
[tool.hatch.build.targets.wheel]
|
|
380
|
-
|
|
380
|
+
only-include = [
|
|
381
381
|
"src/specfact_cli",
|
|
382
382
|
]
|
|
383
|
+
sources = ["src"]
|
|
383
384
|
|
|
384
385
|
[tool.hatch.build.targets.wheel.force-include]
|
|
385
386
|
"resources/prompts" = "specfact_cli/resources/prompts"
|
|
@@ -387,7 +388,6 @@ packages = [
|
|
|
387
388
|
"resources/schemas" = "specfact_cli/resources/schemas"
|
|
388
389
|
"resources/mappings" = "specfact_cli/resources/mappings"
|
|
389
390
|
"resources/keys" = "specfact_cli/resources/keys"
|
|
390
|
-
"modules/backlog-core" = "specfact_cli/modules/backlog-core"
|
|
391
391
|
"modules/bundle-mapper" = "specfact_cli/modules/bundle-mapper"
|
|
392
392
|
# Note: resources/semgrep files are in src/specfact_cli/resources/semgrep/ and are automatically included
|
|
393
393
|
|
|
@@ -3414,6 +3414,21 @@ class AdoAdapter(BridgeAdapter, BacklogAdapterMixin, BacklogAdapter):
|
|
|
3414
3414
|
}
|
|
3415
3415
|
)
|
|
3416
3416
|
|
|
3417
|
+
provider_fields = payload.get("provider_fields")
|
|
3418
|
+
provider_field_values = provider_fields.get("fields") if isinstance(provider_fields, dict) else None
|
|
3419
|
+
if isinstance(provider_field_values, dict):
|
|
3420
|
+
for field_name, field_value in provider_field_values.items():
|
|
3421
|
+
normalized_field = str(field_name).strip()
|
|
3422
|
+
if not normalized_field:
|
|
3423
|
+
continue
|
|
3424
|
+
patch_document.append(
|
|
3425
|
+
{
|
|
3426
|
+
"op": "add",
|
|
3427
|
+
"path": f"/fields/{normalized_field}",
|
|
3428
|
+
"value": field_value,
|
|
3429
|
+
}
|
|
3430
|
+
)
|
|
3431
|
+
|
|
3417
3432
|
sprint = str(payload.get("sprint") or "").strip()
|
|
3418
3433
|
if sprint:
|
|
3419
3434
|
patch_document.append(
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Shared backlog conversion helpers retained by core adapters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from specfact_cli.backlog.converter import (
|
|
6
|
+
convert_ado_work_item_to_backlog_item,
|
|
7
|
+
convert_github_issue_to_backlog_item,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"convert_ado_work_item_to_backlog_item",
|
|
13
|
+
"convert_github_issue_to_backlog_item",
|
|
14
|
+
]
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
"""Category group commands: project,
|
|
1
|
+
"""Category group commands: project, code, spec, govern."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from specfact_cli.groups.backlog_group import app as backlog_app
|
|
6
5
|
from specfact_cli.groups.codebase_group import app as codebase_app
|
|
7
6
|
from specfact_cli.groups.govern_group import app as govern_app
|
|
8
7
|
from specfact_cli.groups.project_group import app as project_app
|
|
@@ -10,7 +9,6 @@ from specfact_cli.groups.spec_group import app as spec_app
|
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
__all__ = [
|
|
13
|
-
"backlog_app",
|
|
14
12
|
"codebase_app",
|
|
15
13
|
"govern_app",
|
|
16
14
|
"project_app",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Generic category group builder for bundle-owned command surfaces."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from beartype import beartype
|
|
9
|
+
from icontract import ensure, require
|
|
10
|
+
|
|
11
|
+
from specfact_cli.registry.registry import CommandRegistry
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@require(lambda app: app is not None)
|
|
15
|
+
@beartype
|
|
16
|
+
def _register_members(app: typer.Typer, members: Sequence[tuple[str, str]]) -> int:
|
|
17
|
+
"""Register member module sub-apps and return how many were added."""
|
|
18
|
+
added = 0
|
|
19
|
+
for display_name, cmd_name in members:
|
|
20
|
+
try:
|
|
21
|
+
member_app = CommandRegistry.get_module_typer(cmd_name)
|
|
22
|
+
if member_app is not None:
|
|
23
|
+
app.add_typer(member_app, name=display_name)
|
|
24
|
+
added += 1
|
|
25
|
+
except ValueError:
|
|
26
|
+
continue
|
|
27
|
+
return added
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@require(lambda name: isinstance(name, str) and len(name) > 0)
|
|
31
|
+
@require(lambda help_text: isinstance(help_text, str) and len(help_text) > 0)
|
|
32
|
+
@ensure(lambda result: isinstance(result, typer.Typer))
|
|
33
|
+
@beartype
|
|
34
|
+
def build_member_group(
|
|
35
|
+
*,
|
|
36
|
+
name: str,
|
|
37
|
+
help_text: str,
|
|
38
|
+
members: Sequence[tuple[str, str]],
|
|
39
|
+
flatten_same_name: str | None = None,
|
|
40
|
+
install_hint_module: str | None = None,
|
|
41
|
+
) -> typer.Typer:
|
|
42
|
+
"""Build a lazy category group from registered member modules."""
|
|
43
|
+
app = typer.Typer(name=name, help=help_text, no_args_is_help=True)
|
|
44
|
+
added = _register_members(app, members)
|
|
45
|
+
|
|
46
|
+
if added == 0 and install_hint_module:
|
|
47
|
+
placeholder = typer.Typer(help=f"{help_text} (module not loaded).")
|
|
48
|
+
|
|
49
|
+
@placeholder.command("install")
|
|
50
|
+
def _install_hint() -> None:
|
|
51
|
+
from specfact_cli.utils.prompts import print_warning
|
|
52
|
+
|
|
53
|
+
print_warning(f"No {name} module loaded. Install with: specfact module install {install_hint_module}")
|
|
54
|
+
|
|
55
|
+
app.add_typer(placeholder, name=name)
|
|
56
|
+
|
|
57
|
+
if flatten_same_name:
|
|
58
|
+
app._specfact_flatten_same_name = flatten_same_name
|
|
59
|
+
|
|
60
|
+
return app
|
|
@@ -56,7 +56,14 @@ def discover_all_modules(
|
|
|
56
56
|
effective_custom_root = custom_root or CUSTOM_MODULES_ROOT
|
|
57
57
|
|
|
58
58
|
roots: list[tuple[str, Path]] = [("builtin", effective_builtin_root)]
|
|
59
|
+
project_matches_user_root = False
|
|
59
60
|
if effective_project_root is not None:
|
|
61
|
+
try:
|
|
62
|
+
project_matches_user_root = effective_project_root.resolve() == effective_user_root.resolve()
|
|
63
|
+
except OSError:
|
|
64
|
+
project_matches_user_root = effective_project_root == effective_user_root
|
|
65
|
+
|
|
66
|
+
if effective_project_root is not None and not project_matches_user_root:
|
|
60
67
|
roots.append(("project", effective_project_root))
|
|
61
68
|
roots.extend(
|
|
62
69
|
[
|
|
@@ -879,14 +879,24 @@ def get_installed_bundles(
|
|
|
879
879
|
|
|
880
880
|
# Bundle name -> (group_name, help_str, build_app_fn) for conditional category mounting.
|
|
881
881
|
def _build_bundle_to_group() -> dict[str, tuple[str, str, Any]]:
|
|
882
|
-
from specfact_cli.groups.backlog_group import build_app as build_backlog_app
|
|
883
882
|
from specfact_cli.groups.codebase_group import build_app as build_codebase_app
|
|
884
883
|
from specfact_cli.groups.govern_group import build_app as build_govern_app
|
|
884
|
+
from specfact_cli.groups.member_group import build_member_group
|
|
885
885
|
from specfact_cli.groups.project_group import build_app as build_project_app
|
|
886
886
|
from specfact_cli.groups.spec_group import build_app as build_spec_app
|
|
887
887
|
|
|
888
888
|
return {
|
|
889
|
-
"specfact-backlog": (
|
|
889
|
+
"specfact-backlog": (
|
|
890
|
+
"backlog",
|
|
891
|
+
"Backlog and policy commands.",
|
|
892
|
+
lambda: build_member_group(
|
|
893
|
+
name="backlog",
|
|
894
|
+
help_text="Backlog and policy commands.",
|
|
895
|
+
members=(("backlog", "backlog"), ("policy", "policy")),
|
|
896
|
+
flatten_same_name="backlog",
|
|
897
|
+
install_hint_module="nold-ai/specfact-backlog",
|
|
898
|
+
),
|
|
899
|
+
),
|
|
890
900
|
"specfact-codebase": (
|
|
891
901
|
"code",
|
|
892
902
|
"Codebase quality commands: analyze, drift, validate, repro.",
|
|
@@ -1171,26 +1181,20 @@ def register_module_package_commands(
|
|
|
1171
1181
|
if category_grouping_enabled:
|
|
1172
1182
|
_mount_installed_category_groups(packages, enabled_map)
|
|
1173
1183
|
discovered_count = protocol_full + protocol_partial + protocol_legacy
|
|
1174
|
-
if discovered_count and (protocol_partial > 0 or protocol_legacy > 0):
|
|
1175
|
-
|
|
1176
|
-
"Module compatibility check: "
|
|
1177
|
-
|
|
1178
|
-
|
|
1184
|
+
if discovered_count and (protocol_partial > 0 or protocol_legacy > 0) and is_debug_mode():
|
|
1185
|
+
logger.info(
|
|
1186
|
+
"Module compatibility check: %s/%s compliant (full=%s, partial=%s, legacy=%s)",
|
|
1187
|
+
protocol_full + protocol_partial,
|
|
1188
|
+
discovered_count,
|
|
1189
|
+
protocol_full,
|
|
1190
|
+
protocol_partial,
|
|
1191
|
+
protocol_legacy,
|
|
1179
1192
|
)
|
|
1180
1193
|
if partial_modules:
|
|
1181
1194
|
partial_desc = ", ".join(f"{name} ({'/'.join(ops)})" for name, ops in sorted(partial_modules))
|
|
1182
|
-
|
|
1195
|
+
logger.info("Partially compliant modules: %s", partial_desc)
|
|
1183
1196
|
if legacy_modules:
|
|
1184
|
-
|
|
1185
|
-
if is_debug_mode():
|
|
1186
|
-
logger.info(
|
|
1187
|
-
"Protocol-compliant: %s/%s modules (Full=%s, Partial=%s, Legacy=%s)",
|
|
1188
|
-
protocol_full + protocol_partial,
|
|
1189
|
-
discovered_count,
|
|
1190
|
-
protocol_full,
|
|
1191
|
-
protocol_partial,
|
|
1192
|
-
protocol_legacy,
|
|
1193
|
-
)
|
|
1197
|
+
logger.info("Legacy modules: %s", ", ".join(sorted(set(legacy_modules))))
|
|
1194
1198
|
for module_id, reason in skipped:
|
|
1195
1199
|
logger.debug("Skipped module '%s': %s", module_id, reason)
|
|
1196
1200
|
|
|
@@ -121,10 +121,6 @@ SPECFACT_COMMANDS = [
|
|
|
121
121
|
"specfact.06-sync",
|
|
122
122
|
"specfact.07-contracts",
|
|
123
123
|
"specfact.compare",
|
|
124
|
-
"specfact.sync-backlog",
|
|
125
|
-
"specfact.backlog-daily",
|
|
126
|
-
"specfact.backlog-refine",
|
|
127
|
-
"specfact.backlog-add",
|
|
128
124
|
"specfact.validate",
|
|
129
125
|
]
|
|
130
126
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Validation helpers for release and command-surface audits."""
|
|
2
|
+
|
|
3
|
+
from specfact_cli.validation.command_audit import (
|
|
4
|
+
CommandAuditCase,
|
|
5
|
+
build_command_audit_cases,
|
|
6
|
+
official_marketplace_module_ids,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"CommandAuditCase",
|
|
12
|
+
"build_command_audit_cases",
|
|
13
|
+
"official_marketplace_module_ids",
|
|
14
|
+
]
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Helpers for command-package runtime validation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
AuditMode = Literal["help-only", "fixture-backed", "dry-run"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class CommandAuditCase:
|
|
18
|
+
"""One command-path audit case."""
|
|
19
|
+
|
|
20
|
+
command_path: str
|
|
21
|
+
argv: tuple[str, ...]
|
|
22
|
+
phase: str
|
|
23
|
+
mode: AuditMode
|
|
24
|
+
owner: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _resolve_modules_repo_root() -> Path | None:
|
|
28
|
+
configured = os.environ.get("SPECFACT_MODULES_REPO", "").strip()
|
|
29
|
+
if configured:
|
|
30
|
+
candidate = Path(configured).expanduser().resolve()
|
|
31
|
+
if candidate.exists():
|
|
32
|
+
return candidate
|
|
33
|
+
|
|
34
|
+
current = Path(__file__).resolve()
|
|
35
|
+
for parent in current.parents:
|
|
36
|
+
sibling = parent.parent / "specfact-cli-modules"
|
|
37
|
+
if sibling.exists():
|
|
38
|
+
return sibling.resolve()
|
|
39
|
+
direct = parent / "specfact-cli-modules"
|
|
40
|
+
if direct.exists():
|
|
41
|
+
return direct.resolve()
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _ensure_bundle_sources_on_sys_path() -> None:
|
|
46
|
+
modules_repo = _resolve_modules_repo_root()
|
|
47
|
+
if modules_repo is None:
|
|
48
|
+
return
|
|
49
|
+
packages_root = modules_repo / "packages"
|
|
50
|
+
if not packages_root.exists():
|
|
51
|
+
return
|
|
52
|
+
for bundle_src in packages_root.glob("*/src"):
|
|
53
|
+
bundle_src_str = str(bundle_src.resolve())
|
|
54
|
+
if bundle_src_str not in sys.path:
|
|
55
|
+
sys.path.insert(0, bundle_src_str)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _command_info_name(command_info: object) -> str:
|
|
59
|
+
explicit_name = getattr(command_info, "name", None)
|
|
60
|
+
if isinstance(explicit_name, str) and explicit_name:
|
|
61
|
+
return explicit_name
|
|
62
|
+
callback = getattr(command_info, "callback", None)
|
|
63
|
+
callback_name = getattr(callback, "__name__", "")
|
|
64
|
+
return callback_name.replace("_", "-") if callback_name else ""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _collect_typer_paths(app: object, prefix: str) -> set[str]:
|
|
68
|
+
paths: set[str] = set()
|
|
69
|
+
|
|
70
|
+
for command_info in list(getattr(app, "registered_commands", [])):
|
|
71
|
+
command_name = _command_info_name(command_info)
|
|
72
|
+
if command_name:
|
|
73
|
+
paths.add(f"{prefix} {command_name}")
|
|
74
|
+
|
|
75
|
+
for group_info in list(getattr(app, "registered_groups", [])):
|
|
76
|
+
group_name = getattr(group_info, "name", "") or ""
|
|
77
|
+
if not group_name:
|
|
78
|
+
nested_app = getattr(group_info, "typer_instance", None)
|
|
79
|
+
nested_info = getattr(nested_app, "info", None) if nested_app is not None else None
|
|
80
|
+
group_name = getattr(nested_info, "name", "") or ""
|
|
81
|
+
if not group_name:
|
|
82
|
+
continue
|
|
83
|
+
group_prefix = f"{prefix} {group_name}"
|
|
84
|
+
paths.add(group_prefix)
|
|
85
|
+
nested_app = getattr(group_info, "typer_instance", None)
|
|
86
|
+
if nested_app is not None:
|
|
87
|
+
paths.update(_collect_typer_paths(nested_app, group_prefix))
|
|
88
|
+
|
|
89
|
+
return paths
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _import_typer(module_path: str, attr_name: str = "app") -> object:
|
|
93
|
+
module = importlib.import_module(module_path)
|
|
94
|
+
return getattr(module, attr_name)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def official_marketplace_module_ids() -> tuple[str, ...]:
|
|
98
|
+
"""Return the official marketplace module ids that make up the full CLI surface."""
|
|
99
|
+
return (
|
|
100
|
+
"nold-ai/specfact-project",
|
|
101
|
+
"nold-ai/specfact-spec",
|
|
102
|
+
"nold-ai/specfact-codebase",
|
|
103
|
+
"nold-ai/specfact-backlog",
|
|
104
|
+
"nold-ai/specfact-govern",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _explicit_cases() -> list[CommandAuditCase]:
|
|
109
|
+
return [
|
|
110
|
+
CommandAuditCase("specfact", ("--help",), "root", "help-only", "specfact-core"),
|
|
111
|
+
CommandAuditCase("project", ("project", "--help"), "project", "help-only", "nold-ai/specfact-project"),
|
|
112
|
+
CommandAuditCase("spec", ("spec", "--help"), "spec", "help-only", "nold-ai/specfact-spec"),
|
|
113
|
+
CommandAuditCase("code", ("code", "--help"), "code", "help-only", "nold-ai/specfact-codebase"),
|
|
114
|
+
CommandAuditCase("backlog", ("backlog", "--help"), "backlog", "help-only", "nold-ai/specfact-backlog"),
|
|
115
|
+
CommandAuditCase("govern", ("govern", "--help"), "govern", "help-only", "nold-ai/specfact-govern"),
|
|
116
|
+
CommandAuditCase(
|
|
117
|
+
"module init", ("module", "init", "--scope", "user"), "core", "fixture-backed", "specfact-core"
|
|
118
|
+
),
|
|
119
|
+
CommandAuditCase("module search", ("module", "search", "specfact"), "core", "fixture-backed", "specfact-core"),
|
|
120
|
+
CommandAuditCase("module list", ("module", "list", "--show-origin"), "core", "fixture-backed", "specfact-core"),
|
|
121
|
+
CommandAuditCase(
|
|
122
|
+
"module show",
|
|
123
|
+
("module", "show", "nold-ai/specfact-backlog"),
|
|
124
|
+
"core",
|
|
125
|
+
"fixture-backed",
|
|
126
|
+
"specfact-core",
|
|
127
|
+
),
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def build_command_audit_cases() -> list[CommandAuditCase]:
|
|
132
|
+
"""Build the full command audit matrix for core and official bundle command paths."""
|
|
133
|
+
_ensure_bundle_sources_on_sys_path()
|
|
134
|
+
app_specs = [
|
|
135
|
+
("specfact_cli.modules.init.src.commands", "init", "core", "specfact-core", "import"),
|
|
136
|
+
("specfact_cli.modules.module_registry.src.commands", "module", "core", "specfact-core", "import"),
|
|
137
|
+
("specfact_cli.modules.upgrade.src.commands", "upgrade", "core", "specfact-core", "import"),
|
|
138
|
+
("specfact_project.project.commands", "project", "project", "nold-ai/specfact-project", "import"),
|
|
139
|
+
("specfact_spec.spec.commands", "spec", "spec", "nold-ai/specfact-spec", "import"),
|
|
140
|
+
("specfact_codebase.code.commands", "code", "code", "nold-ai/specfact-codebase", "import"),
|
|
141
|
+
("specfact_backlog.backlog.commands", "backlog", "backlog", "nold-ai/specfact-backlog", "import"),
|
|
142
|
+
("specfact_govern.govern.commands", "govern", "govern", "nold-ai/specfact-govern", "import"),
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
cases: dict[str, CommandAuditCase] = {case.command_path: case for case in _explicit_cases()}
|
|
146
|
+
for module_path, prefix, phase, owner, _load_mode in app_specs:
|
|
147
|
+
app = _import_typer(module_path)
|
|
148
|
+
cases.setdefault(
|
|
149
|
+
prefix,
|
|
150
|
+
CommandAuditCase(prefix, (*tuple(prefix.split()), "--help"), phase, "help-only", owner),
|
|
151
|
+
)
|
|
152
|
+
for command_path in sorted(_collect_typer_paths(app, prefix)):
|
|
153
|
+
cases.setdefault(
|
|
154
|
+
command_path,
|
|
155
|
+
CommandAuditCase(
|
|
156
|
+
command_path,
|
|
157
|
+
(*tuple(command_path.split()), "--help"),
|
|
158
|
+
phase,
|
|
159
|
+
"help-only",
|
|
160
|
+
owner,
|
|
161
|
+
),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
phase_order = {"root": 0, "core": 1, "project": 2, "spec": 3, "code": 4, "backlog": 5, "govern": 6}
|
|
165
|
+
return sorted(cases.values(), key=lambda case: (phase_order.get(case.phase, 99), case.command_path))
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Create backlog items with guided interactive flow and hierarchy checks"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# SpecFact Backlog Add 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
|
-
Create a new backlog item in GitHub or Azure DevOps using the `specfact backlog add` workflow. The command supports interactive prompts, parent hierarchy validation, DoR checks, and provider-specific fields.
|
|
18
|
-
|
|
19
|
-
**When to use:** Adding new work items (epic/feature/story/task/bug) with consistent quality and parent-child structure.
|
|
20
|
-
|
|
21
|
-
**Quick:** `/specfact.backlog-add --adapter github --project-id owner/repo --type story --title "..."`
|
|
22
|
-
|
|
23
|
-
## Parameters
|
|
24
|
-
|
|
25
|
-
### Required
|
|
26
|
-
|
|
27
|
-
- `--adapter ADAPTER` - Backlog adapter (`github`, `ado`)
|
|
28
|
-
- `--project-id PROJECT` - Project context
|
|
29
|
-
- GitHub: `owner/repo`
|
|
30
|
-
- ADO: `org/project`
|
|
31
|
-
|
|
32
|
-
### Common options
|
|
33
|
-
|
|
34
|
-
- `--type TYPE` - Backlog item type (provider/template specific)
|
|
35
|
-
- `--title TITLE` - Item title
|
|
36
|
-
- `--body BODY` - Item body/description
|
|
37
|
-
- `--parent PARENT_ID` - Optional parent issue/work item id
|
|
38
|
-
- `--non-interactive` - Disable prompt flow and require explicit inputs
|
|
39
|
-
- `--check-dor` - Run Definition of Ready checks before create
|
|
40
|
-
- `--template TEMPLATE` - Optional backlog template override
|
|
41
|
-
- `--custom-config PATH` - Optional mapping/config override file
|
|
42
|
-
|
|
43
|
-
### Adapter-specific options
|
|
44
|
-
|
|
45
|
-
- GitHub:
|
|
46
|
-
- `--repo-owner OWNER`
|
|
47
|
-
- `--repo-name NAME`
|
|
48
|
-
- `--github-token TOKEN` (or `GITHUB_TOKEN`)
|
|
49
|
-
- Azure DevOps:
|
|
50
|
-
- `--ado-org ORG`
|
|
51
|
-
- `--ado-project PROJECT`
|
|
52
|
-
- `--ado-token TOKEN` (or `AZURE_DEVOPS_TOKEN`)
|
|
53
|
-
- `--ado-base-url URL` (optional)
|
|
54
|
-
|
|
55
|
-
## Workflow
|
|
56
|
-
|
|
57
|
-
### Step 1: Execute command
|
|
58
|
-
|
|
59
|
-
Run the CLI command with user arguments:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
specfact backlog add [OPTIONS]
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Step 2: Interactive completion (if inputs are missing)
|
|
66
|
-
|
|
67
|
-
- Prompt for missing required fields.
|
|
68
|
-
- Prompt for optional quality fields (acceptance criteria, points, priority) when supported.
|
|
69
|
-
- Validate parent selection and allowed hierarchy before create.
|
|
70
|
-
|
|
71
|
-
### Step 3: Confirm and create
|
|
72
|
-
|
|
73
|
-
- Show planned create payload summary.
|
|
74
|
-
- Execute provider create operation.
|
|
75
|
-
- Return created item id/key/url.
|
|
76
|
-
|
|
77
|
-
## CLI Enforcement
|
|
78
|
-
|
|
79
|
-
- Always execute `specfact backlog add` for creation.
|
|
80
|
-
- Do not create provider issues/work items directly outside CLI unless user explicitly requests a manual path.
|
|
81
|
-
|
|
82
|
-
## Input Contract
|
|
83
|
-
|
|
84
|
-
- This command does not use `--export-to-tmp`/`--import-from-tmp` artifacts.
|
|
85
|
-
- Provide values through CLI options or interactive prompts; do not fabricate external tmp-file schemas.
|
|
86
|
-
- Do not ask Copilot to output `## Item N:` sections, `**ID**` labels, or markdown tmp files for this command.
|
|
87
|
-
|
|
88
|
-
## Context
|
|
89
|
-
|
|
90
|
-
{ARGS}
|