trusty-mpm 1.3.5

trusty-mpm: unified multi-agent orchestration platform (core, daemon, CLI, TUI, Telegram)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
---
name: tm-workflow
description: The single trusty-mpm delivery workflow — phases and gates, the ticketing/workflow/version-control ownership boundary and handoff, worktree and branch discipline, changelog, PR body, review gate, squash-merge, cleanup, and how a project customizes the workflow via CLAUDE.md
user-invocable: true
version: "2.0.0"
category: pm-workflow
tags: [workflow, delivery-chain, pr, branch-protection, worktree, changelog, customization, verification-gates, pm-required]
effort: medium
---

# tm-workflow — The Delivery Workflow

<!-- #5202: this skill absorbed the retired `tm-pr-workflow`. There is one
     workflow skill. Issue policy lives in `tm-ticketing`; git and PR API
     mechanics live in the `version-control` agent. -->

This is the **sole workflow authority**: the complete sequence from an accepted
outcome to a merged PR and a closed issue, plus the gates applied along the way
and the mechanism a project uses to customize any of it.

It states policy and performs no operations. It never creates or mutates an
issue, a branch, a commit, or a PR — those are delegated, per the boundary
below.

## Ownership Boundary — Route by Artifact, Not by Verb

| Surface | Owns | Does not own |
|---|---|---|
| Core PM instructions | Detect the work shape, load this skill and `tm-ticketing`, preserve user authority, route the resulting actions | Tracker, git, or PR mechanics |
| **`tm-workflow`** (here) | The delivery sequence and its policy: phases/gates, worktree/branch conventions, changelog, PR body requirements, review, merge, cleanup, handoffs | Creating or mutating issues, branches, commits, or PRs |
| `tm-ticketing` + the `ticketing` agent | Whether an issue should exist; search/dedup; issue title and body; labels, assignee, milestone, comments, state, parent/child links | Any git operation, and any PR mutation — including PR title and body |
| The `version-control` agent | Branch/worktree/commit/push mechanics and the whole PR lifecycle: create, title/body, issue-closing links, reviewers, checks, update-branch, merge, branch cleanup | Authoring workflow policy, deciding whether an issue is warranted, changing issue metadata or state |

**The rule is the artifact, not "bookkeeping versus mechanics."** Every Issue API
operation (`gh issue …`, `mcp__mcp-ticketer__*`, `aitrackdown`) routes to
`ticketing` under P6. Every Pull Request API operation (`gh pr …`, including
`create`, `edit`, `view`, `list`, `diff`, `review`, `checks`, `update-branch`,
`merge`) and every git operation routes to `version-control` under P7. A PR body
is part of the PR, so it is version control's — splitting one `gh pr edit` across
two agents was the defect this replaced.

### The Handoff (stated once, here)

1. **PM → `ticketing`**: the finding or accepted outcome. Ticketing runs its own
   promotion and dedup gate and returns the canonical issue ID/URL, the outcome
   statement, and the closure conditions.
2. **PM → `version-control`**: the work summary, files changed, test evidence,
   the review verdict, and the issue context ticketing returned. Version control
   writes the PR body and inserts the correct `Closes owner/repo#N` (or a
   non-closing relationship link when the PR does not finish the issue).
3. **After merge, PM → `ticketing`**: the merged PR number and squash SHA, for
   the completion comment or the close.

**Neither specialist delegates to the other.** The PM carries context between
them. A `ticketing` dispatch that ends "…then have version-control open the PR"
is a routing error.

## The Full Delivery Chain

```
accepted outcome -> optional issue -> worktree branch -> one cohesive PR
                 -> applicable gates -> trusty-review gate
                 -> squash-merge -> worktree cleanup -> issue closed
```

The chain starts at an **accepted outcome**, not at a ticket. The issue step is
**optional** for docs/CI/chore work and for a small fix the user explicitly asked
for that completes in one PR. It stays **required** for features, reproduced
defects, security work, cross-release dependencies, and any work that must
survive the current session. Whether a given finding earns an issue at all is
decided by the promotion gate in `tm-ticketing`, not here.

Every other step matters. Skipping the worktree step or the review gate is a
protocol violation the PM must not take on the user's behalf unasked.

## One Outcome, One PR

