taskledger 0.1.1__tar.gz → 0.2.0__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 (174) hide show
  1. taskledger-0.2.0/.github/workflows/pre-commit.yml +31 -0
  2. {taskledger-0.1.1 → taskledger-0.2.0}/.pre-commit-config.yaml +10 -5
  3. {taskledger-0.1.1 → taskledger-0.2.0}/.taskledger.toml +10 -1
  4. {taskledger-0.1.1 → taskledger-0.2.0}/API.md +6 -0
  5. {taskledger-0.1.1 → taskledger-0.2.0}/CHANGELOG.md +44 -0
  6. taskledger-0.2.0/Makefile +9 -0
  7. {taskledger-0.1.1/taskledger.egg-info → taskledger-0.2.0}/PKG-INFO +81 -21
  8. {taskledger-0.1.1 → taskledger-0.2.0}/README.md +79 -20
  9. {taskledger-0.1.1 → taskledger-0.2.0}/docs/api.rst +6 -0
  10. {taskledger-0.1.1 → taskledger-0.2.0}/docs/command_contract.rst +96 -2
  11. taskledger-0.2.0/docs/service_boundary_whitelist.rst +57 -0
  12. {taskledger-0.1.1 → taskledger-0.2.0}/docs/usage.rst +66 -5
  13. {taskledger-0.1.1 → taskledger-0.2.0}/pyproject.toml +7 -1
  14. {taskledger-0.1.1 → taskledger-0.2.0}/skills/taskledger/SKILL.md +47 -19
  15. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/_version.py +3 -3
  16. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/project.py +114 -6
  17. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/tasks.py +12 -0
  18. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli.py +247 -13
  19. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_implement.py +21 -26
  20. taskledger-0.2.0/taskledger/cli_ledger.py +511 -0
  21. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_migrate.py +11 -2
  22. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_misc.py +147 -19
  23. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_task.py +200 -0
  24. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/command_inventory.py +13 -2
  25. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/domain/models.py +17 -0
  26. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/domain/states.py +11 -1
  27. taskledger-0.2.0/taskledger/exchange.py +763 -0
  28. taskledger-0.2.0/taskledger/ids.py +40 -0
  29. taskledger-0.2.0/taskledger/services/command_runner.py +22 -0
  30. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/doctor.py +231 -20
  31. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/handoff.py +13 -1
  32. taskledger-0.2.0/taskledger/services/implementation_flow.py +464 -0
  33. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/navigation.py +60 -11
  34. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/plan_lint.py +12 -1
  35. taskledger-0.2.0/taskledger/services/planning_flow.py +387 -0
  36. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/releases.py +9 -0
  37. taskledger-0.2.0/taskledger/services/task_queries.py +81 -0
  38. taskledger-0.2.0/taskledger/services/task_reports.py +919 -0
  39. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/tasks.py +721 -959
  40. taskledger-0.2.0/taskledger/services/tree.py +504 -0
  41. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/validation.py +6 -6
  42. taskledger-0.2.0/taskledger/services/validation_flow.py +394 -0
  43. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/atomic.py +26 -2
  44. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/init.py +33 -16
  45. taskledger-0.2.0/taskledger/storage/ledger_config.py +278 -0
  46. taskledger-0.2.0/taskledger/storage/migrations.py +509 -0
  47. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/paths.py +13 -3
  48. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/project_config.py +75 -26
  49. taskledger-0.2.0/taskledger/storage/project_identity.py +160 -0
  50. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/task_store.py +64 -22
  51. {taskledger-0.1.1 → taskledger-0.2.0/taskledger.egg-info}/PKG-INFO +81 -21
  52. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger.egg-info/SOURCES.txt +22 -1
  53. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger.egg-info/requires.txt +1 -0
  54. taskledger-0.2.0/tests/__init__.py +0 -0
  55. taskledger-0.2.0/tests/conftest.py +13 -0
  56. taskledger-0.2.0/tests/support/__init__.py +1 -0
  57. taskledger-0.2.0/tests/support/builders.py +231 -0
  58. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_active_task.py +12 -6
  59. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_agent_session_protocol.py +73 -12
  60. taskledger-0.2.0/tests/test_atomic_fast_io.py +30 -0
  61. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_cli_command_contract.py +6 -0
  62. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_command_example_linter.py +1 -0
  63. taskledger-0.2.0/tests/test_compact_mutation_output.py +331 -0
  64. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_delta_remaining_contracts.py +56 -206
  65. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_doctor.py +25 -0
  66. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_handoff_lifecycle.py +9 -1
  67. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_json_contracts.py +1 -1
  68. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_locks_audit.py +10 -2
  69. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_plan_approval_contract.py +42 -0
  70. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_plan_lint.py +101 -0
  71. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_project_root_config.py +2 -2
  72. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_question_plan_regeneration.py +101 -23
  73. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_release_changelog.py +46 -316
  74. taskledger-0.2.0/tests/test_service_boundaries.py +375 -0
  75. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_sidecar_collections.py +1 -1
  76. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_storage_bundle_layout.py +219 -5
  77. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_storage_common.py +11 -9
  78. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_storage_init.py +2 -2
  79. taskledger-0.2.0/tests/test_storage_migration.py +965 -0
  80. taskledger-0.2.0/tests/test_task_report.py +332 -0
  81. taskledger-0.2.0/tests/test_taskledger_branch_scoped_ledgers.py +145 -0
  82. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_taskledger_cli_api_parity.py +1 -0
  83. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_taskledger_v2_cli.py +310 -154
  84. taskledger-0.2.0/tests/test_taskledger_v2_exchange.py +675 -0
  85. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_todo_implementation_gate.py +47 -170
  86. taskledger-0.2.0/tests/test_tree_command.py +573 -0
  87. taskledger-0.1.1/.github/workflows/pre-commit.yml +0 -13
  88. taskledger-0.1.1/taskledger/exchange.py +0 -370
  89. taskledger-0.1.1/taskledger/ids.py +0 -19
  90. taskledger-0.1.1/taskledger/storage/migrations.py +0 -207
  91. taskledger-0.1.1/tests/conftest.py +0 -8
  92. taskledger-0.1.1/tests/test_storage_migration.py +0 -429
  93. taskledger-0.1.1/tests/test_taskledger_v2_exchange.py +0 -373
  94. {taskledger-0.1.1 → taskledger-0.2.0}/.codecrate.toml +0 -0
  95. {taskledger-0.1.1 → taskledger-0.2.0}/.github/workflows/codecov.yml +0 -0
  96. {taskledger-0.1.1 → taskledger-0.2.0}/.github/workflows/python-publish.yml +0 -0
  97. {taskledger-0.1.1 → taskledger-0.2.0}/.github/workflows/tests.yml +0 -0
  98. {taskledger-0.1.1 → taskledger-0.2.0}/.gitignore +0 -0
  99. {taskledger-0.1.1 → taskledger-0.2.0}/.readthedocs.yaml +0 -0
  100. {taskledger-0.1.1 → taskledger-0.2.0}/.ruff.toml +0 -0
  101. {taskledger-0.1.1 → taskledger-0.2.0}/AGENTS.md +0 -0
  102. {taskledger-0.1.1 → taskledger-0.2.0}/LICENSE +0 -0
  103. {taskledger-0.1.1 → taskledger-0.2.0}/docs/Makefile +0 -0
  104. {taskledger-0.1.1 → taskledger-0.2.0}/docs/architecture_taskledger_split.rst +0 -0
  105. {taskledger-0.1.1 → taskledger-0.2.0}/docs/build.sh +0 -0
  106. {taskledger-0.1.1 → taskledger-0.2.0}/docs/conf.py +0 -0
  107. {taskledger-0.1.1 → taskledger-0.2.0}/docs/full_task_cycle.rst +0 -0
  108. {taskledger-0.1.1 → taskledger-0.2.0}/docs/index.rst +0 -0
  109. {taskledger-0.1.1 → taskledger-0.2.0}/docs/multi_repo.rst +0 -0
  110. {taskledger-0.1.1 → taskledger-0.2.0}/docs/public_surface.rst +0 -0
  111. {taskledger-0.1.1 → taskledger-0.2.0}/docs/requirements.txt +0 -0
  112. {taskledger-0.1.1 → taskledger-0.2.0}/setup.cfg +0 -0
  113. {taskledger-0.1.1 → taskledger-0.2.0}/setup.py +0 -0
  114. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/__init__.py +0 -0
  115. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/__main__.py +0 -0
  116. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/__init__.py +0 -0
  117. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/handoff.py +0 -0
  118. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/introductions.py +0 -0
  119. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/locks.py +0 -0
  120. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/plans.py +0 -0
  121. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/questions.py +0 -0
  122. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/releases.py +0 -0
  123. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/search.py +0 -0
  124. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/api/task_runs.py +0 -0
  125. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_actor.py +0 -0
  126. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_common.py +0 -0
  127. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_plan.py +0 -0
  128. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_question.py +0 -0
  129. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_release.py +0 -0
  130. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/cli_validate.py +0 -0
  131. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/domain/__init__.py +0 -0
  132. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/domain/policies.py +0 -0
  133. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/errors.py +0 -0
  134. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/launcher.py +0 -0
  135. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/py.typed +0 -0
  136. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/search.py +0 -0
  137. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/__init__.py +0 -0
  138. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/actors.py +0 -0
  139. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/dashboard.py +0 -0
  140. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/handoff_lifecycle.py +0 -0
  141. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/phase5_lock_transfer.py +0 -0
  142. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/serve_read_model.py +0 -0
  143. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/services/web_dashboard.py +0 -0
  144. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/__init__.py +0 -0
  145. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/common.py +0 -0
  146. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/events.py +0 -0
  147. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/frontmatter.py +0 -0
  148. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/indexes.py +0 -0
  149. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/locks.py +0 -0
  150. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/meta.py +0 -0
  151. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/storage/repos.py +0 -0
  152. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger/timeutils.py +0 -0
  153. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger.egg-info/dependency_links.txt +0 -0
  154. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger.egg-info/entry_points.txt +0 -0
  155. {taskledger-0.1.1 → taskledger-0.2.0}/taskledger.egg-info/top_level.txt +0 -0
  156. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_actor_harness_state.py +0 -0
  157. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_cli_import_resilience.py +0 -0
  158. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_command_inventory.py +0 -0
  159. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_docs_and_skill.py +0 -0
  160. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_domain_policies.py +0 -0
  161. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_events.py +0 -0
  162. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_implementation_change_scan.py +0 -0
  163. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_legacy_cleanup_contracts.py +0 -0
  164. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_lifecycle_policies.py +0 -0
  165. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_models_v1_schema.py +0 -0
  166. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_plan_todo_materialization.py +0 -0
  167. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_question_add_many.py +0 -0
  168. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_question_filter_answers.py +0 -0
  169. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_search.py +0 -0
  170. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_serve_dashboard.py +0 -0
  171. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_services_dashboard.py +0 -0
  172. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_storage_repos.py +0 -0
  173. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_task_events.py +0 -0
  174. {taskledger-0.1.1 → taskledger-0.2.0}/tests/test_tasks_service_static.py +0 -0
