tcw-cli 2.8.1__tar.gz → 2.8.3__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 (233) hide show
  1. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/PKG-INFO +26 -5
  2. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/README.md +25 -4
  3. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/pyproject.toml +1 -1
  4. tcw_cli-2.8.3/tcw/__init__.py +1 -0
  5. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/jira.py +5 -1
  6. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw_cli.egg-info/PKG-INFO +26 -5
  7. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_client.py +63 -1
  8. tcw_cli-2.8.1/tcw/__init__.py +0 -1
  9. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/LICENSE +0 -0
  10. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/setup.cfg +0 -0
  11. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/capabilities/__init__.py +0 -0
  12. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/capabilities/cli.py +0 -0
  13. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/cli.py +0 -0
  14. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/cli_suggest.py +0 -0
  15. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/harness.py +0 -0
  16. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/refs.py +0 -0
  17. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/__init__.py +0 -0
  18. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/dist/client/assets/index-C5_pngMt.css +0 -0
  19. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/dist/client/assets/index-Dss8_ZG_.js +0 -0
  20. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/dist/client/index.html +0 -0
  21. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/dist/client/theme-init.js +0 -0
  22. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/dist/server.cjs +0 -0
  23. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/serve/runtime.py +0 -0
  24. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/stdin.py +0 -0
  25. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/__init__.py +0 -0
  26. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/base.py +0 -0
  27. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/checkouts.py +0 -0
  28. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/config_edit.py +0 -0
  29. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/fs.py +0 -0
  30. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/project.py +0 -0
  31. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/store/yaml_source.py +0 -0
  32. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/taxonomy/__init__.py +0 -0
  33. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/taxonomy/cli.py +0 -0
  34. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/__init__.py +0 -0
  35. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/claim.py +0 -0
  36. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/create.py +0 -0
  37. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/intake.py +0 -0
  38. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/ownership.py +0 -0
  39. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/progress.py +0 -0
  40. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/tracker/sync.py +0 -0
  41. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/validate.py +0 -0
  42. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/__init__.py +0 -0
  43. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/cli.py +0 -0
  44. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/generate.py +0 -0
  45. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/hooks.py +0 -0
  46. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/audit-backlog.md +0 -0
  47. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/consolidate-plans.md +0 -0
  48. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/create-work.md +0 -0
  49. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/decompose.md +0 -0
  50. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/delegation.md +0 -0
  51. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/documentation-sync.md +0 -0
  52. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/post-mortem.md +0 -0
  53. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/search.md +0 -0
  54. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/triage-issues.md +0 -0
  55. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/procedures/unattended-work.md +0 -0
  56. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/projection.py +0 -0
  57. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/implement.md +0 -0
  58. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/inbox.md +0 -0
  59. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/plan.md +0 -0
  60. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/postmortem.md +0 -0
  61. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/request.md +0 -0
  62. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/spec.md +0 -0
  63. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/prompts/verify.md +0 -0
  64. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/recursion.py +0 -0
  65. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/resolve.py +0 -0
  66. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw/work/templates.py +0 -0
  67. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw_cli.egg-info/SOURCES.txt +0 -0
  68. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw_cli.egg-info/dependency_links.txt +0 -0
  69. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw_cli.egg-info/entry_points.txt +0 -0
  70. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw_cli.egg-info/requires.txt +0 -0
  71. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tcw_cli.egg-info/top_level.txt +0 -0
  72. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_already_integrated_check.py +0 -0
  73. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_blocker_cycles_through_unreadable_items.py +0 -0
  74. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_boardless_delegate_and_slices.py +0 -0
  75. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_body_prompt.py +0 -0
  76. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capabilities.py +0 -0
  77. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capabilities_federation.py +0 -0
  78. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capabilities_reset.py +0 -0
  79. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capabilities_rm.py +0 -0
  80. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capabilities_sidecar.py +0 -0
  81. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capability_gate_children.py +0 -0
  82. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_capability_ref_wording.py +0 -0
  83. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_check_versions.py +0 -0
  84. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_child_status.py +0 -0
  85. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_cli_help_coverage.py +0 -0
  86. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_command_suggestions.py +0 -0
  87. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_committed_paths.py +0 -0
  88. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_config_edit.py +0 -0
  89. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_config_edit_writers.py +0 -0
  90. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_configuration_text_home.py +0 -0
  91. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_creation_commits.py +0 -0
  92. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_cross_node_blocker_cycles.py +0 -0
  93. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_cross_node_blockers.py +0 -0
  94. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_cut_version.py +0 -0
  95. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_damaged_state_on_edit.py +0 -0
  96. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_detached_worktree_teardown.py +0 -0
  97. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_documentation_config.py +0 -0
  98. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_documentation_prompt.py +0 -0
  99. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_documentation_sync_wiring.py +0 -0
  100. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_documented_cli_surface.py +0 -0
  101. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_duplicate_slug_refusals.py +0 -0
  102. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_dynamic_skill_marker.py +0 -0
  103. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_edit_refusal.py +0 -0
  104. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_edit_type.py +0 -0
  105. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_environment_hardness.py +0 -0
  106. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_epic_completability_across_checkouts.py +0 -0
  107. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_epic_completable.py +0 -0
  108. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_eval_coverage.py +0 -0
  109. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_eval_files_changed.py +0 -0
  110. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_eval_fixture.py +0 -0
  111. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_eval_grading.py +0 -0
  112. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_eval_runner.py +0 -0
  113. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_external_work_store.py +0 -0
  114. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_falsification_rule.py +0 -0
  115. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_generate_hook.py +0 -0
  116. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_harness.py +0 -0
  117. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_inbox_title.py +0 -0
  118. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_init_configured_tree_path.py +0 -0
  119. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_initiative_node_qualified.py +0 -0
  120. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_interrupted_claim.py +0 -0
  121. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_item_tags_read.py +0 -0
  122. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_legacy_store_config.py +0 -0
  123. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_lifecycle_baseline.py +0 -0
  124. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_lifecycle_config_tags.py +0 -0
  125. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_lifecycle_hooks.py +0 -0
  126. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_lifecycle_inert.py +0 -0
  127. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_lifecycle_policy.py +0 -0
  128. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_lifecycle_validation.py +0 -0
  129. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_literal_store_names.py +0 -0
  130. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_local_qualified_blockers.py +0 -0
  131. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_multiproject.py +0 -0
  132. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_non_git_writes.py +0 -0
  133. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_override_in_linked_worktree.py +0 -0
  134. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_override_letter_case.py +0 -0
  135. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_override_references.py +0 -0
  136. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_planning_gates_after_start.py +0 -0
  137. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_plugin_manifests.py +0 -0
  138. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_procedure_config.py +0 -0
  139. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_procedure_verb.py +0 -0
  140. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_project_graph_paths.py +0 -0
  141. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_project_overrides.py +0 -0
  142. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_project_registry.py +0 -0
  143. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_projection.py +0 -0
  144. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_prompt_fallback.py +0 -0
  145. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_qualified_ref.py +0 -0
  146. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_recursion.py +0 -0
  147. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_refs.py +0 -0
  148. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_remote_session_setup.py +0 -0
  149. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_rename_work_item.py +0 -0
  150. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_repo_lifecycle.py +0 -0
  151. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_resolve.py +0 -0
  152. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_resolve_procedure.py +0 -0
  153. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_retention.py +0 -0
  154. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_routing_nodes.py +0 -0
  155. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_scaffold.py +0 -0
  156. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve.py +0 -0
  157. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve_descendants.py +0 -0
  158. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve_duplicate_slug.py +0 -0
  159. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve_projection.py +0 -0
  160. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve_resolve.py +0 -0
  161. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve_runtime.py +0 -0
  162. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_serve_write.py +0 -0
  163. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_session_bootstrap.py +0 -0
  164. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_shipped_procedures.py +0 -0
  165. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_shipped_prompts.py +0 -0
  166. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_show_json.py +0 -0
  167. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_sidecar_paths_in_validate.py +0 -0
  168. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_skill_flow.py +0 -0
  169. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_skill_lifecycle_parity.py +0 -0
  170. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_skill_path_pointers.py +0 -0
  171. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_smoke.py +0 -0
  172. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_stage_validate.py +0 -0
  173. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_stage_verb.py +0 -0
  174. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_stale_item_path.py +0 -0
  175. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_status_parity.py +0 -0
  176. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_stdin.py +0 -0
  177. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_stdin_cli.py +0 -0
  178. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_store_bounds.py +0 -0
  179. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_store_editor.py +0 -0
  180. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_store_lock.py +0 -0
  181. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_store_nodes.py +0 -0
  182. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_store_provisioning.py +0 -0
  183. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_store_publication.py +0 -0
  184. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_subprocess_stdin.py +0 -0
  185. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_taxonomy.py +0 -0
  186. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_taxonomy_rm_gaps.py +0 -0
  187. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tombstone.py +0 -0
  188. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_absent.py +0 -0
  189. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_binding.py +0 -0
  190. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_catch_up_moves.py +0 -0
  191. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_claim.py +0 -0
  192. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_claimability.py +0 -0
  193. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_cli.py +0 -0
  194. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_comment.py +0 -0
  195. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_config.py +0 -0
  196. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_create.py +0 -0
  197. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_gate.py +0 -0
  198. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_hardening.py +0 -0
  199. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_help.py +0 -0
  200. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_hold.py +0 -0
  201. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_import.py +0 -0
  202. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_import_returns.py +0 -0
  203. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_inheritance.py +0 -0
  204. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_link.py +0 -0
  205. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_message_tidy.py +0 -0
  206. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_ownership.py +0 -0
  207. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_pre_backlog.py +0 -0
  208. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_replay.py +0 -0
  209. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_strict.py +0 -0
  210. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_strict_gate.py +0 -0
  211. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_surface.py +0 -0
  212. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_sync.py +0 -0
  213. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_sync_config.py +0 -0
  214. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_tracker_validate.py +0 -0
  215. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_transition_hints.py +0 -0
  216. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_unattended_work_skill.py +0 -0
  217. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_unplanned_start.py +0 -0
  218. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_unpushed_version_script.py +0 -0
  219. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_unreadable_capabilities_sidecar.py +0 -0
  220. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_unreadable_item_files.py +0 -0
  221. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_unreadable_state_gates.py +0 -0
  222. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_untag_invalid_tags.py +0 -0
  223. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_upstream_projects.py +0 -0
  224. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_validate.py +0 -0
  225. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_validate_moved_stores.py +0 -0
  226. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_validate_target.py +0 -0
  227. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_work.py +0 -0
  228. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_work_autocommit.py +0 -0
  229. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_work_review.py +0 -0
  230. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_work_start.py +0 -0
  231. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_work_tags.py +0 -0
  232. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_worktree_completion.py +0 -0
  233. {tcw_cli-2.8.1 → tcw_cli-2.8.3}/tests/test_worktree_sibling_nodes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tcw-cli