A PR contains one primary outcome and everything required to make that outcome
safely shippable: implementation, regression tests, necessary refactoring,
documentation/API updates, the changelog fragment, and in-scope review fixes.

- Do not split those artifacts into separate PRs because different agents
  produced them. The engineer's code, the QA agent's test, and the doc update for
  one outcome are one PR.
- **One PR may close several tickets** when one coherent change satisfies them
  (`Closes #A`, `Closes #B`). Prefer that over several coupled PRs with an
  artificial merge order.
- Split only when the outcomes can be reviewed, deployed, or reverted
  independently, or when risk or size makes a stack materially safer to review.

## The 5-Phase Model and Its Dispatch Briefs

The instruction package's CORE phase table is canonical for **whether** a phase
runs and carries each skip condition. Where a phase runs, its gate is blocking —
"conditional" governs entry, never rigour (#4594). A project may replace the
whole workflow section via a `WORKFLOW` marker in its `CLAUDE.md` (see
"Customizing the Workflow" below) if its delivery process differs.

**Phase 1 — Research** (`research`). Required for ambiguous requirements,
multiple possible approaches, or an unfamiliar codebase. Skipped when the user
gave an explicit command or the task is simple operational work.

```
Task: Analyze requirements for [feature]
Return: Technical requirements, gaps, measurable criteria, approach
```

**Phase 2 — Code Analysis** (`code-analyzer`, sonnet — NOT `code-critic`, which
is a separate agent).

```
Task: Review proposed solution
Use: think/deepthink for analysis
Return: Approval status with specific recommendations
```

Decision: APPROVED → Implementation. NEEDS_IMPROVEMENT → back to Research.
BLOCKED → escalate to the user.

**Phase 3 — Implementation** (the language-specific engineer where one exists).
Requirements: complete code, error handling, test proof, and the changelog entry
described below. Skip only for docs-only/CI-only changes.

**Phase 4 — QA.** Routing: `api-qa` for APIs, `web-qa` for UI, `qa` otherwise.
The gate itself is `tm-verification-protocols`.

**Phase 5 — Documentation** (`documentation`). Skipped for an internal refactor
with no public API change.

### Override Commands

| User says | Effect |
|---|---|
| "Skip workflow" | Bypass the phase sequence |
| "Go directly to [phase]" | Jump to that phase |
| "No QA needed" | Skip phase 4 (not recommended) |
| "Emergency fix" | Bypass Research |

Honour the override and name the bypassed gate in the completion report, so the
missing evidence is visible rather than implied.

### Verification Gates Are Not an Override Target

The verification-gate contract in `tm-verification-protocols` is a
project-independent invariant enforced by CB#8. A custom `WORKFLOW` override can
change *when* QA runs, never *whether* a completion claim requires evidence.

## Sprint, then Harden — the Rest of the Doctrine

The instruction package states the two phases, where to spend the verification
budget, and the hard line (never turn red green by deleting coverage). Two
derived rules live here because they apply only at a specific moment:

- **A branch that has drawn 3+ review rounds is evidence to close and fold**, not
  to attempt round 4. Worked example: #4202 → #4207.
- **Branch = workstream, and it is durable. Worktree = writer, and it is
  ephemeral.** Keep worktrees short-lived; keep branches workstream-scoped.

Slow feature release *causes* too many things in flight. Shortening time-to-land
is the fix; capping WIP treats the symptom.

## Worktree Discipline (Mandatory Before Any Edit)

The main checkout is **inspection-only** — read-only `git status`/`log`/`diff`/
`show` and file reads. No edits, no builds or test runs (whatever the project's
gate is: `cargo build`/`test`, `npm run build`/`test`, `pytest`, …), no
destructive git ops. All write-side work happens in a dedicated worktree branched
off `origin/main`:

```bash
git fetch origin main
git worktree add -b <feature-or-fix-branch> \
                  .claude/worktrees/<dirname> origin/main
cd .claude/worktrees/<dirname>
```

Always `git fetch origin main` first and branch off `origin/main`, never local
`main` — local `main` can be stale and branching from it has caused lost commits.

**Experiments stay session-local.** Promote an experiment to a branch and
worktree only once its result is accepted for implementation.

Every subagent dispatch must name the exact worktree path it is confined to, and
must forbid leaving it into the main checkout, `git reset --hard`,
`git checkout .`, and `git stash` against main. QA agents get their own worktree
(e.g. `.claude/worktrees/qa-<ticket-or-pass>`), same as engineering agents.

Clean up after merge with `git worktree remove --force <path>` (which deletes the
worktree directory and never the main checkout), then `git branch -D <branch>`
and, when the squash-merge did not already do it, `git push origin --delete
<branch>` — the branch goes last, because until the squash-merge lands it is the
only durable copy of the workstream.

**Escape hatch — stash first.** If you genuinely must run one command from the
main checkout, stash, operate, restore:

```bash
git -C /path/to/main-checkout stash push -u -m "pre-op-safety $(date +%s)"
# … do the op …
git -C /path/to/main-checkout stash pop
```

Surface the stash name in your report if popping fails, so a human can restore
it manually.

## Git Security Review (Mandatory Before Push)

Before any `git push`, delegate a credential scan to the `security` agent:

1. `git diff origin/main HEAD` — the diff about to be pushed.
2. `security` scans it for API keys, passwords, private keys, and tokens, and
   returns either clean or the list of blocked items.
3. **Block the push if secrets are detected.** A leaked credential in git history
   survives the commit being reverted.

## Branch Protection

All pushes to `main`/`master` require a feature branch + PR — no exceptions,
including "trivial" docs/chore/typo work (which may skip the linked-issue step
but still requires branch + PR + squash-merge). The only bypass is release
tooling (version-bump / lockfile-update commits per the release workflow), and
only for those commit types.

When a user asks to "commit to main" / "push to main" / "merge to main",
proactively translate: "Creating feature branch workflow instead" — don't wait
for a git error to correct course.

## Changelog Requirement (Before Merge)

Changelogs go stale when updating them is left to "sometime at release", so it is
part of every PR. Every PR that changes a package's source records one bullet per
user-visible change. Docs-only / CI-only PRs may skip this.

**Prefer a per-PR fragment file.** When the package has a `changelog.d/`
directory, that is where the entry goes:

```
<package>/changelog.d/<issue-or-pr-number>-<short-slug>.md

Fixed   <- line 1: Breaking|Added|Fixed|Performance|Changed|Removed|Security|Documentation

- the bullet text, in the package CHANGELOG's existing style
```

One new file per PR, named after the issue/PR number, means two concurrent PRs
never touch the same lines. A shared `## [Unreleased]` section guarantees a
conflict instead. Release time assembles the fragments into `CHANGELOG.md` and
deletes them; never hand-edit `CHANGELOG.md` in a package that uses fragments.

If the package has no `changelog.d/`, add the bullet to `CHANGELOG.md` under the
topmost `## [Unreleased]` heading (create it if absent), matching the file's
existing style.

- A PR that changes source and lands without a matching changelog entry is a
  **review-gate failure** — the same tier as a failing build/test/lint gate.
  Treat it exactly like CB#8: block the merge, delegate back to the engineer,
  don't wave it through as "trivial."
- If the project also runs automated changelog generation at release time, check
  the project's root `CLAUDE.md` for which mechanism owns `CHANGELOG.md` before
  assuming they coexist. Two writers to one file is a defect; do not invent a
  precedence rule on the fly.

## Minimal PR Body (seven fields)

The `version-control` agent writes this; the PM supplies the material.

1. Primary outcome and linked issue(s), with the `Closes owner/repo#N` link.
2. What changed, and what is intentionally out of scope.
3. Risk / blast radius.
4. Test evidence at the applicable levels.
5. Baseline/pre-existing failures and their canonical issue (see below).
6. Documentation/changelog status.
7. Review-finding disposition: fixed here, kept on the parent, or separately
   ticketed.

**PR body freshness**: when scope or claims change mid-flight, delegate the
update to `version-control` immediately rather than leaving stale assertions.

## Baseline-Failure Protocol (Red That Isn't Yours)

When a required gate goes red, establish whose red it is before doing anything
else.

1. Never turn red green by removing coverage. That hard line is stated in the
   instruction package ("Sprint, then Harden") and is the entry condition for the
   rest of this protocol.
2. Determine whether the branch caused the failure: run the same gate on the base
   branch, check the failing test's recent history, or reproduce it in isolation.
3. **Branch-caused** → fix it in this PR.
4. **Pre-existing** → the disposition is `tm-ticketing`'s to decide (`COMMENT`,
   `REOPEN`, `NEW REGRESSION`, or `NO TICKET`). Hand the run URL, SHA, command,
   and failure signature to `ticketing` and let its gate choose; a single
   unrelated red run is an observation, not automatically a ticket.
