agentleFS
mhyllemhylle/claude-skills-collection/skills/tt-workflow-run/SKILL.md

tt-workflow-run

Skill20 starsChanged 36 days agoMITView on GitHub

Tasktracker-native autonomous build-loop orchestrator. Drives a first-class workflow_run end-to-end: resumes the project's open run or starts one through the start gates (lifecycle completeness, zero defects in), then loops over getNextReadyTask — activate the slice's phase, take a drift baseline, run the phase by following /tt-implement-phase in this session until its PHASE_RESULT, re-scan drift and defects, read measured time, and call workflow_recordIteration (per-slice architecture and defect gates plus a versioned, measured-only by-layer effort projection) — until the backlog drains, then workflow_completeRun. Logs the run's own insights (no-data friction, patterns, new defects). Use when the user wants to run the workflow, start an autonomous build loop, or drive the backlog to done in a tasktracker project with a passable lifecycle ("/tt-workflow-run"). Prefer /tt-implement-plan when you only want phases run in order, with no run entity, projection or per-slice gate ledger.

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

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

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

    If you just want to execute phases in order with no measured run, use /tt-implement-plan.

    line 62
  2. Very specific:

    Start with acknowledgeBaseline: true.

    line 159
  3. Distinctive:

    After the baseline defects are cleared, strict zero-defects-in holds for every subsequent slice — a new defect above the (now lower) …

    line 161
  4. Very specific:

    When getNextReadyTask returns null:

    line 251

≈ “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

tt-workflow-run

<!-- contents: generated by tests/skill_structure.py --write; edit headings, not this block -->

Contents

  • How this differs from /tt-implement-plan
  • CRITICAL: Orchestrator pattern (kept from /tt-implement-plan)
  • The MCP surface this skill uses (all already shipped, P100/P101)
  • Workflow
    • Step 0 — Locate the project, resume an open run, pre-flight the gates (this session, inline)
    • Step 1 — Start the run (Gates 1 + 2)
    • Step 2 — The loop (per-slice protocol)
    • Step 3 — Complete the run
    • Optional outer cadence — /loop
  • Handling a blocked gate
  • Anti-patterns to avoid
  • Quality checklist
  • Resources
    • Related skills
  • Key principles
<!-- /contents -->

A thin, tasktracker-native orchestrator that turns an autonomous Claude Code build loop into a visible, auditable, resumable, projectable workflow_run. It is the session layer between the loop (which executes) and the tasktracker spine (project → phase → task → requirement+AC → time-log → insight).

It does not merely record the loop — it enforces the lifecycle through three backend gates that already exist (shipped in P99–P101), measures real build-time per slice, auto-logs insights, verifies architecture is followed each slice, and re-projects remaining effort from measured time only as an append-only versioned series.

Design source of truth: brainstorm 92898896 → "Solution Description (v1)" doc ba161e43-7697-4167-9fc7-f314ca68c3af. The four forks are LOCKED (A: new entity; B: loose coupling; C: lean v1 dogfooded, UI v2; D: getTimeLog preview folded in). Re-read it before changing this skill.

How this differs from /tt-implement-plan

/tt-implement-plan/tt-workflow-run (this skill)
Unit driventhe plan's phase tasks, in author ordera first-class workflow_run over the next-ready backlog
Slice selectionnext pending phasetasktracker_getNextReadyTask(projectId) — dependency-free, ranked
Pre-conditionsreadiness plan row satisfiedGate 1 (lifecycle completeness) + Gate 2 (zero-defects-in), enforced server-side as 412
Per-slice gatesnoneGate 3 architecture-followed (drift hash-diff) + Gate 2 defect-delta, every slice
Time / projectionnonegetTimeSummary measured ms → workflow_recordIteration appends a by-layer projection version
Run entitynoneworkflow_run row with status machine + projection series; resumable across sessions
Insight loggingper-phase, via /tt-implement-phaseper-phase plus the run's OWN insights (no-data friction, patterns, new-defect)

If you just want to execute phases in order with no measured run, use /tt-implement-plan. If you want the run entity + measured projection + per-slice gates on top, use this skill. Both delegate the actual code work to /tt-implement-phase.

CRITICAL: Orchestrator pattern (kept from /tt-implement-plan)

