tcw-cli 2.1.3__tar.gz → 2.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.
- {tcw_cli-2.1.3/tcw_cli.egg-info → tcw_cli-2.2.0}/PKG-INFO +153 -42
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/README.md +152 -41
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/pyproject.toml +1 -1
- tcw_cli-2.2.0/tcw/__init__.py +1 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/capabilities/cli.py +12 -8
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/serve/__init__.py +41 -0
- tcw_cli-2.1.3/tcw/serve/dist/client/assets/index-Dz5B7M8G.js → tcw_cli-2.2.0/tcw/serve/dist/client/assets/index-CCjF_dHr.js +24 -24
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/serve/dist/client/index.html +1 -1
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/store/base.py +306 -5
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/store/fs.py +48 -3
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/taxonomy/cli.py +9 -7
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/tracker/intake.py +87 -65
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/tracker/jira.py +30 -0
- tcw_cli-2.2.0/tcw/tracker/progress.py +163 -0
- tcw_cli-2.2.0/tcw/tracker/sync.py +410 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/cli.py +595 -87
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/projection.py +63 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0/tcw_cli.egg-info}/PKG-INFO +153 -42
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw_cli.egg-info/SOURCES.txt +12 -1
- tcw_cli-2.2.0/tests/test_cli_help_coverage.py +55 -0
- tcw_cli-2.2.0/tests/test_configuration_text_home.py +61 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_documentation_config.py +2 -1
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_documentation_sync_wiring.py +24 -24
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_eval_fixture.py +1 -1
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_eval_grading.py +51 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_plugin_manifests.py +1 -1
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_repo_lifecycle.py +3 -1
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_skill_lifecycle_parity.py +133 -56
- tcw_cli-2.2.0/tests/test_skill_path_pointers.py +25 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_binding.py +27 -6
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_client.py +25 -0
- tcw_cli-2.2.0/tests/test_tracker_comment.py +550 -0
- tcw_cli-2.2.0/tests/test_tracker_help.py +88 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_import.py +2 -3
- tcw_cli-2.2.0/tests/test_tracker_link.py +295 -0
- tcw_cli-2.2.0/tests/test_tracker_strict.py +714 -0
- tcw_cli-2.2.0/tests/test_tracker_surface.py +405 -0
- tcw_cli-2.2.0/tests/test_tracker_sync.py +965 -0
- tcw_cli-2.2.0/tests/test_tracker_sync_config.py +113 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_validate.py +7 -5
- tcw_cli-2.1.3/tcw/__init__.py +0 -1
- tcw_cli-2.1.3/tests/test_tracker_link.py +0 -192
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/LICENSE +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/setup.cfg +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/capabilities/__init__.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/cli.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/refs.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/serve/dist/client/assets/index-CXNiOIeg.css +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/serve/dist/client/theme-init.js +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/serve/dist/server.cjs +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/serve/runtime.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/stdin.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/store/__init__.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/store/checkouts.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/store/project.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/taxonomy/__init__.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/tracker/__init__.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/tracker/claim.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/validate.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/__init__.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/generate.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/hooks.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/implement.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/inbox.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/plan.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/postmortem.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/request.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/spec.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/prompts/verify.md +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/recursion.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/resolve.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw/work/templates.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw_cli.egg-info/dependency_links.txt +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw_cli.egg-info/entry_points.txt +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw_cli.egg-info/requires.txt +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tcw_cli.egg-info/top_level.txt +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_body_prompt.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_capabilities.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_capabilities_federation.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_capabilities_reset.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_capabilities_rm.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_capabilities_sidecar.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_capability_ref_wording.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_committed_paths.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_cut_version.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_documentation_prompt.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_documented_cli_surface.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_environment_hardness.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_epic_completable.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_eval_coverage.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_eval_files_changed.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_eval_runner.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_external_work_store.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_falsification_rule.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_generate_hook.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_inbox_title.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_lifecycle_baseline.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_lifecycle_hooks.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_lifecycle_inert.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_lifecycle_policy.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_lifecycle_validation.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_multiproject.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_non_git_writes.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_project_overrides.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_project_registry.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_projection.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_prompt_fallback.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_qualified_ref.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_recursion.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_refs.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_remote_session_setup.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_resolve.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_retention.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_scaffold.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_serve.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_serve_descendants.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_serve_projection.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_serve_resolve.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_serve_runtime.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_serve_write.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_session_bootstrap.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_shipped_prompts.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_show_json.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_skill_flow.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_smoke.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_stage_verb.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_status_parity.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_stdin.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_stdin_cli.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_store_bounds.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_store_editor.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_store_nodes.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_store_provisioning.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_store_publication.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_subprocess_stdin.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_taxonomy.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tombstone.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_absent.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_claim.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_claimability.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_cli.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_config.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_inheritance.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_tracker_replay.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_unpushed_version_script.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_validate.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_validate_target.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_work.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_work_autocommit.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_work_review.py +0 -0
- {tcw_cli-2.1.3 → tcw_cli-2.2.0}/tests/test_work_tags.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tcw-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
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
|
|
@@ -247,7 +247,7 @@ other's content.
|
|
|
247
247
|
- [Documentation](#documentation)
|
|
248
248
|
- [Skills — the judgment layer](#skills--the-judgment-layer)
|
|
249
249
|
- [Reading a lifecycle stage](#reading-a-lifecycle-stage)
|
|
250
|
-
- [Review agents and
|
|
250
|
+
- [Review agents and command skills](#review-agents-and-command-skills)
|
|
251
251
|
- [Status](#status)
|
|
252
252
|
- [Further reading](#further-reading)
|
|
253
253
|
|
|
@@ -430,20 +430,20 @@ by installing `tcw-cli` from PyPI with `pipx`, so one installed mid-session
|
|
|
430
430
|
cannot run until the next one begins. That first session needs network access. It
|
|
431
431
|
installs over an existing `pipx install tcw-cli` rather than beside it, and
|
|
432
432
|
leaves a development checkout (`pip install -e .`) alone. If `tcw` goes missing
|
|
433
|
-
anyway, `pipx install tcw-cli` is the whole fix — the **`tcw-
|
|
433
|
+
anyway, `pipx install tcw-cli` is the whole fix — the **`tcw-setup`** skill
|
|
434
434
|
carries the cases where it is not.
|
|
435
435
|
|
|
436
|
-
In **Codex
|
|
436
|
+
In **Codex**:
|
|
437
437
|
|
|
438
438
|
```bash
|
|
439
439
|
codex plugin marketplace add brocef/TCW --ref main
|
|
440
440
|
codex plugin add tcw@tcw
|
|
441
441
|
```
|
|
442
442
|
|
|
443
|
-
Codex has no session-start hook, so ask the agent to run the **`tcw-
|
|
444
|
-
|
|
443
|
+
Codex has no session-start hook, so ask the agent to run the **`tcw-setup`**
|
|
444
|
+
skill — it runs the same install script Claude runs automatically.
|
|
445
445
|
|
|
446
|
-
The plugin ships the agent skills,
|
|
446
|
+
The plugin ships the agent skills, command skills, and read-only review agents
|
|
447
447
|
listed under [Skills](#skills--the-judgment-layer).
|
|
448
448
|
|
|
449
449
|
### As a Python package
|
|
@@ -565,8 +565,10 @@ projects. Each component group also has its own `init`: `tcw taxonomy init`,
|
|
|
565
565
|
`tcw capabilities init`, `tcw work init`.
|
|
566
566
|
|
|
567
567
|
To bootstrap a taxonomy or capabilities ledger on a project that already has a
|
|
568
|
-
codebase,
|
|
569
|
-
|
|
568
|
+
codebase, ask for the `tcw-setup` skill — the assistant studies your code,
|
|
569
|
+
proposes a first draft, refines it with you, and writes it. To change a working
|
|
570
|
+
project's configuration afterwards — documentation entries, lifecycle bindings,
|
|
571
|
+
a tracker, where stores live — ask for the `tcw-configure` skill.
|
|
570
572
|
|
|
571
573
|
---
|
|
572
574
|
|
|
@@ -579,8 +581,9 @@ a work item.
|
|
|
579
581
|
tcw work tracker list # tickets the configured query selects
|
|
580
582
|
tcw work tracker show ENG-482 # one ticket, and whether it is yours to take
|
|
581
583
|
tcw work tracker import ENG-482 # take the ticket and get a work item for it
|
|
582
|
-
tcw work tracker link <slug> ENG-482 #
|
|
584
|
+
tcw work tracker link <slug> ENG-482 # record that an item and a ticket are the same work
|
|
583
585
|
tcw work tracker unlink <slug> --reason "wrong ticket"
|
|
586
|
+
tcw work tracker sync --all # retry tickets that did not follow their items
|
|
584
587
|
```
|
|
585
588
|
|
|
586
589
|
Configuration goes in the node's `tcw-config.yaml`:
|
|
@@ -596,6 +599,11 @@ work:
|
|
|
596
599
|
token-env: TCW_JIRA_API_TOKEN
|
|
597
600
|
transitions:
|
|
598
601
|
claim: Start Progress
|
|
602
|
+
statuses: # optional: where a bound ticket goes as its item moves
|
|
603
|
+
active: In Progress
|
|
604
|
+
review: In Review
|
|
605
|
+
completed: Done
|
|
606
|
+
discarded: Won't Do
|
|
599
607
|
timeout-seconds: 15 # optional
|
|
600
608
|
```
|
|
601
609
|
|
|
@@ -654,14 +662,113 @@ refused, and so is one that is already closed.
|
|
|
654
662
|
Running `import` again for the same ticket in the same node gives you the same item
|
|
655
663
|
rather than a second one, and if the first run took the ticket but stopped before creating the
|
|
656
664
|
item, the second run finishes the job. One ticket can deliberately become several
|
|
657
|
-
items with `--part api`, `--part web`, and so on.
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
665
|
+
items with `--part api`, `--part web`, and so on.
|
|
666
|
+
|
|
667
|
+
**Recording that a ticket and an item are the same work.** `tracker link` is the
|
|
668
|
+
other half, and it does only that: it writes the cross-reference down and leaves
|
|
669
|
+
Jira alone. The ticket keeps its status and whoever holds it — you can link a ticket
|
|
670
|
+
somebody else is assigned, because writing a note about a ticket takes it from
|
|
671
|
+
nobody. On your side nothing but the binding is written, so the item keeps its
|
|
672
|
+
status, its owner and its documents. Any item can be linked, a finished one
|
|
673
|
+
included, which is how work that is already done gets tied to the ticket that
|
|
674
|
+
tracked it; the same goes for `unlink`, so a binding pointed at the wrong ticket is
|
|
675
|
+
repairable wherever you find it. A finished item's folder is kept out of git by
|
|
676
|
+
default, so a binding on one stays on your machine along with the rest of that
|
|
677
|
+
item. `unlink` keeps a record of what was bound and your
|
|
678
|
+
reason, and like `link` it never changes the ticket in Jira.
|
|
679
|
+
|
|
680
|
+
**Seeing which ticket an item answers.** A bound item says so wherever you read it:
|
|
681
|
+
`tcw work show` adds a `tracker:` line with the ticket, the provider, the part and
|
|
682
|
+
the ticket's link; its row on `tcw work list` ends with the ticket key, and notes the part and anything
|
|
683
|
+
not yet sent to the ticket; `tcw work show
|
|
684
|
+
--json` carries it as `tracker`; and `tcw serve`'s item page shows the ticket as a
|
|
685
|
+
link. What you see is what the binding records, not what Jira says right now, so
|
|
686
|
+
none of it needs the tracker configured or reachable. A binding file that cannot be
|
|
687
|
+
read is reported in the same places instead of breaking the board.
|
|
688
|
+
|
|
689
|
+
**Tickets follow their items.** `link` claims nothing, so `tcw work start` does:
|
|
690
|
+
starting a bound item claims its ticket by the same rules `import` uses. After that,
|
|
691
|
+
`submit`, `rework`, `complete` and discarding move the ticket to the status you map
|
|
692
|
+
the item's new status to under `statuses` (`discarded` can name a status per
|
|
693
|
+
resolution, such as `duplicate: Duplicate`); a status you leave out sends nothing,
|
|
694
|
+
and `active` is required once you map any other. `import` on a ticket that is only
|
|
695
|
+
linked still refuses rather than claiming it.
|
|
696
|
+
|
|
697
|
+
TCW moves a ticket only when it is assigned to you and is still where the item's
|
|
698
|
+
previous status left it. A ticket someone else holds, one moved on in Jira, or one
|
|
699
|
+
whose workflow does not offer a single transition to the mapped status is left
|
|
700
|
+
alone. Your local move always happens and is committed first; when the ticket does
|
|
701
|
+
not follow, the command exits 1, says the item moved, and records why — *pending*
|
|
702
|
+
when Jira could not be reached or your credentials are missing, *conflicting* when
|
|
703
|
+
Jira's answer stopped it. `tcw work show` and `tcw work list` show that state, and
|
|
704
|
+
`tcw work tracker sync <slug>` (or `--all`) retries it once the cause is fixed. `sync`
|
|
705
|
+
acts only on items you started, because it acts as whoever runs it. A ticket that
|
|
706
|
+
followed first time leaves no record and no change in your repository.
|
|
707
|
+
|
|
708
|
+
Two things are not caught: a move made in `tcw serve`, and a command interrupted
|
|
709
|
+
between its commit and its call to Jira, leave no record, so the board shows them as
|
|
710
|
+
in step; `sync <slug>` checks such an item but will not move its ticket. And a
|
|
711
|
+
binding whose ticket link is on a different Jira site from the one configured is
|
|
712
|
+
never written through — `import` and `link` refuse it and name the item.
|
|
713
|
+
|
|
714
|
+
Five limits to know. A ticket bound to several parts moves only when the last open
|
|
715
|
+
part here moves; parts in other nodes are not seen. On a workflow that lets anyone start a ticket from any status,
|
|
716
|
+
two people can both take the same ticket, and TCW does not stop that outside strict
|
|
717
|
+
mode (below). Two runs by the
|
|
718
|
+
same Jira account at the same moment can both create an item. Each node keeps its
|
|
663
719
|
own bindings: importing one ticket in two nodes of a workspace, even nodes sharing
|
|
664
|
-
inherited settings, gives two items, one in each.
|
|
720
|
+
inherited settings, gives two items, one in each. And a ticket held by a finished
|
|
721
|
+
item can be bound to a second item, open or finished, with no warning — a discarded
|
|
722
|
+
item's ticket is meant to be available again, and TCW cannot tell that case from the
|
|
723
|
+
other.
|
|
724
|
+
|
|
725
|
+
**Comments on the ticket.** Set `comments: true` in the `tracker` block and each
|
|
726
|
+
move also leaves a short comment on the ticket, such as
|
|
727
|
+
`TCW: "Checkout page" (part api) went to review.`, for anyone who follows the work
|
|
728
|
+
in Jira rather than in the repository. A `link` template adds a link, for example
|
|
729
|
+
`link: https://tcw.example.com/work/{slug}` for a team that hosts `tcw serve`; the
|
|
730
|
+
only placeholders are `{project}` and `{slug}`. Nothing from `spec.md`, `plan.md` or
|
|
731
|
+
the other lifecycle documents is ever copied. A comment is posted only while the
|
|
732
|
+
ticket is assigned to you, and a ticket held by someone else gets none. When a
|
|
733
|
+
comment cannot be posted, the command exits 1, `show` prints a `tracker comment:`
|
|
734
|
+
line, and `tcw work tracker sync` sends it later. Before resending, it looks for the
|
|
735
|
+
comment on the ticket, so a post that landed without an answer is not repeated.
|
|
736
|
+
Limits: a newer move's comment replaces one still waiting; two runs at once, or an
|
|
737
|
+
edited or deleted comment, can still give a repeat; moves in `tcw serve` post
|
|
738
|
+
nothing. On a Jira Service Management project a comment may be visible to
|
|
739
|
+
customers, so leave comments off there unless item titles may be seen. Every copy
|
|
740
|
+
of `tcw` on the project must understand these keys before you set them: an older
|
|
741
|
+
one treats the whole `tracker` block as broken.
|
|
742
|
+
|
|
743
|
+
**Strict mode: no work without a ticket.** Set `strict: true` in the `tracker` block
|
|
744
|
+
when every piece of work must come from a ticket you have claimed. Then:
|
|
745
|
+
|
|
746
|
+
- `tcw work new` and `tcw work inbox accept` refuse and point you at
|
|
747
|
+
`tcw work tracker import <ticket>`. `new --epic` is allowed; epics are never gated.
|
|
748
|
+
- `tcw work start` refuses an item with no ticket. For a bound item it claims the
|
|
749
|
+
ticket *first*, and starts the item only if the claim worked.
|
|
750
|
+
- `submit`, `rework` and completing as `done` read the ticket first and refuse unless
|
|
751
|
+
it is assigned to you and is where the item's last step left it. A `--worktree`
|
|
752
|
+
item is checked before anything is merged.
|
|
753
|
+
- A claim on a workflow that would let a second person claim the same ticket is
|
|
754
|
+
refused, by `start` and by `import`; the ticket is left claimed for you to release.
|
|
755
|
+
- An epic can be created and started, since it only groups work, but not with
|
|
756
|
+
`--worktree`.
|
|
757
|
+
- A ticket shared by several parts is recognised only from the parts' items in
|
|
758
|
+
this checkout. If the part that held the ticket back was completed elsewhere, or
|
|
759
|
+
was not kept (`work.retain`), the last part's `complete` is refused; put the
|
|
760
|
+
ticket in the status the message names, or discard.
|
|
761
|
+
- Discarding is always allowed. `drop` refuses an item that was ever bound — discard
|
|
762
|
+
it instead, so the record stays.
|
|
763
|
+
- `tcw serve` refuses the same changes, since it cannot check a ticket, and names the
|
|
764
|
+
command to use.
|
|
765
|
+
|
|
766
|
+
A refusal changes nothing in your project and says what to fix; a `start` or `import`
|
|
767
|
+
refused after claiming leaves the ticket claimed. There is no flag to get past it;
|
|
768
|
+
`--force` and `--take-over` do not. Strict mode needs Jira: while it cannot be
|
|
769
|
+
reached, gated commands refuse. It also needs `statuses.active`,
|
|
770
|
+
`statuses.completed` and a `statuses.discarded` covering every discard reason, which
|
|
771
|
+
`tcw validate` checks. To turn it off, set `strict: false` or remove the key.
|
|
665
772
|
|
|
666
773
|
Two guarantees worth stating plainly. A project with no `tracker` block behaves
|
|
667
774
|
exactly as before, with no new required setting and no network access. And
|
|
@@ -691,48 +798,52 @@ Every command group also has `--help`, and a `check` that validates its tree.
|
|
|
691
798
|
## Skills — the judgment layer
|
|
692
799
|
|
|
693
800
|
The CLI is the _mechanism_. Fifteen skills in [`skills/`](skills/) supply the
|
|
694
|
-
_judgment_ that drives it — the parts a deterministic tool cannot decide.
|
|
695
|
-
|
|
696
|
-
|
|
801
|
+
_judgment_ that drives it — the parts a deterministic tool cannot decide. They
|
|
802
|
+
come in three groups, told apart by name: eight core skills (seven in the table
|
|
803
|
+
below, and `tcw-work-stage`, which composes a lifecycle stage and is described
|
|
804
|
+
after it), four `tcw-commands-*` skills for the everyday workflow, and three
|
|
805
|
+
optional `tcw-extras-*` skills.
|
|
697
806
|
|
|
698
807
|
| Skill | What it does |
|
|
699
808
|
| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
700
809
|
| [`tcw-work`](skills/tcw-work/SKILL.md) | Plans a request through spec and plan, drives implementation and verification, triages the inbox, runs the lifecycle, decomposes epics, searches the board |
|
|
701
810
|
| [`tcw-capabilities`](skills/tcw-capabilities/SKILL.md) | The capability-delta planning check, contradiction detection, and the ledger flip at completion |
|
|
702
|
-
| [`tcw-taxonomy`](skills/tcw-taxonomy/SKILL.md) | Declaring vocabulary and features, linking them, and
|
|
703
|
-
| [`tcw-
|
|
704
|
-
| [`tcw-
|
|
705
|
-
| [`tcw-triage-issues`](skills/tcw-triage-issues/SKILL.md) | Sweeps **your** project's GitHub issues and turns the ones worth doing into work items |
|
|
811
|
+
| [`tcw-taxonomy`](skills/tcw-taxonomy/SKILL.md) | Declaring vocabulary and features, linking them, and resolving vocabulary inherited from another project |
|
|
812
|
+
| [`tcw-setup`](skills/tcw-setup/SKILL.md) | Gets TCW working: installs or repairs the CLI, sets up a repository, starts a taxonomy or capabilities ledger |
|
|
813
|
+
| [`tcw-configure`](skills/tcw-configure/SKILL.md) | Changes a project's configuration: lifecycle bindings, Definition of Done, documentation entries, tracker, stores, connected and inherited projects |
|
|
706
814
|
| [`documentation-sync`](skills/documentation-sync/SKILL.md) | Keeps README, changelogs, release notes, and driving skills moving with the code that changes them |
|
|
707
815
|
| [`tcw-post-mortem`](skills/tcw-post-mortem/SKILL.md) | Finds which lifecycle stage could first have caught a problem, once one has surfaced |
|
|
708
|
-
|
|
816
|
+
|
|
817
|
+
**Extras.** `tcw-extras-*` skills are optional, built for one way of working, and not needed to use TCW.
|
|
818
|
+
|
|
819
|
+
| Skill | What it does |
|
|
820
|
+
| ----- | ------------ |
|
|
821
|
+
| [`tcw-extras-autonomous-work`](skills/tcw-extras-autonomous-work/SKILL.md) | Drives work items to completion unattended, consulting two read-only advisors wherever the lifecycle would ask you |
|
|
822
|
+
| [`tcw-extras-triage-issues`](skills/tcw-extras-triage-issues/SKILL.md) | Sweeps **your** project's GitHub issues and turns the ones worth doing into work items |
|
|
823
|
+
| [`tcw-extras-report`](skills/tcw-extras-report/SKILL.md) | Reporting a `tcw` bug or suggestion upstream to [this project's issues](https://github.com/brocef/TCW/issues) |
|
|
709
824
|
|
|
710
825
|
They name `tcw` commands and never reimplement tool logic: mechanism stays in the
|
|
711
826
|
binary, judgment stays in the skills.
|
|
712
827
|
|
|
713
828
|
### Reading a lifecycle stage
|
|
714
829
|
|
|
715
|
-
|
|
716
|
-
and the instructions your project resolves for it,
|
|
717
|
-
file you open and a command you run separately.
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
the stage id, so it reaches all seven stages including `inbox` and `postmortem`.
|
|
722
|
-
The other five bake their stage in and ask only for the work item, which is
|
|
723
|
-
optional: `tcw-work-stage-request`, `tcw-work-stage-spec`,
|
|
724
|
-
`tcw-work-stage-plan`, `tcw-work-stage-implement`, `tcw-work-stage-verify`.
|
|
830
|
+
One more skill, [`tcw-work-stage`](skills/tcw-work-stage/SKILL.md), hands you a
|
|
831
|
+
stage's own working document and the instructions your project resolves for it,
|
|
832
|
+
as a single read rather than a file you open and a command you run separately.
|
|
833
|
+
It takes the stage id and the work item, so it reaches all seven stages
|
|
834
|
+
including `inbox` and `postmortem`, under Claude and Codex alike. It only reads
|
|
835
|
+
— `tcw work stage gate` is still what refuses.
|
|
725
836
|
|
|
726
|
-
### Review agents and
|
|
837
|
+
### Review agents and command skills
|
|
727
838
|
|
|
728
839
|
Three read-only review agents ship alongside them — `tcw-verifier`,
|
|
729
840
|
`tcw-backlog-auditor`, and `tcw-post-mortem`, which accelerates the skill of the
|
|
730
|
-
same name
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
841
|
+
same name. Four command skills carry the everyday workflows:
|
|
842
|
+
`tcw-commands-plan-work`, `tcw-commands-drive-work-to-completion`,
|
|
843
|
+
`tcw-commands-verify-work` and `tcw-commands-process-inbox`. The three extras,
|
|
844
|
+
`tcw-extras-autonomous-work`, `tcw-extras-triage-issues` and
|
|
845
|
+
`tcw-extras-report`, are optional. Under Claude and Codex alike, every entry
|
|
846
|
+
point is a skill.
|
|
736
847
|
|
|
737
848
|
---
|
|
738
849
|
|
|
@@ -31,7 +31,7 @@ other's content.
|
|
|
31
31
|
- [Documentation](#documentation)
|
|
32
32
|
- [Skills — the judgment layer](#skills--the-judgment-layer)
|
|
33
33
|
- [Reading a lifecycle stage](#reading-a-lifecycle-stage)
|
|
34
|
-
- [Review agents and
|
|
34
|
+
- [Review agents and command skills](#review-agents-and-command-skills)
|
|
35
35
|
- [Status](#status)
|
|
36
36
|
- [Further reading](#further-reading)
|
|
37
37
|
|
|
@@ -214,20 +214,20 @@ by installing `tcw-cli` from PyPI with `pipx`, so one installed mid-session
|
|
|
214
214
|
cannot run until the next one begins. That first session needs network access. It
|
|
215
215
|
installs over an existing `pipx install tcw-cli` rather than beside it, and
|
|
216
216
|
leaves a development checkout (`pip install -e .`) alone. If `tcw` goes missing
|
|
217
|
-
anyway, `pipx install tcw-cli` is the whole fix — the **`tcw-
|
|
217
|
+
anyway, `pipx install tcw-cli` is the whole fix — the **`tcw-setup`** skill
|
|
218
218
|
carries the cases where it is not.
|
|
219
219
|
|
|
220
|
-
In **Codex
|
|
220
|
+
In **Codex**:
|
|
221
221
|
|
|
222
222
|
```bash
|
|
223
223
|
codex plugin marketplace add brocef/TCW --ref main
|
|
224
224
|
codex plugin add tcw@tcw
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
-
Codex has no session-start hook, so ask the agent to run the **`tcw-
|
|
228
|
-
|
|
227
|
+
Codex has no session-start hook, so ask the agent to run the **`tcw-setup`**
|
|
228
|
+
skill — it runs the same install script Claude runs automatically.
|
|
229
229
|
|
|
230
|
-
The plugin ships the agent skills,
|
|
230
|
+
The plugin ships the agent skills, command skills, and read-only review agents
|
|
231
231
|
listed under [Skills](#skills--the-judgment-layer).
|
|
232
232
|
|
|
233
233
|
### As a Python package
|
|
@@ -349,8 +349,10 @@ projects. Each component group also has its own `init`: `tcw taxonomy init`,
|
|
|
349
349
|
`tcw capabilities init`, `tcw work init`.
|
|
350
350
|
|
|
351
351
|
To bootstrap a taxonomy or capabilities ledger on a project that already has a
|
|
352
|
-
codebase,
|
|
353
|
-
|
|
352
|
+
codebase, ask for the `tcw-setup` skill — the assistant studies your code,
|
|
353
|
+
proposes a first draft, refines it with you, and writes it. To change a working
|
|
354
|
+
project's configuration afterwards — documentation entries, lifecycle bindings,
|
|
355
|
+
a tracker, where stores live — ask for the `tcw-configure` skill.
|
|
354
356
|
|
|
355
357
|
---
|
|
356
358
|
|
|
@@ -363,8 +365,9 @@ a work item.
|
|
|
363
365
|
tcw work tracker list # tickets the configured query selects
|
|
364
366
|
tcw work tracker show ENG-482 # one ticket, and whether it is yours to take
|
|
365
367
|
tcw work tracker import ENG-482 # take the ticket and get a work item for it
|
|
366
|
-
tcw work tracker link <slug> ENG-482 #
|
|
368
|
+
tcw work tracker link <slug> ENG-482 # record that an item and a ticket are the same work
|
|
367
369
|
tcw work tracker unlink <slug> --reason "wrong ticket"
|
|
370
|
+
tcw work tracker sync --all # retry tickets that did not follow their items
|
|
368
371
|
```
|
|
369
372
|
|
|
370
373
|
Configuration goes in the node's `tcw-config.yaml`:
|
|
@@ -380,6 +383,11 @@ work:
|
|
|
380
383
|
token-env: TCW_JIRA_API_TOKEN
|
|
381
384
|
transitions:
|
|
382
385
|
claim: Start Progress
|
|
386
|
+
statuses: # optional: where a bound ticket goes as its item moves
|
|
387
|
+
active: In Progress
|
|
388
|
+
review: In Review
|
|
389
|
+
completed: Done
|
|
390
|
+
discarded: Won't Do
|
|
383
391
|
timeout-seconds: 15 # optional
|
|
384
392
|
```
|
|
385
393
|
|
|
@@ -438,14 +446,113 @@ refused, and so is one that is already closed.
|
|
|
438
446
|
Running `import` again for the same ticket in the same node gives you the same item
|
|
439
447
|
rather than a second one, and if the first run took the ticket but stopped before creating the
|
|
440
448
|
item, the second run finishes the job. One ticket can deliberately become several
|
|
441
|
-
items with `--part api`, `--part web`, and so on.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
449
|
+
items with `--part api`, `--part web`, and so on.
|
|
450
|
+
|
|
451
|
+
**Recording that a ticket and an item are the same work.** `tracker link` is the
|
|
452
|
+
other half, and it does only that: it writes the cross-reference down and leaves
|
|
453
|
+
Jira alone. The ticket keeps its status and whoever holds it — you can link a ticket
|
|
454
|
+
somebody else is assigned, because writing a note about a ticket takes it from
|
|
455
|
+
nobody. On your side nothing but the binding is written, so the item keeps its
|
|
456
|
+
status, its owner and its documents. Any item can be linked, a finished one
|
|
457
|
+
included, which is how work that is already done gets tied to the ticket that
|
|
458
|
+
tracked it; the same goes for `unlink`, so a binding pointed at the wrong ticket is
|
|
459
|
+
repairable wherever you find it. A finished item's folder is kept out of git by
|
|
460
|
+
default, so a binding on one stays on your machine along with the rest of that
|
|
461
|
+
item. `unlink` keeps a record of what was bound and your
|
|
462
|
+
reason, and like `link` it never changes the ticket in Jira.
|
|
463
|
+
|
|
464
|
+
**Seeing which ticket an item answers.** A bound item says so wherever you read it:
|
|
465
|
+
`tcw work show` adds a `tracker:` line with the ticket, the provider, the part and
|
|
466
|
+
the ticket's link; its row on `tcw work list` ends with the ticket key, and notes the part and anything
|
|
467
|
+
not yet sent to the ticket; `tcw work show
|
|
468
|
+
--json` carries it as `tracker`; and `tcw serve`'s item page shows the ticket as a
|
|
469
|
+
link. What you see is what the binding records, not what Jira says right now, so
|
|
470
|
+
none of it needs the tracker configured or reachable. A binding file that cannot be
|
|
471
|
+
read is reported in the same places instead of breaking the board.
|
|
472
|
+
|
|
473
|
+
**Tickets follow their items.** `link` claims nothing, so `tcw work start` does:
|
|
474
|
+
starting a bound item claims its ticket by the same rules `import` uses. After that,
|
|
475
|
+
`submit`, `rework`, `complete` and discarding move the ticket to the status you map
|
|
476
|
+
the item's new status to under `statuses` (`discarded` can name a status per
|
|
477
|
+
resolution, such as `duplicate: Duplicate`); a status you leave out sends nothing,
|
|
478
|
+
and `active` is required once you map any other. `import` on a ticket that is only
|
|
479
|
+
linked still refuses rather than claiming it.
|
|
480
|
+
|
|
481
|
+
TCW moves a ticket only when it is assigned to you and is still where the item's
|
|
482
|
+
previous status left it. A ticket someone else holds, one moved on in Jira, or one
|
|
483
|
+
whose workflow does not offer a single transition to the mapped status is left
|
|
484
|
+
alone. Your local move always happens and is committed first; when the ticket does
|
|
485
|
+
not follow, the command exits 1, says the item moved, and records why — *pending*
|
|
486
|
+
when Jira could not be reached or your credentials are missing, *conflicting* when
|
|
487
|
+
Jira's answer stopped it. `tcw work show` and `tcw work list` show that state, and
|
|
488
|
+
`tcw work tracker sync <slug>` (or `--all`) retries it once the cause is fixed. `sync`
|
|
489
|
+
acts only on items you started, because it acts as whoever runs it. A ticket that
|
|
490
|
+
followed first time leaves no record and no change in your repository.
|
|
491
|
+
|
|
492
|
+
Two things are not caught: a move made in `tcw serve`, and a command interrupted
|
|
493
|
+
between its commit and its call to Jira, leave no record, so the board shows them as
|
|
494
|
+
in step; `sync <slug>` checks such an item but will not move its ticket. And a
|
|
495
|
+
binding whose ticket link is on a different Jira site from the one configured is
|
|
496
|
+
never written through — `import` and `link` refuse it and name the item.
|
|
497
|
+
|
|
498
|
+
Five limits to know. A ticket bound to several parts moves only when the last open
|
|
499
|
+
part here moves; parts in other nodes are not seen. On a workflow that lets anyone start a ticket from any status,
|
|
500
|
+
two people can both take the same ticket, and TCW does not stop that outside strict
|
|
501
|
+
mode (below). Two runs by the
|
|
502
|
+
same Jira account at the same moment can both create an item. Each node keeps its
|
|
447
503
|
own bindings: importing one ticket in two nodes of a workspace, even nodes sharing
|
|
448
|
-
inherited settings, gives two items, one in each.
|
|
504
|
+
inherited settings, gives two items, one in each. And a ticket held by a finished
|
|
505
|
+
item can be bound to a second item, open or finished, with no warning — a discarded
|
|
506
|
+
item's ticket is meant to be available again, and TCW cannot tell that case from the
|
|
507
|
+
other.
|
|
508
|
+
|
|
509
|
+
**Comments on the ticket.** Set `comments: true` in the `tracker` block and each
|
|
510
|
+
move also leaves a short comment on the ticket, such as
|
|
511
|
+
`TCW: "Checkout page" (part api) went to review.`, for anyone who follows the work
|
|
512
|
+
in Jira rather than in the repository. A `link` template adds a link, for example
|
|
513
|
+
`link: https://tcw.example.com/work/{slug}` for a team that hosts `tcw serve`; the
|
|
514
|
+
only placeholders are `{project}` and `{slug}`. Nothing from `spec.md`, `plan.md` or
|
|
515
|
+
the other lifecycle documents is ever copied. A comment is posted only while the
|
|
516
|
+
ticket is assigned to you, and a ticket held by someone else gets none. When a
|
|
517
|
+
comment cannot be posted, the command exits 1, `show` prints a `tracker comment:`
|
|
518
|
+
line, and `tcw work tracker sync` sends it later. Before resending, it looks for the
|
|
519
|
+
comment on the ticket, so a post that landed without an answer is not repeated.
|
|
520
|
+
Limits: a newer move's comment replaces one still waiting; two runs at once, or an
|
|
521
|
+
edited or deleted comment, can still give a repeat; moves in `tcw serve` post
|
|
522
|
+
nothing. On a Jira Service Management project a comment may be visible to
|
|
523
|
+
customers, so leave comments off there unless item titles may be seen. Every copy
|
|
524
|
+
of `tcw` on the project must understand these keys before you set them: an older
|
|
525
|
+
one treats the whole `tracker` block as broken.
|
|
526
|
+
|
|
527
|
+
**Strict mode: no work without a ticket.** Set `strict: true` in the `tracker` block
|
|
528
|
+
when every piece of work must come from a ticket you have claimed. Then:
|
|
529
|
+
|
|
530
|
+
- `tcw work new` and `tcw work inbox accept` refuse and point you at
|
|
531
|
+
`tcw work tracker import <ticket>`. `new --epic` is allowed; epics are never gated.
|
|
532
|
+
- `tcw work start` refuses an item with no ticket. For a bound item it claims the
|
|
533
|
+
ticket *first*, and starts the item only if the claim worked.
|
|
534
|
+
- `submit`, `rework` and completing as `done` read the ticket first and refuse unless
|
|
535
|
+
it is assigned to you and is where the item's last step left it. A `--worktree`
|
|
536
|
+
item is checked before anything is merged.
|
|
537
|
+
- A claim on a workflow that would let a second person claim the same ticket is
|
|
538
|
+
refused, by `start` and by `import`; the ticket is left claimed for you to release.
|
|
539
|
+
- An epic can be created and started, since it only groups work, but not with
|
|
540
|
+
`--worktree`.
|
|
541
|
+
- A ticket shared by several parts is recognised only from the parts' items in
|
|
542
|
+
this checkout. If the part that held the ticket back was completed elsewhere, or
|
|
543
|
+
was not kept (`work.retain`), the last part's `complete` is refused; put the
|
|
544
|
+
ticket in the status the message names, or discard.
|
|
545
|
+
- Discarding is always allowed. `drop` refuses an item that was ever bound — discard
|
|
546
|
+
it instead, so the record stays.
|
|
547
|
+
- `tcw serve` refuses the same changes, since it cannot check a ticket, and names the
|
|
548
|
+
command to use.
|
|
549
|
+
|
|
550
|
+
A refusal changes nothing in your project and says what to fix; a `start` or `import`
|
|
551
|
+
refused after claiming leaves the ticket claimed. There is no flag to get past it;
|
|
552
|
+
`--force` and `--take-over` do not. Strict mode needs Jira: while it cannot be
|
|
553
|
+
reached, gated commands refuse. It also needs `statuses.active`,
|
|
554
|
+
`statuses.completed` and a `statuses.discarded` covering every discard reason, which
|
|
555
|
+
`tcw validate` checks. To turn it off, set `strict: false` or remove the key.
|
|
449
556
|
|
|
450
557
|
Two guarantees worth stating plainly. A project with no `tracker` block behaves
|
|
451
558
|
exactly as before, with no new required setting and no network access. And
|
|
@@ -475,48 +582,52 @@ Every command group also has `--help`, and a `check` that validates its tree.
|
|
|
475
582
|
## Skills — the judgment layer
|
|
476
583
|
|
|
477
584
|
The CLI is the _mechanism_. Fifteen skills in [`skills/`](skills/) supply the
|
|
478
|
-
_judgment_ that drives it — the parts a deterministic tool cannot decide.
|
|
479
|
-
|
|
480
|
-
|
|
585
|
+
_judgment_ that drives it — the parts a deterministic tool cannot decide. They
|
|
586
|
+
come in three groups, told apart by name: eight core skills (seven in the table
|
|
587
|
+
below, and `tcw-work-stage`, which composes a lifecycle stage and is described
|
|
588
|
+
after it), four `tcw-commands-*` skills for the everyday workflow, and three
|
|
589
|
+
optional `tcw-extras-*` skills.
|
|
481
590
|
|
|
482
591
|
| Skill | What it does |
|
|
483
592
|
| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
484
593
|
| [`tcw-work`](skills/tcw-work/SKILL.md) | Plans a request through spec and plan, drives implementation and verification, triages the inbox, runs the lifecycle, decomposes epics, searches the board |
|
|
485
594
|
| [`tcw-capabilities`](skills/tcw-capabilities/SKILL.md) | The capability-delta planning check, contradiction detection, and the ledger flip at completion |
|
|
486
|
-
| [`tcw-taxonomy`](skills/tcw-taxonomy/SKILL.md) | Declaring vocabulary and features, linking them, and
|
|
487
|
-
| [`tcw-
|
|
488
|
-
| [`tcw-
|
|
489
|
-
| [`tcw-triage-issues`](skills/tcw-triage-issues/SKILL.md) | Sweeps **your** project's GitHub issues and turns the ones worth doing into work items |
|
|
595
|
+
| [`tcw-taxonomy`](skills/tcw-taxonomy/SKILL.md) | Declaring vocabulary and features, linking them, and resolving vocabulary inherited from another project |
|
|
596
|
+
| [`tcw-setup`](skills/tcw-setup/SKILL.md) | Gets TCW working: installs or repairs the CLI, sets up a repository, starts a taxonomy or capabilities ledger |
|
|
597
|
+
| [`tcw-configure`](skills/tcw-configure/SKILL.md) | Changes a project's configuration: lifecycle bindings, Definition of Done, documentation entries, tracker, stores, connected and inherited projects |
|
|
490
598
|
| [`documentation-sync`](skills/documentation-sync/SKILL.md) | Keeps README, changelogs, release notes, and driving skills moving with the code that changes them |
|
|
491
599
|
| [`tcw-post-mortem`](skills/tcw-post-mortem/SKILL.md) | Finds which lifecycle stage could first have caught a problem, once one has surfaced |
|
|
492
|
-
|
|
600
|
+
|
|
601
|
+
**Extras.** `tcw-extras-*` skills are optional, built for one way of working, and not needed to use TCW.
|
|
602
|
+
|
|
603
|
+
| Skill | What it does |
|
|
604
|
+
| ----- | ------------ |
|
|
605
|
+
| [`tcw-extras-autonomous-work`](skills/tcw-extras-autonomous-work/SKILL.md) | Drives work items to completion unattended, consulting two read-only advisors wherever the lifecycle would ask you |
|
|
606
|
+
| [`tcw-extras-triage-issues`](skills/tcw-extras-triage-issues/SKILL.md) | Sweeps **your** project's GitHub issues and turns the ones worth doing into work items |
|
|
607
|
+
| [`tcw-extras-report`](skills/tcw-extras-report/SKILL.md) | Reporting a `tcw` bug or suggestion upstream to [this project's issues](https://github.com/brocef/TCW/issues) |
|
|
493
608
|
|
|
494
609
|
They name `tcw` commands and never reimplement tool logic: mechanism stays in the
|
|
495
610
|
binary, judgment stays in the skills.
|
|
496
611
|
|
|
497
612
|
### Reading a lifecycle stage
|
|
498
613
|
|
|
499
|
-
|
|
500
|
-
and the instructions your project resolves for it,
|
|
501
|
-
file you open and a command you run separately.
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
the stage id, so it reaches all seven stages including `inbox` and `postmortem`.
|
|
506
|
-
The other five bake their stage in and ask only for the work item, which is
|
|
507
|
-
optional: `tcw-work-stage-request`, `tcw-work-stage-spec`,
|
|
508
|
-
`tcw-work-stage-plan`, `tcw-work-stage-implement`, `tcw-work-stage-verify`.
|
|
614
|
+
One more skill, [`tcw-work-stage`](skills/tcw-work-stage/SKILL.md), hands you a
|
|
615
|
+
stage's own working document and the instructions your project resolves for it,
|
|
616
|
+
as a single read rather than a file you open and a command you run separately.
|
|
617
|
+
It takes the stage id and the work item, so it reaches all seven stages
|
|
618
|
+
including `inbox` and `postmortem`, under Claude and Codex alike. It only reads
|
|
619
|
+
— `tcw work stage gate` is still what refuses.
|
|
509
620
|
|
|
510
|
-
### Review agents and
|
|
621
|
+
### Review agents and command skills
|
|
511
622
|
|
|
512
623
|
Three read-only review agents ship alongside them — `tcw-verifier`,
|
|
513
624
|
`tcw-backlog-auditor`, and `tcw-post-mortem`, which accelerates the skill of the
|
|
514
|
-
same name
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
625
|
+
same name. Four command skills carry the everyday workflows:
|
|
626
|
+
`tcw-commands-plan-work`, `tcw-commands-drive-work-to-completion`,
|
|
627
|
+
`tcw-commands-verify-work` and `tcw-commands-process-inbox`. The three extras,
|
|
628
|
+
`tcw-extras-autonomous-work`, `tcw-extras-triage-issues` and
|
|
629
|
+
`tcw-extras-report`, are optional. Under Claude and Codex alike, every entry
|
|
630
|
+
point is a skill.
|
|
520
631
|
|
|
521
632
|
---
|
|
522
633
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tcw-cli"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2.0"
|
|
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.2.0"
|
|
@@ -286,38 +286,42 @@ def add_subparser(sub: argparse._SubParsersAction) -> None:
|
|
|
286
286
|
pl.set_defaults(func=_list)
|
|
287
287
|
|
|
288
288
|
ps = g.add_parser("show", help="read a capability by path")
|
|
289
|
-
ps.add_argument("id", metavar="path"
|
|
289
|
+
ps.add_argument("id", metavar="path",
|
|
290
|
+
help="capability path, e.g. web/login (alias-prefixed if inherited)")
|
|
290
291
|
ps.set_defaults(func=_show)
|
|
291
292
|
|
|
292
293
|
g.add_parser("path", help="print the capabilities store folder path").set_defaults(func=_path)
|
|
293
294
|
|
|
294
295
|
pa = g.add_parser("add", help="scaffold a capability folder")
|
|
295
|
-
pa.add_argument("path", metavar="namespace/path"
|
|
296
|
-
|
|
296
|
+
pa.add_argument("path", metavar="namespace/path",
|
|
297
|
+
help="path for the new capability, namespace folder first")
|
|
298
|
+
pa.add_argument("name", nargs="?",
|
|
299
|
+
help="display name (default: titled from the last path segment)")
|
|
297
300
|
pa.add_argument("-s", "--status", default="Missing")
|
|
298
301
|
pa.set_defaults(func=_add)
|
|
299
302
|
|
|
300
303
|
pset = g.add_parser("set", help="update a capability's status/fields in place")
|
|
301
|
-
pset.add_argument("id", metavar="path"
|
|
304
|
+
pset.add_argument("id", metavar="path",
|
|
305
|
+
help="capability path to update; an inherited one gains a local override")
|
|
302
306
|
pset.add_argument("--status", help="shorthand for --field Status=<S>")
|
|
303
307
|
pset.add_argument("--field", action="append", metavar="K=V",
|
|
304
308
|
help="set a metadata field (repeatable; Subject accepts a,b,c)")
|
|
305
309
|
pset.set_defaults(func=_set)
|
|
306
310
|
|
|
307
311
|
prst = g.add_parser("reset", help="drop a local override, re-inheriting upstream")
|
|
308
|
-
prst.add_argument("id", metavar="path")
|
|
312
|
+
prst.add_argument("id", metavar="path", help="path of the local override to drop")
|
|
309
313
|
prst.set_defaults(func=_reset)
|
|
310
314
|
|
|
311
315
|
prm = g.add_parser("rm", help="remove a local capability")
|
|
312
|
-
prm.add_argument("id", metavar="path")
|
|
316
|
+
prm.add_argument("id", metavar="path", help="path of the local capability to remove")
|
|
313
317
|
prm.set_defaults(func=_rm)
|
|
314
318
|
|
|
315
319
|
pse = g.add_parser("search", help="search names + bodies")
|
|
316
|
-
pse.add_argument("query")
|
|
320
|
+
pse.add_argument("query", help="text matched case-insensitively in names + bodies")
|
|
317
321
|
pse.set_defaults(func=_search)
|
|
318
322
|
|
|
319
323
|
pe = g.add_parser("extends", help="federate another project's capabilities")
|
|
320
|
-
pe.add_argument("project_id")
|
|
324
|
+
pe.add_argument("project_id", help="registered project ID whose capabilities to federate")
|
|
321
325
|
pe.add_argument("--rm", action="store_true", help="remove the project instead")
|
|
322
326
|
pe.set_defaults(func=_extends)
|
|
323
327
|
|