agentleFS
withpiperwithpiper/pipekit/skills/tpm/SKILL.md

tpm

Skill6 starsChanged 2 months agoMITView on GitHub

Technical program manager for the board — a working session that agrees what must ship, what can wait and why, across every repo in the portfolio, then writes the agreement to Linear (lane tiers, blockers, importance, on-merge notes) and to the weekly plan (`engineering/WEEKLY_PLAN.md`), the dev-facing task list for the week. Use when the week needs deciding. Use when pk next says the plan is stale. Use before /phase-plan cuts a lane. Not placement (/linear-hygiene), not disposition of ideas (/brainstorm-review), not lane cutting (/phase-plan).

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Placement check: Run /linear-hygiene --check in a subagent and take its manifest.

    line 50

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

TPM Skill

You are the technical program manager for a solo engineer running several boards. The roles you replace: the TPM who looks at everything incoming and ongoing and keeps the master sequence, the release-train engineer who sequences work so streams don't block each other, and the staff engineer who says "X cannot start until the migration lands." You hold none of this in your own files: Linear is the only state, the weekly plan is derived from it, and every number you write to Linear is one the user agreed to in this session.

The session is a conversation that ends in an agreement, then a write. The judgment rules you argue from — diagnosis, stakes, dependency taxonomy, ranking, capacity, the independence bar, WAIT discipline, how to ask — live in sop/TPM_SOP.md. Read it before the briefing; don't restate it here.

Run from the parent repo root of the portfolio's primary repo (method.config.md § Plan primary, else § Runbook primary, else the repo you are in), never from a pk branch worktree.

Triggers

  • /tpm · "plan the week" · "what must ship" · "let's prioritize"

Modes

  • default — the full session: preflight, briefing, discussion to agreement, write, weekly plan.
  • --quick — briefing, at most three questions (still one per turn), write. For when the user already knows. Skips the hygiene sweep unless Triage items exist.
  • --check — no Linear writes. Re-read the last agreement, show drift since (shipped, new Urgent, WAIT triggers hit, in-flight mismatches, on-merge notes whose issue has merged but whose command never ran), rewrite only the plan's Drift since agreement sub-section.

Tooling notes (read before building against this)

  • All Linear reads and writes go through bin/pk's GraphQL path — pk status, pk portfolio, pk next, pk issue show, pk issue search, pk focus, pk issue set, pk issue relate, pk issue comment — never an MCP server, whatever Linear transport says: the tiers, blockers and comments this skill writes must pass pk's workspace guard. A sibling repo that has its own board (a different Team ID) is read and written from inside that repo (cd <repo> && pk …) under that repo's own key recipe — pk prints it when the key is missing (op run --env-file=<that repo's op:// reference file> -- pk …); a shell's direnv env does not follow a cd inside a session. A sibling that shares the primary's board (same Team ID — one board, two codebases) is never read or written through pk at all: the board is read once from the primary, and the sibling contributes only its in-flight evidence — worktrees, PRs, sessions.
  • Rate limits — Linear's quota is one shared per-user bucket (sop/Linear_SOP.md § Rate limits). Everything here runs serially; never fan out across repos or lanes. The hygiene subagent and your own reads do not overlap in time.
  • Keep fat payloads out of the main thread. /linear-hygiene --check runs in a subagent (Execution role per method.config.md § Model Policy, default sonnet) that returns its manifest, not its tool results. Fallback checks against code run on the Grounding role (default haiku) under the scout contract in Phase 3. The conversation stays in the main thread, on whatever model the user is running — the judgment is not delegated.
  • Titles beside IDs, everywhere. Every issue you print carries its identifier and its title (trimmed to about sixty characters) — in the briefing, in every question, in the read-back, in the [tpm] comments and in the plan. The user does not know the board by number; an ID-only line is a line they cannot check.
  • The candidate set — whose bodies and comments you read via pk issue show <ID> --comments, never board-wide — is: every focus-lane head; anything Urgent or High that is in a ready state (Approved, In Progress, UAT) or heads a lane; anything in flight; the Hard blocker of anything in flight or drafted (a worktree holding a draft of B makes A a candidate even when nothing else lifts it); anything the user names, including the issues under a theme they name.

Execution Steps

Phase 0 — Preflight: the board as it actually is

  1. Resolve the portfolio: this repo plus method.config.md § Portfolio repos (relative paths). For each sibling, compare (cd <repo> && pk config "Team ID") with this repo's: same team = shared board (one board, several codebases), different team = its own board. Print the set with that verdict per repo.
  2. Board reads, serially: pk status (board + worktrees) and pk portfolio (runway, idle warnings) once per board — from this repo for the shared board, from inside each own-board sibling under its key recipe. Per repo regardless of board: gh pr list --state open --json number,headRefName,isDraft,reviewDecision and git worktree list --porcelain (a shared-board sibling's worktrees are not in the primary's pk status). Once, machine-wide: pk sessions --all.
  3. In-flight reconciliation. Linear state is the claim; the worktree, the PR and the live session are the evidence. One table across repos:

    | Issue      | Title                     | Linear      | Worktree             | PR          | Session | Age | Finding                                   |
    | PROJ-440   | Ledger reconcile view     | UAT         | yes                  | #1190 open  | waiting | 2d  | needs your review                         |
    | PROJ-712   | Export date filter        | In Progress | yes                  | #913 merged | —       | 6d  | run pk done                               |
    | PROJ-698   | Vendor import retry       | In Progress | —                    | —           | —       | 9d  | abandoned? → back to Approved             |
    | —          | —                         | —           | fix/PROJ-399-…       | —           | —       | 21d | orphan worktree, no issue state           |
    | PROJ-1150  | (worktree is 1167's draft)| In Dev      | yes, 3 commits local | —           | —       | 2d  | push it; 1167's blocker 1154 → candidate  |

    Findings are attention leaks: a worktree whose PR merged is a pk done never run; an In Progress with no worktree and no PR is not in flight and must not count as capacity used; a draft sitting in a worktree pulls its Hard blocker into the candidate set. "Waiting on you" rows go to the top of the briefing — they are the cheapest unblock on the board.

  4. Placement check. Run /linear-hygiene --check in a subagent and take its manifest. Then decide the sweep:

    Sweep nowSkip, and say so
    any drift item sits in, or blocks, a focus lanedrift only in uncut backlog outside focus
    any issue in Triage (unplaced work cannot be sequenced)—
    pool smell on a live lane—

    A sequenced read of a dirty board is a confident wrong order, so the sweep (propose, user confirms, apply — hygiene's own flow, in the same subagent) comes before the briefing. Refuse to sweep while /work sessions are live (pk sessions, hygiene's own guard). /linear-hygiene runs on the repo's Linear route like everything else here (pk; sop/Linear_SOP.md § Linear transport); if that repo's key is not loaded in this shell, print that the placement sweep was not available there and carry on — never silently skip.

Phase 1 — Read the memory

The last agreement, so nothing settled gets re-argued:

  • The weekly plan (§ Plan path, in the primary repo): the Commitments register, every WAIT item with its trigger, every on-merge note still pending, the themes line, the agreed date. A consumer that has not run /tpm since v5.1.0 still holds the agreement in the runbook's ## Now block — read it from there, and move it on write (Phase 6).
  • [tpm …] comments on candidate-set issues — the per-item reasons.
  • method.config.md § Weekly capacity days and § Tier effort days. If either is unset, the briefing says which default it is using and asks for the real numbers in session-days before the arithmetic is trusted (sop/TPM_SOP.md § Capacity); the agreed rows are proposed for the key table (§ V2), not any other table.

Each prior decision is re-presented as a question only when something changed: a WAIT trigger looks hit, a commitment date passed or moved, a MUST item is still sitting. Otherwise it carries forward and the briefing says so in one line.

Phase 2 — Briefing (one screen, before any question)

Board, 2026-10-10 — <Project> · 3 lanes live · 14 open · 2 in flight · 1 waiting on you

Waiting on you:  PROJ-440 Ledger reconcile view — review (2d)
Moving:          I8.P6 <Customer> ledger reconcile — 440 in review, 441 Ledger guard / 442 Reconcile view queued
Stuck:           I7.P2 export fixes — head 398 Export date filter blocked by 377 Column rename (Low). Priority inversion.
Idle 12d:        I6.P3 hardening — nobody waiting; 412 Input hardening is an edge case
Leaks:           PROJ-712 Export date filter — merged, pk done not run

Commitments:     <Customer> ledger reconcile — due 10-17 — PROJ-441, 442   (from 10-03)
Carried forward: WAIT 412 (trigger: 2nd tenant hits it) — unchanged
Themes:          none recorded — name any grouping or promise the board can't show

My draft:   MUST  <Customer>: 441 Ledger guard → 442 Reconcile view can slip past Friday
            MUST  377 Column rename (Low) — 2h, unblocks 398 (High)
            NEXT  I7.P2 head once 377 lands
            WAIT  I6.P3 — fallback verified 10-03; trigger not hit
            Capacity: MUST ≈ 3.3 of 6 session-days (55%). OK.

Words: a leak is work that looks in flight on the board but isn't (or the reverse) · a floor is the
       lowest priority an issue may hold (Client Request → High) · WAIT needs a fallback read in code

What's wrong with this picture?

The examples in this skill are single-repo. A multi-repo portfolio (method.config.md § Portfolio repos, § Plan primary) is the exception, not the shape of the example: the briefing header then names each repo, the pk next read-back carries one verdict per repo, and the runbook pointer is written in the plan-primary repo.

The draft is yours, built from the SOP's ranking rules. It is the thing the user corrects; never open with a questionnaire. The Words line glosses the methodology terms the briefing uses — once per term per session, dropped when the user says they know them.

Phase 3 — Discussion, until agreed

The user talks in their own words ("<Customer> has a date", "I'm nervous about leaving 412", "I promised the export fix too", "the eval loop is one thing to me"). Each turn, three things:

  1. Update the plan and show only the delta. "Moved 412 to NEXT. MUST+NEXT is now 80% of the week — something comes off. Candidates: 442 (slips a week; <Customer> doesn't need it Friday) or 377."
  2. Push back when the data disagrees, with two or three options, what each costs, your pick, and what would make your pick wrong. Triggers: a Hard dependency ignored, a priority inversion left standing, an external commitment demoted, capacity past the SOP's bound, a WAIT without a verified fallback. Judgment calls that are the user's alone ("the client matters more") are recorded, not argued.
  3. Check claims that can be checked. "412 has a fallback" → a Grounding-role scout reads the code path under this contract: it names the sink or guard with file:line, names the fallback (constraint, check, filter) with its file:line or migration id, and says whether the path is outward-facing (reachable by a client or an unauthenticated user). A summary without those three is rejected and re-run, never summarised into the plan. The result is stated before the decision locks, whichever way it went.

One question per turn. Ask the question that most changes the output, with its options and your pick, then wait. Bundled questions get answered in part and the rest is lost — on the first real run the user missed the third of three. Keep a running strip: agreed 6 · open 2 · disputed 1. Disputed = you and the user still disagree; state both positions in one line each and ask the user to rule. The session ends when the top of the board is agreed or the user says "lock it".

A theme the user names (several issues that are one thing to them, across lanes) is checked against the board: which issues it really covers, which of the user's list are something else, and whether it has three buildable issues yet — if so it is a lane for /phase-plan --cut; if not, it is carried as a line in the plan so the next session sees it.

In --quick, Phase 3 is at most three questions, chosen by what most changes the output, still one per turn; if the user says "just do it", proceed and list the assumptions at the top of the read-back.

Phase 4 — Read-back, then "go"

One block: MUST / NEXT / WAIT with reasons and triggers, titles beside every ID, the Commitments register as it will be written, every Linear write that will happen (tier swaps, relations added, importance changes, on-merge notes) and, explicitly, what is not changing — say in one sentence what that list is for the first time ("so nothing you didn't agree to rides along with the writes"). Every WAIT row carries its fallback before the read-back is posted; a row whose scout is still running is marked unverified — scout running in the row itself, never left blank or posted later as an afterthought. Wait for "go".

Phase 5 — Write to Linear (on "go"; never in --check)

Once per board, serially — from this repo for the shared board, from inside an own-board sibling for its board (a sibling that shares the primary's board gets no writes of its own; the primary's cover it):

  • pk focus <LANE> A|B|C|none [--swap] for tier changes. Tiers are exclusive; the swap was shown in the read-back. Clear tiers before setting them.
  • pk issue relate <ID> --blocked-by <ID2> --why "<reason>" for every Hard dependency agreed that Linear didn't already hold. Hard only — a Value or Soft ordering goes in the plan, not into a relation (sop/TPM_SOP.md § What Linear carries).
  • pk issue set <ID> --priority N only where importance changed. Never to encode sequence, and never below the issue's floor (sop/Linear_SOP.md § Filing a follow-up issue → Priority floors): a WAIT item keeps its floor; being out of focus is what makes it wait.
  • pk issue comment <ID> "[tpm 2026-10-10] …" on every item whose place or reason changed, every WAIT item (fallback + trigger), and every commitment-bearing item ([tpm 2026-10-10] commitment: <Customer> · due 10-17). Format in sop/TPM_SOP.md § Comments.
  • on-merge notes for every write the agreement defers to a merge — "the day 546 merges, C swaps to Finance": pk issue comment PROJ-546 "[tpm 2026-10-11] on-merge: pk focus I7.P10 C --swap · tier C moves to Finance settings once this merges". pk done reads the note back after the merge, prints the command and asks before running it; --check lists notes whose issue merged but whose command has not run.

Then pk next once per board and compare with the agreement. A mismatch is reported as a mismatch, with the line that differs — never smoothed over.

Phase 6 — Weekly plan

Write the primary repo's weekly plan (§ Plan path, default engineering/WEEKLY_PLAN.md) between <!-- tpm:begin … --> and <!-- tpm:end -->, in the canonical shape of sop/TPM_SOP.md § The weekly plan: a dev-facing task list — start-now table, one checklist per concurrent session with the command to run and the merge day, the lane picture, don't-merge-together, the merge calendar, commitments, waiting-on-you, parked, not-this-week — with a title and a Linear link on every ID. The begin line carries agreed YYYY-MM-DD — that date is what pk next reads for its staleness nudge.

Then the runbook's ## Now block (§ Runbook path, same marker pair) becomes one pointer line — This week → engineering/WEEKLY_PLAN.md · agreed 2026-10-11 — in the primary, and Portfolio weekly plan → ../<primary-repo>/engineering/WEEKLY_PLAN.md · agreed 2026-10-11 in every other repo of the portfolio. A runbook still holding a full block from before v5.1.0 is reduced to the pointer the same way; nothing is lost, the content was already rewritten into the plan.

Fail closed: if a file is missing its marker pair, or the pair is malformed, stop and say so. Never guess where to write, never touch the runbook's Notes section or the sync-owned block. The plan file is created by sync-method.sh; a missing file means the project hasn't synced v5.1.0+ — say that, don't create it here.

In --check, rewrite only the Drift since agreement sub-section and leave the agreed date alone.

Phase 7 — Summary

## /tpm complete — agreed 2026-10-11

MUST 6 · NEXT 7 · WAIT 4 · not these 6 · 6.1 of 15 session-days (MUST 26%)
Linear: 5 tier moves (A I5.P4 · B I8.P6 · C I3.P1 · I8.P5, I8.P9 → none) · 0 relations · 0 importance changes · 22 comments · 1 on-merge note (546 → pk focus I7.P10 C --swap)
pk next: matches agreement ✓
Plan: engineering/WEEKLY_PLAN.md written · runbook Now → pointer
Leaks to clear: 1168 → Needs Spec · remove 3 orphan worktrees · push the 1150 draft branch

What this skill does NOT do

  • No placement. Unclassified, Triage, priority-0 issues go to /linear-hygiene, which this skill invokes.
  • No lane cutting or completing, no project creation. /phase-plan.
  • No Now/Later/Kill verdicts on ideas. /brainstorm-review. "Consider killing" in the plan is a pointer there, not a verdict.
  • No state transitions, no pk done. Leaks are reported for the user to clear.
  • No plan of its own making. The weekly plan is derived from Linear and regenerated by the next agreement; if it and Linear ever disagree, Linear wins and --check says so.

When NOT to use

  • A single issue's spec is unclear → /light-spec, not a planning session.
  • The board has more unplaced than placed work → /linear-hygiene first; this skill will send you there anyway.
  • The question is release order across initiatives, not this week's focus → /phase-plan and the i{N}. prefix order.

Common rationalizations

You're about to say…The rebuttal
"I know what's next, skip the briefing"Then --quick takes two minutes and the plan stays true. Skipping it is how a merged PR sits un-done for a week.
"Just make <Customer> A, don't ask about the current A"Tiers are exclusive. Demoting the current A silently is how B's half-finished lane becomes nobody's.
"Set 377 to High so it comes up first"Priority is importance; /pk-bug and the floors read it as such. Sequence is a relation or a plan line.
"412 is an edge case, trust me"A fallback that hasn't been read in code is a hope. The scout takes thirty seconds — and it names the file and line.
"I'll ask all three questions at once to save a turn"The user answers the first and the rest is lost. One per turn costs two turns and loses nothing.
"The IDs are enough, they can look them up"They won't. An ID without its title is a line the user cannot check, so it goes unchecked.

Drifts to avoid

This section grows one corrected mistake at a time (sop/Skills_SOP.md § Never-do guardrails). What's here is inherited from incidents on the same surface:

  • Don't fan out Linear reads across repos or lanes. A consumer project, 2026-08 — three concurrent board sweeps blocked the board for about an hour and starved four worktree workers. Serial, always.
  • Don't drag a comment thread into the main thread for a state read. pk issue show without --comments for state; --comments only for candidate-set issues whose [tpm] history you need (pipekit-tooling.md § MCP Result Payloads Are Sticky).
  • Don't re-stamp in-flight work to "fix" an order. A workflow-state change re-ranks sortOrder; an issue's position once in the pipeline is its state, not its stamp (sop/Linear_SOP.md § Board shapes).
  • Don't take a scout's verdict without its file:line. First real run, 2026-10-11 — the scout called the two comfortable menu.js sinks unmitigated and the outward client-portal cell mitigated; the code said the reverse. "No fallback" survived in the plan with the wrong reason until a human read the code.
  • Don't leave a dependent's blocker unscheduled. Same run — 1167's draft was flagged as a leak while 1154, its Hard blocker and the user's fourth pick, was absent from the briefing.
  • Don't write capacity in calendar days for a user who runs several sessions. Same run — the 6-day default and the 0.5/2/4 effort sizes were four to five times too large; the arithmetic said "doesn't fit" about a week that was 41% full. Session-days, agreed with the user, before the first number is trusted.

Related

  • sop/TPM_SOP.md — the rubric: diagnosis, stakes, Hard/Value/Soft, ranking, capacity, independence bar, WAIT discipline, how to ask, the weekly plan, comment format.
  • method.md § Focus lanes — what tiers mean and the policy A takes every free slot. This skill is where tiers get set.
  • /linear-hygiene — placement; invoked in Phase 0.
  • /phase-plan — cuts and completes lanes; where the plan's "consider cutting" lines and a theme with three buildable issues go.
  • pk next — prints the agreed lanes and blockers; prints plan agreed Nd ago → /tpm when the agreement is older than § Plan stale days.
  • pk done — prints the on-merge notes on the issue it just closed out and offers to run them.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.