@@ -0,0 +1,31 @@
1
+ name: pre-commit
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+
7
+ jobs:
8
+ pre-commit:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.13"
17
+
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: "20"
21
+
22
+ - name: Install Python tools
23
+ run: |
24
+ python -m pip install --upgrade pip
25
+ python -m pip install "ruff==0.15.12"
26
+
27
+ - name: Install Node tools
28
+ run: |
29
+ npm install -g prettier@2.7.1 @prettier/plugin-xml@2.2.0 eslint
30
+
31
+ - uses: pre-commit/action@v3.0.1
@@ -17,14 +17,19 @@ exclude: |
17
17
  (LICENSE.*|COPYING.*)|
18
18
  default_language_version:
19
19
  python: python3
20
- node: "16.17.0"
21
20
  repos:
22
- - repo: https://github.com/astral-sh/ruff-pre-commit
23
- rev: v0.15.12
21
+ - repo: local
24
22
  hooks:
25
- - id: ruff
26
- args: [--fix, --exit-non-zero-on-fix, --config=.ruff.toml]
23
+ - id: ruff-check
24
+ name: ruff check
25
+ entry: ruff check --fix --exit-non-zero-on-fix --config=.ruff.toml --force-exclude
26
+ language: system
27
+ types_or: [python, pyi]
27
28
  - id: ruff-format
29
+ name: ruff format
30
+ entry: ruff format --force-exclude
31
+ language: system
32
+ types_or: [python, pyi]
28
33
  - repo: https://github.com/asottile/pyupgrade
29
34
  rev: v3.21.2
30
35
  hooks:
@@ -1,8 +1,11 @@
1
1
  # Project-local taskledger configuration.
2
2
  # This file lives in the source project root.
3
- config_version = 1
3
+ config_version = 2
4
4
  taskledger_dir = '.taskledger'
5
5
 
6
+ # Stable project identity. Commit this with your source tree.
7
+ project_uuid = "081c7c05-2d10-42b7-9b37-3d814c2f400a"
8
+
6
9
  # Project-local taskledger overrides.
7
10
  # The source-budget settings below are the active composition defaults.
8
11
  # Lower them for stricter prompts, or raise them when a run needs more context.
@@ -18,3 +21,9 @@ taskledger_dir = '.taskledger'
18
21
  # workflow_schema = "opsx-lite"
19
22
  # project_context = "Project-specific workflow guidance."
20
23
  # default_artifact_order = ["analysis", "plan", "implementation", "validation"]
24
+
25
+ # Taskledger branch-scoped state. This block is intentionally safe to commit.
26
+ ledger_ref = "main"
27
+ ledger_parent_ref = ""
28
+ ledger_next_task_number = 60
29
+ ledger_branch_guard = "off"
@@ -54,10 +54,12 @@ from taskledger.errors import (
54
54
  - `project_export`
55
55
  - `project_import`
56
56
  - `project_snapshot`
57
+ - `project_tree`
57
58
 
58
59
  ### `taskledger.api.tasks`
59
60
 
60
61
  - `create_task`
62
+ - `record_completed_task`
61
63
  - `show_active_task`
62
64
  - `activate_task`
63
65
  - `deactivate_task`
@@ -82,10 +84,14 @@ from taskledger.errors import (
82
84
  - `todo_status`
83
85
  - `next_todo`
84
86
  - `task_dossier`
87
+ - `render_task_report`
88
+ - `TaskReportOptions`
85
89
  - `next_action`
86
90
  - `can_perform`
87
91
  - `reindex`
88
92
  - `repair_task_record`
93
+ - `repair_orphaned_planning_run`
94
+ - `repair_planning_command_changes`
89
95
 
90
96
  ### `taskledger.api.plans`
91
97
 
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.1.2 - 2026-04-30
4
+
5
+ ### Fixed
6
+
7
+ - Fixed orphaned planning run lifecycle recovery so plan regeneration safely finishes the latest orphaned planning run with audit evidence, plan approval rejects tasks with any running run, and `implement start` reports structured conflict details including run id, run type, lock match status, and suggested diagnostic command.
8
+ - Aligned `next-action` and `can implement` so they never recommend `implement start` when a running run or run/lock mismatch blocks implementation.
9
+ - Expanded `taskledger doctor` and `taskledger doctor locks` to report run/lock mismatches with specific repair guidance.
10
+
11
+ ### Added
12
+
13
+ - Added `taskledger repair run` for guarded, reasoned, audited repair of orphaned running planning runs.
14
+
15
+ ### Documentation
16
+
17
+ - Updated taskledger skill, command contract, and API docs with running-run conflict protocol and `repair run` usage.
18
+
19
+ ### Quality
20
+
21
+ - Expanded regression coverage for plan regeneration recovery, approval guards, next-action alignment, doctor diagnostics, and repair lifecycle. Targeted pytest, ruff, format, and mypy passed.
22
+
23
+ ## v0.1.1 - 2026-04-29
24
+
25
+ ### Added
26
+
27
+ - Added `task follow-up` to create linked post-completion child tasks, preserve closure metadata, and show parent and follow-up relationships in task and handoff views.
28
+ - Added durable release records and a new `taskledger release` command group with `tag`, `list`, `show`, and `changelog`, including export/import support and public API coverage.
29
+ - Added planning helpers with `question add-many`, `plan template`, richer regeneration hints in `next-action`, and recovery commands for orphaned implementation work with `implement resume`, `task uncancel`, and `can implement-resume`.
30
+
31
+ ### Changed
32
+
33
+ - Hardened CLI startup so optional command-group import failures no longer block core commands, and launcher failures return structured diagnostics.
34
+
35
+ ### Fixed
36
+
37
+ - Fixed recovery guidance for uncancelled tasks with orphaned implementation runs so `next-action` and `can implement` recommend `implement resume` instead of a fresh start.
38
+
39
+ ### Documentation
40
+
41
+ - Documented release tagging, changelog generation, planning helpers, follow-up task workflow, and recovery semantics across README, RST docs, API docs, and the taskledger skill.
42
+
43
+ ### Quality
44
+
45
+ - Expanded regression coverage for follow-up tasks, release workflow, CLI import resilience, planning helpers, and implementation recovery. Repo-wide pytest, ruff, and mypy passed.
46
+
3
47
  ## v0.1.0 - 2026-04-29
4
48
 
5
49
  ### Added
@@ -0,0 +1,9 @@
1
+ .PHONY: release-check
2
+
3
+ release-check:
4
+ python3 -m compileall -q taskledger tests
5
+ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python3 -m pytest -q
6
+ python3 -m ruff check --config=.ruff.toml .
7
+ python3 -m mypy taskledger
8
+ python3 -m build
9
+ python3 -m twine check dist/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskledger
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: Durable project-state storage and CLI for coding workflows
5
5
  Author: Taskledger Contributors
6
6
  Maintainer: Holger Nahrstaedt
@@ -33,6 +33,7 @@ Provides-Extra: dev
33
33
  Requires-Dist: build; extra == "dev"
34
34
  Requires-Dist: mypy; extra == "dev"
35
35
  Requires-Dist: pytest; extra == "dev"
36
+ Requires-Dist: pytest-xdist; extra == "dev"
36
37
  Requires-Dist: ruff; extra == "dev"
37
38
  Requires-Dist: twine; extra == "dev"
38
39
  Requires-Dist: types-PyYAML; extra == "dev"
@@ -40,6 +41,11 @@ Provides-Extra: rich
40
41
  Requires-Dist: rich; extra == "rich"
41
42
  Dynamic: license-file
42
43
 
44
+ [![PyPI - Version](https://img.shields.io/pypi/v/taskledger)](https://pypi.org/project/taskledger/)
45
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/taskledger)
46
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/taskledger)
47
+ [![codecov](https://codecov.io/gh/holgern/taskledger/graph/badge.svg?token=6usFHwM5Ul)](https://codecov.io/gh/holgern/taskledger)
48
+
43
49
  # taskledger
44
50
 
45
51
  `taskledger` is a task-first durable state layer for staged coding work. It keeps
@@ -131,14 +137,15 @@ taskledger validate check --criterion ac-0001 --status pass --evidence "pytest -
131
137
  taskledger validate finish --result passed --summary "Validated the rewrite."
132
138
  ```
133
139
 
134
- If validation finds an implementation bug, keep the accepted plan and restart
135
- implementation explicitly:
140
+ For manually completed work (e.g., manual testing, operations tasks, or work
141
+ completed outside the task-first lifecycle), use `task record` to create a
142
+ done task directly without acquiring lifecycle locks. **Note**: `task record`
143
+ does not replace the normal task lifecycle; it is for recording work already
144
+ completed, not as a shortcut for active task management.
136
145
 
137
146
  ```bash
138
- taskledger validate finish --result failed --summary "Parser edge case still fails."
139
- taskledger next-action
140
- taskledger context --for implementation --format markdown
141
- taskledger implement restart --summary "Fix failed validation findings."
147
+ taskledger task record "Deploy to production" --summary "Deployed v0.4.1 to prod" --change "infra/deploy.sh:run:Updated prod config" --evidence "Monitoring shows no errors"
148
+ taskledger task record "Manual API testing" --summary "Tested new endpoints" --allow-empty-record --reason "Exploratory testing, no formal changes tracked"
142
149
  ```
143
150
 
144
151
  If validation finds an implementation bug, keep the accepted plan and restart
@@ -265,21 +272,47 @@ fresh-context transfer.
265
272
  ## Storage layout
266
273
 
267
274
  `taskledger` keeps project-local configuration in the workspace root and durable
268
- records under the configured storage root:
275
+ records under the configured storage root. The checked-in `.taskledger.toml`
276
+ stores only a branch-scoped ledger pointer and next task number. Operational task
277
+ state remains ignored under `.taskledger/ledgers/<ledger_ref>/`:
269
278
 
270
279
  ```text
271
- taskledger.toml
280
+ .taskledger.toml
272
281
  .taskledger/
273
- intros/
274
- releases/
275
- tasks/
276
- events/
277
- indexes/ # optional derived caches and registries
282
+ storage.yaml
283
+ ledgers/
284
+ main/
285
+ intros/
286
+ releases/
287
+ tasks/
288
+ events/
289
+ indexes/ # optional derived caches and registries
278
290
  ```
279
291
 
280
- Markdown files are canonical. Task, plan, and run listings scan those records
281
- directly. JSON files under `.taskledger/indexes/` are optional derived caches or
282
- registries and are not required for task correctness.
292
+ Markdown files are canonical. Task, plan, and run listings scan only the current
293
+ ledger by default. JSON files under the current ledger's `indexes/` directory are
294
+ optional derived caches or registries and are not required for task correctness.
295
+
296
+ ### Branch-scoped ledgers
297
+
298
+ `.taskledger/` stays ignored and local. `.taskledger.toml` is safe to commit and
299
+ contains the current `ledger_ref`, optional parent ref, and the next logical task
300
+ number for the checked-out source branch.
301
+
302
+ When starting long-lived branch-local work, fork the ledger pointer after creating
303
+ the Git branch:
304
+
305
+ ```bash
306
+ git checkout -b feature-a
307
+ taskledger ledger fork feature-a
308
+ git add .taskledger.toml
309
+ ```
310
+
311
+ Returning to a branch whose `.taskledger.toml` points back to `main` hides the
312
+ feature branch's active task and task list. Two ledgers may both contain a logical
313
+ `task-0030`; this is expected because task IDs are scoped by `ledger_ref`. Use
314
+ `taskledger ledger adopt --from REF TASK_REF` when branch-local task history
315
+ should be copied into the current ledger.
283
316
 
284
317
  You can also point `taskledger.toml` at an external storage root:
285
318
 
@@ -347,6 +380,7 @@ taskledger context --for planning --format markdown
347
380
  taskledger context --for implementation --format markdown
348
381
  taskledger context --for validation --format json
349
382
  taskledger task dossier --format markdown
383
+ taskledger task report --task task-0030 -o task30.md
350
384
  taskledger handoff create --mode implementation --intended-actor agent --intended-harness codex
351
385
  taskledger handoff claim handoff-0001
352
386
  taskledger handoff close handoff-0001 --reason "Implementation started."
@@ -407,24 +441,50 @@ for task-first handoff guidance.
407
441
  ## Export, import, and snapshots
408
442
 
409
443
  ```bash
410
- taskledger --json export
411
- taskledger import ./taskledger-export.json --replace
444
+ taskledger export ./taskledger-transfer.tar.gz
445
+ taskledger import ./taskledger-transfer.tar.gz --replace
412
446
  taskledger snapshot ./artifacts
413
447
  ```
414
448
 
449
+ Cross-machine imports preserve durable task/run data, but imported runtime locks
450
+ are quarantined by default. After importing an in-progress implementation,
451
+ run:
452
+
453
+ ```bash
454
+ taskledger next-action
455
+ taskledger implement resume --reason "Continue imported implementation."
456
+ ```
457
+
458
+ Use `--lock-policy keep` only for diagnostic full-fidelity lock restoration.
459
+
415
460
  ## Skill packaging
416
461
 
462
+ Agent workflows work best when the `taskledger` skill is installed in the
463
+ coding harness. The CLI has a task-first lifecycle with explicit planning,
464
+ approval, implementation, validation, locks, and handoff gates; without the
465
+ skill, an agent may not know the intended command sequence or gate semantics.
466
+
417
467
  The canonical skill file lives at:
418
468
 
419
469
  ```text
420
470
  skills/taskledger/SKILL.md
421
471
  ```
422
472
 
423
- No additional `skills/taskledger/examples/` directory is required.
473
+ Keep this skill outside the Python package. No additional
474
+ `skills/taskledger/examples/` directory is required.
424
475
 
425
476
  ## Development
426
477
 
427
478
  ```bash
428
- pytest -q
479
+ python -m pytest -m "not slow"
480
+ python -m pytest -m "not slow" -n auto
481
+ python -m pytest -n auto
482
+ python -m pytest
429
483
  ruff check .
430
484
  ```
485
+
486
+ Full release-readiness sweep:
487
+
488
+ ```bash
489
+ make release-check
490
+ ```
@@ -1,3 +1,8 @@
1
+ [![PyPI - Version](https://img.shields.io/pypi/v/taskledger)](https://pypi.org/project/taskledger/)
2
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/taskledger)
3
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/taskledger)
4
+ [![codecov](https://codecov.io/gh/holgern/taskledger/graph/badge.svg?token=6usFHwM5Ul)](https://codecov.io/gh/holgern/taskledger)
5
+
1
6
  # taskledger
2
7
 
3
8
  `taskledger` is a task-first durable state layer for staged coding work. It keeps
@@ -89,14 +94,15 @@ taskledger validate check --criterion ac-0001 --status pass --evidence "pytest -
89
94
  taskledger validate finish --result passed --summary "Validated the rewrite."
90
95
  ```
91
96
 
92
- If validation finds an implementation bug, keep the accepted plan and restart
93
- implementation explicitly:
97
+ For manually completed work (e.g., manual testing, operations tasks, or work
98
+ completed outside the task-first lifecycle), use `task record` to create a
99
+ done task directly without acquiring lifecycle locks. **Note**: `task record`
100
+ does not replace the normal task lifecycle; it is for recording work already
101
+ completed, not as a shortcut for active task management.
94
102
 
95
103
  ```bash
96
- taskledger validate finish --result failed --summary "Parser edge case still fails."
97
- taskledger next-action
98
- taskledger context --for implementation --format markdown
99
- taskledger implement restart --summary "Fix failed validation findings."
104
+ taskledger task record "Deploy to production" --summary "Deployed v0.4.1 to prod" --change "infra/deploy.sh:run:Updated prod config" --evidence "Monitoring shows no errors"
105
+ taskledger task record "Manual API testing" --summary "Tested new endpoints" --allow-empty-record --reason "Exploratory testing, no formal changes tracked"
100
106
  ```
101
107
 
102
108
  If validation finds an implementation bug, keep the accepted plan and restart
@@ -223,21 +229,47 @@ fresh-context transfer.
223
229
  ## Storage layout
224
230
 
225
231
  `taskledger` keeps project-local configuration in the workspace root and durable
226
- records under the configured storage root:
232
+ records under the configured storage root. The checked-in `.taskledger.toml`
233
+ stores only a branch-scoped ledger pointer and next task number. Operational task
234
+ state remains ignored under `.taskledger/ledgers/<ledger_ref>/`:
227
235
 
228
236
  ```text
229
- taskledger.toml
237
+ .taskledger.toml
230
238
  .taskledger/
231
- intros/
232
- releases/
233
- tasks/
234
- events/
235
- indexes/ # optional derived caches and registries
239
+ storage.yaml
240
+ ledgers/
241
+ main/
242
+ intros/
243
+ releases/
244
+ tasks/
245
+ events/
246
+ indexes/ # optional derived caches and registries
236
247
  ```
237
248
 
238
- Markdown files are canonical. Task, plan, and run listings scan those records
239
- directly. JSON files under `.taskledger/indexes/` are optional derived caches or
240
- registries and are not required for task correctness.
249
+ Markdown files are canonical. Task, plan, and run listings scan only the current
250
+ ledger by default. JSON files under the current ledger's `indexes/` directory are
251
+ optional derived caches or registries and are not required for task correctness.
252
+
253
+ ### Branch-scoped ledgers
254
+
255
+ `.taskledger/` stays ignored and local. `.taskledger.toml` is safe to commit and
256
+ contains the current `ledger_ref`, optional parent ref, and the next logical task
257
+ number for the checked-out source branch.
258
+
259
+ When starting long-lived branch-local work, fork the ledger pointer after creating
260
+ the Git branch:
261
+
262
+ ```bash
263
+ git checkout -b feature-a
264
+ taskledger ledger fork feature-a
265
+ git add .taskledger.toml
266
+ ```
267
+
268
+ Returning to a branch whose `.taskledger.toml` points back to `main` hides the
269
+ feature branch's active task and task list. Two ledgers may both contain a logical
270
+ `task-0030`; this is expected because task IDs are scoped by `ledger_ref`. Use
271
+ `taskledger ledger adopt --from REF TASK_REF` when branch-local task history
272
+ should be copied into the current ledger.
241
273
 
242
274
  You can also point `taskledger.toml` at an external storage root:
243
275
 
@@ -305,6 +337,7 @@ taskledger context --for planning --format markdown
305
337
  taskledger context --for implementation --format markdown
306
338
  taskledger context --for validation --format json
307
339
  taskledger task dossier --format markdown
340
+ taskledger task report --task task-0030 -o task30.md
308
341
  taskledger handoff create --mode implementation --intended-actor agent --intended-harness codex
309
342
  taskledger handoff claim handoff-0001
310
343
  taskledger handoff close handoff-0001 --reason "Implementation started."
@@ -365,24 +398,50 @@ for task-first handoff guidance.
365
398
  ## Export, import, and snapshots
366
399
 
367
400
  ```bash
368
- taskledger --json export
369
- taskledger import ./taskledger-export.json --replace
401
+ taskledger export ./taskledger-transfer.tar.gz
402
+ taskledger import ./taskledger-transfer.tar.gz --replace
370
403
  taskledger snapshot ./artifacts
371
404
  ```
372
405
 
406
+ Cross-machine imports preserve durable task/run data, but imported runtime locks
407
+ are quarantined by default. After importing an in-progress implementation,
408
+ run:
409
+
410
+ ```bash
411
+ taskledger next-action
412
+ taskledger implement resume --reason "Continue imported implementation."
413
+ ```
414
+
415
+ Use `--lock-policy keep` only for diagnostic full-fidelity lock restoration.
416
+
373
417
  ## Skill packaging
374
418
 
419
+ Agent workflows work best when the `taskledger` skill is installed in the
420
+ coding harness. The CLI has a task-first lifecycle with explicit planning,
421
+ approval, implementation, validation, locks, and handoff gates; without the
422
+ skill, an agent may not know the intended command sequence or gate semantics.
423
+
375
424
  The canonical skill file lives at:
376
425
 
377
426
  ```text
378
427
  skills/taskledger/SKILL.md
379
428
  ```
380
429
 
381
- No additional `skills/taskledger/examples/` directory is required.
430
+ Keep this skill outside the Python package. No additional
431
+ `skills/taskledger/examples/` directory is required.
382
432
 
383
433
  ## Development
384
434
 
385
435
  ```bash
386
- pytest -q
436
+ python -m pytest -m "not slow"
437
+ python -m pytest -m "not slow" -n auto
438
+ python -m pytest -n auto
439
+ python -m pytest
387
440
  ruff check .
388
441
  ```
442
+
443
+ Full release-readiness sweep:
444
+
445
+ ```bash
446
+ make release-check
447
+ ```
@@ -33,11 +33,13 @@ Project API
33
33
  - ``project_export``
34
34
  - ``project_import``
35
35
  - ``project_snapshot``
36
+ - ``project_tree``
36
37
 
37
38
  Task API
38
39
  --------
39
40
 
40
41
  - ``create_task``
42
+ - ``record_completed_task``
41
43
  - ``show_active_task``
42
44
  - ``activate_task``
43
45
  - ``deactivate_task``
@@ -62,10 +64,14 @@ Task API
62
64
  - ``todo_status``
63
65
  - ``next_todo``
64
66
  - ``task_dossier``
67
+ - ``render_task_report``
68
+ - ``TaskReportOptions``
65
69
  - ``next_action``
66
70
  - ``can_perform``
67
71
  - ``reindex``
68
72
  - ``repair_task_record``
73
+ - ``repair_orphaned_planning_run``
74
+ - ``repair_planning_command_changes``
69
75
 
70
76
  Plan API
71
77
  --------
@@ -34,6 +34,19 @@ when explicitly targeting another task.
34
34
 
35
35
  Optional positional task refs are not supported.
36
36
 
37
+ Archive import lock policy
38
+ --------------------------
39
+
40
+ Archive imports support explicit lock handling:
41
+
42
+ .. code-block:: bash
43
+
44
+ taskledger import ./taskledger-transfer.tar.gz --replace [--lock-policy drop|quarantine|keep]
45
+
46
+ The default is ``quarantine`` so imported source-machine runtime locks are not
47
+ restored as active ``lock.yaml`` files. ``keep`` is diagnostic-only behavior
48
+ for full-fidelity lock restoration.
49
+
37
50
  Positional Resource Refs
38
51
  ------------------------
39
52
 
@@ -41,6 +54,8 @@ Positional refs are reserved for the direct resource being changed or shown:
41
54
 
42
55
  .. code-block:: bash
43
56
 
57
+ taskledger task create TITLE [options]
58
+ taskledger task record TITLE [options]
44
59
  taskledger task activate TASK_REF
45
60
  taskledger task follow-up PARENT_REF TITLE [options]
46
61
  taskledger todo done TODO_ID --task TASK_REF --evidence "pytest -q"
@@ -61,11 +76,32 @@ Release boundaries are durable project records, not task lifecycle states:
61
76
  taskledger release show 0.4.1
62
77
  taskledger release changelog 0.4.2 --since 0.4.1 --until-task task-0035 --output /tmp/taskledger-0.4.2-changelog-source.md
63
78
 
64
- ``release tag`` writes a durable release record under ``.taskledger/releases/``.
79
+ ``release tag`` writes a durable release record under the current ledger's
80
+ ``releases/`` directory.
65
81
  ``release changelog`` is read-oriented: it renders Markdown or JSON changelog
66
82
  context from done tasks and may write an external output file, but it does not
67
83
  mutate ledger state.
68
84
 
85
+ Ledger commands
86
+ ---------------
87
+
88
+ Branch-scoped ledgers isolate ignored local task state by the checked-in
89
+ ``ledger_ref`` stored in ``.taskledger.toml``:
90
+
91
+ .. code-block:: bash
92
+
93
+ taskledger ledger status
94
+ taskledger ledger list
95
+ taskledger ledger fork feature-a
96
+ taskledger ledger switch main
97
+ taskledger ledger adopt --from feature-a task-0030
98
+ taskledger ledger doctor
99
+
100
+ ``ledger fork`` creates a new local namespace under
101
+ ``.taskledger/ledgers/<ref>/`` and updates only Taskledger-owned ledger keys in
102
+ ``.taskledger.toml``. ``ledger switch`` changes the checked-in pointer to an
103
+ existing local ledger. ``ledger adopt`` copies a task from another local ledger
104
+ into the current ledger and renumbers on collision.
69
105
  ``next-action`` result contract
70
106
  -------------------------------
71
107
 
@@ -114,9 +150,55 @@ status but ``active_stage`` is missing, ``next-action`` must not report
114
150
  ``The task is cancelled.`` For an orphaned implementation with a still-running
115
151
  latest implementation run and no active lock, it should direct agents to
116
152
  ``taskledger implement resume --task TASK_REF --reason "..."``.
153
+ For an approved task with a non-implementation run still marked running,
154
+ ``next-action`` must not direct agents to ``taskledger implement start``.
155
+ It should report a repair-oriented action and point to ``taskledger doctor``.
117
156
  Truly cancelled tasks recover through ``taskledger task uncancel --reason "..."``
157
+
158
+ Compact mutation output
159
+ ........................
160
+
161
+ Mutation commands emit compact acknowledgements instead of full task or run records.
162
+ This reduces LLM context consumption during implementation loops.
163
+
164
+ The following commands produce compact output:
165
+
166
+ - ``todo add``: emits ``todo_added`` result with new todo, progress, and next command.
167
+ - ``todo done`` / ``todo undone``: emits ``todo_update`` result with todo id, status, progress, and next command.
168
+ - ``implement finish``: emits ``task_lifecycle`` result with task id, run id, status, and next command.
169
+
170
+ Human mode shows a one-line summary:
171
+
172
+ .. code-block:: text
173
+
174
+ added todo-0001 on task-0001 (0/3 done)
175
+ done todo-0001 on task-0001 (1/3 done)
176
+ finished implementation run-0001 task task-0001 -> implemented
177
+
178
+ JSON mode wraps the compact result in the standard success envelope with ``result_type``.
179
+
180
+ For full task, run, or todo details after a mutation, use:
181
+
182
+ - ``taskledger task show`` or ``taskledger status`` for task-level detail.
183
+ - ``taskledger todo show TODO_ID`` for individual todo detail.
184
+ - ``taskledger next-action`` for the next concrete step.
185
+ - ``taskledger todo next`` for the next open todo.
118
186
  to a durable non-active stage rather than directly re-entering an active stage.
119
187
 
188
+ Run and lock repair
189
+ -------------------
190
+
191
+ ``taskledger doctor`` and ``taskledger doctor locks`` report running runs without
192
+ matching active locks. Orphaned running planning runs can be finished only
193
+ through an explicit repair command with a reason:
194
+
195
+ .. code-block:: bash
196
+
197
+ taskledger repair run --task TASK_REF --run RUN_ID --reason "Planning was already completed."
198
+
199
+ The repair command refuses to finish non-planning runs, non-running runs, or
200
+ runs that still have a matching active lock.
201
+
120
202
  Post-completion follow-up deltas
121
203
  --------------------------------
122
204
 
@@ -244,6 +326,11 @@ Taskledger uses:
244
326
  * per-record ``object_type``
245
327
  * per-file ``file_version`` for durable Markdown/YAML/JSON record files
246
328
 
329
+ Storage layout version history:
330
+
331
+ * Layout 2: Introduced branch-scoped ledgers under ``taskledger_dir/ledgers/<ledger_ref>/``
332
+ * Layout 3: Consolidates layout-2 root-level task state into branch-scoped ledgers; migrates legacy root ``tasks/``, ``events/``, ``intros/``, ``releases/``, and ``active-task.yaml`` into the active ledger namespace
333
+
247
334
  Taskledger does not silently rewrite storage during read-only commands.
248
335
 
249
336
  If the installed taskledger version can read but not write an older workspace,
@@ -257,7 +344,14 @@ To migrate:
257
344
  taskledger migrate plan
258
345
  taskledger migrate apply --backup
259
346
 
260
- Indexes under ``taskledger_dir/indexes/`` are optional derived caches or
347
+ After migration to layout 3, verify health with:
348
+
349
+ .. code-block:: bash
350
+
351
+ taskledger doctor
352
+ taskledger ledger doctor
353
+
354
+ Indexes under ``taskledger_dir/ledgers/<ledger_ref>/indexes/`` are optional derived caches or
261
355
  registries. Task, plan, and run commands must continue to work from canonical
262
356
  Markdown/YAML records even when task/run/plan JSON cache files are absent. The
263
357
  remaining derived caches may be plain JSON arrays with no version metadata and