5. Report the gate result in exactly this shape:

   ```
   change-specific gates pass; <gate name> blocked by canonical issue #N
   ```

   Never report "all tests pass" while a gate is red, whoever caused it. Merge
   disposition then follows branch protection and the risk tier; a red required
   check is never merged around.

## The trusty-review Gate

Before merge, delegate to the review gate:

```
mcp__trusty-review__review_diff   # in-progress diff review
mcp__trusty-review__review_pr     # open-PR review (correctness/design/security)
```

This is CB#8's evidence for a PR-shaped completion claim — "the PR is ready"
requires a review verdict (or human approval), not just green CI.

## Squash-Merge Is Required

PRs merge via **squash-merge only** — one clean commit on `main` per PR. Delete
the feature branch immediately after. No merge commits, no rebase-merge, for PRs
landing on `main`.

```bash
gh pr merge <PR> --squash --delete-branch
```

After a squash-merge the local feature branch shows as "unmerged" to git (the
squashed commit has a different hash). That is expected, not a failed merge.

## Shipped Defaults on the PR

These trusty-mpm framework defaults override any harness default and belong in
the `version-control` delegation brief:

- **`--assignee @me --label trusty-mpm --label ws/<session-name>`** on every
  `gh pr create`. The assignee + `trusty-mpm` label identify which PRs a
  trusty-mpm session owns; `ws/<session-name>` (this session's tmux session name,
  via `tmux display-message -p '#{session_name}'`) tracks per-workstream
  activity. A workstream is a **label**, never a milestone.

  ```bash
  gh label create trusty-mpm \
    --description "Created/managed by a trusty-mpm session" --color 8250df \
    2>/dev/null || true
  gh pr create --assignee @me --label trusty-mpm --label "ws/<session-name>" \
    --title "…" --body "…"
  ```

  The equivalent issue-side defaults, and the type/component/priority label
  families that stack on them, are `tm-ticketing`'s — do not restate them in a
  version-control brief.

