taskledger 0.5.1__tar.gz → 0.5.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.
- {taskledger-0.5.1 → taskledger-0.5.2}/.taskledger.toml +1 -1
- {taskledger-0.5.1 → taskledger-0.5.2}/CHANGELOG.md +25 -0
- {taskledger-0.5.1/taskledger.egg-info → taskledger-0.5.2}/PKG-INFO +1 -1
- {taskledger-0.5.1 → taskledger-0.5.2}/skills/taskledger/SKILL.md +35 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/_version.py +3 -3
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli.py +1 -1
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_lint.py +32 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_review.py +64 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/tasks.py +19 -5
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/workflow_guidance.py +26 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/workspace_snapshot.py +25 -24
- {taskledger-0.5.1 → taskledger-0.5.2/taskledger.egg-info}/PKG-INFO +1 -1
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/SOURCES.txt +2 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/scm_file_list.json +2 -0
- taskledger-0.5.2/taskledger.egg-info/scm_version.json +8 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/conftest.py +24 -41
- taskledger-0.5.2/tests/test_cli_runner_compatibility.py +184 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_docs_and_skill.py +12 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_input_cli.py +6 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_lint.py +111 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_review.py +26 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_workflow_guidance.py +11 -0
- taskledger-0.5.2/tests/test_workspace_snapshot.py +74 -0
- taskledger-0.5.1/taskledger.egg-info/scm_version.json +0 -8
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/building_blocks/al_block_0083.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/concepts/al_concept_0081.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/runtime/al_runtime_0076.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/runtime/al_runtime_0084.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0001.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0002.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0003.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0004.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0005.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0006.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0007.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0008.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0009.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0010.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0011.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0012.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0029.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0030.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0031.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0032.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0033.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0034.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0040.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0041.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0042.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0043.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0044.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0045.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0082.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0016.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0017.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0018.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0019.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0020.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0021.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0022.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0023.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0046.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0047.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0048.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0049.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0050.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0051.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/deployment/al_deploy_0039.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0061.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0062.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0063.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0064.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0065.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0066.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0067.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0068.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0069.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0070.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0071.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0072.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0073.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0052.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0053.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0054.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0055.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0056.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/requirements/al_content_0013.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/requirements/al_content_0014.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/requirements/al_content_0015.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0057.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0058.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0059.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0060.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0035.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0036.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0037.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0038.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0074.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0075.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0077.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0078.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/stakeholders/al_content_0079.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/stakeholders/al_content_0080.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0024.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0025.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0026.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0027.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0028.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/source-state.json +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/storage.yaml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.archledger.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.codecrate.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/codecov.yml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/pre-commit.yml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/python-publish.yml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/tests.yml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.gitignore +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.planledger.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.pre-commit-config.yaml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.readthedocs.yaml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.releaseledger.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.ruff.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/.specweave.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/AGENTS.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/API.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/ARCHITECTURE.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/LICENSE +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/Makefile +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/README.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/Makefile +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/api.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/architecture_taskledger_split.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/build.sh +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/command_contract.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/conf.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/full_task_cycle.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/index.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/multi_repo.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/public_surface.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/requirements.txt +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/service_boundary_whitelist.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/sync.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/transfer.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/docs/usage.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/pyproject.toml +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/scripts/find_code_clones.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/setup.cfg +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/setup.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/README.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/UNMAPPED_TESTS.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/evidence/.gitkeep +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/evidence/taskledger-test-feature-coverage.json +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/.gitkeep +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/active_task/active-task.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/actor_harness_state/actor-harness-state.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/actor_resolution/actor-resolution.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/agent_command_logging/agent-command-logging.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/agent_session_protocol/agent-session-protocol.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/atomic_fast_io/atomic-fast-io.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_cli/bdd-cli.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_gherkin/bdd-gherkin.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_models/bdd-models.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_report_import/bdd-report-import.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_storage/bdd-storage.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_validation_integration/bdd-validation-integration.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/cli_command_contract/cli-command-contract.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/cli_import_resilience/cli-import-resilience.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/code_reviews/code-reviews.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/command_example_linter/command-example-linter.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/command_inventory/command-inventory.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/command_runner/command-runner.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/compact_mutation_output/compact-mutation-output.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/config_cli/config-cli.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/delta_remaining_contracts/delta-remaining-contracts.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/docs_and_skill/docs-and-skill.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/doctor/doctor.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/domain_policies/domain-policies.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/event_logging_config/event-logging-config.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/events/events.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/file_link_snapshots/file-link-snapshots.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/find_code_clones_script/find-code-clones-script.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/handoff_lifecycle/handoff-lifecycle.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/help_subprocess/help-subprocess.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/implementation_change_scan/implementation-change-scan.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/implementation_checks/implementation-checks.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/json_contracts/json-contracts.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/legacy_cleanup_contracts/legacy-cleanup-contracts.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/lifecycle_policies/lifecycle-policies.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/lock_diagnostics/lock-diagnostics.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/locks_audit/locks-audit.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/models_v1_schema/models-v1-schema.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/monitor/monitor.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/next_action_expired_lock/next-action-expired-lock.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/no_log_feature/no-log-feature.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_approval_contract/plan-approval-contract.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_lint/plan-lint.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_review/plan-review.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_revision_workflow/plan-revision-workflow.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_todo_materialization/plan-todo-materialization.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/project_root_config/project-root-config.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/question_add_many/question-add-many.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/question_filter_answers/question-filter-answers.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/question_plan_regeneration/question-plan-regeneration.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/ready_work/ready-work.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/release_changelog/release-changelog.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/search/search.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/service_boundaries/service-boundaries.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/services_dashboard/services-dashboard.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/sidecar_collections/sidecar-collections.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_bundle_layout/storage-bundle-layout.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_common/storage-common.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_init/storage-init.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_migration/storage-migration.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_repos/storage-repos.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_sync/storage-sync.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/sync_git/sync-git.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_archive/archive.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_events/events.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_markdown_export/markdown-export.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_report/report.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_branch_scoped_ledgers/taskledger-branch-scoped-ledgers.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_cli_api_parity/taskledger-cli-api-parity.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_v2_cli/taskledger-v2-cli.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_v2_exchange/taskledger-v2-exchange.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/tasks_service_static/tasks-service-static.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/todo_implementation_gate/todo-implementation-gate.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/trace/trace.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/tree_command/tree-command.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/usage_cli/usage-cli.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_cli/worker-pipeline-cli.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_config/worker-pipeline-config.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_context/worker-pipeline-context.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_handoff/worker-pipeline-handoff.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_plan_template/worker-pipeline-plan-template.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_todos/worker-pipeline-todos.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/workflow_guidance/workflow-guidance.feature +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/manifest.json +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/mappings/.gitkeep +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/.gitkeep +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/coverage-gaps.md +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/coverage.json +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/mappings.json +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/__main__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/handoff.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/introductions.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/locks.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/plans.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/project.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/questions.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/releases.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/reviews.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/search.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/storage.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/sync.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/task_runs.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/tasks.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_actor.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_archive.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_common.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_implement.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_ledger.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_migrate.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_misc.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_pipeline.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_plan.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_question.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_ref.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_release.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_review.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_storage.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_sync.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_task.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_trace.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_validate.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/command_inventory.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/_model_utils.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/active_state.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/actor.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/change.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/check.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/event.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/handoff.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/lock.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/models.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/plan.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/policies.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/question.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/release.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/review.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/run.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/sidecars.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/states.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/task.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/errors.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/exchange.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/ids.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/launcher.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/py.typed +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/refs.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/search.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/actors.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/agent_logging.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/agent_transcripts.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/change_tracking.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/check_tracking.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/code_review.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/command_runner.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/dashboard.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor_checks/migration_checks.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor_checks/project_scan.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor_checks/task_checks.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/event_logging.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/file_links.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/git_sync.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/git_utils.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/handoff.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/handoff_lifecycle.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/implementation_flow.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/lock_diagnostics.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/monitor.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/navigation.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/next_action_model.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/next_action_payload.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/phase5_lock_transfer.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_editing.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_hash.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_input.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_materialization.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/planning_flow.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/ready_work.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/releases.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/run_store.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/storage_locations.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_archive.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_collections.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_events.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_export.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_lifecycle.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_queries.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_repair.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_reports.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/trace.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/tree.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/usage.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/validation.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/validation_flow.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/worker_context.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/worker_pipeline.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/agent_logs.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/atomic.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/common.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/events.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/frontmatter.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/indexes.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/init.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/ledger_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/locks.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/meta.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/migrations.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/paths.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/project_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/project_identity.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/repos.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/sidecar_index.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/task_index.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/task_store.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/toml_edit.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/worker_pipeline_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/yaml_store.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/timeutils.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/dependency_links.txt +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/entry_points.txt +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/requires.txt +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/top_level.txt +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/support/__init__.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/support/builders.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/support/fake_command_runner.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_active_task.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_actor_harness_state.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_actor_resolution.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_agent_command_logging.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_agent_session_protocol.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_atomic_fast_io.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_cli_command_contract.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_cli_import_resilience.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_code_reviews.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_command_example_linter.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_command_inventory.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_command_runner.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_compact_mutation_output.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_config_cli.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_delta_remaining_contracts.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_doctor.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_domain_policies.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_event_logging_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_events.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_file_link_snapshots.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_find_code_clones_script.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_handoff_lifecycle.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_help_subprocess.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_implementation_change_scan.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_implementation_checks.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_import_boundaries.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_json_contracts.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_ledgercore_dependency.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_legacy_cleanup_contracts.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_lifecycle_policies.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_lock_diagnostics.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_locks_audit.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_models_v1_schema.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_monitor.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_next_action_expired_lock.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_no_log_feature.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_performance_caching.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_approval_contract.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_input.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_revision_workflow.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_todo_materialization.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_project_root_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_question_add_many.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_question_filter_answers.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_question_plan_regeneration.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_ready_work.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_release_changelog.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_resource_refs.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_search.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_service_boundaries.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_services_dashboard.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_sidecar_collections.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_bundle_layout.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_common.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_init.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_migration.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_repos.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_sync.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_yaml_store.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_sync_git.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_archive.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_events.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_markdown_export.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_report.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_branch_scoped_ledgers.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_cli_api_parity.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_v2_cli.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_v2_exchange.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_tasks_service_static.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_todo_implementation_gate.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_trace.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_tree_command.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_usage_cli.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_validation_git_snapshot_recovery.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_cli.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_config.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_context.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_handoff.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_plan_template.py +0 -0
- {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_todos.py +0 -0
|
@@ -9,7 +9,7 @@ project_uuid = "081c7c05-2d10-42b7-9b37-3d814c2f400a"
|
|
|
9
9
|
# Taskledger branch-scoped state. This block is intentionally safe to commit.
|
|
10
10
|
ledger_ref = "main"
|
|
11
11
|
ledger_parent_ref = ""
|
|
12
|
-
ledger_next_task_number =
|
|
12
|
+
ledger_next_task_number = 139
|
|
13
13
|
ledger_branch_guard = "off"
|
|
14
14
|
|
|
15
15
|
[prompt_profiles.planning]
|
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v0.5.2] - 2026-07-10
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added plan review approval brief with decision status, question status, and structured body heading lint rule
|
|
8
|
+
|
|
9
|
+
### Quality
|
|
10
|
+
|
|
11
|
+
- Improved type safety in WorkspaceContentSnapshot and WorktreePathEntry deserialization with round-trip tests
|
|
12
|
+
|
|
13
|
+
<!-- generated by releaseledger -->
|
|
14
|
+
|
|
15
|
+
## [v0.5.1] - 2026-06-26
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Added plan check command and plan input service for validating editable plan input without creating or revising plans
|
|
20
|
+
- Added implement snapshot refresh command to accept current workspace as implementation snapshot when validation is blocked by IMPLEMENTATION_SNAPSHOT_MISMATCH
|
|
21
|
+
|
|
22
|
+
### Documentation
|
|
23
|
+
|
|
24
|
+
- Converted Sphinx RST documentation to Markdown with myst-parser
|
|
25
|
+
|
|
26
|
+
<!-- generated by releaseledger -->
|
|
27
|
+
|
|
3
28
|
## [v0.5.0] - 2026-06-14
|
|
4
29
|
|
|
5
30
|
### Added
|
|
@@ -215,6 +215,41 @@ not create changelog entries, render changelog context, or edit `CHANGELOG.md`.
|
|
|
215
215
|
21. After `taskledger plan upsert --from-answers`, run `taskledger question status`. If it still reports `Plan regeneration needed: True`, do not ask for approval. Inspect `taskledger question answers`, `taskledger plan show --version N`, and `taskledger doctor`.
|
|
216
216
|
22. Before asking the user to approve, run `taskledger plan review --version N` and paste or summarize the rendered review. Then run `taskledger plan lint --version N` if the review did not include lint. Do not record approval until the user explicitly approves.
|
|
217
217
|
23. Record approval only with clear user intent such as approve, accept, go ahead, or start implementation. Prefer `taskledger plan accept --version N --note "User approved in harness: ..."` for normal chat approval. Use `taskledger plan approve --version N --actor user --approval-source explicit_chat --note "..."` only when explicit actor/source metadata is needed (advanced).
|
|
218
|
+
|
|
219
|
+
### Approval presentation protocol
|
|
220
|
+
|
|
221
|
+
Before asking the user to approve a proposed plan:
|
|
222
|
+
|
|
223
|
+
1. Run `taskledger plan review --version N`.
|
|
224
|
+
2. Present a readable approval brief in chat. Do not only say that the plan is ready.
|
|
225
|
+
3. Include, in this order:
|
|
226
|
+
- scope / decision status
|
|
227
|
+
- required question status as `Questions X/Y answered`
|
|
228
|
+
- proposed plan title
|
|
229
|
+
- `Summary`
|
|
230
|
+
- `Implementation Changes`
|
|
231
|
+
- `Tests`
|
|
232
|
+
- `Assumptions`
|
|
233
|
+
- `Out of Scope / Deferred`
|
|
234
|
+
- exact approval instruction
|
|
235
|
+
4. Use the stored plan body and machine-readable commitments from the review output. Do not invent extra scope.
|
|
236
|
+
5. If review output reports blockers, do not ask for approval. Present the blockers and the next remediation command.
|
|
237
|
+
6. If no blockers remain, ask for explicit approval using wording like:
|
|
238
|
+
`Reply with "approve" or "go ahead" to start implementation.`
|
|
239
|
+
|
|
240
|
+
Bad approval prompt:
|
|
241
|
+
|
|
242
|
+
```text
|
|
243
|
+
Plan plan-v1 is ready for approval. It covers tests and docs. Reply approve.
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Good approval prompt:
|
|
247
|
+
|
|
248
|
+
```text
|
|
249
|
+
Use the structured approval brief above, including scope status, question counts,
|
|
250
|
+
summary, implementation changes, tests, assumptions, and out-of-scope notes.
|
|
251
|
+
```
|
|
252
|
+
|
|
218
253
|
24. Never replace a user-provided rich plan with only generated YAML criteria and todos. Preserve the user's plan body after the front matter and use front matter only to expose machine-readable fields to Taskledger.
|
|
219
254
|
25. A Taskledger plan is not just YAML front matter. The YAML block is for machine-readable `goal`, `acceptance_criteria`, `todos`, file links, and test commands. The rich human plan must remain as Markdown after the second `---`. Before approval, inspect `taskledger plan show --version N` or the saved `plan-vN.md` and verify that the accepted plan body is non-empty and contains the implementation rationale.
|
|
220
255
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.5.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 5,
|
|
21
|
+
__version__ = version = '0.5.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g1e080d8af'
|
|
@@ -14,7 +14,7 @@ import typer
|
|
|
14
14
|
|
|
15
15
|
try:
|
|
16
16
|
from typer._click import (
|
|
17
|
-
exceptions as _typer_click_exceptions,
|
|
17
|
+
exceptions as _typer_click_exceptions,
|
|
18
18
|
)
|
|
19
19
|
except ImportError: # pragma: no cover - older Typer
|
|
20
20
|
TyperClickException: Any = None
|
|
@@ -34,6 +34,13 @@ _PLACEHOLDER_PATTERNS: list[re.Pattern[str]] = [
|
|
|
34
34
|
re.compile(r"\bclean up\b", re.IGNORECASE),
|
|
35
35
|
]
|
|
36
36
|
|
|
37
|
+
_REQUIRED_APPROVAL_HEADINGS = (
|
|
38
|
+
"Summary",
|
|
39
|
+
"Implementation Changes",
|
|
40
|
+
"Tests",
|
|
41
|
+
"Assumptions",
|
|
42
|
+
)
|
|
43
|
+
|
|
37
44
|
|
|
38
45
|
@dataclass(frozen=True, slots=True)
|
|
39
46
|
class PlanLintIssue:
|
|
@@ -154,6 +161,31 @@ def _run_lint_rules(plan: PlanRecord, strict: bool) -> list[PlanLintIssue]:
|
|
|
154
161
|
hint="Add implementation notes after the closing `---` separator.",
|
|
155
162
|
)
|
|
156
163
|
)
|
|
164
|
+
|
|
165
|
+
# 3c. missing_approval_heading
|
|
166
|
+
missing_approval_headings = [
|
|
167
|
+
heading
|
|
168
|
+
for heading in _REQUIRED_APPROVAL_HEADINGS
|
|
169
|
+
if _body_section(plan.body, heading) is None
|
|
170
|
+
]
|
|
171
|
+
if missing_approval_headings:
|
|
172
|
+
severity: Severity = "error" if strict else "warning"
|
|
173
|
+
issues.append(
|
|
174
|
+
PlanLintIssue(
|
|
175
|
+
severity=severity,
|
|
176
|
+
code="missing_approval_heading",
|
|
177
|
+
location="plan.body",
|
|
178
|
+
message=(
|
|
179
|
+
"Plan body should include approval-ready headings: "
|
|
180
|
+
+ ", ".join(_REQUIRED_APPROVAL_HEADINGS)
|
|
181
|
+
+ "."
|
|
182
|
+
),
|
|
183
|
+
hint=(
|
|
184
|
+
"Use `taskledger plan template --file ./plan.md` and keep the "
|
|
185
|
+
"approval-ready body structure."
|
|
186
|
+
),
|
|
187
|
+
)
|
|
188
|
+
)
|
|
157
189
|
# 4. todo_not_concrete
|
|
158
190
|
for index, todo in enumerate(plan.todos):
|
|
159
191
|
if not _todo_is_concrete(todo):
|
|
@@ -49,6 +49,24 @@ def build_plan_review_payload(
|
|
|
49
49
|
open_required = _required_open_question_ids(questions)
|
|
50
50
|
stale_answer_ids = _stale_answer_question_ids(questions, plan)
|
|
51
51
|
|
|
52
|
+
required_questions = [
|
|
53
|
+
question for question in questions if question.required_for_plan
|
|
54
|
+
]
|
|
55
|
+
answered_required_questions = [
|
|
56
|
+
question for question in required_questions if question.status == "answered"
|
|
57
|
+
]
|
|
58
|
+
open_required_questions = [
|
|
59
|
+
question for question in required_questions if question.status == "open"
|
|
60
|
+
]
|
|
61
|
+
question_status = {
|
|
62
|
+
"required_answered": len(answered_required_questions),
|
|
63
|
+
"required_total": len(required_questions),
|
|
64
|
+
"required_open": [
|
|
65
|
+
{"id": question.id, "text": question.question}
|
|
66
|
+
for question in open_required_questions
|
|
67
|
+
],
|
|
68
|
+
}
|
|
69
|
+
|
|
52
70
|
if task.status_stage != "plan_review":
|
|
53
71
|
blockers.append(
|
|
54
72
|
{
|
|
@@ -125,6 +143,23 @@ def build_plan_review_payload(
|
|
|
125
143
|
warnings.append("Plan lint was not included in this review output.")
|
|
126
144
|
|
|
127
145
|
approval_ready = len(blockers) == 0
|
|
146
|
+
|
|
147
|
+
if open_required_questions:
|
|
148
|
+
decision_status = (
|
|
149
|
+
"Approval is blocked because required planning questions remain unanswered."
|
|
150
|
+
)
|
|
151
|
+
elif stale_answer_ids:
|
|
152
|
+
decision_status = (
|
|
153
|
+
"Approval is blocked because answered questions are not reflected "
|
|
154
|
+
"in this plan."
|
|
155
|
+
)
|
|
156
|
+
elif blockers:
|
|
157
|
+
decision_status = "Approval is blocked by review blockers."
|
|
158
|
+
else:
|
|
159
|
+
decision_status = (
|
|
160
|
+
"No required planning decision remains; review assumptions and "
|
|
161
|
+
"out-of-scope notes before approving."
|
|
162
|
+
)
|
|
128
163
|
commands = (
|
|
129
164
|
_review_commands(plan.plan_version) if options.include_next_commands else []
|
|
130
165
|
)
|
|
@@ -140,6 +175,8 @@ def build_plan_review_payload(
|
|
|
140
175
|
"plan_version": plan.plan_version,
|
|
141
176
|
"plan_status": plan.status,
|
|
142
177
|
"approval_ready": approval_ready,
|
|
178
|
+
"decision_status": decision_status,
|
|
179
|
+
"question_status": question_status,
|
|
143
180
|
"blockers": blockers,
|
|
144
181
|
"warnings": warnings,
|
|
145
182
|
"lint": lint_payload,
|
|
@@ -208,6 +245,7 @@ def render_plan_review_markdown(payload: dict[str, object]) -> str:
|
|
|
208
245
|
lines.append(f"- {warning}")
|
|
209
246
|
lines.append("")
|
|
210
247
|
|
|
248
|
+
_append_approval_brief(lines, payload)
|
|
211
249
|
lines.append("## Summary")
|
|
212
250
|
lines.append("")
|
|
213
251
|
lines.append(str(payload.get("summary") or "(no summary available)"))
|
|
@@ -296,6 +334,32 @@ def render_plan_review_markdown(payload: dict[str, object]) -> str:
|
|
|
296
334
|
return result
|
|
297
335
|
|
|
298
336
|
|
|
337
|
+
def _append_approval_brief(lines: list[str], payload: dict[str, object]) -> None:
|
|
338
|
+
lines.append("## Approval Brief")
|
|
339
|
+
lines.append("")
|
|
340
|
+
lines.append(f"- Decision status: {payload.get('decision_status')}")
|
|
341
|
+
question_status = payload.get("question_status")
|
|
342
|
+
if isinstance(question_status, dict):
|
|
343
|
+
answered = question_status.get("required_answered", 0)
|
|
344
|
+
total = question_status.get("required_total", 0)
|
|
345
|
+
lines.append(f"- Questions {answered}/{total} answered.")
|
|
346
|
+
lines.append("")
|
|
347
|
+
lines.append("### Unanswered Required Questions")
|
|
348
|
+
lines.append("")
|
|
349
|
+
open_questions = (
|
|
350
|
+
question_status.get("required_open")
|
|
351
|
+
if isinstance(question_status, dict)
|
|
352
|
+
else None
|
|
353
|
+
)
|
|
354
|
+
if isinstance(open_questions, list) and open_questions:
|
|
355
|
+
for question in open_questions:
|
|
356
|
+
if isinstance(question, dict):
|
|
357
|
+
lines.append(f"- {question.get('id')}: {question.get('text')}")
|
|
358
|
+
else:
|
|
359
|
+
lines.append("- none")
|
|
360
|
+
lines.append("")
|
|
361
|
+
|
|
362
|
+
|
|
299
363
|
def render_plan_review(
|
|
300
364
|
workspace_root: Path,
|
|
301
365
|
task_ref: str,
|
|
@@ -2012,15 +2012,29 @@ def _render_plan_template(
|
|
|
2012
2012
|
"<!-- Required: keep this body. It is the implementation handoff context.",
|
|
2013
2013
|
" Run `taskledger plan check --file ./plan.md` before upsert. -->",
|
|
2014
2014
|
"",
|
|
2015
|
-
"
|
|
2015
|
+
"# <short approval plan title>",
|
|
2016
2016
|
"",
|
|
2017
|
-
"
|
|
2017
|
+
"## Summary",
|
|
2018
2018
|
"",
|
|
2019
|
-
"
|
|
2019
|
+
"<2-5 sentences describing the outcome, rationale, and boundaries>",
|
|
2020
2020
|
"",
|
|
2021
|
-
"
|
|
2021
|
+
"## Implementation Changes",
|
|
2022
2022
|
"",
|
|
2023
|
-
"
|
|
2023
|
+
"- <specific code/config/docs change>",
|
|
2024
|
+
"- <specific code/config/docs change>",
|
|
2025
|
+
"",
|
|
2026
|
+
"## Tests",
|
|
2027
|
+
"",
|
|
2028
|
+
"- <test command or regression case>",
|
|
2029
|
+
"- <manual verification, if needed>",
|
|
2030
|
+
"",
|
|
2031
|
+
"## Assumptions",
|
|
2032
|
+
"",
|
|
2033
|
+
"- <assumption the approver should accept>",
|
|
2034
|
+
"",
|
|
2035
|
+
"## Out of Scope",
|
|
2036
|
+
"",
|
|
2037
|
+
"- <nearby cleanup or behavior change intentionally excluded>",
|
|
2024
2038
|
"",
|
|
2025
2039
|
"## Plan input checklist before upsert",
|
|
2026
2040
|
"",
|
|
@@ -93,6 +93,32 @@ Use this editable plan-input contract:
|
|
|
93
93
|
Todo-level `files:` is not captured.
|
|
94
94
|
- Keep enough Markdown body content for the implementer handoff.
|
|
95
95
|
|
|
96
|
+
Approval-ready Markdown body structure:
|
|
97
|
+
|
|
98
|
+
Use these headings after the closing `---` front matter:
|
|
99
|
+
|
|
100
|
+
# <Plan title>
|
|
101
|
+
|
|
102
|
+
## Summary
|
|
103
|
+
|
|
104
|
+
Explain the intended outcome and why the plan is bounded.
|
|
105
|
+
|
|
106
|
+
## Implementation Changes
|
|
107
|
+
|
|
108
|
+
List the concrete code, config, docs, and behavior changes.
|
|
109
|
+
|
|
110
|
+
## Tests
|
|
111
|
+
|
|
112
|
+
List the automated and manual checks that prove the plan.
|
|
113
|
+
|
|
114
|
+
## Assumptions
|
|
115
|
+
|
|
116
|
+
List assumptions the user should accept before approval.
|
|
117
|
+
|
|
118
|
+
## Out of Scope
|
|
119
|
+
|
|
120
|
+
List adjacent cleanup or behavior changes intentionally excluded.
|
|
121
|
+
|
|
96
122
|
Minimal front matter:
|
|
97
123
|
|
|
98
124
|
```yaml
|
|
@@ -34,15 +34,15 @@ class WorktreePathEntry:
|
|
|
34
34
|
|
|
35
35
|
@classmethod
|
|
36
36
|
def from_dict(cls, data: dict[str, object]) -> WorktreePathEntry:
|
|
37
|
+
size = data.get("size")
|
|
38
|
+
content_hash = data.get("content_hash")
|
|
37
39
|
return cls(
|
|
38
40
|
path=str(data["path"]),
|
|
39
41
|
status=str(data["status"]),
|
|
40
42
|
exists=bool(data["exists"]),
|
|
41
43
|
kind=str(data["kind"]),
|
|
42
|
-
size=
|
|
43
|
-
content_hash=
|
|
44
|
-
if isinstance(data.get("content_hash"), str)
|
|
45
|
-
else None,
|
|
44
|
+
size=size if isinstance(size, int) else None,
|
|
45
|
+
content_hash=content_hash if isinstance(content_hash, str) else None,
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
|
|
@@ -70,29 +70,30 @@ class WorkspaceContentSnapshot:
|
|
|
70
70
|
|
|
71
71
|
@classmethod
|
|
72
72
|
def from_dict(cls, data: dict[str, object]) -> WorkspaceContentSnapshot:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
raw_entries = data.get("entries")
|
|
74
|
+
entries = (
|
|
75
|
+
tuple(
|
|
76
|
+
WorktreePathEntry.from_dict(item)
|
|
77
|
+
for item in raw_entries
|
|
78
|
+
if isinstance(item, dict)
|
|
79
|
+
)
|
|
80
|
+
if isinstance(raw_entries, list)
|
|
81
|
+
else ()
|
|
77
82
|
)
|
|
83
|
+
git_commit = data.get("git_commit")
|
|
84
|
+
dirty = data.get("dirty")
|
|
85
|
+
content_hash = data.get("content_hash")
|
|
86
|
+
paths_hash = data.get("paths_hash")
|
|
87
|
+
entry_count = data.get("entry_count")
|
|
88
|
+
captured_at = data.get("captured_at")
|
|
78
89
|
return cls(
|
|
79
|
-
git_commit=
|
|
80
|
-
if isinstance(
|
|
81
|
-
else None,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if isinstance(data.get("content_hash"), str)
|
|
85
|
-
else None,
|
|
86
|
-
paths_hash=data.get("paths_hash")
|
|
87
|
-
if isinstance(data.get("paths_hash"), str)
|
|
88
|
-
else None,
|
|
89
|
-
entry_count=data.get("entry_count")
|
|
90
|
-
if isinstance(data.get("entry_count"), int)
|
|
91
|
-
else len(entries),
|
|
90
|
+
git_commit=git_commit if isinstance(git_commit, str) else None,
|
|
91
|
+
dirty=dirty if isinstance(dirty, bool) else None,
|
|
92
|
+
content_hash=content_hash if isinstance(content_hash, str) else None,
|
|
93
|
+
paths_hash=paths_hash if isinstance(paths_hash, str) else None,
|
|
94
|
+
entry_count=entry_count if isinstance(entry_count, int) else len(entries),
|
|
92
95
|
entries=entries,
|
|
93
|
-
captured_at=
|
|
94
|
-
if isinstance(data.get("captured_at"), str)
|
|
95
|
-
else None,
|
|
96
|
+
captured_at=captured_at if isinstance(captured_at, str) else None,
|
|
96
97
|
)
|
|
97
98
|
|
|
98
99
|
|
|
@@ -379,6 +379,7 @@ tests/test_agent_session_protocol.py
|
|
|
379
379
|
tests/test_atomic_fast_io.py
|
|
380
380
|
tests/test_cli_command_contract.py
|
|
381
381
|
tests/test_cli_import_resilience.py
|
|
382
|
+
tests/test_cli_runner_compatibility.py
|
|
382
383
|
tests/test_code_reviews.py
|
|
383
384
|
tests/test_command_example_linter.py
|
|
384
385
|
tests/test_command_inventory.py
|
|
@@ -456,6 +457,7 @@ tests/test_worker_pipeline_handoff.py
|
|
|
456
457
|
tests/test_worker_pipeline_plan_template.py
|
|
457
458
|
tests/test_worker_pipeline_todos.py
|
|
458
459
|
tests/test_workflow_guidance.py
|
|
460
|
+
tests/test_workspace_snapshot.py
|
|
459
461
|
tests/support/__init__.py
|
|
460
462
|
tests/support/builders.py
|
|
461
463
|
tests/support/fake_command_runner.py
|
|
@@ -293,6 +293,7 @@
|
|
|
293
293
|
"tests/test_sync_git.py",
|
|
294
294
|
"tests/test_docs_and_skill.py",
|
|
295
295
|
"tests/test_worker_pipeline_handoff.py",
|
|
296
|
+
"tests/test_workspace_snapshot.py",
|
|
296
297
|
"tests/test_worker_pipeline_todos.py",
|
|
297
298
|
"tests/test_storage_init.py",
|
|
298
299
|
"tests/test_help_subprocess.py",
|
|
@@ -319,6 +320,7 @@
|
|
|
319
320
|
"tests/test_storage_yaml_store.py",
|
|
320
321
|
"tests/test_command_example_linter.py",
|
|
321
322
|
"tests/test_taskledger_v2_cli.py",
|
|
323
|
+
"tests/test_cli_runner_compatibility.py",
|
|
322
324
|
"tests/test_storage_repos.py",
|
|
323
325
|
"tests/test_command_inventory.py",
|
|
324
326
|
"tests/test_domain_policies.py",
|
|
@@ -12,32 +12,30 @@ if str(ROOT) not in sys.path:
|
|
|
12
12
|
sys.dont_write_bytecode = True
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
# Tests create many short-lived Markdown/YAML records under tmp_path.
|
|
16
|
-
# Production durability still fsyncs; pytest opts into faster temporary IO.
|
|
17
|
-
os.environ.setdefault("TASKLEDGER_TEST_FAST_IO", "1")
|
|
18
|
-
|
|
19
15
|
import shutil # noqa: E402
|
|
20
16
|
import weakref # noqa: E402
|
|
21
|
-
from
|
|
22
|
-
from typing import IO, Any # noqa: E402
|
|
17
|
+
from typing import Any # noqa: E402
|
|
23
18
|
|
|
24
|
-
import click # noqa: E402
|
|
25
|
-
import click.testing # noqa: E402
|
|
26
19
|
import pytest # noqa: E402
|
|
20
|
+
import typer.testing as typer_testing # noqa: E402
|
|
27
21
|
from typer import Typer # noqa: E402
|
|
28
22
|
from typer.main import get_command as _typer_get_command # noqa: E402
|
|
29
23
|
from typer.testing import CliRunner as _TyperCliRunner # noqa: E402
|
|
30
24
|
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
25
|
+
# Some test modules still instantiate ``CliRunner(mix_stderr=False)`` for
|
|
26
|
+
# historical reasons. Newer Typer/Click releases reject that argument, so the
|
|
27
|
+
# constructor wrapper below discards it. This shim exists only for test
|
|
28
|
+
# source compatibility and is unrelated to command caching.
|
|
35
29
|
_original_cli_runner_init = _TyperCliRunner.__init__
|
|
36
30
|
|
|
37
31
|
|
|
38
|
-
def _patched_cli_runner_init(
|
|
32
|
+
def _patched_cli_runner_init(
|
|
33
|
+
self: _TyperCliRunner,
|
|
34
|
+
*args: Any,
|
|
35
|
+
**kwargs: Any,
|
|
36
|
+
) -> None:
|
|
39
37
|
kwargs.pop("mix_stderr", None)
|
|
40
|
-
_original_cli_runner_init(self, **kwargs)
|
|
38
|
+
_original_cli_runner_init(self, *args, **kwargs)
|
|
41
39
|
|
|
42
40
|
|
|
43
41
|
_TyperCliRunner.__init__ = _patched_cli_runner_init # type: ignore[assignment]
|
|
@@ -52,8 +50,16 @@ from tests.support.builders import ( # noqa: E402
|
|
|
52
50
|
|
|
53
51
|
# Typer rebuilds the full Click command tree on every CliRunner.invoke call.
|
|
54
52
|
# Taskledger's CLI is intentionally broad, so repeated rebuilds dominate the
|
|
55
|
-
# CLI-heavy test suite, especially on Windows. Cache the immutable Click
|
|
56
|
-
# tree per Typer app for tests; each invocation still gets a fresh
|
|
53
|
+
# CLI-heavy test suite, especially on Windows. Cache the immutable Click
|
|
54
|
+
# command tree per Typer app for tests; each invocation still gets a fresh
|
|
55
|
+
# Click context.
|
|
56
|
+
#
|
|
57
|
+
# The cache is implemented by swapping the private command-lookup helper used
|
|
58
|
+
# by ``typer.testing``. Typer's own ``CliRunner.invoke`` then calls our cached
|
|
59
|
+
# function instead of rebuilding the command tree. We do NOT replace
|
|
60
|
+
# ``CliRunner.invoke`` with ``click.testing.CliRunner.invoke`` because the two
|
|
61
|
+
# runner implementations do not share instance state; on Click 8.1.x the
|
|
62
|
+
# cross-class call reads ``self.mix_stderr`` and raises AttributeError.
|
|
57
63
|
_CLICK_COMMAND_CACHE: weakref.WeakKeyDictionary[Typer, Any] = (
|
|
58
64
|
weakref.WeakKeyDictionary()
|
|
59
65
|
)
|
|
@@ -67,31 +73,8 @@ def _cached_click_command(app: Typer) -> Any:
|
|
|
67
73
|
return cached
|
|
68
74
|
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
app: Typer,
|
|
73
|
-
args: str | Sequence[str] | None = None,
|
|
74
|
-
input: bytes | str | IO[Any] | None = None,
|
|
75
|
-
env: Mapping[str, str | None] | None = None,
|
|
76
|
-
catch_exceptions: bool = True,
|
|
77
|
-
color: bool = False,
|
|
78
|
-
**extra: Any,
|
|
79
|
-
) -> click.testing.Result:
|
|
80
|
-
if not hasattr(self, "capture"):
|
|
81
|
-
self.capture = "sys"
|
|
82
|
-
return click.testing.CliRunner.invoke(
|
|
83
|
-
self, # type: ignore[arg-type]
|
|
84
|
-
_cached_click_command(app),
|
|
85
|
-
args=args,
|
|
86
|
-
input=input,
|
|
87
|
-
env=env,
|
|
88
|
-
catch_exceptions=catch_exceptions,
|
|
89
|
-
color=color,
|
|
90
|
-
**extra,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
_TyperCliRunner.invoke = _invoke_with_cached_click_command # type: ignore[assignment]
|
|
76
|
+
if hasattr(typer_testing, "_get_command"):
|
|
77
|
+
typer_testing._get_command = _cached_click_command # type: ignore[attr-defined]
|
|
95
78
|
|
|
96
79
|
|
|
97
80
|
def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
|