3
- Version: 2.8.1
3
+ Version: 2.8.3
4
4
  Summary: Taxonomy · Capabilities · Work — a storage-abstracted framework for describing and evolving a software project.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -218,8 +218,8 @@ Dynamic: license-file
218
218
 
219
219
  TCW keeps three things about a software project inside the repository, next to
220
220
  the code: what the project deals with, what a user can do with it, and what is
221
- being changed. One command-line tool, `tcw`, and an agent plugin for Claude Code
222
- and Codex keep all three in step with the code.
221
+ being changed. One command-line tool, `tcw`, and an agent plugin for Claude Code,
222
+ Codex, and Pi keep all three in step with the code.
223
223
 
224
224
  | Component | Answers |
225
225
  | ---------------- | ------------------------------------------------------- |
@@ -309,7 +309,28 @@ skill — it runs the same install script Claude runs automatically. Every tcw
309
309
  skill also asks the agent to run the plugin's version check once per session,
310
310
  which warns when the CLI and the skills come from different releases.
311
311
 
312
- The plugin ships the skills and read-only review agents described in
312
+ In **Pi**:
313
+
314
+ ```bash
315
+ pi install git:github.com/brocef/TCW
316
+ ```
317
+
318
+ Add `-l` to install for the current project instead of your personal settings.
319
+ For a development checkout, use `pi install /absolute/path/to/TCW`.
320
+ Start a new Pi session, then run `/skill:setup` to install or check the `tcw`
321
+ CLI. You can also install it yourself with `pipx install tcw-cli`.
322
+ Invoke skills with `/skill:work`, `/skill:capabilities`, or `/skill:taxonomy`.
323
+
324
+ Pi loads the same skills through the official `pi` declaration in `package.json`.
325
+ It does not run TCW's Claude session-start hook or shell injections; the skills
326
+ provide explicit commands for setup, version checks, and lifecycle instructions.
327
+ Claude's custom review agents are not installed as Pi agents. When delegation
328
+ is unavailable, run ordinary lifecycle stages in the main session; autonomous
329
+ work still requires the advisors named by that workflow.
330
+ Git installation also installs the repository's Node package dependencies,
331
+ which support the TCW web app; local-path installation uses the checkout directly.
332
+
333
+ The plugin ships the skills and Claude Code read-only review agents described in
313
334
  [Skills and Agents](#skills-and-agents).
314
335
 
315
336
  ### CLI
@@ -940,7 +961,7 @@ resolve, what has to be true before an item completes. What a command cannot
940
961
  decide (what a request really asks for, whether a spec is good enough, whether
941
962
  the work is finished) is judgment, and the plugin's skills guide an agent through
942
963
  it. Skills name `tcw` commands and never reimplement them. Every entry point is a
943
- skill, so they work the same way under Claude Code and Codex.
964
+ skill, with the same CLI-backed lifecycle under Claude Code, Codex, and Pi.
944
965
 
945
966
  The skills for a single axis are listed in that axis's section above. These cut
946
967
  across the axes.
@@ -2,8 +2,8 @@
2
2
 
3
3
  TCW keeps three things about a software project inside the repository, next to
4
4
  the code: what the project deals with, what a user can do with it, and what is
5
- being changed. One command-line tool, `tcw`, and an agent plugin for Claude Code
6
- and Codex keep all three in step with the code.
5
+ being changed. One command-line tool, `tcw`, and an agent plugin for Claude Code,
6
+ Codex, and Pi keep all three in step with the code.
7
7
 
8
8
  | Component | Answers |
9
9
  | ---------------- | ------------------------------------------------------- |
@@ -93,7 +93,28 @@ skill — it runs the same install script Claude runs automatically. Every tcw
93
93
  skill also asks the agent to run the plugin's version check once per session,
94
94
  which warns when the CLI and the skills come from different releases.
95
95
 
96
- The plugin ships the skills and read-only review agents described in
96
+ In **Pi**:
97
+
98
+ ```bash
99
+ pi install git:github.com/brocef/TCW
100
+ ```
101
+
102
+ Add `-l` to install for the current project instead of your personal settings.
103
+ For a development checkout, use `pi install /absolute/path/to/TCW`.
104
+ Start a new Pi session, then run `/skill:setup` to install or check the `tcw`
105
+ CLI. You can also install it yourself with `pipx install tcw-cli`.
106
+ Invoke skills with `/skill:work`, `/skill:capabilities`, or `/skill:taxonomy`.
107
+
108
+ Pi loads the same skills through the official `pi` declaration in `package.json`.
109
+ It does not run TCW's Claude session-start hook or shell injections; the skills
110
+ provide explicit commands for setup, version checks, and lifecycle instructions.
111
+ Claude's custom review agents are not installed as Pi agents. When delegation
112
+ is unavailable, run ordinary lifecycle stages in the main session; autonomous
113
+ work still requires the advisors named by that workflow.
114
+ Git installation also installs the repository's Node package dependencies,
115
+ which support the TCW web app; local-path installation uses the checkout directly.
116
+
117
+ The plugin ships the skills and Claude Code read-only review agents described in
97
118
  [Skills and Agents](#skills-and-agents).
98
119
 
99
120
  ### CLI
@@ -724,7 +745,7 @@ resolve, what has to be true before an item completes. What a command cannot
724
745
  decide (what a request really asks for, whether a spec is good enough, whether
725
746
  the work is finished) is judgment, and the plugin's skills guide an agent through
726
747
  it. Skills name `tcw` commands and never reimplement them. Every entry point is a
727
- skill, so they work the same way under Claude Code and Codex.
748
+ skill, with the same CLI-backed lifecycle under Claude Code, Codex, and Pi.
728
749
 
729
750
  The skills for a single axis are listed in that axis's section above. These cut
730
751
  across the axes.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tcw-cli"
7
- version = "2.8.1"
7
+ version = "2.8.3"
8
8
  description = "Taxonomy · Capabilities · Work — a storage-abstracted framework for describing and evolving a software project."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -0,0 +1 @@
1
+ __version__ = "2.8.3"
@@ -149,7 +149,11 @@ class JiraClient:
149
149
  request = urllib.request.Request(
150
150
  f"{self.config.base_url}{path}", data=payload, method=method)
151
151
  credentials = base64.b64encode(f"{email}:{token}".encode("utf-8")).decode("ascii")
152
- request.add_header("Authorization", f"Basic {credentials}")
152
+ # Unredirected: urllib copies every `add_header` header onto the request a
153
+ # redirect produces, whatever host it points at, which would hand the
154
+ # user's email and API token to that host. A redirected request now goes
155
+ # without them.
156
+ request.add_unredirected_header("Authorization", f"Basic {credentials}")
153
157
  request.add_header("Accept", "application/json")
154
158
  if payload is not None:
155
159
  request.add_header("Content-Type", "application/json")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tcw-cli
3
- Version: 2.8.1
3
+ Version: 2.8.3
4
4
  Summary: Taxonomy · Capabilities · Work — a storage-abstracted framework for describing and evolving a software project.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -218,8 +218,8 @@ Dynamic: license-file
218
218
 
219
219
  TCW keeps three things about a software project inside the repository, next to
220
220
  the code: what the project deals with, what a user can do with it, and what is
221
- being changed. One command-line tool, `tcw`, and an agent plugin for Claude Code
222
- and Codex keep all three in step with the code.
221
+ being changed. One command-line tool, `tcw`, and an agent plugin for Claude Code,
222
+ Codex, and Pi keep all three in step with the code.
223
223
 
224
224
  | Component | Answers |
225
225
  | ---------------- | ------------------------------------------------------- |
@@ -309,7 +309,28 @@ skill — it runs the same install script Claude runs automatically. Every tcw
309
309
  skill also asks the agent to run the plugin's version check once per session,
310
310
  which warns when the CLI and the skills come from different releases.
311
311
 
312
- The plugin ships the skills and read-only review agents described in
312
+ In **Pi**:
313
+
314
+ ```bash
315
+ pi install git:github.com/brocef/TCW
316
+ ```
317
+
318
+ Add `-l` to install for the current project instead of your personal settings.
319
+ For a development checkout, use `pi install /absolute/path/to/TCW`.
320
+ Start a new Pi session, then run `/skill:setup` to install or check the `tcw`
321
+ CLI. You can also install it yourself with `pipx install tcw-cli`.
322
+ Invoke skills with `/skill:work`, `/skill:capabilities`, or `/skill:taxonomy`.
323
+
324
+ Pi loads the same skills through the official `pi` declaration in `package.json`.
325
+ It does not run TCW's Claude session-start hook or shell injections; the skills
326
+ provide explicit commands for setup, version checks, and lifecycle instructions.
327
+ Claude's custom review agents are not installed as Pi agents. When delegation
328
+ is unavailable, run ordinary lifecycle stages in the main session; autonomous
329
+ work still requires the advisors named by that workflow.
330
+ Git installation also installs the repository's Node package dependencies,
331
+ which support the TCW web app; local-path installation uses the checkout directly.
332
+
333
+ The plugin ships the skills and Claude Code read-only review agents described in
313
334
  [Skills and Agents](#skills-and-agents).
314
335
 
315
336
  ### CLI
@@ -940,7 +961,7 @@ resolve, what has to be true before an item completes. What a command cannot
940
961
  decide (what a request really asks for, whether a spec is good enough, whether
941
962
  the work is finished) is judgment, and the plugin's skills guide an agent through
942
963
  it. Skills name `tcw` commands and never reimplement them. Every entry point is a
943
- skill, so they work the same way under Claude Code and Codex.
964
+ skill, with the same CLI-backed lifecycle under Claude Code, Codex, and Pi.
944
965
 
945
966
  The skills for a single axis are listed in that axis's section above. These cut
946
967
  across the axes.
@@ -300,7 +300,9 @@ def test_the_authorization_header_is_built_from_the_named_variables(monkeypatch)
300
300
  captured = {}
301
301
 
302
302
  def fake_urlopen(request, timeout=None):
303
- captured["headers"] = dict(request.headers)
303
+ # `header_items()` rather than `headers`: the authorization header is
304
+ # an unredirected one, which `headers` does not include.
305
+ captured["headers"] = dict(request.header_items())
304
306
  captured["timeout"] = timeout
305
307
  captured["url"] = request.full_url
306
308
 
@@ -501,3 +503,63 @@ def test_a_server_that_drops_the_connection_is_unavailable_not_a_crash():
501
503
  finally:
502
504
  thread.join(timeout=5)
503
505
  listener.close()
506
+
507
+
508
+ def test_a_redirect_to_another_host_does_not_carry_the_credentials():
509
+ """urllib copies every header added with `add_header` onto the request a
510
+ redirect produces, whatever host it points at. So the authorization header has
511
+ to be an unredirected one, or a redirect from the tracker (or anything between
512
+ it and us) to another host receives the user's email and API token. Two real
513
+ local servers: the first answers 302 to the second, under a different host
514
+ name and port, and the second records what it was sent."""
515
+ import http.server
516
+ import threading
517
+
518
+ seen = {}
519
+
520
+ def handler(name, answer):
521
+ class Handler(http.server.BaseHTTPRequestHandler):
522
+ def do_GET(self):
523
+ seen[name] = self.headers.get("Authorization")
524
+ answer(self)
525
+
526
+ def log_message(self, *args):
527
+ pass
528
+ return Handler
529
+
530
+ def ok(request_handler):
531
+ body = b"{}"
532
+ request_handler.send_response(200)
533
+ request_handler.send_header("Content-Type", "application/json")
534
+ request_handler.send_header("Content-Length", str(len(body)))
535
+ request_handler.end_headers()
536
+ request_handler.wfile.write(body)
537
+
538
+ other = http.server.HTTPServer(("127.0.0.1", 0), handler("other", ok))
539
+ other_port = other.server_address[1]
540
+
541
+ def redirect(request_handler):
542
+ request_handler.send_response(302)
543
+ request_handler.send_header(
544
+ "Location", f"http://localhost:{other_port}/rest/api/3/myself")
545
+ request_handler.send_header("Content-Length", "0")
546
+ request_handler.end_headers()
547
+
548
+ tracker = http.server.HTTPServer(("127.0.0.1", 0), handler("tracker", redirect))
549
+ servers = (tracker, other)
550
+ threads = [threading.Thread(target=s.serve_forever, daemon=True) for s in servers]
551
+ for thread in threads:
552
+ thread.start()
553
+ try:
554
+ config = dataclasses.replace(
555
+ CONFIG, base_url=f"http://127.0.0.1:{tracker.server_address[1]}",
556
+ timeout_seconds=5)
557
+ jira.JiraClient(config).myself()
558
+ finally:
559
+ for server in servers:
560
+ server.shutdown()
561
+ server.server_close()
562
+
563
+ assert seen["tracker"] is not None and seen["tracker"].startswith("Basic ")
564
+ assert "other" in seen, "the redirect was never followed"
565
+ assert seen["other"] is None
@@ -1 +0,0 @@
1
- __version__ = "2.8.1"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes