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.
Files changed (466) hide show
  1. {taskledger-0.5.1 → taskledger-0.5.2}/.taskledger.toml +1 -1
  2. {taskledger-0.5.1 → taskledger-0.5.2}/CHANGELOG.md +25 -0
  3. {taskledger-0.5.1/taskledger.egg-info → taskledger-0.5.2}/PKG-INFO +1 -1
  4. {taskledger-0.5.1 → taskledger-0.5.2}/skills/taskledger/SKILL.md +35 -0
  5. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/_version.py +3 -3
  6. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli.py +1 -1
  7. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_lint.py +32 -0
  8. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_review.py +64 -0
  9. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/tasks.py +19 -5
  10. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/workflow_guidance.py +26 -0
  11. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/workspace_snapshot.py +25 -24
  12. {taskledger-0.5.1 → taskledger-0.5.2/taskledger.egg-info}/PKG-INFO +1 -1
  13. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/SOURCES.txt +2 -0
  14. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/scm_file_list.json +2 -0
  15. taskledger-0.5.2/taskledger.egg-info/scm_version.json +8 -0
  16. {taskledger-0.5.1 → taskledger-0.5.2}/tests/conftest.py +24 -41
  17. taskledger-0.5.2/tests/test_cli_runner_compatibility.py +184 -0
  18. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_docs_and_skill.py +12 -0
  19. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_input_cli.py +6 -0
  20. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_lint.py +111 -0
  21. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_review.py +26 -0
  22. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_workflow_guidance.py +11 -0
  23. taskledger-0.5.2/tests/test_workspace_snapshot.py +74 -0
  24. taskledger-0.5.1/taskledger.egg-info/scm_version.json +0 -8
  25. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/building_blocks/al_block_0083.md +0 -0
  26. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/concepts/al_concept_0081.md +0 -0
  27. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/runtime/al_runtime_0076.md +0 -0
  28. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/archive/records/runtime/al_runtime_0084.md +0 -0
  29. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0001.md +0 -0
  30. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0002.md +0 -0
  31. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0003.md +0 -0
  32. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0004.md +0 -0
  33. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0005.md +0 -0
  34. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0006.md +0 -0
  35. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0007.md +0 -0
  36. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0008.md +0 -0
  37. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0009.md +0 -0
  38. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0010.md +0 -0
  39. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0011.md +0 -0
  40. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/profiles/arc42/sections/al_content_0012.md +0 -0
  41. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0029.md +0 -0
  42. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0030.md +0 -0
  43. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0031.md +0 -0
  44. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0032.md +0 -0
  45. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0033.md +0 -0
  46. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/building_blocks/al_block_0034.md +0 -0
  47. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0040.md +0 -0
  48. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0041.md +0 -0
  49. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0042.md +0 -0
  50. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0043.md +0 -0
  51. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0044.md +0 -0
  52. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0045.md +0 -0
  53. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/concepts/al_concept_0082.md +0 -0
  54. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0016.md +0 -0
  55. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0017.md +0 -0
  56. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0018.md +0 -0
  57. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/constraints/al_constraint_0019.md +0 -0
  58. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0020.md +0 -0
  59. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0021.md +0 -0
  60. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0022.md +0 -0
  61. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/contexts/al_context_0023.md +0 -0
  62. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0046.md +0 -0
  63. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0047.md +0 -0
  64. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0048.md +0 -0
  65. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0049.md +0 -0
  66. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0050.md +0 -0
  67. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/decisions/al_adr_0051.md +0 -0
  68. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/deployment/al_deploy_0039.md +0 -0
  69. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0061.md +0 -0
  70. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0062.md +0 -0
  71. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0063.md +0 -0
  72. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0064.md +0 -0
  73. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0065.md +0 -0
  74. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0066.md +0 -0
  75. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0067.md +0 -0
  76. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0068.md +0 -0
  77. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0069.md +0 -0
  78. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0070.md +0 -0
  79. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0071.md +0 -0
  80. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0072.md +0 -0
  81. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/glossary/al_glossary_0073.md +0 -0
  82. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0052.md +0 -0
  83. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0053.md +0 -0
  84. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0054.md +0 -0
  85. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0055.md +0 -0
  86. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/quality_requirements/al_quality_0056.md +0 -0
  87. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/requirements/al_content_0013.md +0 -0
  88. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/requirements/al_content_0014.md +0 -0
  89. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/requirements/al_content_0015.md +0 -0
  90. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0057.md +0 -0
  91. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0058.md +0 -0
  92. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0059.md +0 -0
  93. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/risks/al_risk_0060.md +0 -0
  94. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0035.md +0 -0
  95. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0036.md +0 -0
  96. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0037.md +0 -0
  97. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0038.md +0 -0
  98. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0074.md +0 -0
  99. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0075.md +0 -0
  100. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0077.md +0 -0
  101. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/runtime/al_runtime_0078.md +0 -0
  102. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/stakeholders/al_content_0079.md +0 -0
  103. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/stakeholders/al_content_0080.md +0 -0
  104. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0024.md +0 -0
  105. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0025.md +0 -0
  106. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0026.md +0 -0
  107. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0027.md +0 -0
  108. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/records/strategy/al_strategy_0028.md +0 -0
  109. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/source-state.json +0 -0
  110. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger/storage.yaml +0 -0
  111. {taskledger-0.5.1 → taskledger-0.5.2}/.archledger.toml +0 -0
  112. {taskledger-0.5.1 → taskledger-0.5.2}/.codecrate.toml +0 -0
  113. {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/codecov.yml +0 -0
  114. {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/pre-commit.yml +0 -0
  115. {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/python-publish.yml +0 -0
  116. {taskledger-0.5.1 → taskledger-0.5.2}/.github/workflows/tests.yml +0 -0
  117. {taskledger-0.5.1 → taskledger-0.5.2}/.gitignore +0 -0
  118. {taskledger-0.5.1 → taskledger-0.5.2}/.planledger.toml +0 -0
  119. {taskledger-0.5.1 → taskledger-0.5.2}/.pre-commit-config.yaml +0 -0
  120. {taskledger-0.5.1 → taskledger-0.5.2}/.readthedocs.yaml +0 -0
  121. {taskledger-0.5.1 → taskledger-0.5.2}/.releaseledger.toml +0 -0
  122. {taskledger-0.5.1 → taskledger-0.5.2}/.ruff.toml +0 -0
  123. {taskledger-0.5.1 → taskledger-0.5.2}/.specweave.toml +0 -0
  124. {taskledger-0.5.1 → taskledger-0.5.2}/AGENTS.md +0 -0
  125. {taskledger-0.5.1 → taskledger-0.5.2}/API.md +0 -0
  126. {taskledger-0.5.1 → taskledger-0.5.2}/ARCHITECTURE.md +0 -0
  127. {taskledger-0.5.1 → taskledger-0.5.2}/LICENSE +0 -0
  128. {taskledger-0.5.1 → taskledger-0.5.2}/Makefile +0 -0
  129. {taskledger-0.5.1 → taskledger-0.5.2}/README.md +0 -0
  130. {taskledger-0.5.1 → taskledger-0.5.2}/docs/Makefile +0 -0
  131. {taskledger-0.5.1 → taskledger-0.5.2}/docs/api.md +0 -0
  132. {taskledger-0.5.1 → taskledger-0.5.2}/docs/architecture_taskledger_split.md +0 -0
  133. {taskledger-0.5.1 → taskledger-0.5.2}/docs/build.sh +0 -0
  134. {taskledger-0.5.1 → taskledger-0.5.2}/docs/command_contract.md +0 -0
  135. {taskledger-0.5.1 → taskledger-0.5.2}/docs/conf.py +0 -0
  136. {taskledger-0.5.1 → taskledger-0.5.2}/docs/full_task_cycle.md +0 -0
  137. {taskledger-0.5.1 → taskledger-0.5.2}/docs/index.md +0 -0
  138. {taskledger-0.5.1 → taskledger-0.5.2}/docs/multi_repo.md +0 -0
  139. {taskledger-0.5.1 → taskledger-0.5.2}/docs/public_surface.md +0 -0
  140. {taskledger-0.5.1 → taskledger-0.5.2}/docs/requirements.txt +0 -0
  141. {taskledger-0.5.1 → taskledger-0.5.2}/docs/service_boundary_whitelist.md +0 -0
  142. {taskledger-0.5.1 → taskledger-0.5.2}/docs/sync.md +0 -0
  143. {taskledger-0.5.1 → taskledger-0.5.2}/docs/transfer.md +0 -0
  144. {taskledger-0.5.1 → taskledger-0.5.2}/docs/usage.md +0 -0
  145. {taskledger-0.5.1 → taskledger-0.5.2}/pyproject.toml +0 -0
  146. {taskledger-0.5.1 → taskledger-0.5.2}/scripts/find_code_clones.py +0 -0
  147. {taskledger-0.5.1 → taskledger-0.5.2}/setup.cfg +0 -0
  148. {taskledger-0.5.1 → taskledger-0.5.2}/setup.py +0 -0
  149. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/README.md +0 -0
  150. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/UNMAPPED_TESTS.md +0 -0
  151. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/evidence/.gitkeep +0 -0
  152. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/evidence/taskledger-test-feature-coverage.json +0 -0
  153. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/.gitkeep +0 -0
  154. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/active_task/active-task.feature +0 -0
  155. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/actor_harness_state/actor-harness-state.feature +0 -0
  156. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/actor_resolution/actor-resolution.feature +0 -0
  157. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/agent_command_logging/agent-command-logging.feature +0 -0
  158. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/agent_session_protocol/agent-session-protocol.feature +0 -0
  159. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/atomic_fast_io/atomic-fast-io.feature +0 -0
  160. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_cli/bdd-cli.feature +0 -0
  161. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_gherkin/bdd-gherkin.feature +0 -0
  162. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_models/bdd-models.feature +0 -0
  163. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_report_import/bdd-report-import.feature +0 -0
  164. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_storage/bdd-storage.feature +0 -0
  165. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/bdd_validation_integration/bdd-validation-integration.feature +0 -0
  166. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/cli_command_contract/cli-command-contract.feature +0 -0
  167. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/cli_import_resilience/cli-import-resilience.feature +0 -0
  168. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/code_reviews/code-reviews.feature +0 -0
  169. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/command_example_linter/command-example-linter.feature +0 -0
  170. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/command_inventory/command-inventory.feature +0 -0
  171. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/command_runner/command-runner.feature +0 -0
  172. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/compact_mutation_output/compact-mutation-output.feature +0 -0
  173. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/config_cli/config-cli.feature +0 -0
  174. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/delta_remaining_contracts/delta-remaining-contracts.feature +0 -0
  175. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/docs_and_skill/docs-and-skill.feature +0 -0
  176. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/doctor/doctor.feature +0 -0
  177. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/domain_policies/domain-policies.feature +0 -0
  178. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/event_logging_config/event-logging-config.feature +0 -0
  179. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/events/events.feature +0 -0
  180. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/file_link_snapshots/file-link-snapshots.feature +0 -0
  181. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/find_code_clones_script/find-code-clones-script.feature +0 -0
  182. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/handoff_lifecycle/handoff-lifecycle.feature +0 -0
  183. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/help_subprocess/help-subprocess.feature +0 -0
  184. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/implementation_change_scan/implementation-change-scan.feature +0 -0
  185. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/implementation_checks/implementation-checks.feature +0 -0
  186. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/json_contracts/json-contracts.feature +0 -0
  187. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/legacy_cleanup_contracts/legacy-cleanup-contracts.feature +0 -0
  188. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/lifecycle_policies/lifecycle-policies.feature +0 -0
  189. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/lock_diagnostics/lock-diagnostics.feature +0 -0
  190. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/locks_audit/locks-audit.feature +0 -0
  191. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/models_v1_schema/models-v1-schema.feature +0 -0
  192. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/monitor/monitor.feature +0 -0
  193. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/next_action_expired_lock/next-action-expired-lock.feature +0 -0
  194. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/no_log_feature/no-log-feature.feature +0 -0
  195. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_approval_contract/plan-approval-contract.feature +0 -0
  196. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_lint/plan-lint.feature +0 -0
  197. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_review/plan-review.feature +0 -0
  198. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_revision_workflow/plan-revision-workflow.feature +0 -0
  199. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/plan_todo_materialization/plan-todo-materialization.feature +0 -0
  200. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/project_root_config/project-root-config.feature +0 -0
  201. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/question_add_many/question-add-many.feature +0 -0
  202. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/question_filter_answers/question-filter-answers.feature +0 -0
  203. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/question_plan_regeneration/question-plan-regeneration.feature +0 -0
  204. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/ready_work/ready-work.feature +0 -0
  205. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/release_changelog/release-changelog.feature +0 -0
  206. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/search/search.feature +0 -0
  207. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/service_boundaries/service-boundaries.feature +0 -0
  208. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/services_dashboard/services-dashboard.feature +0 -0
  209. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/sidecar_collections/sidecar-collections.feature +0 -0
  210. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_bundle_layout/storage-bundle-layout.feature +0 -0
  211. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_common/storage-common.feature +0 -0
  212. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_init/storage-init.feature +0 -0
  213. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_migration/storage-migration.feature +0 -0
  214. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_repos/storage-repos.feature +0 -0
  215. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/storage_sync/storage-sync.feature +0 -0
  216. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/sync_git/sync-git.feature +0 -0
  217. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_archive/archive.feature +0 -0
  218. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_events/events.feature +0 -0
  219. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_markdown_export/markdown-export.feature +0 -0
  220. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/task_report/report.feature +0 -0
  221. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_branch_scoped_ledgers/taskledger-branch-scoped-ledgers.feature +0 -0
  222. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_cli_api_parity/taskledger-cli-api-parity.feature +0 -0
  223. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_v2_cli/taskledger-v2-cli.feature +0 -0
  224. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/taskledger_v2_exchange/taskledger-v2-exchange.feature +0 -0
  225. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/tasks_service_static/tasks-service-static.feature +0 -0
  226. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/todo_implementation_gate/todo-implementation-gate.feature +0 -0
  227. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/trace/trace.feature +0 -0
  228. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/tree_command/tree-command.feature +0 -0
  229. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/usage_cli/usage-cli.feature +0 -0
  230. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_cli/worker-pipeline-cli.feature +0 -0
  231. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_config/worker-pipeline-config.feature +0 -0
  232. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_context/worker-pipeline-context.feature +0 -0
  233. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_handoff/worker-pipeline-handoff.feature +0 -0
  234. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_plan_template/worker-pipeline-plan-template.feature +0 -0
  235. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/worker_pipeline_todos/worker-pipeline-todos.feature +0 -0
  236. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/features/workflow_guidance/workflow-guidance.feature +0 -0
  237. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/manifest.json +0 -0
  238. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/mappings/.gitkeep +0 -0
  239. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/.gitkeep +0 -0
  240. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/coverage-gaps.md +0 -0
  241. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/coverage.json +0 -0
  242. {taskledger-0.5.1 → taskledger-0.5.2}/specs/behavior/reports/specweave/mappings.json +0 -0
  243. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/__init__.py +0 -0
  244. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/__main__.py +0 -0
  245. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/__init__.py +0 -0
  246. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/config.py +0 -0
  247. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/handoff.py +0 -0
  248. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/introductions.py +0 -0
  249. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/locks.py +0 -0
  250. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/plans.py +0 -0
  251. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/project.py +0 -0
  252. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/questions.py +0 -0
  253. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/releases.py +0 -0
  254. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/reviews.py +0 -0
  255. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/search.py +0 -0
  256. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/storage.py +0 -0
  257. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/sync.py +0 -0
  258. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/task_runs.py +0 -0
  259. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/api/tasks.py +0 -0
  260. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_actor.py +0 -0
  261. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_archive.py +0 -0
  262. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_common.py +0 -0
  263. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_config.py +0 -0
  264. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_implement.py +0 -0
  265. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_ledger.py +0 -0
  266. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_migrate.py +0 -0
  267. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_misc.py +0 -0
  268. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_pipeline.py +0 -0
  269. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_plan.py +0 -0
  270. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_question.py +0 -0
  271. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_ref.py +0 -0
  272. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_release.py +0 -0
  273. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_review.py +0 -0
  274. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_storage.py +0 -0
  275. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_sync.py +0 -0
  276. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_task.py +0 -0
  277. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_trace.py +0 -0
  278. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/cli_validate.py +0 -0
  279. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/command_inventory.py +0 -0
  280. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/__init__.py +0 -0
  281. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/_model_utils.py +0 -0
  282. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/active_state.py +0 -0
  283. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/actor.py +0 -0
  284. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/change.py +0 -0
  285. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/check.py +0 -0
  286. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/event.py +0 -0
  287. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/handoff.py +0 -0
  288. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/lock.py +0 -0
  289. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/models.py +0 -0
  290. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/plan.py +0 -0
  291. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/policies.py +0 -0
  292. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/question.py +0 -0
  293. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/release.py +0 -0
  294. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/review.py +0 -0
  295. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/run.py +0 -0
  296. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/sidecars.py +0 -0
  297. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/states.py +0 -0
  298. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/domain/task.py +0 -0
  299. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/errors.py +0 -0
  300. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/exchange.py +0 -0
  301. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/ids.py +0 -0
  302. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/launcher.py +0 -0
  303. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/py.typed +0 -0
  304. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/refs.py +0 -0
  305. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/search.py +0 -0
  306. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/__init__.py +0 -0
  307. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/actors.py +0 -0
  308. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/agent_logging.py +0 -0
  309. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/agent_transcripts.py +0 -0
  310. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/change_tracking.py +0 -0
  311. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/check_tracking.py +0 -0
  312. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/code_review.py +0 -0
  313. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/command_runner.py +0 -0
  314. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/dashboard.py +0 -0
  315. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor.py +0 -0
  316. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor_checks/migration_checks.py +0 -0
  317. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor_checks/project_scan.py +0 -0
  318. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/doctor_checks/task_checks.py +0 -0
  319. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/event_logging.py +0 -0
  320. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/file_links.py +0 -0
  321. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/git_sync.py +0 -0
  322. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/git_utils.py +0 -0
  323. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/handoff.py +0 -0
  324. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/handoff_lifecycle.py +0 -0
  325. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/implementation_flow.py +0 -0
  326. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/lock_diagnostics.py +0 -0
  327. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/monitor.py +0 -0
  328. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/navigation.py +0 -0
  329. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/next_action_model.py +0 -0
  330. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/next_action_payload.py +0 -0
  331. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/phase5_lock_transfer.py +0 -0
  332. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_editing.py +0 -0
  333. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_hash.py +0 -0
  334. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_input.py +0 -0
  335. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/plan_materialization.py +0 -0
  336. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/planning_flow.py +0 -0
  337. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/ready_work.py +0 -0
  338. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/releases.py +0 -0
  339. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/run_store.py +0 -0
  340. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/storage_locations.py +0 -0
  341. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_archive.py +0 -0
  342. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_collections.py +0 -0
  343. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_events.py +0 -0
  344. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_export.py +0 -0
  345. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_lifecycle.py +0 -0
  346. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_queries.py +0 -0
  347. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_repair.py +0 -0
  348. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/task_reports.py +0 -0
  349. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/trace.py +0 -0
  350. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/tree.py +0 -0
  351. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/usage.py +0 -0
  352. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/validation.py +0 -0
  353. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/validation_flow.py +0 -0
  354. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/worker_context.py +0 -0
  355. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/services/worker_pipeline.py +0 -0
  356. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/__init__.py +0 -0
  357. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/agent_logs.py +0 -0
  358. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/atomic.py +0 -0
  359. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/common.py +0 -0
  360. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/events.py +0 -0
  361. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/frontmatter.py +0 -0
  362. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/indexes.py +0 -0
  363. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/init.py +0 -0
  364. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/ledger_config.py +0 -0
  365. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/locks.py +0 -0
  366. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/meta.py +0 -0
  367. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/migrations.py +0 -0
  368. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/paths.py +0 -0
  369. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/project_config.py +0 -0
  370. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/project_identity.py +0 -0
  371. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/repos.py +0 -0
  372. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/sidecar_index.py +0 -0
  373. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/task_index.py +0 -0
  374. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/task_store.py +0 -0
  375. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/toml_edit.py +0 -0
  376. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/worker_pipeline_config.py +0 -0
  377. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/storage/yaml_store.py +0 -0
  378. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger/timeutils.py +0 -0
  379. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/dependency_links.txt +0 -0
  380. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/entry_points.txt +0 -0
  381. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/requires.txt +0 -0
  382. {taskledger-0.5.1 → taskledger-0.5.2}/taskledger.egg-info/top_level.txt +0 -0
  383. {taskledger-0.5.1 → taskledger-0.5.2}/tests/__init__.py +0 -0
  384. {taskledger-0.5.1 → taskledger-0.5.2}/tests/support/__init__.py +0 -0
  385. {taskledger-0.5.1 → taskledger-0.5.2}/tests/support/builders.py +0 -0
  386. {taskledger-0.5.1 → taskledger-0.5.2}/tests/support/fake_command_runner.py +0 -0
  387. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_active_task.py +0 -0
  388. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_actor_harness_state.py +0 -0
  389. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_actor_resolution.py +0 -0
  390. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_agent_command_logging.py +0 -0
  391. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_agent_session_protocol.py +0 -0
  392. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_atomic_fast_io.py +0 -0
  393. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_cli_command_contract.py +0 -0
  394. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_cli_import_resilience.py +0 -0
  395. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_code_reviews.py +0 -0
  396. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_command_example_linter.py +0 -0
  397. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_command_inventory.py +0 -0
  398. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_command_runner.py +0 -0
  399. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_compact_mutation_output.py +0 -0
  400. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_config_cli.py +0 -0
  401. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_delta_remaining_contracts.py +0 -0
  402. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_doctor.py +0 -0
  403. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_domain_policies.py +0 -0
  404. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_event_logging_config.py +0 -0
  405. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_events.py +0 -0
  406. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_file_link_snapshots.py +0 -0
  407. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_find_code_clones_script.py +0 -0
  408. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_handoff_lifecycle.py +0 -0
  409. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_help_subprocess.py +0 -0
  410. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_implementation_change_scan.py +0 -0
  411. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_implementation_checks.py +0 -0
  412. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_import_boundaries.py +0 -0
  413. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_json_contracts.py +0 -0
  414. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_ledgercore_dependency.py +0 -0
  415. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_legacy_cleanup_contracts.py +0 -0
  416. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_lifecycle_policies.py +0 -0
  417. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_lock_diagnostics.py +0 -0
  418. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_locks_audit.py +0 -0
  419. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_models_v1_schema.py +0 -0
  420. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_monitor.py +0 -0
  421. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_next_action_expired_lock.py +0 -0
  422. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_no_log_feature.py +0 -0
  423. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_performance_caching.py +0 -0
  424. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_approval_contract.py +0 -0
  425. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_input.py +0 -0
  426. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_revision_workflow.py +0 -0
  427. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_plan_todo_materialization.py +0 -0
  428. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_project_root_config.py +0 -0
  429. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_question_add_many.py +0 -0
  430. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_question_filter_answers.py +0 -0
  431. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_question_plan_regeneration.py +0 -0
  432. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_ready_work.py +0 -0
  433. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_release_changelog.py +0 -0
  434. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_resource_refs.py +0 -0
  435. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_search.py +0 -0
  436. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_service_boundaries.py +0 -0
  437. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_services_dashboard.py +0 -0
  438. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_sidecar_collections.py +0 -0
  439. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_bundle_layout.py +0 -0
  440. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_common.py +0 -0
  441. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_init.py +0 -0
  442. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_migration.py +0 -0
  443. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_repos.py +0 -0
  444. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_sync.py +0 -0
  445. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_storage_yaml_store.py +0 -0
  446. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_sync_git.py +0 -0
  447. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_archive.py +0 -0
  448. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_events.py +0 -0
  449. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_markdown_export.py +0 -0
  450. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_task_report.py +0 -0
  451. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_branch_scoped_ledgers.py +0 -0
  452. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_cli_api_parity.py +0 -0
  453. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_v2_cli.py +0 -0
  454. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_taskledger_v2_exchange.py +0 -0
  455. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_tasks_service_static.py +0 -0
  456. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_todo_implementation_gate.py +0 -0
  457. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_trace.py +0 -0
  458. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_tree_command.py +0 -0
  459. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_usage_cli.py +0 -0
  460. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_validation_git_snapshot_recovery.py +0 -0
  461. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_cli.py +0 -0
  462. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_config.py +0 -0
  463. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_context.py +0 -0
  464. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_handoff.py +0 -0
  465. {taskledger-0.5.1 → taskledger-0.5.2}/tests/test_worker_pipeline_plan_template.py +0 -0
  466. {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 = 136
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskledger
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Durable project-state storage and CLI for coding workflows
5
5
  Author: Taskledger Contributors
6
6
  Maintainer: Holger Nahrstaedt
@@ -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.1'
22
- __version_tuple__ = version_tuple = (0, 5, 1)
21
+ __version__ = version = '0.5.2'
22
+ __version_tuple__ = version_tuple = (0, 5, 2)
23
23
 
24
- __commit_id__ = commit_id = 'ga6ec6591d'
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, # type: ignore[import-not-found]
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
- "## Goal",
2015
+ "# <short approval plan title>",
2016
2016
  "",
2017
- "<repeat or expand the goal in human prose>",
2017
+ "## Summary",
2018
2018
  "",
2019
- "## Implementation notes",
2019
+ "<2-5 sentences describing the outcome, rationale, and boundaries>",
2020
2020
  "",
2021
- "<describe the approach, architecture, and key decisions>",
2021
+ "## Implementation Changes",
2022
2022
  "",
2023
- "## Validation plan",
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=data.get("size") if isinstance(data.get("size"), int) else None,
43
- content_hash=data.get("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
- entries = tuple(
74
- WorktreePathEntry.from_dict(item)
75
- for item in data.get("entries", [])
76
- if isinstance(item, dict)
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=data.get("git_commit")
80
- if isinstance(data.get("git_commit"), str)
81
- else None,
82
- dirty=data.get("dirty") if isinstance(data.get("dirty"), bool) else None,
83
- content_hash=data.get("content_hash")
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=data.get("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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskledger
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Durable project-state storage and CLI for coding workflows
5
5
  Author: Taskledger Contributors
6
6
  Maintainer: Holger Nahrstaedt
@@ -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",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.5.2",
3
+ "distance": 0,
4
+ "node": "g1e080d8afa12581b6fc5d5484e86b05060f16b56",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-07-10"
8
+ }
@@ -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 collections.abc import Mapping, Sequence # noqa: E402
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
- # Click 8.2+ removed ``mix_stderr`` from CliRunner.__init__. Typer's
32
- # CliRunner inherits from Click, so passing ``mix_stderr=False`` raises
33
- # TypeError/AttributeError on modern Click. Patch __init__ to silently
34
- # accept and discard the parameter so every test file keeps working.
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(self: _TyperCliRunner, **kwargs: Any) -> None:
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 command
56
- # tree per Typer app for tests; each invocation still gets a fresh Click context.
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
- def _invoke_with_cached_click_command(
71
- self: _TyperCliRunner,
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: