specfact-cli 0.26.7__tar.gz → 0.26.8__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.26.7 → specfact_cli-0.26.8}/PKG-INFO +12 -5
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/README.md +10 -4
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/pyproject.toml +2 -1
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/field_mappings/ado_agile.yaml +1 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/field_mappings/ado_default.yaml +1 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/field_mappings/ado_kanban.yaml +1 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/field_mappings/ado_safe.yaml +1 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/field_mappings/ado_scrum.yaml +1 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/__init__.py +1 -1
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/ado.py +12 -1
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/converter.py +20 -2
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/mappers/ado_mapper.py +23 -3
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/backlog_commands.py +560 -108
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/init.py +86 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/.gitignore +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/LICENSE.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/mappings/node-async.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/mappings/python-async.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/mappings/speckit-default.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/shared/cli-enforcement.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.01-import.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.02-plan.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.03-review.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.04-sdd.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.05-enforce.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.06-sync.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.07-contracts.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.backlog-refine.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.compare.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.sync-backlog.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/prompts/specfact.validate.md +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/schemas/deviation.schema.json +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/schemas/plan.schema.json +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/schemas/protocol.schema.json +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/defaults/defect_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/defaults/enabler_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/defaults/spike_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/defaults/user_story_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/frameworks/safe/safe_feature_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/frameworks/scrum/user_story_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/personas/developer/developer_task_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/personas/product-owner/user_story_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/providers/ado/work_item_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/github-action.yml.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/persona/architect.md.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/persona/developer.md.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/persona/product-owner.md.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/plan.bundle.yaml.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/pr-template.md.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/protocol.yaml.j2 +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/telemetry.yaml.example +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/backlog_base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/github.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/openspec.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/openspec_parser.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/registry.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/adapters/speckit.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/agents/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/agents/analyze_agent.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/agents/base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/agents/plan_agent.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/agents/registry.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/agents/sync_agent.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/ambiguity_scanner.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/code_analyzer.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/constitution_evidence_extractor.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/contract_extractor.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/control_flow_analyzer.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/graph_analyzer.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/relationship_mapper.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/requirement_extractor.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/analyzers/test_pattern_extractor.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/adapters/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/adapters/base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/adapters/local_yaml_adapter.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/ai_refiner.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/filters.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/format_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/formats/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/formats/base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/formats/markdown_format.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/formats/structured_format.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/mappers/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/mappers/base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/mappers/github_mapper.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/mappers/template_config.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/backlog/template_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/cli.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/analyze.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/auth.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/contract_cmd.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/drift.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/enforce.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/generate.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/import_cmd.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/migrate.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/plan.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/project_cmd.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/repro.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/sdd.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/spec.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/sync.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/update.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/commands/validate.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/common/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/common/logger_setup.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/common/logging_utils.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/common/text_utils.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/common/utils.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/comparators/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/comparators/plan_comparator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/contracts/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/contracts/crosshair_props.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/enrichers/constitution_enricher.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/enrichers/plan_enricher.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/contract_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/openapi_extractor.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/persona_exporter.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/plan_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/protocol_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/report_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/task_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/test_to_openapi.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/generators/workflow_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/importers/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/importers/speckit_converter.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/importers/speckit_scanner.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/integrations/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/integrations/specmatic.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/merge/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/merge/resolver.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/migrations/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/migrations/plan_migrator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/backlog_item.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/bridge.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/capabilities.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/change.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/contract.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/deviation.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/dor_config.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/enforcement.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/persona_template.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/plan.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/project.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/protocol.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/quality.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/sdd.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/source_tracking.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/models/task.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/modes/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/modes/detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/modes/router.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/parsers/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/parsers/persona_importer.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/resources/semgrep/async.yml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/resources/semgrep/code-quality.yml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/resources/semgrep/feature-detection.yml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/runtime.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/bridge_probe.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/bridge_sync.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/bridge_watch.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/change_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/code_to_spec.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/drift_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/repository_sync.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/spec_to_code.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/spec_to_tests.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/watcher.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/sync/watcher_enhanced.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/telemetry.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/bridge_templates.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/defaults/defect_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/defaults/enabler_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/defaults/spike_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/defaults/user_story_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/frameworks/scrum/user_story_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/personas/product-owner/user_story_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/providers/ado/work_item_v1.yaml +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/registry.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/templates/specification_templates.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/acceptance_criteria.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/auth_tokens.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/bundle_loader.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/code_change_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/console.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/content_sanitizer.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/context_detection.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/enrichment_context.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/enrichment_parser.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/env_manager.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/feature_keys.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/git.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/github_annotations.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/ide_setup.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/incremental_check.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/metadata.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/optional_deps.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/performance.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/progress.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/progressive_disclosure.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/prompts.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/sdd_discovery.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/source_scanner.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/startup_checks.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/structure.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/structured_io.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/suggestions.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/terminal.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/utils/yaml_utils.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/agile_validation.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/change_proposal_integration.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/cli_first_validator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/contract_validator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/fsm.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/repro_checker.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/schema.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/contract_populator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/crosshair_runner.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/crosshair_summary.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/dependency_installer.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/framework_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/frameworks/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/frameworks/base.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/frameworks/django.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/frameworks/drf.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/frameworks/fastapi.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/frameworks/flask.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/harness_generator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/models.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/orchestrator.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/specmatic_runner.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/validators/sidecar/unannotated_detector.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/src/specfact_cli/versioning/__init__.py +0 -0
- {specfact_cli-0.26.7 → specfact_cli-0.26.8}/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.26.
|
|
3
|
+
Version: 0.26.8
|
|
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
|
|
@@ -238,6 +238,7 @@ Requires-Dist: opentelemetry-sdk>=1.27.0
|
|
|
238
238
|
Requires-Dist: pydantic>=2.12.3
|
|
239
239
|
Requires-Dist: python-dotenv>=1.2.1
|
|
240
240
|
Requires-Dist: pyyaml>=6.0.3
|
|
241
|
+
Requires-Dist: questionary>=2.0.1
|
|
241
242
|
Requires-Dist: requests>=2.32.3
|
|
242
243
|
Requires-Dist: rich<13.6.0,>=13.5.2
|
|
243
244
|
Requires-Dist: ruamel-yaml>=0.18.16
|
|
@@ -450,21 +451,26 @@ specfact validate sidecar run my-project /path/to/repo
|
|
|
450
451
|
- **Agile/scrum ready** - DoR checklists, story points, dependencies
|
|
451
452
|
- **Backlog standardization** 🆕 - Template-driven refinement with persona/framework filtering
|
|
452
453
|
- **Sprint/iteration filtering** 🆕 - Filter by sprint, release, iteration for agile workflows
|
|
454
|
+
- **Interactive field mapping** 🆕 - Discover and map Azure DevOps fields with arrow-key navigation
|
|
455
|
+
- **Azure DevOps integration** 🆕 - Full support for ADO work items with automatic token resolution
|
|
453
456
|
|
|
454
457
|
👉 **[Agile/Scrum Workflows](docs/guides/agile-scrum-workflows.md)** - Team collaboration guide
|
|
455
|
-
👉 **[Backlog Refinement](docs/guides/backlog-refinement.md)** 🆕 - Standardize backlog items with templates
|
|
458
|
+
👉 **[Backlog Refinement](docs/guides/backlog-refinement.md)** 🆕 - Standardize backlog items with templates
|
|
459
|
+
👉 **[Custom Field Mapping](docs/guides/custom-field-mapping.md)** 🆕 - Map ADO fields interactively
|
|
456
460
|
|
|
457
461
|
### 🔌 Integrations
|
|
458
462
|
|
|
459
463
|
- **VS Code, Cursor** - Catch bugs before you commit
|
|
460
464
|
- **GitHub Actions** - Automated quality gates
|
|
461
465
|
- **AI IDEs** - Generate prompts for fixing gaps
|
|
462
|
-
- **DevOps tools** - Sync with GitHub Issues, Linear, Jira
|
|
466
|
+
- **DevOps tools** - Sync with GitHub Issues, Azure DevOps, Linear, Jira
|
|
463
467
|
- **Backlog Refinement** 🆕 - AI-assisted template-driven refinement for standardizing work items
|
|
468
|
+
- **Azure DevOps field mapping** 🆕 - Interactive field discovery and mapping for custom ADO process templates
|
|
464
469
|
- **Spec-Kit, OpenSpec, Specmatic** - Works with your existing tools
|
|
465
470
|
|
|
466
471
|
👉 **[Integrations Overview](docs/guides/integrations-overview.md)** - All integration options
|
|
467
|
-
👉 **[Backlog Refinement Guide](docs/guides/backlog-refinement.md)** 🆕 **NEW** - Template-driven backlog standardization
|
|
472
|
+
👉 **[Backlog Refinement Guide](docs/guides/backlog-refinement.md)** 🆕 **NEW** - Template-driven backlog standardization
|
|
473
|
+
👉 **[Custom Field Mapping](docs/guides/custom-field-mapping.md)** 🆕 **NEW** - Interactive ADO field mapping
|
|
468
474
|
|
|
469
475
|
---
|
|
470
476
|
|
|
@@ -529,8 +535,9 @@ specfact validate sidecar run my-project /path/to/repo
|
|
|
529
535
|
- **[Spec-Kit Journey](docs/guides/speckit-journey.md)** - From Spec-Kit to SpecFact
|
|
530
536
|
- **[OpenSpec Journey](docs/guides/openspec-journey.md)** - OpenSpec integration
|
|
531
537
|
- **[Specmatic Integration](docs/guides/specmatic-integration.md)** - API contract testing
|
|
532
|
-
- **[DevOps Adapter Integration](docs/guides/devops-adapter-integration.md)** - GitHub Issues, Linear, Jira
|
|
538
|
+
- **[DevOps Adapter Integration](docs/guides/devops-adapter-integration.md)** - GitHub Issues, Azure DevOps, Linear, Jira
|
|
533
539
|
- **[Backlog Refinement](docs/guides/backlog-refinement.md)** 🆕 **NEW** - AI-assisted template-driven backlog standardization
|
|
540
|
+
- **[Custom Field Mapping](docs/guides/custom-field-mapping.md)** 🆕 **NEW** - Interactive Azure DevOps field mapping
|
|
534
541
|
|
|
535
542
|
👉 **[Full Documentation Index](docs/README.md)** - Browse all documentation
|
|
536
543
|
👉 **[Online Documentation](https://docs.specfact.io/)** - Complete documentation site
|
|
@@ -173,21 +173,26 @@ specfact validate sidecar run my-project /path/to/repo
|
|
|
173
173
|
- **Agile/scrum ready** - DoR checklists, story points, dependencies
|
|
174
174
|
- **Backlog standardization** 🆕 - Template-driven refinement with persona/framework filtering
|
|
175
175
|
- **Sprint/iteration filtering** 🆕 - Filter by sprint, release, iteration for agile workflows
|
|
176
|
+
- **Interactive field mapping** 🆕 - Discover and map Azure DevOps fields with arrow-key navigation
|
|
177
|
+
- **Azure DevOps integration** 🆕 - Full support for ADO work items with automatic token resolution
|
|
176
178
|
|
|
177
179
|
👉 **[Agile/Scrum Workflows](docs/guides/agile-scrum-workflows.md)** - Team collaboration guide
|
|
178
|
-
👉 **[Backlog Refinement](docs/guides/backlog-refinement.md)** 🆕 - Standardize backlog items with templates
|
|
180
|
+
👉 **[Backlog Refinement](docs/guides/backlog-refinement.md)** 🆕 - Standardize backlog items with templates
|
|
181
|
+
👉 **[Custom Field Mapping](docs/guides/custom-field-mapping.md)** 🆕 - Map ADO fields interactively
|
|
179
182
|
|
|
180
183
|
### 🔌 Integrations
|
|
181
184
|
|
|
182
185
|
- **VS Code, Cursor** - Catch bugs before you commit
|
|
183
186
|
- **GitHub Actions** - Automated quality gates
|
|
184
187
|
- **AI IDEs** - Generate prompts for fixing gaps
|
|
185
|
-
- **DevOps tools** - Sync with GitHub Issues, Linear, Jira
|
|
188
|
+
- **DevOps tools** - Sync with GitHub Issues, Azure DevOps, Linear, Jira
|
|
186
189
|
- **Backlog Refinement** 🆕 - AI-assisted template-driven refinement for standardizing work items
|
|
190
|
+
- **Azure DevOps field mapping** 🆕 - Interactive field discovery and mapping for custom ADO process templates
|
|
187
191
|
- **Spec-Kit, OpenSpec, Specmatic** - Works with your existing tools
|
|
188
192
|
|
|
189
193
|
👉 **[Integrations Overview](docs/guides/integrations-overview.md)** - All integration options
|
|
190
|
-
👉 **[Backlog Refinement Guide](docs/guides/backlog-refinement.md)** 🆕 **NEW** - Template-driven backlog standardization
|
|
194
|
+
👉 **[Backlog Refinement Guide](docs/guides/backlog-refinement.md)** 🆕 **NEW** - Template-driven backlog standardization
|
|
195
|
+
👉 **[Custom Field Mapping](docs/guides/custom-field-mapping.md)** 🆕 **NEW** - Interactive ADO field mapping
|
|
191
196
|
|
|
192
197
|
---
|
|
193
198
|
|
|
@@ -252,8 +257,9 @@ specfact validate sidecar run my-project /path/to/repo
|
|
|
252
257
|
- **[Spec-Kit Journey](docs/guides/speckit-journey.md)** - From Spec-Kit to SpecFact
|
|
253
258
|
- **[OpenSpec Journey](docs/guides/openspec-journey.md)** - OpenSpec integration
|
|
254
259
|
- **[Specmatic Integration](docs/guides/specmatic-integration.md)** - API contract testing
|
|
255
|
-
- **[DevOps Adapter Integration](docs/guides/devops-adapter-integration.md)** - GitHub Issues, Linear, Jira
|
|
260
|
+
- **[DevOps Adapter Integration](docs/guides/devops-adapter-integration.md)** - GitHub Issues, Azure DevOps, Linear, Jira
|
|
256
261
|
- **[Backlog Refinement](docs/guides/backlog-refinement.md)** 🆕 **NEW** - AI-assisted template-driven backlog standardization
|
|
262
|
+
- **[Custom Field Mapping](docs/guides/custom-field-mapping.md)** 🆕 **NEW** - Interactive Azure DevOps field mapping
|
|
257
263
|
|
|
258
264
|
👉 **[Full Documentation Index](docs/README.md)** - Browse all documentation
|
|
259
265
|
👉 **[Online Documentation](https://docs.specfact.io/)** - Complete documentation site
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specfact-cli"
|
|
7
|
-
version = "0.26.
|
|
7
|
+
version = "0.26.8"
|
|
8
8
|
description = "Brownfield-first CLI: Reverse engineer legacy Python → specs → enforced contracts. Automate legacy code documentation and prevent modernization regressions."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -37,6 +37,7 @@ dependencies = [
|
|
|
37
37
|
# CLI framework
|
|
38
38
|
"typer>=0.20.0",
|
|
39
39
|
"rich>=13.5.2,<13.6.0", # Compatible with semgrep (requires rich~=13.5.2)
|
|
40
|
+
"questionary>=2.0.1", # Interactive prompts with arrow key navigation
|
|
40
41
|
|
|
41
42
|
# Template engine
|
|
42
43
|
"jinja2>=3.1.6",
|
|
@@ -7,6 +7,7 @@ framework: agile
|
|
|
7
7
|
field_mappings:
|
|
8
8
|
System.Description: description
|
|
9
9
|
System.AcceptanceCriteria: acceptance_criteria
|
|
10
|
+
Microsoft.VSTS.Common.AcceptanceCriteria: acceptance_criteria # Alternative field name
|
|
10
11
|
Microsoft.VSTS.Scheduling.StoryPoints: story_points
|
|
11
12
|
Microsoft.VSTS.Common.BusinessValue: business_value
|
|
12
13
|
Microsoft.VSTS.Common.Priority: priority
|
|
@@ -7,6 +7,7 @@ framework: default
|
|
|
7
7
|
field_mappings:
|
|
8
8
|
System.Description: description
|
|
9
9
|
System.AcceptanceCriteria: acceptance_criteria
|
|
10
|
+
Microsoft.VSTS.Common.AcceptanceCriteria: acceptance_criteria # Alternative field name
|
|
10
11
|
Microsoft.VSTS.Common.StoryPoints: story_points
|
|
11
12
|
Microsoft.VSTS.Scheduling.StoryPoints: story_points
|
|
12
13
|
Microsoft.VSTS.Common.BusinessValue: business_value
|
|
@@ -7,6 +7,7 @@ framework: kanban
|
|
|
7
7
|
field_mappings:
|
|
8
8
|
System.Description: description
|
|
9
9
|
System.AcceptanceCriteria: acceptance_criteria
|
|
10
|
+
Microsoft.VSTS.Common.AcceptanceCriteria: acceptance_criteria # Alternative field name
|
|
10
11
|
Microsoft.VSTS.Common.Priority: priority
|
|
11
12
|
System.WorkItemType: work_item_type
|
|
12
13
|
System.State: state
|
{specfact_cli-0.26.7 → specfact_cli-0.26.8}/resources/templates/backlog/field_mappings/ado_safe.yaml
RENAMED
|
@@ -8,6 +8,7 @@ framework: safe
|
|
|
8
8
|
field_mappings:
|
|
9
9
|
System.Description: description
|
|
10
10
|
System.AcceptanceCriteria: acceptance_criteria
|
|
11
|
+
Microsoft.VSTS.Common.AcceptanceCriteria: acceptance_criteria # Alternative field name
|
|
11
12
|
Microsoft.VSTS.Scheduling.StoryPoints: story_points
|
|
12
13
|
Microsoft.VSTS.Common.BusinessValue: business_value
|
|
13
14
|
Microsoft.VSTS.Common.Priority: priority
|
|
@@ -7,6 +7,7 @@ framework: scrum
|
|
|
7
7
|
field_mappings:
|
|
8
8
|
System.Description: description
|
|
9
9
|
System.AcceptanceCriteria: acceptance_criteria
|
|
10
|
+
Microsoft.VSTS.Common.AcceptanceCriteria: acceptance_criteria # Alternative field name
|
|
10
11
|
Microsoft.VSTS.Scheduling.StoryPoints: story_points
|
|
11
12
|
Microsoft.VSTS.Common.BusinessValue: business_value
|
|
12
13
|
Microsoft.VSTS.Common.Priority: priority
|
|
@@ -3067,8 +3067,19 @@ class AdoAdapter(BridgeAdapter, BacklogAdapterMixin, BacklogAdapter):
|
|
|
3067
3067
|
ado_fields = ado_mapper.map_from_canonical(canonical_fields)
|
|
3068
3068
|
|
|
3069
3069
|
# Get reverse mapping to find ADO field names for canonical fields
|
|
3070
|
+
# Use same preference logic as map_from_canonical: prefer System.* over Microsoft.VSTS.Common.*
|
|
3070
3071
|
field_mappings = ado_mapper._get_field_mappings()
|
|
3071
|
-
reverse_mappings
|
|
3072
|
+
reverse_mappings: dict[str, str] = {}
|
|
3073
|
+
for ado_field, canonical in field_mappings.items():
|
|
3074
|
+
if canonical not in reverse_mappings:
|
|
3075
|
+
# First mapping for this canonical field - use it
|
|
3076
|
+
reverse_mappings[canonical] = ado_field
|
|
3077
|
+
else:
|
|
3078
|
+
# Multiple mappings exist - prefer System.* over Microsoft.VSTS.Common.*
|
|
3079
|
+
current_ado_field = reverse_mappings[canonical]
|
|
3080
|
+
# Prefer System.* fields for write operations (more common in Scrum)
|
|
3081
|
+
if ado_field.startswith("System.") and not current_ado_field.startswith("System."):
|
|
3082
|
+
reverse_mappings[canonical] = ado_field
|
|
3072
3083
|
|
|
3073
3084
|
# Update description (body_markdown) - always use System.Description
|
|
3074
3085
|
if update_fields is None or "body" in update_fields or "body_markdown" in update_fields:
|
|
@@ -220,9 +220,27 @@ def convert_ado_work_item_to_backlog_item(
|
|
|
220
220
|
assigned_to = fields.get("System.AssignedTo", {})
|
|
221
221
|
if assigned_to:
|
|
222
222
|
if isinstance(assigned_to, dict):
|
|
223
|
-
|
|
223
|
+
# Extract all available identifiers (displayName, uniqueName, mail) for flexible filtering
|
|
224
|
+
# This allows filtering to work with any of these identifiers as mentioned in help text
|
|
225
|
+
# Priority order: displayName (for display) > uniqueName > mail
|
|
226
|
+
assignee_candidates = []
|
|
227
|
+
if assigned_to.get("displayName"):
|
|
228
|
+
assignee_candidates.append(assigned_to["displayName"].strip())
|
|
229
|
+
if assigned_to.get("uniqueName"):
|
|
230
|
+
assignee_candidates.append(assigned_to["uniqueName"].strip())
|
|
231
|
+
if assigned_to.get("mail"):
|
|
232
|
+
assignee_candidates.append(assigned_to["mail"].strip())
|
|
233
|
+
|
|
234
|
+
# Remove duplicates while preserving order (displayName first)
|
|
235
|
+
seen = set()
|
|
236
|
+
for candidate in assignee_candidates:
|
|
237
|
+
if candidate and candidate not in seen:
|
|
238
|
+
assignees.append(candidate)
|
|
239
|
+
seen.add(candidate)
|
|
224
240
|
else:
|
|
225
|
-
|
|
241
|
+
assignee_str = str(assigned_to).strip()
|
|
242
|
+
if assignee_str:
|
|
243
|
+
assignees = [assignee_str]
|
|
226
244
|
|
|
227
245
|
tags = []
|
|
228
246
|
ado_tags = fields.get("System.Tags", "")
|
|
@@ -32,6 +32,7 @@ class AdoFieldMapper(FieldMapper):
|
|
|
32
32
|
DEFAULT_FIELD_MAPPINGS = {
|
|
33
33
|
"System.Description": "description",
|
|
34
34
|
"System.AcceptanceCriteria": "acceptance_criteria",
|
|
35
|
+
"Microsoft.VSTS.Common.AcceptanceCriteria": "acceptance_criteria", # Alternative field name
|
|
35
36
|
"Microsoft.VSTS.Common.StoryPoints": "story_points",
|
|
36
37
|
"Microsoft.VSTS.Scheduling.StoryPoints": "story_points", # Alternative field name
|
|
37
38
|
"Microsoft.VSTS.Common.BusinessValue": "business_value",
|
|
@@ -146,6 +147,9 @@ class AdoFieldMapper(FieldMapper):
|
|
|
146
147
|
"""
|
|
147
148
|
Map canonical fields back to ADO field format.
|
|
148
149
|
|
|
150
|
+
When multiple ADO fields map to the same canonical field, prefers System.* fields
|
|
151
|
+
over Microsoft.VSTS.Common.* fields for better compatibility with Scrum templates.
|
|
152
|
+
|
|
149
153
|
Args:
|
|
150
154
|
canonical_fields: Dict of canonical field names to values
|
|
151
155
|
|
|
@@ -155,8 +159,19 @@ class AdoFieldMapper(FieldMapper):
|
|
|
155
159
|
# Use custom mapping if available, otherwise use defaults
|
|
156
160
|
field_mappings = self._get_field_mappings()
|
|
157
161
|
|
|
158
|
-
#
|
|
159
|
-
|
|
162
|
+
# Build reverse mapping with preference for System.* fields over Microsoft.VSTS.Common.*
|
|
163
|
+
# This ensures write operations use the more common System.* fields (better Scrum compatibility)
|
|
164
|
+
reverse_mappings: dict[str, str] = {}
|
|
165
|
+
for ado_field, canonical in field_mappings.items():
|
|
166
|
+
if canonical not in reverse_mappings:
|
|
167
|
+
# First mapping for this canonical field - use it
|
|
168
|
+
reverse_mappings[canonical] = ado_field
|
|
169
|
+
else:
|
|
170
|
+
# Multiple mappings exist - prefer System.* over Microsoft.VSTS.Common.*
|
|
171
|
+
current_ado_field = reverse_mappings[canonical]
|
|
172
|
+
# Prefer System.* fields for write operations (more common in Scrum)
|
|
173
|
+
if ado_field.startswith("System.") and not current_ado_field.startswith("System."):
|
|
174
|
+
reverse_mappings[canonical] = ado_field
|
|
160
175
|
|
|
161
176
|
ado_fields: dict[str, Any] = {}
|
|
162
177
|
|
|
@@ -195,6 +210,10 @@ class AdoFieldMapper(FieldMapper):
|
|
|
195
210
|
"""
|
|
196
211
|
Extract field value from ADO fields dict using mapping.
|
|
197
212
|
|
|
213
|
+
Supports multiple field name alternatives for the same canonical field.
|
|
214
|
+
Checks all ADO fields that map to the canonical field and returns the first found value.
|
|
215
|
+
Priority: custom mapping > default mapping (handled by _get_field_mappings merge order).
|
|
216
|
+
|
|
198
217
|
Args:
|
|
199
218
|
fields_dict: ADO fields dict
|
|
200
219
|
field_mappings: Field mappings (ADO field name -> canonical field name)
|
|
@@ -203,7 +222,8 @@ class AdoFieldMapper(FieldMapper):
|
|
|
203
222
|
Returns:
|
|
204
223
|
Field value or None if not found
|
|
205
224
|
"""
|
|
206
|
-
# Find ADO field
|
|
225
|
+
# Find all ADO field names that map to this canonical field
|
|
226
|
+
# Check all alternatives and return the first found value
|
|
207
227
|
for ado_field, canonical in field_mappings.items():
|
|
208
228
|
if canonical == canonical_field:
|
|
209
229
|
value = fields_dict.get(ado_field)
|