The tech lead's standing loop for keeping development unblocked across a sprint. Defines phase-by-phase protocol enforcement, merge-queue monitoring, and escalation triggers. Invoke at session start, again after every significant state change, and whenever devs look idle.
Install
npx skillscat add loopdive/js2/tech-lead-loop Install via the SkillsCat registry.
Tech Lead Loop
The tech lead is the orchestrator of a multi-dev sprint. This skill defines the
standing loop the tech lead runs to keep development unblocked, enforce protocol,
and move the merge queue forward — without becoming a bottleneck.
The loop has five phases. You cycle through them continuously for the
duration of the sprint. Each phase has triggers, a checklist, and the specific
sub-skills / slash commands to invoke.
Never delegate understanding. This skill tells you what to check; you must
read the results and decide.
Principles
- Devs are authoritative for their own PRs. Tech lead only intervenes when a
dev is truly stuck, when claims conflict, or when the merge queue stalls. - TaskList is the canonical dispatch mechanism. Populate it at sprint start and whenever new issues are added mid-sprint. Devs self-serve — they claim tasks, self-merge, and claim the next task without waiting for tech lead direction.
- SendMessage only for escalations and exceptions. Devs contact tech lead only if TaskList is empty, they are blocked >30 min, or CI criteria force an escalation. Tech lead contacts devs only when they are stuck/silent or there is a file conflict to resolve.
- Every protocol correction issued to one dev should be generalized. If you
correct one dev, broadcast the canonical protocol to all devs within the next
cycle — individual corrections rot. - Keep tool calls parallel when independent. One message with five Bash
calls is dramatically faster than five sequential ones. - Measure the merge queue, not the task queue. The right metric is
"how many PRs are ready to merge but unmerged" — stalls there compound.
Phase 0 — Session start / context load
Trigger: fresh conversation, or resume after /compact or context rollover.
Checklist:
- Read the current sprint doc:
plan/issues/sprints/<N>/sprint.md - Read the tech lead handoff:
plan/agent-context/tech-lead.md git status && git branch --show-current && git log --oneline origin/main -10gh pr list --state open --limit 20— snapshot of inherited open PRsls .claude/worktrees/— inherited worktrees (may contain WIP)- Read
plan/method/file-locks.mdif it exists — active dev claims - Read
.claude/memory/MEMORY.mdtop section — critical rules + feedback index TaskList— if empty, create tasks fromplan/issues/sprints/{N}/(current sprint dir, filter bystatus: ready) before touching any dev.
Output: before touching any dev, write a 3–5 sentence situation summary to
yourself (not to the user) covering baseline, open PRs, active dev claims,
known blockers. This is your working model.
Do not reply to the user with a situation recap — that's context waste.
Start doing Phase 1 work.
Phase 1 — Dispatch
Trigger: idle devs, TaskList is empty or has unclaimed tasks, unstarted sprint items.
Goal: TaskList is populated and every ready dev can self-serve.
Checklist:
- Populate TaskList first. For each issue in
plan/issues/sprints/{N}/withstatus: readythat doesn't have a task yet:TaskCreate. If feasibility ishardand no impl spec exists, run/architect-specfirst. - Count active devs vs unclaimed tasks. Target: up to 8 devs, each on a distinct issue, no two devs in the same function.
- Idle notifications are normal — devs are between tasks and will self-claim. Do not ping unless they've been silent for >20 min with no commits (see Phase 3).
- Conflict resolution — if two devs claim the same file/function: first specific-scope claim wins; message the later dev directly with a different task.
Only use SendMessage dispatch as fallback when a dev reports TaskList is empty and you can't immediately add a task (e.g., issue needs an arch spec first).
Phase 2 — Merge queue management
Trigger: a dev pushes a PR, a CI status feed update lands, or gh pr list
shows ≥3 open PRs.
Goal: the merge queue never stalls. A self-merge-eligible PR should land
within a few minutes of CI reporting.
Checklist:
- Pull latest main:
git pull --ff-only origin main - List open PRs with CI data:
for p in $(gh pr list --state open --json number --jq '.[].number'); do cat .claude/ci-status/pr-$p.json 2>/dev/null | \ jq -r '"PR #\(.pr) Δ\(.delta) impr=\(.improvements) regr=\(.regressions) ratio=\(.regressions * 100 / (.improvements // 1))%"' done - For each PR, classify:
- Self-merge eligible (Δ>0, ratio<10%, scope≤5 files, no bucket>50):
the dev should run/dev-self-merge. If they haven't, ping them. - Needs investigation (ratio≥10% or bucket>50): ping the owner with the
specificgh run view <id> --log-failedcommand and a hypothesis about
the regression cluster. - No owner / orphan (dev from an earlier session, dev non-responsive):
you enqueue viagh pr merge <N> --auto(NO--merge/strategy flag — the queue owns the strategy and rejects--merge --auto; queue re-runs the required checks on the merged state). Reserve--admin --mergefor true hotfix bypass. - Stale CI (new commits pushed after feed wrote): wait for fresh feed,
don't merge until CI catches up.
- Self-merge eligible (Δ>0, ratio<10%, scope≤5 files, no bucket>50):
- If the queue has >5 self-merge-eligible PRs, send a broadcast reminding devs
to merge their own PRs before starting new work (protocol point 6). - After merges land, baseline advances — remind devs to
git merge maininto
their branches before pushing new commits.
Sub-skills / commands:
/dev-self-merge— devs use this; you reference it in pings/pr-conflict-refresh— devs use this to rebase branches after main moves/merge-wave— for batched merges when the queue is deep/handle-regression— if a merged PR causes downstream breakage/bisect-regression— for tracking down which merge broke the baseline
Phase 3 — Stuck / silent dev triage
Trigger: a dev has gone silent for >20 minutes OR has only emitted idle
notifications since their last substantive message.
Goal: distinguish "genuinely working on something hard" from "hung /
inbox-broken" without pinging every 5 minutes.
Checklist:
- Check the dev's worktree directly:
WT=.claude/worktrees/issue-<N>-<slug> git -C $WT log --oneline main..HEAD # recent commits git -C $WT diff --stat main..HEAD # uncommitted scope stat -c '%y' $WT/src/**/*.ts 2>/dev/null | sort -r | head -5 # file modtimes - Check
gh pr list --head <branch>— they may have silently pushed a PR
without reporting it. - Interpret:
- Recent commits + recent file modtimes: genuinely working. Do not ping.
- No commits + no file modtimes + no PR + no messages: hung. Ping once
with explicit reply requirement. If no reply in 10 minutes, either:
(a) take over their PR yourself if one exists and is self-merge eligible,
(b) spawn a replacement dev with the worktree state in the prompt,
(c) mark the task for reassignment and move on. - PR exists, dev silent: this is protocol violation #1 (push=ping). Fetch
the CI feed yourself and treat the PR as orphaned — admin-merge if clean,
investigate regressions if not.
- If the problem is "inbox delivery broken" (see
.claude/memory/feedback_tasklist_sync_unreliable.md), fall back to
SendMessage and do not trust their TaskList view.
Do not ping every few minutes. Between-turn idle notifications are normal
and do not indicate a hang.
Phase 4 — Protocol enforcement
Trigger: any individual protocol correction you issue to one dev.
Goal: implicit team norms become explicit, and every dev knows them.
Checklist:
- Keep a mental list of corrections issued in the current session:
- "push = ping"
- "standdown = stop in place"
- "self-merge before new work"
- "file issue file before using the number in a PR title"
- "work in worktrees, not /workspace"
- "investigation PR is a valid output"
- When you've issued ≥2 individual corrections covering the same theme, or
you've corrected ≥2 different devs, broadcast a canonical protocol message
to the full team (one message, 5–10 numbered points). - Request one-line acks. No ack within 10 minutes ⇒ direct follow-up per dev.
- Log recurring patterns to memory as feedback rules:
Follow the feedback type structure in the auto-memory system prompt..claude/memory/feedback_<short-name>.md
Sub-skills / commands:
/create-issue— for follow-up issues devs should file/architect-spec— for handing over hard issues to an architect
Phase 5 — Sprint hygiene
Trigger: every ~30 minutes during an active session, OR whenever the main
branch advances ≥5 PRs since your last cycle.
Goal: the sprint doc, issue files, and memory files reflect current reality.
Nothing important is trapped in conversation context only.
Checklist:
- Update
plan/issues/sprints/<N>/sprint.md"interim results" with the latest
baseline and merge count. - Update completed issues in
plan/issues/—
set frontmatterstatus: done. - Update
plan/log/dependency-graph.md— strike through completed issues. - Write to memory before compacting: any new lesson, dev preference, or
process rule that future sessions need. See.claude/memory/feedback_diary_and_sprints_before_compact.md. - Check token usage with
/context— if approaching 40% of weekly budget,
plan a compact boundary at the next natural pause. - Keep the handoff file
plan/agent-context/tech-lead.mdupdated for any
future fresh team restart. Don't wait for end-of-sprint — restart can
happen at any time (see the inbox-delivery incident 2026-04-11).
Sub-skills / commands:
/sprint-retrospective— at natural phase boundaries/session-wrapup— before /compact or session end/sprint-wrap-up— at sprint end, full closeout/regression-triage— when the harvester needs to run/analyze-regression— for specific regression bucket analysis
Loop summary
Phase 0: context load (once per session start)
↓
┌─── Phase 1: dispatch (every idle dev, every new task)
│ ↓
│ Phase 2: merge queue (every push / every 5 min)
│ ↓
│ Phase 3: stuck triage (only when >20 min silence)
│ ↓
│ Phase 4: protocol enforcement (after ≥2 corrections)
│ ↓
│ Phase 5: sprint hygiene (every ~30 min)
│ ↓
│ [all devs shut down + no tasks?] ──→ Sprint-end wrap-up ──→ STOP
│ ↓ (no)
└─── (continue loop)You don't always run every phase — you trigger on events. But you do
re-enter the loop after every user message, dev message, or tool result.
The sprint-end detection runs every iteration — when it triggers, the
wrap-up is mandatory before the loop can stop.
Sprint-end detection (MUST run before loop exit)
Trigger: all devs shut down AND no unclaimed/unblocked tasks remain.
When this condition is met, the sprint is over. You MUST complete the
wrap-up before stopping the loop. Do NOT just stop — incomplete wrap-ups
lose learnings, leave issues in the wrong state, and force the next
session to reconstruct context from scratch.
Sprint-end checklist (all mandatory, in order):
- Tag:
git tag sprint/<N> - Sprint doc: update
plan/issues/sprints/<N>/sprint.mdwith:- Status:
donein frontmatter - Ending baseline numbers
- Results table (PRs merged, issues completed, issues deferred)
- Acceptance criteria review (checked/unchecked)
- Retrospective (what went well, what didn't, lessons learned)
- Status:
- Diary: append session entry to
plan/diary.md - Handoff: update
plan/agent-context/tech-lead.mdfor next session - Issues: move completed issues from
ready/todone/ - Commit + push: stage all wrap-up files, commit, push, push tags
- Landing page: verify Pages deploy triggered (baseline refresh uses
[skip ci]which also skips deploy — trigger manually if needed) - Shutdown PO: if a PO agent is still alive, send shutdown request
- TeamDelete: clean up team directories and worktrees
- THEN stop the loop — omit ScheduleWakeup only after step 9
If you are about to omit ScheduleWakeup (stop the loop) and have NOT
completed steps 1-9, you are violating this protocol. Go back and do them.
When to pause or break the loop (non-sprint-end)
- User directly asks for something: handle the user request first, loop after.
- Token budget approaching 40%: Phase 5 hygiene + /compact.
- Fresh team restart needed: write
plan/agent-context/tech-lead.md,
TeamDelete, TeamCreate, resume from Phase 0.
Anti-patterns (do NOT do these)
- Stopping the loop without sprint wrap-up. "All devs shut down" is NOT
the exit condition. "All devs shut down + wrap-up complete + tag pushed"
is the exit condition. This is the #1 protocol violation — it happened in
Sprint 41 and required the user to catch it. - Polling devs every minute for status. Idle notifications are normal.
- Running
/compactwithout updating the sprint doc first — lessons
die with the context. Seefeedback_diary_and_sprints_before_compact.md. - Merging your own tech-lead "pipeline restart" commits between dev
merges. Doc commits force every open dev branch to re-merge main. Batch
doc commits AFTER a merge wave completes. - Taking a dev's work away without a direct SendMessage first. Standdown
broadcasts are binding but devs need to see the message before they can
honor it. - Letting TaskList run empty. Devs have no way to self-serve when the queue is empty. Populate it before touching agents.
- Reading files you already read this session to "double-check". Your
context is your source of truth; re-reading burns tokens and cache. - Reporting merge progress to the user in full table form unless they ask
for it. A one-sentence summary is almost always enough. - Asking "do you want me to continue?" every few turns. The user will
tell you to stop if they want to stop.
Cross-references
CLAUDE.md— team config, merge protocol, memory budgetplan/method/team-setup.md— roster, capacity limits.claude/skills/dev-self-merge/SKILL.md— what devs do after push.claude/skills/merge-wave/SKILL.md— batched merges.claude/skills/handle-regression/SKILL.md— when a merge breaks something.claude/skills/create-issue/SKILL.md— filing new issues.claude/skills/architect-spec/SKILL.md— hard-issue pre-work.claude/skills/sprint-wrap-up/SKILL.md— end of sprint.claude/memory/feedback_tasklist_sync_unreliable.md— why SendMessage is canonical.claude/memory/feedback_diary_and_sprints_before_compact.md— hygiene before /compact