THIS SESSION IS THE RUN ORCHESTRATOR + the SINGLE writer of run state. IT NEVER IMPLEMENTS CODE DIRECTLY — for each slice it follows /tt-implement-phase as the phase lead, in this session, and the role agents write the code. The slice runs here because agent reports arrive in this session; a forked lead can't receive them. Only with no subagent tool at all does the code get written in-context (the graceful-degradation mode). "Foreground" or "don't poll" in the user's words is about waiting, not about who writes the code. Run-state writes (workflow_* MCP calls) are always yours and always main-context, regardless of mode.

tt-workflow-run (this session — RUN ORCHESTRATOR + the SINGLE writer of run state)
    │   ⛔ NEVER writes code     ⛔ NEVER uses Write/Edit     (while Agent is available)
    └── follows /tt-implement-phase for each slice, in this session
            ├── orchestrated mode → implementer / mechanic / reviewer agents do the work;
            │                       their reports arrive here as messages
            └── in-context mode  → only when no subagent tool exists
DO (this session)DO NOT
Create + drive the workflow_run (start/record/pause/complete)Write code or edit files
setActiveTask / pauseActiveTask / clearActiveTaskEdit a locked phase body (HTTP 422)
Pick the next slice via getNextReadyTaskInvent a new backend Workflow API (none exists — Fork B)
Lead each slice by /tt-implement-phaseEstimate a slice's duration (principle #11)
Run the two start gates + three per-slice gatesAdvance past a blocked gate without resolving it
Log the run's own defects/learnings/frictionsBury insights in chat narrative

This skill is main-loop-only (it needs to ask the user at gates): it calls sibling skills via the Skill tool, never via an Agent dispatch. Invoking /tt-implement-phase loads its procedure into this session, which then leads the slice: agents are dispatched, their reports arrive here as messages, and the slice ends with the PHASE_RESULT (Step 2c). The tasktracker_workflow_* MCP tools are module-cached at MCP boot — if one isn't visible, the MCP needs a restart (mcp-server/CLAUDE.md), not a workaround. This restart caveat applies ONLY to those MCP tools. The built-in Workflow and Agent tools are top-level main-loop tools — never MCP, never in ToolSearch, never affected by an MCP restart; don't conflate the two.

The MCP surface this skill uses (all already shipped, P100/P101)

Exact tool names — note the tasktracker_ prefix + workflow_ infix:

ToolRole in the loopActive-task
tasktracker_workflow_startRunCreate + start a run; runs Gate 1 + Gate 2; 412 on failure (run persists as enforcing). acknowledgeBaseline: true pins the current open-defect count as the run baseline (bootstrap fallback only).EXEMPT (first-contact, like createProject)
tasktracker_getNextReadyTaskPick the next dependency-free slice. It takes only projectId and can return a non-phase task — map that to its phase (Step 2). null ⇒ backlog drained ⇒ complete.EXEMPT (read)
tasktracker_workflow_setCurrentTaskPoint the run at the picked slice (no iteration recorded).requires active task (heartbeats)
tasktracker_scanArchitectureDriftBaseline (slice start) + re-scan (slice end). Returns bucketed missing / stale / orphaned.EXEMPT (read)
tasktracker_getDefectStatsRe-read .open for the Gate 2 delta vs baseline.EXEMPT (read)
tasktracker_getTimeSummaryMeasured (stopped-segment-only) ms for the slice task.EXEMPT (read)
tasktracker_workflow_recordIterationRuns the advance gates (Gate 3 reqs-link + architecture-followed, Gate 2 defect-delta), records the iteration, appends a projection version, and auto-logs the "no data" friction when hadHeartbeatData: false. 412 on a blocked advance (run → blocked_on_gate).requires active task (heartbeats)
tasktracker_workflow_pauseRun / resumeRunPause before a human gate / resume after.requires active task
tasktracker_workflow_completeRun / abandonRunTerminal.requires active task
tasktracker_workflow_getRun / listRunsInspect run + projection series; listRuns finds an open run to resume (Step 0).EXEMPT (read)

recordIteration key inputs (get these right — they drive the gates + projection):

  • runId, taskId, layer (required) — layer ∈ backend|frontend|fullstack|docs|infra (project-estimate.py taxonomy).
  • measuredMs — from getTimeSummary (bigint → pass as a string for large values; defaults to 0).
  • measurementSource — 'timer' (summed stopped segments) or 'wallclock' (manual fallback).
  • hadHeartbeatData — false when the slice produced no heartbeat-backed time-log data → triggers the run's own "no data" friction (R3 / principle #11).
  • baselineDrift / drift — the slice-START and slice-END scanArchitectureDrift outputs as {missing:[file...], stale:["componentId:file"...], orphaned:["componentId:file"...]} key arrays. Net-new at end vs baseline blocks the advance + logs a defect.
  • remainingByLayer — per-layer count of the run's remaining pending dependency-free slices: the projection multiplier (projected = Σ_layer remaining×mean). Omit the whole object on the final slice and the projection trends to ~0.
  • projectionTrigger — defaults 'slice_complete'; use 'scope_change' / 'defect_baseline_shift' for re-projections not driven by a finished slice.

Workflow

Step 0 — Locate the project, resume an open run, pre-flight the gates (this session, inline)

1. tasktracker_listProjects({search})  — or use the argument hint → projectId.
2. tasktracker_workflow_listRuns({projectId}) — if a run is `running`, `paused` or
   `blocked_on_gate`, resume it instead of starting a new one:
   - tasktracker_workflow_getRun({runId}) — its current task, defect baseline, projection so far.
   - tasktracker_setActiveTask({taskId: <the run's current task>}) — resumeRun needs an active task.
     (No current task → use the slice Step 2 picks.)
   - `paused` / `blocked_on_gate` → tasktracker_workflow_resumeRun({runId}). `running` → just use its runId.
   - If the current task isn't completed, it is the next slice: run Step 2 on it before calling
     getNextReadyTask. A `blocked_on_gate` run resumes at the blocked step — resolve it and
     re-record (see "Handling a blocked gate").
   - Skip the rest of Step 0 and Step 1.
3. tasktracker_getProject({projectId}) — confirm solutionDescription is non-null (Gate 1 input).
4. tasktracker_getProjectReadiness({projectId}) — the requirements row must read `satisfied`
   and unlinkedTaskCount must be 0 for the run's subtree (Gate 1).
5. tasktracker_getDefectStats({projectId}) — note `.open`. This is the Gate 2 input AND the run baseline.

Do not try to pre-satisfy a gate by editing data behind the run's back. If Gate 1 will fail (no solution description, requirements not satisfied, unlinked tasks), STOP — the project needs /tt-create-plan / requirement linking first. If Gate 2 will fail (open defects), see the Bootstrap nuance below — the strict posture refuses to start; the documented fallback is acknowledgeBaseline.

Step 1 — Start the run (Gates 1 + 2)

tasktracker_workflow_startRun({
  projectId,
  name: "<run name>",
  acknowledgeBaseline: <true ONLY for the documented bootstrap case — see below>,
  brainstormId?: <originating brainstorm>,
  sessionId?: <current session>,
})
  • Strict (default): with zero open defects + a passing lifecycle, the run transitions to running with baselineDefectCount = 0. Strict zero-defects-in now holds for the whole run.
  • 412: the start gate failed. The run row persists in status enforcing so you can inspect the structured body (unlinked task ids / open-defect count). Fix the cause (link tasks, resolve defects, or acknowledge the baseline) and retry — do not route around the gate.

startRun is active-task-EXEMPT (it CREATES the run). Right after a successful start, the first setActiveTask (Step 2) begins heartbeating.

Bootstrap nuance (read once — this is the inaugural-run case)

A project that already has an open defect cannot pass strict Gate 2 — but that open defect is often exactly the first thing the loop should fix. The documented bootstrap path:

  1. Start with acknowledgeBaseline: true. The run pins baselineDefectCount = N (the current open count). Only NEW defects above N block advance; the N pre-existing ones don't.
  2. Make the inaugural slice a fix-task for one of those baseline defects (tasktracker_createFixTask({defectInsightId}) — stamps metadata.fixesInsightId so the fix-time rolls into getDefectStats.timeOnDefects). Running it resolves the defect, dropping .open back toward 0.
  3. After the baseline defects are cleared, strict zero-defects-in holds for every subsequent slice — a new defect above the (now lower) baseline blocks advance and is attributed as "ours" (principle #14: pre-existing is not a thing).

acknowledgeBaseline is a one-time bootstrap concession, not a routine knob. Once the backlog is clean, future runs start strict (baseline 0).

Step 2 — The loop (per-slice protocol)

Loop while getNextReadyTask returns a slice. Each iteration is the brainstorm's per-slice protocol, one step per call:

loop:
  slice = tasktracker_getNextReadyTask({projectId})
  if slice == null: break                         # backlog drained → Step 3
  if slice.type != "phase":                       # it can return a task or subtask
    slice = the type "phase" entry of tasktracker_getTaskAncestors({taskId: slice.id})
    # that phase already completed (a straggler task) → take the first not-completed
    # phase from tasktracker_getReadyTasks({projectId}) instead

  # 2a. Focus + point the run at the slice
  tasktracker_setActiveTask({taskId: slice.id})   # heartbeats start; digest carries principles + body
  tasktracker_workflow_setCurrentTask({runId, taskId: slice.id})

  # 2b. Pre-slice drift baseline (Gate 3 input — baseline-subtracted so only the slice's delta is charged)
  baselineDrift = tasktracker_scanArchitectureDrift({projectId})   # capture missing/stale/orphaned key arrays

  # 2c. Run the slice by /tt-implement-phase, in this session (you are the phase lead)
  Skill(skill="tt-implement-phase", args=
    "Execute the slice. Caller: tt-workflow-run. Phase task id: <slice.id>. Project: <name + id>.
     Sub-tasks (getChildTasks), linked requirements + ACs, principles from the setActiveTask digest.
     Unattended: yes   # only when this run is wrapped in /loop with no one to answer")
    /tt-implement-phase: the role agents do the code (Sonnet implementer, Haiku mechanic per unit, Opus reviewer); registers the architecture delta in the SAME
    slice (principle #8 — so the slice's own drift re-scan stays clean), runs verification-loop +
    code-review + ADR compliance, auto-logs defects/learnings/frictions with relatedTaskId = slice.id,
    keeps the slice heartbeating, and leaves the active task on the slice for you.
  Agents report asynchronously: when nothing else is left, end the turn naming what you wait for; the
    report resumes you. Never poll with sleep loops. Blockers mid-slice are asked by the procedure itself.
  PHASE_RESULT FAILED (or BLOCKED, from an unattended run) →
    tasktracker_workflow_pauseRun({runId, reason: "<blocked step — what is needed>"})
    tasktracker_pauseActiveTask()
    ask the user (AskUserQuestion) with the PHASE_RESULT's options; on resume:
    tasktracker_workflow_resumeRun({runId})        # the pointer is still on the slice
    run 2c again with Resume From Step + the decision + the earlier PHASE_RESULT.
    Never record an iteration for an unfinished slice.

  # 2d. Slice-end gate inputs (only after PHASE_RESULT status PASS)
  endDrift  = tasktracker_scanArchitectureDrift({projectId})       # Gate 3 delta
  defects   = tasktracker_getDefectStats({projectId})              # Gate 2 delta (.open vs run baseline)
  time      = tasktracker_getTimeSummary({taskId: slice.id})       # measured (stopped-only) ms
  layer     = classify(slice)                                      # backend|frontend|fullstack|docs|infra

  # 2e. Record the iteration → appends a projection version (runs the advance gates server-side)
  # recordIteration requires an active task: the child left it on the slice — check, and re-set if not.
  if tasktracker_getActiveTask() != slice.id: tasktracker_setActiveTask({taskId: slice.id})
  tasktracker_workflow_recordIteration({
    runId, taskId: slice.id, layer,
    measuredMs: time.totalMs (as string if large),
    measurementSource: time had data ? 'timer' : 'wallclock',
    hadHeartbeatData: <true iff getTimeSummary returned measured data>,
    baselineDrift, drift: endDrift,
    remainingByLayer: <per-layer count of remaining pending dependency-free slices>,  # omit on last slice
  })
  # 412 here ⇒ the advance was BLOCKED (Gate 3 net-new drift / missing req link, or Gate 2 new defect).
  #   The run is now blocked_on_gate. Resolve the cause (re-register the arch delta, link the requirement,
  #   or fix the new defect) within /tt-implement-phase, tasktracker_workflow_resumeRun({runId}), then
  #   re-record. Do NOT skip the slice.

  # 2f. Pause before any human gate
  tasktracker_pauseActiveTask()   # before any message that waits on the human (their think-time isn't work)
  # Don't clear the active task between slices — the next 2a moves it; Step 3 clears it.

Time comes from heartbeats, not timers. getTimeSummary only sees time-log segments that tasktracker MCP calls kept alive; a segment closes after ~5 minutes without one. While the role agents work they keep the slice heartbeating (getCurrentTimer at least every ~4 minutes, confirmed by a HEARTBEAT: line in each report; this session can't heartbeat while it waits), and this session doesn't switch or pause the active task while they run. Never call startTimer — started timers create lease-less rows that absorb other sessions' cost (one phase read 12h18m against 3h16m of real work); stopTimer is only for a timer found still running on a slice at its close.

The run's OWN insights (R3 — log these, don't narrate them)

/tt-implement-phase logs the slice's insights. ON TOP of that, this skill logs the run's own:

ConditionToolNotes
The slice produced no heartbeat-backed time datarecordIteration({hadHeartbeatData:false}) auto-logs it, OR tasktracker_logFriction"no data" — never estimate the duration (principle #11). The auto-log stamps run_id + iteration_id.
A notable cross-slice pattern emergedtasktracker_logLearningE.g., "drift baseline-subtraction means an unrelated stale component never blocks an unrelated slice."
.open rose above the run baselinetasktracker_logDefectThe new error is "ours" (principle #14). recordIteration also blocks the advance.

Per R3, auto-logged slice insights carry relatedTaskId = slice.id AND their metadata is stamped with run_id + iteration_id (no new column). When you log the run's own insight manually, set relatedTaskId to the slice and reference the run/iteration in the body.

Classifying the slice layer

Map the slice to the project-estimate.py taxonomy: frontend (Angular templates/components/styles), backend (NestJS services/controllers/entities), fullstack (both in one slice), docs (markdown/skill files), infra (CI, compose, migrations-only). When a slice touches both backend + frontend, classify fullstack (don't split the iteration).

Step 3 — Complete the run

When getNextReadyTask returns null:

tasktracker_workflow_completeRun({runId})          # terminal; sets ended_at
tasktracker_workflow_getRun({runId})               # confirm the projection series is populated
tasktracker_getDefectStats({projectId})            # confirm .open == baseline (no nets introduced)
tasktracker_clearActiveTask()

Then emit the closing summary (counts, the projection series, insights logged this run, manual verification still owed) in chat — not as a file. If the run ended deliberately short, use abandonRun instead and say why.

Optional outer cadence — /loop

Loose coupling (Fork B) means /loop is orthogonal: you can wrap the whole skill in /loop <interval> /tt-workflow-run <project> for an unattended cadence, but the run does not depend on it. The run entity + gates + projection are pure tasktracker data; /loop just re-invokes the skill, and Step 0 finds the open run with workflow_listRuns and resumes it rather than starting a new one.

Handling a blocked gate

A 412 is the system working, not a failure to route around.

WhereCauseResolution
startRun 412Gate 1: no solution description / requirements not satisfied / unlinked tasksFix the lifecycle (/tt-create-plan, link requirements), then retry.
startRun 412Gate 2: open defects, no ackResolve them, OR start with acknowledgeBaseline: true and clear them as inaugural slices.
recordIteration 412Gate 3: net-new drift (a new file no component cites; an edited component whose driftHash wasn't refreshed)Register/refresh the architecture component in-slice (principle #8), then re-record.
recordIteration 412Gate 3: the slice task has no requirement link in its hierarchyLink it to a requirement, then re-record.
recordIteration 412Gate 2: .open rose above baselineThe new defect is ours — fix it (a follow-up slice), then re-record.

On any 412 the run sits in enforcing (start) or blocked_on_gate (advance). pauseActiveTask before surfacing the blocker to the user; resume from the blocked step, not from Step 0 — for an advance, workflow_resumeRun({runId}) with the slice still active, then re-record.

Anti-patterns to avoid

  • ❌ Writing code in this session while the Agent tool is available, including when the user asked for "foreground" work. Dispatch the implementer, as /tt-implement-phase describes.
  • ❌ Polling agents with sleep/wait loops, or saying "I'll wait" and then ending the slice. End the turn; the report resumes you.
  • ❌ Inventing a backend Workflow API. Fork B is loose coupling — the loop is a skill over existing MCP tools only.
  • ❌ Estimating a slice's duration when heartbeating was off. The answer is "no data" → friction (principle #11). Never synthesize a measuredMs.
  • ❌ Skipping setActiveTask before a slice — no heartbeats, no measured time, the projection goes blind.
  • ❌ Calling startTimer, or switching/pausing the active task while role agents are working.
  • ❌ Scanning drift, reading time, or recording an iteration before the slice's PHASE_RESULT is written.
  • ❌ Starting a new run while the project already has a running, paused or blocked_on_gate one — resume it (Step 0).
  • ❌ Routing around a gate (editing data to dodge a 412, or skipping a blocked slice). Resolve the cause.
  • ❌ Editing a locked phase/slice body. Design notes go to a sub-task; the body is the contract.
  • ❌ acknowledgeBaseline: true as a routine convenience. It is a one-time bootstrap concession; once clean, start strict.
  • ❌ Re-deriving scope from the brainstorm mid-run. The slice's task body (from setActiveTask) is the locked contract.
  • ❌ Burying the run's own defects/learnings/frictions in chat. Log them via logDefect/logLearning/logFriction.
  • ❌ Running this as an Agent-dispatched subagent — invoke it in the main loop; call siblings via Skill.

Quality checklist

  • Step 0: project located; an open run (running / paused / blocked_on_gate) resumed rather than duplicated; otherwise Gate 1 inputs (solution description, requirements satisfied, zero unlinked) checked and Gate 2 baseline (.open) noted.
  • Step 1: startRun ran the gates; strict by default; acknowledgeBaseline used ONLY for the documented bootstrap case, with the inaugural slice resolving a baseline defect.
  • Step 2: every slice was a phase (a non-phase pick mapped to its phase), did setActiveTask + setCurrentTask, captured a pre-slice drift baseline, led the slice by /tt-implement-phase until its PHASE_RESULT, re-scanned drift + re-read defect stats, read getTimeSummary, and recordIteration'd (with the slice active) with the right layer + drift arrays + remainingByLayer. No startTimer.
  • R3: slice insights carry relatedTaskId + run_id/iteration_id; the run logged its OWN "no data" friction whenever heartbeating was off.
  • pauseActiveTask before every human-gate message.
  • No locked-body edits; no invented backend API; no synthesized durations.
  • Step 3: completeRun; projection series populated; .open back at baseline; clearActiveTask.
  • No code written in this session (Write/Edit unused); all slice code came from the role agents (or the in-context mode when no subagent tool exists).

Resources

This skill reuses the tasktracker references already shipped with the sibling skills:

  • /tt-implement-phase references/insight-cookbook.md — when/how to logDefect / logLearning / logFriction.
  • /tt-workflow-audit references/workflow-tasktracker-contract.md — the shared tt-workflow-* contract (parent owns writes, no Date/RNG in any workflow script, MCP reachability, prod safety). This skill is sequential (single active task) — it does NOT use the parallel Workflow tool — but the active-task / locked-body / prod-write rules in that contract still apply. Namespace note: the tasktracker_workflow_* MCP tools this skill uses (workflow_startRun, workflow_recordIteration, …) are run-TRACKING tools — NOT the built-in Workflow orchestration tool; they only share the word "workflow". The siblings /tt-workflow-audit and /tt-workflow-build are the ones that invoke the built-in Workflow tool.

Related skills

  • /tt-implement-phase — the per-slice procedure. This session follows it for every slice.
  • /tt-implement-plan — the no-run-entity alternative: executes phases in order without projection or per-slice gates.
  • /tt-create-plan — upstream: produces the requirements + linked tasks Gate 1 checks for.
  • /loop — optional outer cadence; orthogonal to the run.
  • /devflow:code-review, /verification-loop, /adr — quality gates inside /tt-implement-phase.

Key principles

  1. Orchestrate, never implement. The role agents do the code; this session drives the run and leads each slice by /tt-implement-phase.
  2. Loose coupling (Fork B). The run is pure tasktracker data over existing MCP tools; no backend Workflow API; /loop optional.
  3. Enforce, don't record. The three gates (lifecycle, zero-defects-in, architecture-followed) are 412s, not advisories.
  4. Measured time only (principle #11). Projection consumes getTimeSummary (stopped segments); no heartbeat data ⇒ "no data" friction, never an estimate.
  5. Zero-error invariant (principle #14). A defect above baseline is ours and blocks advance. acknowledgeBaseline is a one-time bootstrap.
  6. Active-task discipline. setActiveTask per slice, pauseActiveTask before human waits, clearActiveTask on completion; time from heartbeats, never startTimer.
  7. The run logs its own insights. Friction / learning / defect for the loop itself — in tasktracker, not chat.
  8. Locked bodies are sacred. Slice scope is the contract; notes go to sub-tasks.

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.