From 266efcd228c86775217427e181af789aba2e07d6 Mon Sep 17 00:00:00 2001 From: Xenrya Date: Mon, 12 Oct 2026 20:50:12 +0800 Subject: [PATCH] Run ticket workers as launched threads and adapt to T3 nightlies Swarm workers and per-PR interrogation leads become top-level threads bound to their worktree, so T3 shows each one's real branch. A delegate child inherits the parent's checkout and was labelled with its branch. delegate-subagents gains a Launched workers section for launching, waiting, reading, further rounds, and cancelling those threads. It also follows the October 11-12 T3 nightlies: per-provider runtime modes, providers turned off per project, automatic continuations after a server restart, and stopping Claude workflows. pr gains an optional review-guide step, and implement treats a launched worker like a delegated task. Co-Authored-By: Claude Opus 5.5 --- skills/engineering/implement/SKILL.md | 6 +- skills/engineering/interrogation/SKILL.md | 52 +++++++++-- skills/engineering/pr/SKILL.md | 20 +++-- .../orchestration/delegate-subagents/SKILL.md | 72 ++++++++++++---- skills/orchestration/swarm-tickets/SKILL.md | 86 +++++++++---------- .../swarm-tickets/agents/openai.yaml | 6 +- .../swarm-tickets/references/example.md | 45 +++++----- 7 files changed, 185 insertions(+), 102 deletions(-) diff --git a/skills/engineering/implement/SKILL.md b/skills/engineering/implement/SKILL.md index 09f657f..fe2307a 100644 --- a/skills/engineering/implement/SKILL.md +++ b/skills/engineering/implement/SKILL.md @@ -11,9 +11,9 @@ Implement the work described by the user in the specification or tickets, follow Resolve referenced skills through the current harness's available-skills catalog and read their `SKILL.md` before following them. In Codex, apply those instructions directly with the available tools. If a referenced skill is unavailable, perform its step directly and report that fallback. -1. Find the issue tracker in `docs/agents/issue-tracker.md`, the file the `## Agent skills` block in `AGENTS.md` or `CLAUDE.md` points to. If it is missing, invoke the `setup-xenrya-stack` skill and continue once it reports. As a subagent, stop and report the missing file instead, since setup needs the user's answers. Done when you have read the tracker file, and you follow it for every step that reads or updates an issue. +1. Find the issue tracker in `docs/agents/issue-tracker.md`, the file the `## Agent skills` block in `AGENTS.md` or `CLAUDE.md` points to. If it is missing, invoke the `setup-xenrya-stack` skill and continue once it reports. When a parent's brief started you (a delegated task or a launched worker thread), stop and report the missing file instead, since setup needs the user's answers. Done when you have read the tracker file, and you follow it for every step that reads or updates an issue. 2. Implement the requested behavior. Use the `tdd` skill where possible, at pre-agreed seams. -3. Run the repository's typecheck and affected test files regularly during implementation. Run the full test suite once implementation is complete. As a subagent, follow the brief's Validation field: when it says the parent runs the full suite, skip it and say so. Report unavailable checks or existing failures accurately, and don't fix failures the brief lists as already on the base branch. -4. Commit the task's changes and push to the current branch, unless the user's instructions or repository rules specify another delivery path. Use the `pr` skill to prepare and open the pull request. As a subagent, follow the brief's delivery instructions instead: when the parent owns commits and PRs, leave the changes uncommitted. +3. Run the repository's typecheck and affected test files regularly during implementation. Run the full test suite once implementation is complete. When a parent's brief started you, follow its Validation field: when it says the parent runs the full suite, skip it and say so. Report unavailable checks or existing failures accurately, and don't fix failures the brief lists as already on the base branch. +4. Commit the task's changes and push to the current branch, unless the user's instructions or repository rules specify another delivery path. Use the `pr` skill to prepare and open the pull request. When a parent's brief started you, follow its delivery instructions instead: when the parent owns commits and PRs, leave the changes uncommitted. Report the implemented behavior, validation results, and pull request URL, including any unresolved findings or skipped checks. diff --git a/skills/engineering/interrogation/SKILL.md b/skills/engineering/interrogation/SKILL.md index d0968bb..f0d295f 100644 --- a/skills/engineering/interrogation/SKILL.md +++ b/skills/engineering/interrogation/SKILL.md @@ -38,25 +38,61 @@ Before spawning reviewers, state the intent explicitly. Derive this from: - PR description if one exists - The code itself -Write one clear paragraph for each scope; with several PRs, each PR's intent comes from its ticket and description. If you're unsure about the intent, ask the user before proceeding. +Write one clear paragraph for each scope; with several PRs, each PR's intent comes from its ticket and description. A PR's review guide is not a source: an agent wrote it. If you're unsure about the intent, ask the user before proceeding. ## Step 3, Delegate Reviewers Read and follow [delegate-subagents](../../orchestration/delegate-subagents/SKILL.md), or its installed copy from the active harness's skill catalog. Apply its instructions with the available tools; a harness-specific Skill tool is not required. +### Where each review runs + +Reviewers are `delegate_task` children, so they inherit the checkout of the thread that dispatches them, and T3 labels them with that thread's branch. Run each scope's review from a thread bound to that scope's checkout: + +- **Scope in this thread's checkout** (the current branch, or local files): you are the lead. Do the rest of Step 3 and Steps 4–5 here. +- **Scope in another checkout** (a PR in its own worktree, such as the PRs from `swarm-tickets`): you are the parent. Resolve the reviewer roster below, then launch one **lead thread** per PR, bound to that PR's checkout with `existing_worktree`, as [Launched workers](../../orchestration/delegate-subagents/SKILL.md#launched-workers) describes. Each lead dispatches that PR's reviewers and judges their findings. Launch a fresh lead rather than reusing the thread that wrote the code, so the author doesn't judge its own review. + +Title each lead `Interrogate PR # () [interrogate--pr-r1]`, and send it this brief: + +```text +Read the skill at and act as the lead +for one scope. A parent thread launched you: finish everything in this one turn. + +Scope: PR # (), base at , head , checkout +. This thread is bound to that checkout. Frozen diff: . +Intent: . +Reviewers: . +Repository guidance and glossary: . + +Do Step 3 for this scope only, with one change: dispatch every reviewer in one +message of parallel delegate_task calls with mode "wait" and timeoutMs 1800000, +so the reviews finish inside this turn. Count a reviewer that returns +waitTimedOut as incomplete coverage and give its taskId. Then do Steps 4 and 5 +and return the verdict in the Output Format, starting with +"## Verdict: PR #". Don't edit the repository, apply fixes, commit, push, +or touch PRs or databases. +``` + +The leads wait on their reviewers with `mode: "wait"` because the parent's `t3_thread_wait` returns when the lead's turn ends. A lead that ended its turn to wait for notifications would look finished before its reviews were in. + +As the parent, wait on each lead and read its verdict, the last assistant message, as Launched workers describes. A lead that failed or returned no verdict is missing coverage for its PR. Then go to the Output Format with the leads' verdicts. + +### Dispatching reviewers + +The parent resolves the roster (the next two paragraphs) before it launches leads, and a launched lead uses the roster in its brief. Everything after the roster is the lead's work. + Call `orchestrator_capabilities` and resolve the user's requested models, or a reviewer roster in applicable project instructions, to live `providerInstanceId` and model IDs. An existing `interrogate reviewers` list can supply preferences; it is not a separate model catalog. Check child-task support, cross-provider constraints, and supported model options. Treat `auto` or `inherit-parent` as a request to inherit the caller's selection, rather than as a literal model ID. -Without a requested roster, choose two distinct capable models, preferring different providers. Use a smaller roster if availability requires it and report the reduced diversity. State the selected providers/models before dispatch. Report an unavailable requested model instead of silently substituting a family default. Refresh capabilities and correct actionable dispatch errors; retain valid reviewers and identify any unavailable entries. +Without a requested roster, choose two distinct capable models, preferring different providers. Use a smaller roster if availability requires it, including a provider the project turned off ("is disabled for project"), and report the reduced diversity. State the selected providers/models before dispatch. Report an unavailable requested model instead of silently substituting a family default. Refresh capabilities and correct actionable dispatch errors; retain valid reviewers and identify any unavailable entries. Read [the reviewer prompt](references/reviewer-prompt.md), [review rubric](references/rubric.md), and [code-quality lens](references/code-quality-review.md). Fill the prompt with the intent, checkout path, frozen review scope, surrounding context, repository guidance, and the domain glossary: `GLOSSARY.md`, or the glossaries `GLOSSARY-MAP.md` lists for the touched contexts. Insert the full rubric and code-quality lens into their placeholders. Structural improvements are review proposals; reviewers must leave the implementation unchanged. -Reviewers receive only their supplied task prompt, so include the needed context or absolute paths to accessible snapshot artifacts. Keep each initial review independent of the other reviewers' findings and send the same filled prompt to every selected model. +Reviewers receive only their supplied task prompt, so include the needed context or absolute paths to accessible snapshot artifacts. Keep each initial review independent of the other reviewers' findings and send the same filled prompt to every selected model. Don't send reviewers a PR's review guide: it would steer every reviewer the same way. Use T3-owned child tasks through `delegate_task`, with `role:"review"`, `mode:"async"`, and inherited permission modes. Pass the shared brief as `task` and the resolved selection as `target:{providerInstanceId,model}`. For an inherited selection, omit the corresponding target overrides. With several PRs, give each PR its own reviewers, one per selected model, with that PR's intent and diff. Title each task `Interrogate PR # ()` and give it a `clientRequestId` such as `interrogate--pr--r1`. Launch independent reviewers together when the harness supports parallel tool calls. Retain one stable `clientRequestId` per reviewer/round and every returned `taskId` with its actual provider/model. -The brief must prohibit repository edits, applying fixes, commits, pushes, PR creation, migrations, and database writes. `role:"review"` labels the task; it does not enforce a filesystem restriction, and T3 has no `readonly` or `subagent_type` argument. Child reviews belong to this conversation: never create reviewers with `t3_thread_launch` or `create_threads`. +The brief must prohibit repository edits, applying fixes, commits, pushes, PR creation, migrations, and database writes. `role:"review"` labels the task; it does not enforce a filesystem restriction, and T3 has no `readonly` or `subagent_type` argument. Reviewers are always `delegate_task` children of their lead: never create reviewers with `t3_thread_launch` or `create_threads`. -Follow `delegate-subagents` for completion notifications, `task_status` result collection, cancellation, and any additional review rounds. When only reviewers remain, end the turn and resume on their completion notifications. Collect published results before issuing the verdict; a completed child turn with pending descendants is still unfinished work. Failed, cancelled, or unavailable reviewers must be reported as incomplete coverage. +Follow `delegate-subagents` for completion notifications, `task_status` result collection, cancellation, and any additional review rounds. When only reviewers remain, a lead in its own thread ends the turn and resumes on their completion notifications; a launched lead follows its brief. Collect published results before issuing the verdict; a completed child turn with pending descendants is still unfinished work. Failed, cancelled, or unavailable reviewers must be reported as incomplete coverage. ## Step 4, Synthesize @@ -72,7 +108,7 @@ As results come back, build a unified picture: You are the lead reviewer, a pragmatic senior engineer, not a neutral aggregator. -Read [the lead-judgment framework](references/lead-judgment.md) before categorizing findings. Apply the conversation context, project constraints, and pragmatic filtering that independent reviewers may lack. Verify each actionable claim against the reviewed snapshot and stated intent. A concrete lone-model finding can outweigh unsupported consensus. Missing coverage is not an endorsement. +Read [the lead-judgment framework](references/lead-judgment.md) before categorizing findings. Apply the conversation context, project constraints, and pragmatic filtering that independent reviewers may lack. Verify each actionable claim against the reviewed snapshot and stated intent. A concrete lone-model finding can outweigh unsupported consensus. Missing coverage is not an endorsement. When a reviewed PR has a review guide (`read_pull_request_guide`), you may use its Look closely stops as a coverage check: a stop that no finding covers is one to check yourself. Categorize every finding using these buckets: @@ -89,7 +125,7 @@ For each finding, include: ## Output Format -Present the verdict in this structure. With several PRs, start with a table of PR, reviewers, and Act On count, then give one full verdict per PR. +Present the verdict in this structure. With several PRs, start with a table of PR, lead thread, reviewers, and Act On count, then give one full verdict per PR. Link each lead thread as `[title](t3-thread://v1/)`. Link a PR's review guide when one exists. ### Intent @@ -125,7 +161,7 @@ Identify omitted reviewers, unavailable targets, and failed tasks. Distinguish t Stop after the verdict. Apply nothing until the user asks. When the user asks for fixes: -- If the PRs came from `swarm-tickets`, its phase 7 (Revise) does the fixes. It sends each PR's Act On findings back to that ticket's original worker as a new round in the same workspace, then runs `pr` again for each changed PR. +- If the PRs came from `swarm-tickets`, its phase 7 (Revise) does the fixes. It sends each PR's Act On findings to that ticket's worker thread as a new round, not to the lead thread, then runs `pr` again for each changed PR. - Otherwise, follow `delegate-subagents` phase 4 for a correction round, or fix the code yourself when the user asks you to. In both cases, list the findings being fixed and the ones left alone, so the fixer changes only what was accepted. diff --git a/skills/engineering/pr/SKILL.md b/skills/engineering/pr/SKILL.md index 33b2998..e469d99 100644 --- a/skills/engineering/pr/SKILL.md +++ b/skills/engineering/pr/SKILL.md @@ -45,10 +45,20 @@ author anything. Every claim rests on **proof**: 6. **Publish.** Open or update the PR only when the user or the calling skill asks. If a PR already exists for the branch, update its title and body. Upload the images to the PR. When PR-linking tools are available, link the - PR to the thread. Done when the PR shows the drafted title and body and - every image renders. -7. **Report.** Give the PR URL, or the full title and body when you did not - publish, then the validation results and any skipped checks. + PR to the thread by its URL, so T3 resolves the host. Done when the PR shows + the drafted title and body and every image renders. +7. **Guide.** Only when the user, the calling skill, or the repository + instructions ask for a review guide. After the push, call + `write_pull_request_guides` with the PR's URL. It returns at once and a + guide takes minutes, so don't wait. Record the outcome: `started`, + `running`, or `failed` and why. "Review guides are off" or a repository + with no checkout here is a skipped step, not a blocker. When updating a + PR, call `read_pull_request_guide` first, and rewrite only a guide that + exists and is `stale`. Done when the guide's outcome is recorded, or the + step is skipped because nobody asked. +8. **Report.** Give the PR URL, or the full title and body when you did not + publish, then the validation results, any skipped checks, and the review + guide's outcome when one was asked for. ## Sections @@ -60,6 +70,6 @@ author anything. Every claim rests on **proof**: | **Before and After** | An image table per changed screen, each with one line on what differs. With no images: `No image attached.` followed by the reason. | | **Validation** | A table of check, command, and result. Then the temporary steps, and what wasn't run. | | **Risk** | Contract changes, behaviour that existing clients will notice, and coverage that was lost. | -| Issue reference | `Closes #N` when this PR completes the issue; `Refs #N` for partial or uncertain work. | +| Issue reference | The closing reference `docs/agents/issue-tracker.md` documents, such as `Closes #N`, when this PR completes the issue; `Refs #N` for partial or uncertain work. | | Attribution | A line the harness asks you to end PR descriptions with, such as `🤖 Generated with [Claude Code](https://claude.com/claude-code)`. It goes directly above the Model line. Leave it out when the harness doesn't ask for one. | | Model | The last line: `Model: `, the display name of the model you run as (such as `Claude Opus 5.5`), not its model ID. When other models wrote the branch's code, such as delegated workers, list every display name, comma-separated. | diff --git a/skills/orchestration/delegate-subagents/SKILL.md b/skills/orchestration/delegate-subagents/SKILL.md index cf8e6c9..4664344 100644 --- a/skills/orchestration/delegate-subagents/SKILL.md +++ b/skills/orchestration/delegate-subagents/SKILL.md @@ -16,8 +16,8 @@ You own integration and the final answer. Two rules hold in every phase: -- **Children come from `delegate_task` only.** Never create a child with `t3_thread_launch` or `create_threads`, and never continue one with `t3_thread_send`. Those make top-level threads that never report back to this one, so you can't wait for them, read their results, or cancel them. T3's instructions to use `t3_thread_launch` for work in its own worktree cover top-level threads the user asks for, not children. To give a child its own worktree, follow [Workspace](#workspace). -- **Wait by ending your turn.** A child's completion wakes this thread with a notification. Don't run `sleep`, don't poll `task_status` in a loop, and don't call `t3_thread_wait` on a child's thread. +- **Children come from `delegate_task`, except launched workers.** Don't create a child with `t3_thread_launch` or `create_threads`. Those make top-level threads that never notify this one. Continue a child only as phase 4's [Another round](#4-assess-the-result) describes. The one exception is a **launched worker**: a worker that needs its own workspace binding in T3, such as a worktree, or one that a calling skill (`swarm-tickets`, `interrogation`) tells you to launch. A `delegate_task` child inherits this thread's checkout, so T3 would label it with the wrong branch. Follow [Launched workers](#launched-workers) for those. +- **Wait by ending your turn.** A child's completion wakes this thread with a notification. Don't run `sleep`, don't poll `task_status` in a loop, and don't call `t3_thread_wait` on a child's thread. Launched workers are the exception: nothing wakes you for them, so you wait on them with `t3_thread_wait` as [Launched workers](#launched-workers) describes. The workflow has four phases: **define → resolve target → dispatch → assess**. Other skills, such as `swarm-tickets`, write their own briefs and then follow phases 2–4 here for their workers. @@ -67,8 +67,10 @@ The **target selection** is everything the user said about how the child should - **Unstated parts are inherited.** Leave them out and T3 uses the parent's setting. If the user names only a model, the harness is that model's provider. - **Use catalog values only.** Read the ids and values from the catalog every time. The ids in the examples below come from one install, and custom provider instances carry their own ids. -- **Ask when a name is ambiguous.** If a name matches more than one model ("GPT 6" matches several), ask the user which one they mean. -- **Report targets you can't use.** That covers a disabled provider, a missing model, an effort the model doesn't advertise, and `canRunChildTask: false`. Report the provider's `constraints` and stop. Substituting a different target needs the user's approval. +- **Ask when a name is ambiguous.** If a name matches more than one model ("GPT 6" matches several), ask the user which one they mean. This includes option values: on Claude, "Ultra" can mean `ultracode` or `ultrathink`. `ultracode` runs multi-agent workflows; select it only when the user names it, and tell them it conflicts with a brief that forbids further delegation. +- **Runtime modes are per provider.** When a provider lists `runtimeModes`, the requested mode must be one of them; a provider without the list offers every mode. `delegate_task` refuses a mode outside the list and steps an inherited mode down to the broadest one offered, so put the effective mode in the selection line. `t3_thread_launch` doesn't check: a launched thread whose provider lacks the mode runs as `approval-required`. Before launching, resolve a listed mode with the user, or stop. +- **Projects can turn a provider off.** `orchestrator_capabilities` reflects the machine; a project can still turn an instance off. Treat "is disabled for project" from a dispatch, launch, or send as an unusable target. +- **Report targets you can't use.** That covers a disabled provider, a missing model, an effort the model doesn't advertise, a runtime mode the provider doesn't list, a provider the project turned off, and `canRunChildTask: false`. Report the provider's `constraints` or the error and stop. Substituting a different target needs the user's approval. - **Pick a harness when the user doesn't name one.** If the user asks for "another harness" without saying which, choose an enabled provider that differs from the parent's and state your choice. The two delegations at the top of this skill resolve to: @@ -98,15 +100,9 @@ Call `delegate_task` with: `delegate_task` has no workspace parameter. The child works in whatever directory its brief names, and its shell may start in the parent's checkout. - **Shared checkout** (the default). Give the parent's checkout path, and give concurrent writers disjoint file ownership. -- **Own worktree.** When a child needs its own branch or isolated state, create the worktree yourself before you dispatch (`git worktree add -b `) and run the repository's worktree setup script in it. Run setup for one worktree at a time. Then put this in the brief's Workspace field: - ```text - Workspace: on branch . Your shell may start in - . That is another checkout: do NOT edit files or run - commands there. Run every command with as the working - directory and use absolute paths inside it. - ``` +- **Own worktree.** When a worker needs its own branch or isolated state, create the worktree yourself (`git worktree add -b `) and run the repository's worktree setup script in it, one worktree at a time. Then launch the worker bound to it, as [Launched workers](#launched-workers) describes, instead of calling `delegate_task`. -A delegated task is a child of this conversation. An independent top-level conversation needs its own explicit request from the user, even when the work needs its own worktree. +A launched worker is still your worker: you own its brief, waiting, acceptance, and cancellation. Any other top-level conversation needs its own explicit request from the user. Record the returned `taskId` together with the selection line. For native subagents, record their native agent identifier and use the native lifecycle tools. @@ -119,10 +115,11 @@ Keep doing independent parent work while the child runs. Then wait in one of the | A T3 child | End the turn. Tell the user which `taskId`s are running. T3 wakes you with a notification when each one finishes. | | A child's result needed later in this same turn | One `task_status` call, or dispatch with `mode="wait"` | | A shell process, such as a validation run or a failed child's leftover test run | The harness's background waiting tool from the [harness table](#harness-notes). It notifies you when the process exits. | +| A launched worker | `t3_thread_wait` without ending the turn, as [Launched workers](#launched-workers) describes | If a wait times out, the child is still running: follow the existing task rather than dispatching a copy. -Done when: every assignment has a `taskId` recorded with its selection. +Done when: every assignment has a `taskId`, or a launched worker's `threadId`, recorded with its selection. ## 4. Assess the result @@ -132,10 +129,55 @@ Done when: every assignment has a `taskId` recorded with its selection. **Checking the work.** Compare the deliverables and evidence against the brief's "Done when" criteria. Inspect the artifacts the child produced and run any remaining integration checks. Resolve missing evidence or open objections before you present the work as complete. -**Another round.** To start another delegated round, such as a review or a correction, call `delegate_task` again. Send the original brief, the prior findings, the responses, and any unresolved objections, with a new `clientRequestId` for the round. Track the new `taskId`. The old `childThreadId` is only backing storage: sending it a message with `t3_thread_send` doesn't start a new round. +**Another round.** For another review round, or any round that should start fresh, call `delegate_task` again. Send the original brief, the prior findings, the responses, and any unresolved objections, with a new `clientRequestId` for the round. Track the new `taskId`. A review round never goes to the old `childThreadId`. -**Cancelling.** Use `task_cancel` when the user asks you to stop an owned task, or when the authorized workflow requires it. Cancelling also stops the task's descendants and any later runs on its backing thread. Results that were already published stay available. +A correction that needs the same child's conversation can go to its `childThreadId` instead, once the original task is terminal. Call `t3_thread_send` with `mode: "queue"` and a new `clientRequestId` for the round, reused unchanged on retries. T3 creates a fresh task in that child thread and returns its `taskId`; its completion notifies you like any child, and the original result stays unchanged. Write the message so the round stands on its own: the findings, what not to change, and the brief's Deliverables and Done-when fields. If the send returns no `taskId`, start the round with `delegate_task` instead. + +**Cancelling.** Use `task_cancel` when the user asks you to stop an owned task, or when the authorized workflow requires it. Cancelling also stops the task's descendants and any later runs on its backing thread. Results that were already published stay available. A task whose child had only background work left can report `completed` after `task_cancel`; record it as cancelled and don't accept its summary. + +For launched workers, read, correct, and cancel as [Launched workers](#launched-workers) describes; the rest of this phase still applies. Done when: every assignment is accepted, cancelled, or still running, with evidence for the accepted ones. Finish with the outcome, the delegate's selection line, the validation evidence, and any unresolved work. If a task is still running, give its `taskId` and state, and describe it as running. + +## Launched workers + +A launched worker is a top-level T3 thread that you start with `t3_thread_launch` and follow as your own worker. T3 binds it to its workspace, so its thread shows the real branch. Use one only when the worker needs its own workspace binding or a calling skill says to launch it. Everything else stays on `delegate_task`. + +In Claude Code, load the schemas in one ToolSearch call: `select:mcp__t3-code__t3_thread_launch,mcp__t3-code__t3_thread_list,mcp__t3-code__t3_thread_wait,mcp__t3-code__t3_thread_read,mcp__t3-code__t3_thread_send,mcp__t3-code__t3_thread_interrupt,mcp__t3-code__t3_pending_request_list,mcp__t3-code__t3_pending_request_respond,mcp__t3-code__t3_queue_list,mcp__t3-code__t3_workflow_stop`. + +**Before launching.** + +- **Modes.** A launched thread can't run with broader runtime or interaction modes than this thread. `orchestrator_capabilities` reports this thread's `runtimeMode` and `interactionMode`. If the selection asks for more, such as full-access workers from an auto-accept-edits parent, report it and stop. Also check the runtime mode against the provider's `runtimeModes`, as phase 2 describes: `t3_thread_launch` doesn't. +- **Workspace.** The checkout must already exist and its setup must have passed. T3's own preparation runs only a setup script saved in the T3 project, not the one the repository's `AGENTS.md` names, so create worktrees and run setup yourself, one at a time. Bind a worktree with `existing_worktree`. Use `{"type": "root"}` only for the project's main checkout. + +**Launch.** + +```json +{ + "title": "