- **Attribution footer** — every commit message and PR body ends with exactly:

  ```
  🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
  ```

  NEVER emit `🤖 Generated with Claude Code` or a `Co-Authored-By: Claude …`
  trailer. This is a Framework-Guaranteed Convention stated in the instruction
  package; it is repeated here because it must appear verbatim in the delegation
  brief.

## Delegating the PR

PR creation and every later PR edit go to `version-control` — branch push,
`gh pr create`, the body, the issue-closing link, reviewers, `gh pr checks`, and
the merge. Give it: work summary, files changed, test status, the trusty-review
verdict, the canonical issue context from `ticketing`, and the shipped defaults
above. The PM constructs the brief; it never runs `gh pr` itself (P7 / CB#6).

## Customizing the Workflow

trusty-mpm has no separate "workflow engine" a project configures at runtime. The
PM's phase/gate behavior comes from the bundled instruction package, and a
project customizes it via named-section marker blocks in its root `CLAUDE.md`.
This is implemented in `core/instruction_overrides.rs`,
`core/instruction_pipeline.rs`, and `core/claude_md_sections.rs`.

### How the PM Prompt Is Assembled

The bundled PM prompt has one source of truth: the JSON manifest
`assets/instructions/pm-instruction-package.json` (schema v2), embedded at
compile time via `bundled_pm_package.rs`. It declares section order and
composition; the prose for each section is stored separately in
`assets/instructions/sections/*.md`, pulled in as `include_str!` constants
registered in the `SECTION_SOURCES` table (`core/instruction_pipeline.rs`) — a
missing section file is a compile error, not a launch-time surprise. The nine
marker tokens (`core/claude_md_sections.rs::section_token`) are `IDENTITY`,
`CORE`, `MEMORY`, `SEARCH`, `WORKFLOW`, `AGENT-DELEGATION`, `ENFORCEMENT`,
`NON-OVERRIDABLE-RULES`, and `FRAMEWORK-GUARANTEED-CONVENTIONS`.

**`CORE` is the only one a project cannot replace.** Every other section,
including `NON-OVERRIDABLE-RULES` and `FRAMEWORK-GUARANTEED-CONVENTIONS`, can be
overridden — there is no separate "floor" concept anymore (the
`is_floor()`/`instruction_floor.sha256` machinery was retired by #4286, being the
appearance of a control rather than one a project-owned `CLAUDE.md` could
enforce).

At session start, `core/instruction_overrides.rs::resolve_pm_prompt` (reached via
`build_system_prompt_for*`) composes the final prompt. It is not a file a user
edits — it is composed fresh per launch.

### The One Customization Surface

A project customizes any non-`CORE` section exactly one way: a named-section
marker, `<!-- TRUSTY-MPM: <TOKEN> START v=1 -->` … `<!-- TRUSTY-MPM: <TOKEN> END
-->`, in the project's root `CLAUDE.md` — the sole marker host
(`core/claude_md_sections.rs::HOST_FILES`). This replaces exactly the matching
section, nothing else.

The five legacy per-file overrides
(`.trusty-mpm/{INSTRUCTIONS,AGENT_DELEGATION,WORKFLOW,MEMORY,
PM_INSTRUCTIONS_DEPLOYED}.md`) are RETIRED (#4286) and never read. Never create
one; if a project still has one, move its contents into `CLAUDE.md` and delete
the file — `tm doctor`'s `legacy_overrides` check fails until it is gone.

`CLAUDE.md` is resident in EVERY prompt, so every line there is a standing
per-turn cost. Content needed on every prompt belongs there; content needed only
sometimes belongs in a skill, a doc, or memory.

Robustness: a missing `CLAUDE.md`, a missing marker block, or an empty marker
body all fall back silently to the bundled default — a customization attempt
never blanks a section or crashes launch.

The agent-delegation roster is DYNAMIC, not authored prose: it comes from
`deployed_roster_section` → `roster_from_dirs`, a union of the project tier,
`$CLAUDE_CONFIG_DIR/agents`, and `~/.claude/agents`, rendered by
`generate_authority`. It is non-droppable — `validate_roster` rejects a package
where the roster generator is optional or absent (#4069).

### Trigger Phrases

| User says | PM writes to |
|---|---|
| "remember/always/never/for this project" | Plain prose in `CLAUDE.md` (no marker needed) |
| "use X agent for Y" / "route/change agent" | `<!-- TRUSTY-MPM: AGENT-DELEGATION START v=1 -->` block in `CLAUDE.md` |
| "add/change workflow phase" | `<!-- TRUSTY-MPM: WORKFLOW START v=1 -->` block in `CLAUDE.md` |
| "memory behavior" | `<!-- TRUSTY-MPM: MEMORY START v=1 -->` block in `CLAUDE.md` |

After writing an override, confirm the marker to the user and note it "takes
effect at next session startup" — the resolved prompt is assembled at
session-prepare time, not hot-reloaded.

### Inspecting the Resolved Prompt

```bash
tm sessions instructions       # prints the resolved prompt on stdout
cat .trusty-mpm/last-instructions.md   # the exact stash resolve_pm_prompt wrote
```

`tm sessions instructions` reports every applied, declined, and shadowed marker
on **stderr**, so `tm sessions instructions >/dev/null` alone answers "why didn't
my override apply?". `last-instructions.md` is written by `prepare_session` every
time a prompt is assembled, so the inspectable copy can never diverge from what
the PM received (#382).

## Related Skills

- `tm-ticketing` — whether an issue exists, and everything about its content and lifecycle
- `tm-git-file-tracking` — files must be tracked on the feature branch before PR creation
- `tm-delegation-patterns` — the agent-selection matrices this workflow routes into
- `tm-circuit-breaker` — CB#5 (delegation chain), CB#6 (forbidden `gh` usage), CB#8 (QA/review gate)
- `tm-verification-protocols` — the QA evidence standard every phase gate uses
- `tm-agent-architecture` — how the agents this workflow delegates to are built