team-toon-tack 3.13.0 → 3.14.0

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.
@@ -13,7 +13,7 @@
13
13
  "name": "team-toon-tack",
14
14
  "source": "./",
15
15
  "description": "Linear/Trello task sync & management CLI with commands and skills",
16
- "version": "3.13.0"
16
+ "version": "3.14.0"
17
17
  }
18
18
  ]
19
19
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "team-toon-tack",
3
3
  "description": "Linear/Trello task sync & management CLI for Claude Code - saves tokens vs MCP",
4
- "version": "3.13.0",
4
+ "version": "3.14.0",
5
5
  "author": {
6
6
  "name": "wayne930242",
7
7
  "email": "wayne930242@gmail.com"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-toon-tack",
3
- "version": "3.13.0",
3
+ "version": "3.14.0",
4
4
  "description": "透過 ttt CLI 同步與管理 Linear、Trello 任務。",
5
5
  "author": {
6
6
  "name": "wayne930242"
package/README.md CHANGED
@@ -232,6 +232,13 @@ ttt order export app/2026-11-11-a --handoff # Paste the block into the t
232
232
  glab mr view 900 | ttt order import - # Reads the block out of any text
233
233
  ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0 --dry-run
234
234
  ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0
235
+
236
+ # A ticket pulled out of the train keeps its history
237
+ ttt order return app/2026-11-11-a MP-2 --reason "waits for MP-9" > notice.md # Integrator
238
+ ttt order carry MP-2 --to auto --project app --text notice.md # Coordinator: into the next order
239
+
240
+ # A ticket fixed during integration
241
+ ttt order rework app/2026-11-11-a MP-1 --reason "gate red" # Back to in-progress; a sealed order reopens
235
242
  ```
236
243
 
237
244
  | Command | What it does |
@@ -239,25 +246,31 @@ ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0
239
246
  | `open [<project>/<code>] [--project p] [--reviewer r]` | Open an order. Without an id the code is `<YYYY-MM-DD>-<next letter>`. |
240
247
  | `list [--project p] [--all]` | List orders; closed ones only with `--all`. |
241
248
  | `show <id> [--toon]` | Show an order, or its stored TOON. |
242
- | `set <id> <ticket> [--branch --mr --head --review --tests]` | Record what a worker reported. Each `--tests "<cmd> [@ <sha>] [= <result>]"` appends one run; the SHA defaults to the ticket's head and the result to `pass`. |
249
+ | `set <id> <ticket> [--branch --mr --head --review --tests]` | Record what a worker reported. Each `--tests "<cmd> [@ <sha>] [= <result>]"` appends one run; the SHA defaults to the ticket's head and the result to `pass`. A review is bound to the head it was recorded on. |
243
250
  | `review <id> <ticket>... [--status name]` | Move tickets to the testing status (`status_transitions.testing`, else `dev_testing_status`) and mark them in-review. |
244
251
  | `train <id> [--branch b] [--mr mr]` | Record the train branch and its merge request. |
245
- | `seal <id> --gated-head <sha>` | Fix the batch on the head the gate passed on. Every ticket must be in review or dropped. |
252
+ | `seal <id> --gated-head <sha>` | Fix the batch on the head the gate passed on. Every ticket must be in review, dropped, or returned. |
246
253
  | `drop <id> <ticket> --reason <text>` | Leave a ticket out of the batch. Its remote status is not touched. |
254
+ | `rework <id> <ticket> --reason <text>` | Send an in-review ticket back to in-progress, in the order and at the source (assignee unchanged). A sealed order reopens and its gated head is cleared. |
255
+ | `return <id> <ticket>... --reason <text>` | Writer (normally the integrator): hand tickets back to the coordinator. Marks them returned, moves them to in-progress at the source, and prints a return notice block. Safe to repeat. |
256
+ | `carry <ticket>... --to <id\|auto> [--project p] [--from id \| --text file\|-]` | Coordinator: take tickets into another open order with branch, MR, head, review, and test runs, plus a `carried_from` record. |
247
257
  | `export <id> [--handoff]` | Print the order as a fenced block. `--handoff` makes the local copy read-only. |
248
- | `import <file\|-> [--id id] [--force]` | Take the block from a file or stdin; the importer becomes the writer. |
258
+ | `import <file\|-> [--id id] [--force] [--returns \| --order]` | Take the block from a file or stdin; the importer becomes the writer. A return notice is recorded on the local copy instead, without changing the writer. |
249
259
  | `reclaim <id>` | Take a handed-off order back when it was returned without an export. |
250
260
  | `close <id> --merged <sha> [--version v] [--dry-run]` | Complete every in-review ticket and comment on each. |
251
261
 
252
262
  How an order behaves:
253
263
 
254
264
  - **Storage.** Orders live in `.ttt/orders/<project>/<code>.toon` on the writer's machine and are never committed. Writes are atomic (temp file, then rename) and serialized by a lock per project. The default project is the directory that holds `.ttt`.
255
- - **Stages.** `open` → `sealed` → `merged` → `closed`. A project holds one open order at a time. After the seal, `ttt claim --order auto` opens the next one, and a returned ticket is reworked inside its own order: record the new head with `set`, then `seal` again.
265
+ - **Stages.** `open` → `sealed` → `merged` → `closed`. A project holds one open order at a time. After the seal, `ttt claim --order auto` opens the next one. A ticket fixed inside its order goes through `rework`: the order is `open` again without a gated head, so record the new head with `set`, `review` it, and `seal` again.
266
+ - **Ticket states.** `in-progress`, `in-review`, `dropped`, `returned`, `done`. A dropped or returned ticket is never completed by `close`, does not block `seal` or `close`, and may be taken by another order.
267
+ - **Return and carry.** `return` keeps the ticket's record and adds who returned it, when, and why. The notice it prints (a fenced `toon ttt-return` block) holds the returned tickets' full records. The coordinator's `import` records it on its copy, even a handed-off one, and stays read-only; a text holding both an order block and a notice needs `--returns` or `--order`. `carry` reads the history from a local order (`--from`, else the newest order of the project that holds the ticket) or from a notice or order block in `--text`, and puts the ticket in progress in the destination (`auto`: the project's open order, opened if there is none). A source this machine writes marks the ticket dropped with reason `carried to <order>`. A ticket still held by a writer elsewhere (in progress or in review in a handed-off order) is refused until that writer returns it. `carry` does not change remote statuses.
268
+ - **Stale review.** The head a review was recorded on is stored as `review_head`. When `set --head` moves the head without a new `--review`, `show` marks the review `stale: reviewed <old>, head now <new>` and `seal` warns. Test runs keep the SHA they ran on. Orders written before this field existed are never marked.
256
269
  - **One writer.** Workers report; the coordinator records. `export --handoff` passes the pen to the integrator, and write commands on the handed-off copy refuse with the way back: import the returned copy, or `reclaim`. An import never overwrites a writable local copy without `--force`, and never takes an older revision.
257
- - **Close.** Each in-review ticket goes through the same completion handler as `ttt done`, so `completion_mode` and parent issues apply. Each gets one comment with its MR, the merge commit, the version, and the order id. Dropped tickets are untouched. A ticket canceled at the source, or moved out of review since the seal, stops the close until it is dropped or sent back to review. Close requires the done status: a completion mode that leaves a ticket at testing (`strict_review`, or `upstream_strict` without a parent to take it) fails that ticket and keeps the order merged. A rerun skips what is already done and does not comment twice.
270
+ - **Close.** Each in-review ticket goes through the same completion handler as `ttt done`, so `completion_mode` and parent issues apply. Each gets one comment with its MR, the merge commit, the version, and the order id. Dropped and returned tickets are untouched. A ticket canceled at the source, or moved out of review since the seal, stops the close until it is dropped or sent back to review. Close requires the done status: a completion mode that leaves a ticket at testing (`strict_review`, or `upstream_strict` without a parent to take it) fails that ticket and keeps the order merged. A rerun skips what is already done and does not comment twice.
258
271
  - **Identity.** The writer's name in `owner` and the log is `TTT_ACTOR`, else `<current_user>@<hostname>`.
259
272
 
260
- A ticket rides one order per project at a time: claiming it into a second order of the same project, or having `review` adopt it there, is refused until it is dropped from the first. `review` leaves a Done or Canceled ticket where it is.
273
+ A ticket rides one order per project at a time: claiming or carrying it into a second order of the same project, or having `review` adopt it there, is refused until it is dropped or returned from the first. `review` leaves a Done or Canceled ticket where it is.
261
274
 
262
275
  ### `ttt status`
263
276
 
@@ -299,6 +312,20 @@ Two options widen a `--remote` search beyond what `ttt sync` stores (both need
299
312
  it, because backlog tickets usually belong to no cycle. Trello has no cycles,
300
313
  so there it changes nothing.
301
314
 
315
+ ### `ttt skills` / `ttt skill`
316
+
317
+ Print the agent skill text bundled with this version of the CLI.
318
+ An agent setup installs only a short stub skill that says to run these commands, so the instructions an agent follows always match the installed `ttt`.
319
+
320
+ ```bash
321
+ ttt skills # Bundled skills, their pages, and the ttt version
322
+ ttt skill managing-linear-tasks # The skill; its header lists the pages
323
+ ttt skill managing-linear-tasks orders-coordinator # Work orders: the coordinator's side
324
+ ttt skill managing-linear-tasks orders-integrator # Work orders: the integrator's side
325
+ ```
326
+
327
+ The text lives in `bundled-skills/<name>/index.md` (plus one `<page>.md` per page) inside the package and is read from the installed package's directory, not the working directory.
328
+
302
329
  ### `ttt config`
303
330
 
304
331
  Configure settings.
@@ -374,7 +401,7 @@ Install the plugin for Claude Code integration:
374
401
 
375
402
  ### Auto-Activated Skill
376
403
 
377
- The plugin includes a `managing-linear-tasks` skill that automatically activates when working with tasks, providing workflow guidance and best practices.
404
+ The plugin includes a `managing-linear-tasks` skill that automatically activates when working with tasks. It is a stub: it tells the agent to run `ttt skill managing-linear-tasks`, which prints the full instructions bundled with the installed CLI (see [`ttt skills`](#ttt-skills--ttt-skill)).
378
405
 
379
406
  ## License
380
407
 
package/README.zh-TW.md CHANGED
@@ -226,6 +226,13 @@ ttt order export app/2026-11-11-a --handoff # 把輸出的區塊貼進
226
226
  glab mr view 900 | ttt order import - # 從任何文字中取出工單區塊
227
227
  ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0 --dry-run
228
228
  ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0
229
+
230
+ # 從列車拉下來的票,紀錄跟著走
231
+ ttt order return app/2026-11-11-a MP-2 --reason "等 MP-9" > notice.md # 整合者
232
+ ttt order carry MP-2 --to auto --project app --text notice.md # 協調者:帶進下一張工單
233
+
234
+ # 整合期間要修的票
235
+ ttt order rework app/2026-11-11-a MP-1 --reason "gate 紅燈" # 退回 in-progress;已封的工單重新打開
229
236
  ```
230
237
 
231
238
  | 指令 | 作用 |
@@ -233,25 +240,31 @@ ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0
233
240
  | `open [<project>/<code>] [--project p] [--reviewer r]` | 開工單。不給 id 時,代碼為 `<YYYY-MM-DD>-<下一個字母>`。 |
234
241
  | `list [--project p] [--all]` | 列出工單;加 `--all` 才列已關閉的。 |
235
242
  | `show <id> [--toon]` | 顯示工單,或印出儲存的 TOON。 |
236
- | `set <id> <ticket> [--branch --mr --head --review --tests]` | 記錄 worker 回報的內容。每個 `--tests "<指令> [@ <sha>] [= <結果>]"` 追加一筆測試紀錄;SHA 預設為該票的 head,結果預設為 `pass`。 |
243
+ | `set <id> <ticket> [--branch --mr --head --review --tests]` | 記錄 worker 回報的內容。每個 `--tests "<指令> [@ <sha>] [= <結果>]"` 追加一筆測試紀錄;SHA 預設為該票的 head,結果預設為 `pass`。審查結論綁定記錄當下的 head。 |
237
244
  | `review <id> <ticket>... [--status name]` | 把票改到測試狀態(`status_transitions.testing`,沒有則用 `dev_testing_status`),並在工單標為 in-review。 |
238
245
  | `train <id> [--branch b] [--mr mr]` | 記錄列車分支與它的 MR。 |
239
- | `seal <id> --gated-head <sha>` | 以通過 gate 的 head 封單。每張票都必須已送審或已剔除。 |
246
+ | `seal <id> --gated-head <sha>` | 以通過 gate 的 head 封單。每張票都必須已送審、已剔除或已退回。 |
240
247
  | `drop <id> <ticket> --reason <text>` | 把票從這一批剔除,遠端狀態不動。 |
248
+ | `rework <id> <ticket> --reason <text>` | 把送審中的票退回 in-progress,工單與遠端一起改,指派人不變。已封的工單會重新打開,並清掉 gated head。 |
249
+ | `return <id> <ticket>... --reason <text>` | 寫入者(通常是整合者)把票退回給協調者:標為 returned、遠端改回 in-progress,並印出退回通知區塊。可重複執行。 |
250
+ | `carry <ticket>... --to <id\|auto> [--project p] [--from id \| --text file\|-]` | 協調者把票帶進另一張開著的工單,分支、MR、head、審查結論與測試紀錄一併帶過去,並記下 `carried_from`。 |
241
251
  | `export <id> [--handoff]` | 把工單印成一個 fenced 區塊。加 `--handoff` 後本機這份改為唯讀。 |
242
- | `import <file\|-> [--id id] [--force]` | 從檔案或 stdin 取出區塊;匯入者成為寫入者。 |
252
+ | `import <file\|-> [--id id] [--force] [--returns \| --order]` | 從檔案或 stdin 取出區塊;匯入者成為寫入者。若是退回通知,只記到本機那份工單上,寫入者不變。 |
243
253
  | `reclaim <id>` | 對方退回但沒有匯出時,把已交接的工單收回。 |
244
254
  | `close <id> --merged <sha> [--version v] [--dry-run]` | 完成每張送審中的票,並各留一則留言。 |
245
255
 
246
256
  工單的規則:
247
257
 
248
258
  - **儲存。** 工單存在寫入者機器上的 `.ttt/orders/<project>/<code>.toon`,不進版控。寫入先寫暫存檔再改名,並以每個專案一把鎖排隊。預設專案是 `.ttt` 所在的目錄名稱。
249
- - **階段。** `open` → `sealed` → `merged` → `closed`。一個專案同時只有一張開著的工單。封單之後,`ttt claim --order auto` 會開下一張;被退回的票留在原工單重做:用 `set` 記下新的 head,再 `seal` 一次。
259
+ - **階段。** `open` → `sealed` → `merged` → `closed`。一個專案同時只有一張開著的工單。封單之後,`ttt claim --order auto` 會開下一張。要在原工單內修的票用 `rework`:工單回到 `open`、gated head 清空,接著用 `set` 記下新的 head、`review` 送審,再 `seal` 一次。
260
+ - **票的狀態。** `in-progress`、`in-review`、`dropped`、`returned`、`done`。已剔除或已退回的票不會被 `close` 完成,不會擋住 `seal` 與 `close`,也可以被另一張工單收走。
261
+ - **退回與帶票。** `return` 保留票的紀錄,並記下誰退回、何時、原因。它印出的通知(`toon ttt-return` fenced 區塊)帶著這些票的完整紀錄。協調者 `import` 這份通知時,只記到自己那份工單上,已交接的那份也收,而且維持唯讀;文字裡同時有工單區塊與通知時,要用 `--returns` 或 `--order` 指定。`carry` 的紀錄來源是本機的工單(`--from`,沒給就找該專案最新一張含這張票的工單),或 `--text` 裡的通知或工單區塊;票進到目的工單時是 in-progress(`auto` 指該專案開著的工單,沒有就開一張)。來源工單若由本機寫入,票會標為剔除,原因是 `carried to <order>`。別處的寫入者還握著的票(在已交接的工單裡仍是 in-progress 或 in-review)會被拒絕,要等對方退回。`carry` 不改遠端狀態。
262
+ - **審查過期。** 記錄審查結論時的 head 存在 `review_head`。之後 `set --head` 換了 head 卻沒有新的 `--review`,`show` 會標出 `stale: reviewed <舊>, head now <新>`,`seal` 也會警告。測試紀錄維持各自執行時的 SHA。在這個欄位出現之前寫的工單不會被標記。
250
263
  - **單一寫入者。** Worker 回報,協調者記錄。`export --handoff` 把寫入權交給整合者;之後在已交接的那份上執行寫入指令會被拒絕,訊息會說明怎麼拿回來:匯入對方退回的版本,或執行 `reclaim`。匯入時,本機那份若仍可寫,沒有 `--force` 不會被覆蓋;版本比本機舊的也不會被接受。
251
- - **關單。** 每張送審中的票走與 `ttt done` 相同的完成流程,所以 `completion_mode` 與上層 issue 的規則照常套用。每張票各有一則留言,寫明它的 MR、合併 commit、版本與工單 id。已剔除的票不動。遠端已取消的票會讓關單停下,剔除後才能繼續。重跑時,已完成的票會跳過,留言不會重複。
264
+ - **關單。** 每張送審中的票走與 `ttt done` 相同的完成流程,所以 `completion_mode` 與上層 issue 的規則照常套用。每張票各有一則留言,寫明它的 MR、合併 commit、版本與工單 id。已剔除與已退回的票不動。遠端已取消的票會讓關單停下,剔除後才能繼續。重跑時,已完成的票會跳過,留言不會重複。
252
265
  - **身分。** `owner` 與紀錄中的寫入者名稱取自 `TTT_ACTOR`,未設定時為 `<current_user>@<hostname>`。
253
266
 
254
- 一張票同一時間只搭一張工單:要領進第二張工單,必須先從第一張剔除。
267
+ 一張票同一時間只搭一張工單:要領進或帶進第二張工單,必須先從第一張剔除或退回。
255
268
 
256
269
  ### `ttt status`
257
270
 
@@ -289,6 +302,20 @@ ttt show --remote --any-cycle --creator me # 我建立、不限 cycle 的
289
302
  - `--any-cycle`:不限目前 cycle。`--status Backlog` 會自動帶上它,因為 Backlog 票通常不屬於任何 cycle。
290
303
  Trello 沒有 cycle,所以在 Trello 上沒有作用。
291
304
 
305
+ ### `ttt skills` / `ttt skill`
306
+
307
+ 印出隨這個版本的 CLI 一起安裝的 agent 技能說明。
308
+ Agent 那邊只裝一份短的引導技能,內容是要它執行這兩個指令,所以 agent 照著做的說明一定和裝著的 `ttt` 同一版。
309
+
310
+ ```bash
311
+ ttt skills # 內建的技能、各自的分頁與 ttt 版本
312
+ ttt skill managing-linear-tasks # 印出技能;開頭列出有哪些分頁
313
+ ttt skill managing-linear-tasks orders-coordinator # 工單:協調者這一側
314
+ ttt skill managing-linear-tasks orders-integrator # 工單:整合者這一側
315
+ ```
316
+
317
+ 說明文字放在套件裡的 `bundled-skills/<name>/index.md`(每個分頁另有一份 `<page>.md`),讀取時以安裝的套件目錄為準,與目前所在的目錄無關。
318
+
292
319
  ### `ttt config`
293
320
 
294
321
  配置設定。
@@ -364,7 +391,7 @@ your-project/
364
391
 
365
392
  ### 自動啟用技能
366
393
 
367
- Plugin 包含 `managing-linear-tasks` 技能,在處理任務時會自動啟用,提供工作流程指導和最佳實踐。
394
+ Plugin 包含 `managing-linear-tasks` 技能,在處理任務時會自動啟用。它只是一份短的引導:要 agent 執行 `ttt skill managing-linear-tasks`,印出隨 CLI 一起安裝的完整說明(見 [`ttt skills`](#ttt-skills--ttt-skill))。
368
395
 
369
396
  ## 授權
370
397
 
@@ -0,0 +1,186 @@
1
+ ---
2
+ name: managing-linear-tasks
3
+ description: Drive Linear/Trello task work through the ttt CLI (sync, claim, record, complete) and carry a train batch of tickets in a work order.
4
+ ---
5
+
6
+ ## 執行方式
7
+
8
+ 在 Codex 與 Claude Code 中,使用可用的 shell 工具執行 `ttt` CLI。
9
+ 任務資料以 CLI 的查詢結果為準;透過 CLI 更新 `.ttt/` 內的設定與狀態。
10
+ 使用者要求完成任務時,執行 `ttt done -m "摘要"`。
11
+ Claude Code 也提供 `/ttt:*` slash commands,對應下方相同的 CLI 操作。
12
+
13
+
14
+ # Task Manager (Linear/Trello)
15
+
16
+ Manage developer task workflows using the `ttt` CLI.
17
+
18
+ ## Command Router
19
+
20
+ 依使用者意圖選擇下列 `ttt` CLI 指令:
21
+
22
+ | User Intent | Command | Example |
23
+ |-------------|---------|---------|
24
+ | Sync/fetch issues | `ttt sync` | "sync my issues", "pull from Linear" |
25
+ | Show/search issues | `ttt show` | "show MP-624", "list my tasks", "what issues do I have" |
26
+ | Claim ticket(s) → in-progress | `ttt claim` | "領票", "work on next", "start MP-624", "claim MP-624 MP-625" |
27
+ | Create a new issue | `ttt create` | "create issue", "open a ticket", "new task" |
28
+ | Reassign an issue | `ttt assign` | "assign MP-624 to john", "reassign to jane" |
29
+ | Edit issue fields | `ttt edit` | "rename MP-624", "change priority", "update labels" |
30
+ | Cancel an issue | `ttt cancel` | "cancel MP-624", "abandon this task" |
31
+ | Record an estimate | `ttt estimate` | "estimate MP-624 as 6h", "save 2.5h estimate" |
32
+ | Check/change status | `ttt status` | "what's my current task", "set MP-624 to blocked" |
33
+ | Add a comment | `ttt comment` | "comment on MP-624", "add note to task" |
34
+ | Complete task(s) | `ttt done` | "done", "mark complete", "finish task", "close MP-624 MP-625" |
35
+ | Track a train batch | `ttt order` | "開工單", "seal the order", "hand off the train", "close the batch after merge" |
36
+
37
+ **意圖符合時,透過 shell 工具執行對應的 `ttt` CLI 指令。**
38
+
39
+ ## Quick Reference
40
+
41
+ ```bash
42
+ ttt sync # Sync Todo/In Progress issues
43
+ ttt sync --all # Sync all statuses
44
+ ttt sync MP-624 # Sync specific issue
45
+ ttt show # List all local issues
46
+ ttt show MP-624 # Show issue details
47
+ ttt show --user me # My issues
48
+ ttt show --remote --status Backlog --creator me # Backlog tickets I created (any cycle)
49
+ ttt show --remote --status Backlog --user me # Backlog tickets assigned to me
50
+ ttt claim next # Claim highest priority pending task
51
+ ttt claim next 3 # Claim top 3 pending tasks
52
+ ttt claim MP-624 MP-625 # Batch claim (alias: ttt work-on)
53
+ ttt claim MP-700 # Not in local data (e.g. Backlog)? Fetched from remote, then claimed
54
+ ttt create # Create new issue (interactive)
55
+ ttt create -t "Title" -p 2 # Quick create with flags
56
+ ttt assign MP-624 -a john # Reassign issue
57
+ ttt edit MP-624 -t "New" # Edit title (or -d/-p/-l)
58
+ ttt cancel MP-624 # Cancel an issue
59
+ ttt estimate MP-624 6 # Save a 6-hour human estimate
60
+ ttt status # Current in-progress task
61
+ ttt status MP-624 --set +1 # Advance status
62
+ ttt comment MP-624 -m "msg" # Add comment to issue
63
+ ttt comment -m "msg" # Comment on current task
64
+ ttt done -m "summary" # Complete with message
65
+ ttt done MP-624 --commit <sha> [--repo <path>] # Close a ticket with an earlier commit
66
+ ttt done MP-624 --from-remote # Complete a Todo ticket without claiming it first
67
+ ttt done MP-624 MP-625 -m "summary" # Complete several tickets; done ones are skipped, exit non-zero if any failed
68
+ ttt claim MP-624 --order auto --project app # Claim into the project's open work order
69
+ ttt order close app/2026-11-11-a --merged <sha> --version v1.2.0 # After the merge: whole batch → Done
70
+ ttt skills # Skills bundled with this ttt version; print one with: ttt skill <name> [page]
71
+ ```
72
+
73
+ ## Prerequisites
74
+
75
+ - **Linear**: `LINEAR_API_KEY` env var set
76
+ - **Trello**: `TRELLO_API_KEY` + `TRELLO_TOKEN` env vars set
77
+ - `.ttt/` directory initialized (`ttt init`)
78
+
79
+ ## Standard Workflow
80
+
81
+ ```
82
+ ttt sync → ttt claim next → ttt estimate <id> <hours> → [implement] → git commit → ttt comment -m "notes" → ttt done -m "..."
83
+ ```
84
+
85
+ ## Batch Work on a Train (Work Order)
86
+
87
+ When several tickets ride one integration branch and close together after its merge, claim them with `--order` and skip the per-ticket `ttt done`: closing a ticket before its train merged reports work as done that is not on the integration branch yet.
88
+ One side writes the order at a time, so workers report and the coordinator records.
89
+
90
+ Before working an order, print the page for your side and follow it:
91
+
92
+ - `ttt skill managing-linear-tasks orders-coordinator`: you claim tickets, record worker reports, and build the train.
93
+ - `ttt skill managing-linear-tasks orders-integrator`: you receive the train, merge it, and close its tickets.
94
+
95
+ ```
96
+ Coordinator: ttt claim <ids> --order auto --project <p>
97
+ ttt order set <order> <id> --branch --mr --head --review --tests (per worker report)
98
+ ttt order review <order> <ids> → testing status, assignee kept
99
+ ttt order train <order> --branch --mr
100
+ ttt order seal <order> --gated-head <sha> → no more tickets; the next claim opens a new order
101
+ ttt order export <order> --handoff → block into the train MR; local copy read-only
102
+ Integrator: ttt order import <file|-> → becomes the writer
103
+ ttt order return <order> <ids> --reason → tickets leave the train; notice block to the coordinator
104
+ ttt order close <order> --merged <sha> [--version v] [--dry-run]
105
+ Coordinator: ttt order carry <ids> --to auto --project <p> --text <notice> → next order, history kept
106
+ Writer: ttt order rework <order> <id> --reason → in-review back to in-progress; a sealed order reopens
107
+ ```
108
+
109
+ `ttt order close` runs each in-review ticket through the configured completion mode, comments MR, merge commit, version, and order id on it, and is safe to rerun after a failure.
110
+ Dropped and returned tickets are never completed and do not keep the order open.
111
+ `ttt order --help` lists every command.
112
+
113
+ ## File Structure
114
+
115
+ ```
116
+ .ttt/
117
+ ├── config.toon # Team configuration
118
+ ├── local.toon # Personal settings
119
+ ├── cycle.toon # Current cycle tasks + local estimates (auto-generated)
120
+ ├── orders/ # Work orders: <project>/<code>.toon (never commit, never edit by hand)
121
+ └── output/ # Downloaded attachments
122
+ ```
123
+
124
+ ## Troubleshooting
125
+
126
+ | Problem | Solution |
127
+ |---------|----------|
128
+ | No cycle data | `ttt sync` |
129
+ | Issue not found locally | `ttt show <id> --remote` or `ttt sync <id>` (`ttt status` auto-fetches from remote) |
130
+ | API key not set | Set `LINEAR_API_KEY` or `TRELLO_API_KEY` + `TRELLO_TOKEN` |
131
+ | Stale data | `ttt sync` to refresh |
132
+ | Order is read-only (handed off) | Import the returned copy, or `ttt order reclaim <order>`; a return notice imports without either |
133
+ | Ticket pulled out of a train | Integrator: `ttt order return`; coordinator: `ttt order carry ... --text <notice>` (keeps branch, MR, head, review, tests) |
134
+ | Ticket in review needs a fix | `ttt order rework <order> <id> --reason ...`, then `set`, `review`, and `seal` again |
135
+ | Order takes no more tickets (sealed) | `ttt claim <id> --order auto` opens the next order |
136
+
137
+ ## Common Rationalizations
138
+
139
+ | Excuse | Reality |
140
+ |--------|---------|
141
+ | "I'll edit `cycle.toon` directly, faster" | `cycle.toon` is auto-generated. Manual edits get overwritten on next `ttt sync`. Always go through the CLI. |
142
+ | "I remember this issue ID, no need to sync" | Remote status, assignee, priority may have changed. Run `ttt sync` or `ttt show <id> --remote` first. |
143
+ | "I'll create the issue in the Linear/Trello UI instead" | Bypassing `ttt create` leaves the new issue outside local cycle data. Use the CLI so it gets tracked. |
144
+ | "The MR is open, so I'll `ttt done` each train ticket now" | The ticket is done when its train merges. Record it in the order (`ttt order review`) and let `ttt order close` complete the batch. |
145
+ | "It left the train, I'll just `ttt claim --order auto` it again" | A fresh claim starts an empty record: branch, MR, head, review, and test runs are lost. `ttt order carry` takes them along. |
146
+ | "Task is obvious, skip `ttt done`" | `ttt done` syncs local + remote status, posts a completion comment, reads git commit info. Skipping leaves state inconsistent. |
147
+ | "I know what the task needs without reading it" | Fabricated assumptions produce wrong work. Run `ttt show <id>` before starting. |
148
+ | "Fetch issue details via Linear MCP / web UI" | The CLI is authoritative and token-efficient. Use `ttt show` / `ttt sync`, not alternate data paths. |
149
+
150
+ ## Flowchart — Intent Routing
151
+
152
+ ```dot
153
+ digraph ttt_router {
154
+ rankdir=LR;
155
+
156
+ user [label="User mentions\nLinear/Trello", shape=doublecircle];
157
+ classify [label="Classify intent", shape=diamond];
158
+
159
+ sync [label="ttt sync", shape=box];
160
+ show [label="ttt show", shape=box];
161
+ claim [label="ttt claim", shape=box];
162
+ create [label="ttt create", shape=box];
163
+ assign [label="ttt assign", shape=box];
164
+ edit [label="ttt edit", shape=box];
165
+ cancel [label="ttt cancel", shape=box];
166
+ estimate [label="ttt estimate", shape=box];
167
+ status [label="ttt status", shape=box];
168
+ comment [label="ttt comment", shape=box];
169
+ done [label="ttt done", shape=box];
170
+ order [label="ttt order", shape=box];
171
+
172
+ user -> classify;
173
+ classify -> sync [label="fetch / pull"];
174
+ classify -> show [label="show / list"];
175
+ classify -> claim [label="claim / start / next"];
176
+ classify -> create [label="create / new"];
177
+ classify -> assign [label="assign / reassign"];
178
+ classify -> edit [label="rename / change field"];
179
+ classify -> cancel [label="cancel / abandon"];
180
+ classify -> estimate [label="estimate / Nh"];
181
+ classify -> status [label="current / set status"];
182
+ classify -> comment [label="comment / note"];
183
+ classify -> done [label="done / complete"];
184
+ classify -> order [label="train batch / work order"];
185
+ }
186
+ ```
@@ -0,0 +1,53 @@
1
+ ---
2
+ description: Coordinator's side of a work order (claim, record worker reports, review, seal, hand off, carry returned tickets on).
3
+ ---
4
+
5
+ # Work orders: coordinator
6
+
7
+ You claim tickets, dispatch workers, and build the train.
8
+ The work order is the batch's record from claim to Done: one order per train, one writer at a time.
9
+ You write it until `export --handoff`; from then on the integrator does.
10
+ Workers never write it: they report, you record.
11
+
12
+ Order ids are `<project>/<code>`.
13
+ Use the repository's directory name as the project and pass `--project <repo dir name>` with every `auto`, because one `.ttt` can serve several repositories.
14
+ From a checkout that has no `.ttt` above it (a worktree outside the project), add `--dir <project checkout>/.ttt`.
15
+
16
+ ## Per ticket
17
+
18
+ 1. Claim before dispatch: `ttt claim <ticket> --order auto --project <repo dir name>`. `auto` is the project's open order; after a seal it opens the next one.
19
+ 2. When the worker reports, record it: `ttt order set <order> <ticket> --branch <b> --mr <!n> --head <sha> --review "<verdict>"`, plus one `--tests "<command with filter> @ <sha> = <result>"` per run. The train and the integrator reuse recorded runs instead of running them again.
20
+ 3. When its merge request is open and its review is clean: `ttt order review <order> <ticket>` moves it to the testing status and keeps the assignee.
21
+ 4. A ticket that rides a train is Done when the train merges: the integrator's `ttt order close` completes the whole order then. `ttt done` on it earlier reports work that is not on the integration branch.
22
+
23
+ A review is bound to the head it was recorded on.
24
+ When the head moves afterwards, `show` marks it `stale: reviewed <old>, head now <new>`: get the new head reviewed and record the verdict with `set --review`, or the integrator receives a stale review.
25
+
26
+ ## Tickets that leave the batch
27
+
28
+ | Situation | Do |
29
+ |-----------|----|
30
+ | Not ready for this train, rides the next | `ttt order drop <order> <ticket> --reason "next train"`, seal, then `ttt order carry <ticket> --to auto --project <p> --from <order>` |
31
+ | Its work failed for good | `ttt order drop <order> <ticket> --reason "<failure>"`, then hand the ticket back by your project's rule (status, assignee, comment) |
32
+ | It broke the train's gate and its worker is fixing it | `ttt order rework <order> <ticket> --reason "<gate>"`; when fixed, `set` the new head, review, and tests, then `review` it again |
33
+ | The integrator pulled it out and sent a return notice | `ttt order carry <ticket> --to auto --project <p> --text <notice file or ->` |
34
+
35
+ `carry` keeps branch, MR, head, review, and test runs and records `carried_from`; it does not touch the ticket's status at the source.
36
+ `ttt claim --order auto` on a ticket that left an order starts an empty record, so use it only when there is no history to keep.
37
+ `carry` refuses a ticket its source's writer still holds (in progress or in review in a handed-off order): the writer returns it first.
38
+
39
+ `rework` puts the ticket in progress in the order and at the source, with the assignee unchanged.
40
+ On a sealed order it also reopens the order and clears the gated head, because the gate no longer covers the batch: gate the new head and seal again.
41
+
42
+ ## Train and handoff
43
+
44
+ 1. Link the train: `ttt order train <order> --branch <train branch> --mr <!n>`. A train rebuilt under a new name is recorded the same way; the order's code need not match the train's name.
45
+ 2. When the train's closing gate is green, seal on the gated head: `ttt order seal <order> --gated-head <sha>`. Every ticket must be in review, dropped, or returned, so first drop the ones still in progress (first row above). Seal warns about each stale review.
46
+ 3. `ttt order export <order> --handoff`, and put the printed block in the train's merge request description under `Work order`. Your copy is read-only from here.
47
+
48
+ ## After the handoff
49
+
50
+ - **A return notice** (a `toon ttt-return` block from the integrator): `ttt order carry <tickets> --to auto --project <p> --text <file|->` takes the tickets on and records the notice on your copy. To record it without carrying: `ttt order import <file|->`. A text that holds both the order block and a notice needs `--returns`.
51
+ - **The whole train comes back**: `ttt order import <file|->` of the integrator's `export --handoff` block makes you the writer again; when no block came back, `ttt order reclaim <order>`. Then `rework` the tickets that need fixing, record the fixes, seal with the new gated head, and export again.
52
+
53
+ `ttt order show <order>` prints every ticket's state and history and the order's log; `ttt order --help` lists every command.
@@ -0,0 +1,45 @@
1
+ ---
2
+ description: Integrator's side of a work order (import at receipt, return or rework tickets, close the batch after the merge).
3
+ ---
4
+
5
+ # Work orders: integrator
6
+
7
+ You receive a gated train, merge it, and close its tickets.
8
+ The train's merge request description carries its work order as a fenced `toon ttt-order` block.
9
+ Importing it makes you the order's one writer; the coordinator's copy is read-only from the handoff on.
10
+
11
+ ## At receipt
12
+
13
+ 1. Import from the checkout that holds `.ttt`: `glab mr view <n> -R <repo> | ttt order import -` (GitHub: `gh pr view <n> -R <repo> --json body -q .body | ttt order import -`; a saved file: `ttt order import <file>`).
14
+ 2. `ttt order show <order>`: check the ticket list against what you were told rides the train, the gated head against the train's head, and each ticket's review and test runs. A review marked `stale` was given on an older head. While the gated head is the head you merge, reuse the recorded runs instead of running them again.
15
+
16
+ ## While integrating
17
+
18
+ | Situation | Do |
19
+ |-----------|----|
20
+ | A ticket leaves the train and goes back to its coordinator (it breaks the gate, or waits for a paired change) | `ttt order return <order> <ticket>... --reason "<why>"`, and send the printed notice block to the coordinator |
21
+ | You fix a ticket inside this train | `ttt order rework <order> <ticket> --reason "<why>"`; then `ttt order set` the new head, review, and tests, `ttt order review <order> <ticket>`, and `ttt order seal <order> --gated-head <new sha>` |
22
+ | A ticket is void (canceled, duplicate) | `ttt order drop <order> <ticket> --reason "<why>"` |
23
+ | The whole train goes back | `ttt order export <order> --handoff` into the return message; the coordinator imports it |
24
+
25
+ `return` moves the ticket to in-progress at the source with the assignee unchanged, and the notice carries the ticket's whole record, so the coordinator's `carry` takes branch, MR, head, review, and test runs into its next order.
26
+ For a ticket that will ride a later train use `return`, not `drop`: the coordinator's copy is read-only and learns of a drop only when the order itself comes back.
27
+ Repeating `return` prints the notice again and changes nothing.
28
+
29
+ `rework` on a sealed order reopens it and clears the gated head, so `close` refuses until you seal again on the head you gated.
30
+
31
+ ## After the merge
32
+
33
+ 1. `ttt order close <order> --merged <merge sha> --version <version> --dry-run`, and read what it would do.
34
+ 2. The same command without `--dry-run`. Each in-review ticket goes through the configured completion mode to the done status and gets one comment with its MR, the merge commit, the version, and the order id. Dropped and returned tickets are left alone and do not keep the order open.
35
+ 3. Exit code 1 means a ticket failed and the order stays `merged`: fix the cause named on that ticket's line and rerun the same command. Done tickets are skipped, and no comment is posted twice.
36
+
37
+ `close` is what records the merge on each ticket, so a train's tickets are never closed one by one with `ttt done`.
38
+
39
+ | `close` says | Do |
40
+ |--------------|----|
41
+ | `is not sealed` | A `rework` reopened the order: seal again with the head you gated |
42
+ | `is still in-progress in the order` | `ttt order review` it when it is in the merge; else `return` or `drop` it |
43
+ | `is Canceled at the source` | `ttt order drop <order> <ticket> --reason canceled`, then rerun |
44
+ | `no longer in review` | It moved since the seal: `ttt order review` it when it is in the merge, else `return` it |
45
+ | `is In Review, not Done` | The completion mode stops at testing: move it to Done or change `completion_mode`, then rerun |
@@ -3,7 +3,7 @@ name: ttt:order
3
3
  description: Work orders - carry a train batch of tickets from claim to Done
4
4
  arguments:
5
5
  - name: command
6
- description: "open, list, show, set, review, train, seal, drop, export, import, reclaim, or close"
6
+ description: "open, list, show, set, review, train, seal, drop, rework, return, carry, export, import, reclaim, or close"
7
7
  required: true
8
8
  - name: args
9
9
  description: "Order id (<project>/<code>), ticket ids, and options for the command"
@@ -62,7 +62,7 @@ ttt order close app/2026-11-11-a --merged 9a8b7c6 --version v1.2.0
62
62
  ```
63
63
 
64
64
  `close` completes every in-review ticket through the configured completion mode (parent issues included) and comments MR, merge commit, version, and order id on each.
65
- Dropped tickets are untouched.
65
+ Dropped and returned tickets are untouched.
66
66
  A ticket must reach the done status: under `strict_review` (or `upstream_strict` without a parent) it stops at testing, so close fails it and the order stays merged.
67
67
  When a ticket fails, fix the cause and rerun the same command: done tickets are skipped and no comment is posted twice.
68
68
 
@@ -70,7 +70,22 @@ When a ticket fails, fix the cause and rerun the same command: done tickets are
70
70
 
71
71
  The integrator returns the order with `ttt order export <id> --handoff`, and the coordinator runs `ttt order import <file>`.
72
72
  When nothing came back, the coordinator runs `ttt order reclaim <id>`.
73
- A reworked ticket stays in its order: record the new head and test runs with `set`, then `seal` again with the new gated head and hand off again.
73
+ A ticket that needs a fix stays in its order: `ttt order rework <id> <ticket> --reason ...` sends it back to in-progress (a sealed order reopens and its gated head is cleared), then record the new head, review, and test runs with `set`, `review` it, `seal` with the new gated head, and hand off again.
74
+
75
+ ### A ticket pulled out of the train
76
+
77
+ ```bash
78
+ # Integrator: hand it back; the notice block goes to the coordinator
79
+ ttt order return app/2026-11-11-a MP-625 --reason "waits for MP-630" > notice.md
80
+
81
+ # Coordinator: into the next order with branch, MR, head, review, and test runs
82
+ ttt order carry MP-625 --to auto --project app --text notice.md
83
+ ```
84
+
85
+ `return` marks the ticket returned, moves it to in-progress at the source (assignee unchanged), and `close` skips it.
86
+ `carry` records `carried_from`; when the head moves later without a new `--review`, `show` marks the carried review stale.
87
+ `ttt claim --order auto` on such a ticket would start an empty record instead.
88
+ The per-side rules ship with the CLI: `ttt skill managing-linear-tasks orders-coordinator` and `ttt skill managing-linear-tasks orders-integrator`.
74
89
 
75
90
  ## Full CLI Reference
76
91
 
@@ -89,7 +104,9 @@ Commands:
89
104
  [--review <verdict>] [--tests "<cmd> [@ <sha>] [= <result>]"]...
90
105
  Record a ticket's branch, MR, head, review verdict, and test runs.
91
106
  Each --tests appends one run; the sha defaults to the ticket's
92
- head, the result to "pass".
107
+ head, the result to "pass". A review is bound to the head it was
108
+ recorded on: when --head moves without a new --review, show marks
109
+ the review stale (reviewed <old>, head now <new>).
93
110
  review <id> <ticket>... [--status <name>]
94
111
  Move tickets to the testing status (assignee unchanged) and mark
95
112
  them in-review. An open order adopts a ticket it does not hold yet,
@@ -98,21 +115,45 @@ Commands:
98
115
  train <id> [--branch <b>] [--mr <mr>]
99
116
  Record the train branch and its merge request.
100
117
  seal <id> --gated-head <sha>
101
- Fix the batch: no more tickets. Every ticket must be in review or
102
- dropped. Sealing again records a new gated head.
118
+ Fix the batch: no more tickets. Every ticket must be in review,
119
+ dropped, or returned. Sealing again records a new gated head.
103
120
  drop <id> <ticket> --reason <text>
104
121
  Leave a ticket out of the batch; its remote status is not touched.
122
+ rework <id> <ticket> --reason <text>
123
+ Send an in-review ticket back to work inside its order: in-progress
124
+ here and at the source (assignee unchanged). A sealed order opens
125
+ again and its gated head is cleared, so it must be sealed anew.
126
+ return <id> <ticket>... --reason <text>
127
+ Writer (normally the integrator): hand tickets back to their
128
+ coordinator. Each is marked returned with who/when/why and keeps its
129
+ record; its remote status goes back to in-progress (assignee
130
+ unchanged). Prints a return notice block for the coordinator.
131
+ Close skips returned tickets. Safe to repeat.
132
+ carry <ticket>... --to <id|auto> [--project <p>] [--from <id> | --text <file|->]
133
+ Coordinator: take tickets into another open order with their branch,
134
+ MR, head, review, and test runs, plus a carried_from record. auto is
135
+ the open order of --project (default: the source's project). The
136
+ history comes from a local order (--from, else the newest order of
137
+ the project that holds the ticket) or from a return notice or order
138
+ block in --text. A source this machine writes marks them dropped
139
+ ("carried to <order>"). A ticket must have left its source (returned
140
+ or dropped) unless this machine writes the source. Remote statuses
141
+ are not touched.
105
142
  export <id> [--handoff]
106
143
  Print the order as a fenced block for an MR description or a slip.
107
144
  --handoff makes this copy read-only: the receiver writes from now on.
108
- import <file|-> [--id <id>] [--force]
145
+ import <file|-> [--id <id>] [--force] [--returns | --order]
109
146
  Read the block out of any text and become the order's writer.
147
+ A return notice is recorded on your copy instead, even a handed-off
148
+ one, and does not change who writes. When the text holds both, pick
149
+ with --returns or --order.
110
150
  reclaim <id>
111
151
  Take a handed-off order back when it was returned without an export.
112
152
  close <id> --merged <sha> [--version <v>] [--dry-run]
113
153
  After the train merged: complete every in-review ticket through the
114
154
  configured completion mode, and comment MR, merge commit, version,
115
- and order id on each. Dropped tickets are untouched. Safe to rerun.
155
+ and order id on each. Dropped and returned tickets are untouched.
156
+ Safe to rerun.
116
157
  ```
117
158
 
118
159
  The default project is the directory that holds `.ttt`.
@@ -125,9 +166,11 @@ The writer's name is `TTT_ACTOR`, else `<current_user>@<hostname>`.
125
166
  | `was handed off ... read-only` | Import the returned copy, or `ttt order reclaim <id>` |
126
167
  | `takes no more tickets` | The order is sealed: claim with `--order auto` to use the next one |
127
168
  | `Cannot seal ...: MP-x still in progress` | `ttt order review <id> MP-x` or `ttt order drop <id> MP-x --reason ...` |
128
- | `is not sealed` on close | `ttt order seal <id> --gated-head <sha>` first |
169
+ | `is not sealed` on close | `ttt order seal <id> --gated-head <sha>` first; a `rework` reopens a sealed order |
129
170
  | `is Canceled at the source` on close | `ttt order drop <id> MP-x --reason canceled`, then rerun close |
130
- | `no longer in review` on close | The ticket moved since the seal: `ttt order drop` it, or put it back in review |
171
+ | `no longer in review` on close | The ticket moved since the seal: `ttt order return` or `drop` it, or put it back in review |
172
+ | `is still in-review in order ..., which was handed off` on carry | The order's writer returns the ticket first (`ttt order return`), then carry with the notice (`--text`) |
173
+ | `holds a work order block and a return notice` on import | Pass `--returns` to record the notice, or `--order` to import the order |
131
174
  | `is In Review, not Done` on close | The completion mode stops at testing; move it to Done or change `completion_mode`, then rerun |
132
175
  | `already in order ...` on review | A ticket rides one order per project; drop it there first |
133
176
  | `already exists here as a writable copy` on import | Check which copy is current; replace the local one with `--force` |