atdd 0.2.12__tar.gz → 0.3.1__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.
- {atdd-0.2.12/src/atdd.egg-info → atdd-0.3.1}/PKG-INFO +1 -1
- {atdd-0.2.12 → atdd-0.3.1}/pyproject.toml +6 -1
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/cli.py +14 -4
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/inventory.py +2 -4
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/test_runner.py +1 -1
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/templates/ATDD.md +5 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/templates/SESSION-TEMPLATE.md +9 -0
- atdd-0.3.1/src/atdd/coach/utils/__init__.py +5 -0
- atdd-0.3.1/src/atdd/coach/utils/repo.py +97 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/shared_fixtures.py +2 -0
- atdd-0.3.1/src/atdd/tester/conventions/security.convention.yaml +165 -0
- atdd-0.3.1/src/atdd/tester/validators/test_contract_security.py +569 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_contracts_structure.py +81 -0
- {atdd-0.2.12 → atdd-0.3.1/src/atdd.egg-info}/PKG-INFO +1 -1
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd.egg-info/SOURCES.txt +3 -0
- atdd-0.2.12/src/atdd/tester/validators/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/LICENSE +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/README.md +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/setup.cfg +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/__main__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/add_persistence_metadata.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/analyze_migrations.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/consumers.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/gate.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/infer_governance_status.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/initializer.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/interface.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/migration.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/registry.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/session.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/sync.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/test_interface.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/tests/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/tests/test_telemetry_array_validation.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/commands/traceability.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/conventions/session.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/overlays/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/overlays/claude.md +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/schemas/config.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/schemas/manifest.schema.json +0 -0
- {atdd-0.2.12/src/atdd/coach/utils → atdd-0.3.1/src/atdd/coach/utils/graph}/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/utils/graph/urn.py +0 -0
- {atdd-0.2.12/src/atdd/coach/utils/graph → atdd-0.3.1/src/atdd/coach/validators}/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/test_enrich_wagon_registry.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/test_registry.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/test_session_validation.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/test_traceability.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/test_update_feature_paths.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coach/validators/test_validate_contract_consumers.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/adapter.recipe.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/backend.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/boundaries.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/commons.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/complexity.recipe.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/component-naming.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/design.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/design.recipe.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/dto.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/frontend.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/green.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/presentation.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/refactor.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/technology.convention.yaml +0 -0
- {atdd-0.2.12/src/atdd/coach/validators → atdd-0.3.1/src/atdd/coder/conventions/tests}/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/tests/test_adapter_recipe.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/tests/test_complexity_recipe.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/tests/test_component_taxonomy.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/tests/test_component_urn_naming.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/tests/test_thinness_recipe.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/thinness.recipe.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/train.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/conventions/verification.protocol.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/schemas/design_system.schema.json +0 -0
- {atdd-0.2.12/src/atdd/coder/conventions/tests → atdd-0.3.1/src/atdd/coder/validators}/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_commons_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_complexity.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_cross_language_consistency.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_design_system_compliance.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_dto_testing_patterns.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_green_cross_stack_layers.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_green_layer_dependencies.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_green_python_layer_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_green_supabase_layer_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_import_boundaries.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_init_file_urns.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_preact_layer_boundaries.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_presentation_convention.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_python_architecture.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_quality_metrics.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_station_master_pattern.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_train_infrastructure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_train_urns.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_typescript_architecture.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_usecase_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/coder/validators/test_wagon_boundaries.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/conftest.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/acceptance.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/appendix.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/artifact-naming.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/component.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/criteria.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/feature.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/interface.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/steps.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/train.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/wagon.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/conventions/wmbt.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/acceptance.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/appendix.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/component.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/feature.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/train.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/wagon.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/schemas/wmbt.schema.json +0 -0
- {atdd-0.2.12/src/atdd/coder → atdd-0.3.1/src/atdd/planner}/validators/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/conftest.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_draft_wagon_registry.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_plan_cross_refs.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_plan_uniqueness.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_plan_urn_resolution.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_plan_wagons.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_train_validation.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_wagon_urn_chain.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_wmbt_consistency.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/planner/validators/test_wmbt_vocabulary.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/artifact.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/contract.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/filename.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/migration.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/red.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/routing.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/conventions/telemetry.convention.yaml +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/a11y.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/artifact.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/contract.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/contract.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/db.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/e2e.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/edge_function.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/event.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/http.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/job.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/load.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/metric.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/pack.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/realtime.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/rls.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/script.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/sec.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/storage.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/telemetry.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/telemetry_tracking_manifest.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/test_filename.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/test_intent.schema.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/unit.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/visual.tmpl.json +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/schemas/ws.tmpl.json +0 -0
- {atdd-0.2.12/src/atdd/planner/validators → atdd-0.3.1/src/atdd/tester/utils}/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/utils/filename.py +0 -0
- {atdd-0.2.12/src/atdd/tester/utils → atdd-0.3.1/src/atdd/tester/validators}/__init__.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/cleanup_duplicate_headers.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/cleanup_duplicate_headers_v2.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/conftest.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/coverage_gap_report.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/fix_dual_ac_references.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/remove_duplicate_lines.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_acceptance_urn_filename_mapping.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_acceptance_urn_separator.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_artifact_naming_category.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_contract_schema_compliance.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_coverage_adequacy.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_dual_ac_reference.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_fixture_validity.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_isolation.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_migration_coverage.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_migration_criteria.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_migration_generation.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_python_test_naming.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_red_layer_validation.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_red_python_layer_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_red_supabase_layer_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_telemetry_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_typescript_test_naming.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/tester/validators/test_typescript_test_structure.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd/version_check.py +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd.egg-info/dependency_links.txt +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd.egg-info/entry_points.txt +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd.egg-info/requires.txt +0 -0
- {atdd-0.2.12 → atdd-0.3.1}/src/atdd.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "atdd"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "ATDD Platform - Acceptance Test Driven Development toolkit"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
readme = "README.md"
|
|
@@ -35,3 +35,8 @@ where = ["src"]
|
|
|
35
35
|
[tool.pytest.ini_options]
|
|
36
36
|
pythonpath = ["src"]
|
|
37
37
|
testpaths = ["src/atdd"]
|
|
38
|
+
markers = [
|
|
39
|
+
"tester: marks tests as tester validators",
|
|
40
|
+
"platform: marks tests as platform validators",
|
|
41
|
+
"security: marks tests as security validators",
|
|
42
|
+
]
|
|
@@ -44,6 +44,7 @@ from atdd.coach.commands.initializer import ProjectInitializer
|
|
|
44
44
|
from atdd.coach.commands.session import SessionManager
|
|
45
45
|
from atdd.coach.commands.sync import AgentConfigSync
|
|
46
46
|
from atdd.coach.commands.gate import ATDDGate
|
|
47
|
+
from atdd.coach.utils.repo import find_repo_root
|
|
47
48
|
from atdd.version_check import print_update_notice
|
|
48
49
|
|
|
49
50
|
|
|
@@ -57,8 +58,8 @@ class ATDDCoach:
|
|
|
57
58
|
- Coder: Implementation phase validation
|
|
58
59
|
"""
|
|
59
60
|
|
|
60
|
-
def __init__(self):
|
|
61
|
-
self.repo_root =
|
|
61
|
+
def __init__(self, repo_root: Path = None):
|
|
62
|
+
self.repo_root = repo_root or find_repo_root()
|
|
62
63
|
self.inventory = RepositoryInventory(self.repo_root)
|
|
63
64
|
self.test_runner = TestRunner(self.repo_root)
|
|
64
65
|
self.registry_updater = RegistryUpdater(self.repo_root)
|
|
@@ -290,6 +291,14 @@ Phase descriptions:
|
|
|
290
291
|
|
|
291
292
|
# ----- Existing flag-based arguments (backwards compatible) -----
|
|
292
293
|
|
|
294
|
+
# Repository root override
|
|
295
|
+
parser.add_argument(
|
|
296
|
+
"--repo",
|
|
297
|
+
type=str,
|
|
298
|
+
metavar="PATH",
|
|
299
|
+
help="Target repository root (default: auto-detect from .atdd/)"
|
|
300
|
+
)
|
|
301
|
+
|
|
293
302
|
# Main command groups
|
|
294
303
|
parser.add_argument(
|
|
295
304
|
"--inventory",
|
|
@@ -394,8 +403,9 @@ Phase descriptions:
|
|
|
394
403
|
|
|
395
404
|
# ----- Handle flag-based commands (backwards compatible) -----
|
|
396
405
|
|
|
397
|
-
# Create coach instance
|
|
398
|
-
|
|
406
|
+
# Create coach instance with optional repo override
|
|
407
|
+
repo_path = Path(args.repo) if args.repo else None
|
|
408
|
+
coach = ATDDCoach(repo_root=repo_path)
|
|
399
409
|
|
|
400
410
|
# Handle commands
|
|
401
411
|
if args.inventory:
|
|
@@ -26,7 +26,7 @@ class RepositoryInventory:
|
|
|
26
26
|
"""Generate comprehensive repository inventory."""
|
|
27
27
|
|
|
28
28
|
def __init__(self, repo_root: Path = None):
|
|
29
|
-
self.repo_root = repo_root or Path(
|
|
29
|
+
self.repo_root = repo_root or Path.cwd()
|
|
30
30
|
self.inventory = {
|
|
31
31
|
"inventory": {
|
|
32
32
|
"generated_at": datetime.now().isoformat(),
|
|
@@ -288,7 +288,7 @@ class RepositoryInventory:
|
|
|
288
288
|
feature_files = len(python_tests) + len(ts_tests)
|
|
289
289
|
|
|
290
290
|
meta_cases = planner_cases + tester_cases + coder_cases + platform_cases
|
|
291
|
-
feature_cases = python_cases #
|
|
291
|
+
feature_cases = python_cases # TS case counting would require parsing those languages
|
|
292
292
|
|
|
293
293
|
return {
|
|
294
294
|
"total_files": meta_files + feature_files,
|
|
@@ -312,13 +312,11 @@ class RepositoryInventory:
|
|
|
312
312
|
"feature_tests": {
|
|
313
313
|
"files": {
|
|
314
314
|
"python": len(python_tests),
|
|
315
|
-
"dart": len(dart_tests),
|
|
316
315
|
"typescript": len(ts_tests),
|
|
317
316
|
"total": feature_files
|
|
318
317
|
},
|
|
319
318
|
"cases": {
|
|
320
319
|
"python": python_cases,
|
|
321
|
-
"dart": "not_counted",
|
|
322
320
|
"typescript": "not_counted",
|
|
323
321
|
"total": feature_cases
|
|
324
322
|
}
|
|
@@ -15,7 +15,7 @@ class TestRunner:
|
|
|
15
15
|
"""Run ATDD meta-tests with various configurations."""
|
|
16
16
|
|
|
17
17
|
def __init__(self, repo_root: Path = None):
|
|
18
|
-
self.repo_root = repo_root or Path(
|
|
18
|
+
self.repo_root = repo_root or Path.cwd()
|
|
19
19
|
self.atdd_dir = self.repo_root / "atdd"
|
|
20
20
|
|
|
21
21
|
def run_tests(
|
|
@@ -13,6 +13,11 @@ missions:
|
|
|
13
13
|
#
|
|
14
14
|
# PROTOCOL:
|
|
15
15
|
# ---------
|
|
16
|
+
# 0. TOOL GATE (MANDATORY)
|
|
17
|
+
# If your agent supports plan mode (Claude Code, etc.), enable it NOW.
|
|
18
|
+
# This is a tool capability gate, NOT the ATDD Planner phase.
|
|
19
|
+
# If unavailable, state: "Plan mode unavailable" and proceed.
|
|
20
|
+
#
|
|
16
21
|
# 1. Run this command FIRST:
|
|
17
22
|
#
|
|
18
23
|
# atdd gate
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# TOOL GATE (MANDATORY BEFORE FILLING THIS FILE)
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# If your agent supports plan mode (Claude Code, etc.), enable it NOW.
|
|
6
|
+
# This is a tool capability gate, NOT the ATDD Planner phase.
|
|
7
|
+
# If unavailable, state: "Plan mode unavailable" and proceed.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
-->
|
|
1
10
|
---
|
|
2
11
|
# SESSION METADATA (YAML frontmatter - machine-parseable)
|
|
3
12
|
#
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Repository root detection utility.
|
|
3
|
+
|
|
4
|
+
Finds the consumer repository root using multiple detection strategies:
|
|
5
|
+
1. .atdd/manifest.yaml (preferred - explicit ATDD project marker)
|
|
6
|
+
2. plan/ AND contracts/ both exist (ATDD project structure)
|
|
7
|
+
3. .git/ directory (fallback - any git repo)
|
|
8
|
+
4. cwd (last resort - allows commands to work on uninitialized repos)
|
|
9
|
+
|
|
10
|
+
This ensures ATDD commands operate on the user's repo, not the package root.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from functools import lru_cache
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@lru_cache(maxsize=1)
|
|
19
|
+
def find_repo_root(start: Optional[Path] = None) -> Path:
|
|
20
|
+
"""
|
|
21
|
+
Find repo root by searching upward for ATDD project markers.
|
|
22
|
+
|
|
23
|
+
Detection order (first match wins):
|
|
24
|
+
1. .atdd/manifest.yaml - explicit ATDD project marker
|
|
25
|
+
2. plan/ AND contracts/ both exist - ATDD project structure
|
|
26
|
+
3. .git/ directory - fallback for any git repository
|
|
27
|
+
4. cwd - last resort if no markers found
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
start: Starting directory (default: cwd)
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Path to repo root (falls back to cwd if no markers found)
|
|
34
|
+
|
|
35
|
+
Note:
|
|
36
|
+
Results are cached for performance. If .atdd/manifest.yaml is not found,
|
|
37
|
+
commands may operate in a degraded mode.
|
|
38
|
+
"""
|
|
39
|
+
current = start or Path.cwd()
|
|
40
|
+
current = current.resolve()
|
|
41
|
+
|
|
42
|
+
while current != current.parent:
|
|
43
|
+
# Strategy 1: .atdd/manifest.yaml (preferred)
|
|
44
|
+
if (current / ".atdd" / "manifest.yaml").is_file():
|
|
45
|
+
return current
|
|
46
|
+
|
|
47
|
+
# Strategy 2: plan/ AND contracts/ both exist
|
|
48
|
+
if (current / "plan").is_dir() and (current / "contracts").is_dir():
|
|
49
|
+
return current
|
|
50
|
+
|
|
51
|
+
# Strategy 3: .git/ directory (fallback)
|
|
52
|
+
if (current / ".git").is_dir():
|
|
53
|
+
return current
|
|
54
|
+
|
|
55
|
+
current = current.parent
|
|
56
|
+
|
|
57
|
+
# Strategy 4: Return starting directory as last resort
|
|
58
|
+
# Commands can handle uninitialized repos appropriately
|
|
59
|
+
return start.resolve() if start else Path.cwd().resolve()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def require_repo_root(start: Optional[Path] = None) -> Path:
|
|
63
|
+
"""
|
|
64
|
+
Find repo root, raising RuntimeError if no markers found.
|
|
65
|
+
|
|
66
|
+
This is a stricter version of find_repo_root() for commands that
|
|
67
|
+
require a valid ATDD project structure.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
start: Starting directory (default: cwd)
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Path to repo root
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
RuntimeError: If no ATDD project markers (.atdd/manifest.yaml,
|
|
77
|
+
plan/ + contracts/, or .git/) are found
|
|
78
|
+
"""
|
|
79
|
+
current = start or Path.cwd()
|
|
80
|
+
current = current.resolve()
|
|
81
|
+
start_path = current
|
|
82
|
+
|
|
83
|
+
while current != current.parent:
|
|
84
|
+
# Check for any valid marker
|
|
85
|
+
if (current / ".atdd" / "manifest.yaml").is_file():
|
|
86
|
+
return current
|
|
87
|
+
if (current / "plan").is_dir() and (current / "contracts").is_dir():
|
|
88
|
+
return current
|
|
89
|
+
if (current / ".git").is_dir():
|
|
90
|
+
return current
|
|
91
|
+
|
|
92
|
+
current = current.parent
|
|
93
|
+
|
|
94
|
+
raise RuntimeError(
|
|
95
|
+
f"No ATDD project markers found searching from {start_path}. "
|
|
96
|
+
"Expected one of: .atdd/manifest.yaml, plan/ + contracts/, or .git/"
|
|
97
|
+
)
|
|
@@ -118,6 +118,8 @@ def wagon_manifests() -> List[Tuple[Path, Dict[str, Any]]]:
|
|
|
118
118
|
manifests.append((manifest_path, manifest_data))
|
|
119
119
|
|
|
120
120
|
# Also discover individual wagon manifests (pattern: plan/*/_{wagon}.yaml)
|
|
121
|
+
if not PLAN_DIR.exists():
|
|
122
|
+
return manifests
|
|
121
123
|
for wagon_dir in PLAN_DIR.iterdir():
|
|
122
124
|
if wagon_dir.is_dir() and not wagon_dir.name.startswith("_"):
|
|
123
125
|
for manifest_file in wagon_dir.glob("_*.yaml"):
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
name: "Security Convention"
|
|
3
|
+
description: "Security validation rules for contract schemas"
|
|
4
|
+
|
|
5
|
+
# Validator Specifications
|
|
6
|
+
validators:
|
|
7
|
+
- id: "SPEC-TESTER-SEC-0001"
|
|
8
|
+
name: "Secured operations must declare auth headers"
|
|
9
|
+
test: "test_secured_operations_have_required_headers"
|
|
10
|
+
mode: "hard"
|
|
11
|
+
description: |
|
|
12
|
+
Secured operations must include appropriate authentication headers
|
|
13
|
+
based on their declared security scheme. This ensures that all
|
|
14
|
+
protected endpoints have proper header declarations for auth tokens.
|
|
15
|
+
|
|
16
|
+
- id: "SPEC-TESTER-SEC-0002"
|
|
17
|
+
name: "Operations must have explicit security field"
|
|
18
|
+
test: "test_operations_have_explicit_security"
|
|
19
|
+
mode: "soft (xfail)"
|
|
20
|
+
description: |
|
|
21
|
+
All API operations should declare their security requirements explicitly.
|
|
22
|
+
Use security: [] for public endpoints and security: [{...}] for protected.
|
|
23
|
+
This ensures security posture is intentional, not accidental.
|
|
24
|
+
|
|
25
|
+
- id: "SPEC-TESTER-SEC-0003"
|
|
26
|
+
name: "Secured operations need SEC/RLS acceptance coverage"
|
|
27
|
+
test: "test_secured_operations_have_security_acceptance"
|
|
28
|
+
mode: "soft (xfail)"
|
|
29
|
+
description: |
|
|
30
|
+
Secured operations must have at least one acceptance criteria using
|
|
31
|
+
the SEC (Security) or RLS (Row-Level Security) harness. This ensures
|
|
32
|
+
security requirements are tested.
|
|
33
|
+
|
|
34
|
+
- id: "SPEC-TESTER-SEC-0004"
|
|
35
|
+
name: "Error responses should not expose sensitive data"
|
|
36
|
+
test: "test_error_responses_have_no_sensitive_fields"
|
|
37
|
+
mode: "warning only"
|
|
38
|
+
description: |
|
|
39
|
+
Error responses (4xx/5xx) should not contain fields with sensitive
|
|
40
|
+
names like password, secret, credential, ssn, api_key, private_key.
|
|
41
|
+
This prevents accidental exposure of sensitive data in error messages.
|
|
42
|
+
|
|
43
|
+
# Security Scheme to Header Mapping
|
|
44
|
+
scheme_header_mapping:
|
|
45
|
+
jwt:
|
|
46
|
+
headers: ["authorization"]
|
|
47
|
+
format: "Bearer {token}"
|
|
48
|
+
description: "JSON Web Token authentication"
|
|
49
|
+
|
|
50
|
+
bearer:
|
|
51
|
+
headers: ["authorization"]
|
|
52
|
+
format: "Bearer {token}"
|
|
53
|
+
description: "Bearer token authentication"
|
|
54
|
+
|
|
55
|
+
oauth2:
|
|
56
|
+
headers: ["authorization"]
|
|
57
|
+
format: "Bearer {access_token}"
|
|
58
|
+
description: "OAuth 2.0 authentication"
|
|
59
|
+
|
|
60
|
+
http:
|
|
61
|
+
headers: ["authorization"]
|
|
62
|
+
format: "Varies by scheme (basic, bearer, digest)"
|
|
63
|
+
description: "HTTP authentication"
|
|
64
|
+
|
|
65
|
+
apiKey:
|
|
66
|
+
headers: "dynamic"
|
|
67
|
+
source: "security[].name (default: x-api-key)"
|
|
68
|
+
location: "security[].in (header, query, or cookie)"
|
|
69
|
+
description: "API Key authentication"
|
|
70
|
+
|
|
71
|
+
# Enforcement Modes
|
|
72
|
+
enforcement:
|
|
73
|
+
environment_variable: "ATDD_SECURITY_ENFORCE"
|
|
74
|
+
default: "0"
|
|
75
|
+
modes:
|
|
76
|
+
soft:
|
|
77
|
+
value: "0"
|
|
78
|
+
behavior: "pytest.xfail - test marked as expected failure"
|
|
79
|
+
visibility: "Visible in test output as XFAIL"
|
|
80
|
+
use_case: "Development, incremental adoption"
|
|
81
|
+
|
|
82
|
+
hard:
|
|
83
|
+
value: "1"
|
|
84
|
+
behavior: "pytest.fail - test fails the suite"
|
|
85
|
+
visibility: "Visible as FAILED"
|
|
86
|
+
use_case: "CI/CD, production readiness"
|
|
87
|
+
|
|
88
|
+
# Sensitive Data Detection
|
|
89
|
+
sensitive_data_detection:
|
|
90
|
+
description: "Rules for detecting potentially sensitive fields in error responses"
|
|
91
|
+
|
|
92
|
+
sensitive_fields:
|
|
93
|
+
- "password"
|
|
94
|
+
- "secret"
|
|
95
|
+
- "credential"
|
|
96
|
+
- "ssn"
|
|
97
|
+
- "api_key"
|
|
98
|
+
- "private_key"
|
|
99
|
+
- "token"
|
|
100
|
+
|
|
101
|
+
allowed_exceptions:
|
|
102
|
+
- "error_key"
|
|
103
|
+
- "key_id"
|
|
104
|
+
- "token_type"
|
|
105
|
+
|
|
106
|
+
detection_method: "Substring match (case-insensitive)"
|
|
107
|
+
note: "Review flagged fields manually - not all matches are security issues"
|
|
108
|
+
|
|
109
|
+
# Threat Modeling Integration
|
|
110
|
+
threat_modeling:
|
|
111
|
+
canonical_location: "feature.yaml: security.abuse_cases[]"
|
|
112
|
+
description: |
|
|
113
|
+
Threat models and abuse cases should be documented in the feature YAML
|
|
114
|
+
files under the security.abuse_cases array. This ensures security
|
|
115
|
+
considerations are part of the feature specification.
|
|
116
|
+
|
|
117
|
+
schema:
|
|
118
|
+
abuse_case:
|
|
119
|
+
required:
|
|
120
|
+
- id # Unique identifier (e.g., THREAT-001)
|
|
121
|
+
- name # Short name
|
|
122
|
+
- threat # Description of the threat
|
|
123
|
+
- mitigation # How the threat is addressed
|
|
124
|
+
optional:
|
|
125
|
+
- severity # low, medium, high, critical
|
|
126
|
+
- likelihood # unlikely, possible, likely
|
|
127
|
+
- acceptance_ref # URN to acceptance test covering this threat
|
|
128
|
+
|
|
129
|
+
example:
|
|
130
|
+
security:
|
|
131
|
+
abuse_cases:
|
|
132
|
+
- id: "THREAT-001"
|
|
133
|
+
name: "Session Hijacking"
|
|
134
|
+
threat: "Attacker steals session token via XSS"
|
|
135
|
+
mitigation: "HttpOnly cookies, CSP headers"
|
|
136
|
+
severity: "high"
|
|
137
|
+
acceptance_ref: "acc:auth:D001-SEC-001-session-protection"
|
|
138
|
+
|
|
139
|
+
# Acceptance Coverage Requirements
|
|
140
|
+
acceptance_coverage:
|
|
141
|
+
description: "Requirements for security acceptance test coverage"
|
|
142
|
+
|
|
143
|
+
valid_harnesses:
|
|
144
|
+
- "SEC" # Security-focused tests
|
|
145
|
+
- "RLS" # Row-Level Security tests
|
|
146
|
+
|
|
147
|
+
urn_format: "acc:{wagon}:{WMBT}-{HARNESS}-{NNN}[-{slug}]"
|
|
148
|
+
full_format_required: true
|
|
149
|
+
note: |
|
|
150
|
+
Short refs (without harness) cannot be validated for SEC/RLS coverage.
|
|
151
|
+
Always use the full URN format with the harness identifier.
|
|
152
|
+
|
|
153
|
+
examples:
|
|
154
|
+
valid:
|
|
155
|
+
- "acc:auth:D001-SEC-001-token-validation"
|
|
156
|
+
- "acc:player:P002-RLS-001-own-data-only"
|
|
157
|
+
invalid:
|
|
158
|
+
- "SEC-001" # Missing wagon and WMBT
|
|
159
|
+
- "D001-001" # Missing harness identifier
|
|
160
|
+
|
|
161
|
+
# Cross-References
|
|
162
|
+
references:
|
|
163
|
+
test_file: "atdd/tester/validators/test_contract_security.py"
|
|
164
|
+
contract_convention: "atdd/tester/conventions/contract.convention.yaml"
|
|
165
|
+
api_structure: "contract.convention.yaml#api_structure.authentication"
|