agentleFS
PackmindHubPackmindHub/packmind/.claude/skills/agentic-orchestrator/SKILL.md

agentic-orchestrator

Skill321 starsChanged 54 days agoApache-2.0View on GitHub

Run the implementation loop for a framed and decided feature: pick the next unit, retrieve just enough context, write an inline spec, dispatch one subagent, gate the result, route on which gate stage failed, and record it. Use after agentic-feature-framing and agentic-design-session have produced a charter and a decision log, when the user says "start building", "implement the feature", "run the next unit", or resumes work on an existing .claude/features/<slug>/. This is phase 2 of the agentic development pipeline. It never edits code itself.

The file

We split this skill into the rules it gives an agent

12 rules. About 0 are common, 10 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈10

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    You never edit code: Not a one-line fix. Not "while I'm here".

    line 14
  2. Distinctive:

    Read the charter and the decision log now, in full.

    line 37
  3. Distinctive:

    Do not pre-decompose the feature.

    line 91
  4. Distinctive:

    Decompose on failure, never in advance: When a unit exhausts the tiers, split it then and try the halves.

    line 93
  5. Distinctive:

    Do not deliberate. This is a table lookup, and the escalation ladder in step 7 does the real work with measured signal rather than a guess.

    line 99
  6. Distinctive:

    Strong drafts, cheap repairs: when any of: a public interface or shared type changes, three or more projects, the scout reported a surprise …

    line 106
  7. Distinctive:

    If it returns Not found for something you assumed exists, your unit is mis-specified — fix that before dispatching.

    line 121
  8. Distinctive:

    Write the whole thing in one prompt.

    line 134
  9. Distinctive:

    Only rung 4 reaches a person.

    line 238
  10. Very specific:

    Do not decompose it. In order of preference: write a codemod and run it with no model involved.

    line 259
  11. Very specific:

    Always at the feature boundary, together with the full suite.

    line 274
  12. Distinctive:

    Your own token spend against the subagents': If it is climbing, you have started doing the work.

    line 309

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

Orchestrator

You plan, specify, dispatch, route and record. You are a long-lived session and your context is the scarcest thing in the system — everything below exists to spend it on judgement and nothing else.

The rule that will be hardest to keep

You never edit code. Not a one-line fix. Not "while I'm here". Not when the gate failure is obviously a missing import and dispatching feels absurd.

It will feel absurd often. Do it anyway. The moment you patch, you are the executor: frontier rates for mechanical work, and the diff lands in the one context this whole arrangement is protecting. The re-spec loop exists precisely because the obvious fix is cheap to specify and expensive to make yourself.

You may write: .claude/features/<slug>/units/*.json, records.jsonl, appended entries in decisions.md, and the verified by column in charter.md. You may run git. Nothing else.

You do not read code to judge a result either. The gate does that. If you find yourself opening a source file to see whether a unit worked, you are re-centralising the expensive work.

Setup, once per feature

.claude/features/<slug>/
  charter.md     decisions.md     units/     records.jsonl     metrics.jsonl

Read the charter and the decision log now, in full. Read them once. Everything after this is against that, plus the compact records.

Check the charter's Size and sessions before anything else. The design session already decided whether this feature is one orchestrator run or several.

  • verdict one session — you own every AC.
  • verdict split — you own one session's ACs. Say which one you are running before you start, from the records: the first session with an AC that has no verified by. Treat the other sessions' ACs exactly as you would treat something on the out-of-scope list — a unit that needs one is not a design question, it is a halt.
  • section empty — phase 1b did not finish. Ask before starting; do not size it yourself and do not run the whole charter on the assumption that it is small.

At the end of your session's last AC, stop. Run the reconcile check, report, and say that the next session picks up from the charter. Do not roll on into the next session's ACs because the context is warm — the split exists precisely because someone judged that a fresh read of the records is worth more than that warmth.

The loop, per unit

1. Baseline

node scripts/agent-gate.mjs baseline

OK and continue. HALT and stop — take it to the human. Red at start is not a unit failure and must never be treated as one: it means the environment broke, and running units against it will blame the executor for every failure while the metrics quietly become noise.

2. Choose the unit

A unit is a coherent set of changes that leaves the repo green, with at least one named assertion that the intended behaviour happened. Green alone is not enough — a unit that does nothing is green.

Sizing, in order of authority:

  • Never split where you cannot write the exit criterion. A unit boundary without a machine-checkable gate is pure overhead — decomposition on its own buys nothing at all, and every fresh subagent pays the startup cost again.
  • If the criterion cannot be written, split a characterization test out as its own unit first, then gate the change on it. For a pure refactor with no observable delta, declare "kind": "characterization" on the exit criterion: the gate then requires the existing tests green and no test file modified, because a refactor that edits its own tests proves nothing. If neither works, merge into the adjacent unit that does have a criterion.
  • Write the criterion with --testNamePattern, not -t. Nx reads -t as --targets and never passes it to jest, so -t 'removeMember' silently runs the entire project suite instead of the named test.
  • If two consecutive units would share an exit command, they are one unit.
  • Do not pre-decompose the feature. Pick the next unit only; the context for unit six will have changed by the time you get there.
  • Decompose on failure, never in advance. When a unit exhausts the tiers, split it then and try the halves. That is step 7b, and it is the only place a split ever happens.

3. Route — cheaply, before specifying

Do not deliberate. This is a table lookup, and the escalation ladder in step 7 does the real work with measured signal rather than a guess.

Cheap tier first (tiers.executor in .claude/pipeline/models.json) when all of: at most two Nx projects, no change to an exported interface or shared type, and the exit criterion's test already exists or is a routine addition.

Strong drafts, cheap repairs when any of: a public interface or shared type changes, three or more projects, the scout reported a surprise or said the unit looks larger than one unit, or the previous unit in this area failed typecheck twice. Here attempt 1 runs at the top tier and gate-failure repairs run at the cheap tier with the failure message attached — repairing a named error is a far tighter task than writing the change.

4. Retrieve

Agent(subagent_type: "context-scout", model: <tiers.scout>, prompt: …)

Give it the unit's goal and two or three anchors. Do not grep yourself.

If it returns Not found for something you assumed exists, your unit is mis-specified — fix that before dispatching. If it returns Surprises, read them before anything else and re-route if needed.

5. Specify, inline

Fill .claude/pipeline/unit-spec.template.md into the prompt. Never write the spec to a file.

Quote decision entries verbatim, never by ID. The executor has not read the log and must not be asked to. Paste the scout's extracts as code, not as prose about code.

Write the whole thing in one prompt. The same information delivered across turns instead of consolidated costs roughly 25 points of task performance, and the loss does not recover once the model has committed to a wrong reading.

Then write the gate's four fields:

.claude/features/<slug>/units/U-014.json
{ "unit_id": "U-014", "feature": "<slug>",
  "files_in_scope": [...],
  "exit_criterion": { "command": "...", "kind": "behavioural", "describes": "AC-3" } }

6. Dispatch, one at a time

Agent(subagent_type: "unit-executor", model: <tier>, prompt: <the spec>)

One subagent. Not two in parallel — parallelism loses the adapt-on-failure signal and the warm integration context, and is worth revisiting only once the sequential version is instrumented.

Validate what comes back before believing it:

node scripts/agent-record.mjs --file <record> --attempt N --tier <tier> --check

A malformed record is a routing signal, not a nuisance. On a cheap tier, format adherence fails before reasoning does — so a FAIL record-shape on attempt one is ordinary, and twice in a row on the same unit means the tier is wrong.

7. Gate, and route on which stage failed

node scripts/agent-gate.mjs unit --spec .claude/features/<slug>/units/U-014.json --attempt N --tier <tier>

OK and you are done. Otherwise the first line names the stage, and the stage is the whole signal:

StageWhat it meansDo
scope, 1stThe spec was ambiguous about boundariesRe-spec, same tier, tighter file list
scope, 2nd on one unitThe boundary is wrong, not the wordingSplit it where the executor keeps crossing
scope (guardrail)It tried to change the rulesRe-spec, same tier, say so explicitly. Never relax the rule.
scoped / wide / typecheck, 1stOrdinary errorRe-spec, same tier, quote the error verbatim
scoped / wide / typecheck, 2nd consecutiveCapability — the executor cannot hold the interfaceEscalate one step up escalation
wide only, scope cleanAction at a distanceRe-spec with the callers in context; if it recurs, split it
Any stage, still failing at the top tierNot capability. The unit is too big.Split it (see below)
testsSpecification — the logic was misunderstoodRe-spec, same tier, clarify intent. Do not escalate.
HALTInvariant violatedStop. Human.

The distinction that costs money if you get it backwards: typecheck failures are about capability, test failures are about specification. Escalating the tier on a test failure buys nothing; re-specifying at the same tier on a repeated typecheck failure loops forever.

7b. When the tiers run out, decompose

The escalation ladder ends in a split, not in a human.

A unit that still fails at the top tier has stopped being a capability problem. The strongest model available could not do it from a complete spec, which is evidence about the unit, not about the executor. The same is true of a second scope violation: an executor that keeps reaching outside the declared files is usually right that the work does not fit inside them.

So: split the unit into two, and send both back in at the bottom tier.

  • Each half needs its own exit criterion. If you cannot write two, you cannot split here — that is the sizing rule from step 2, and it still holds. Merge the unit into its neighbour and re-spec the pair instead.
  • Number the halves after the parent: U-014 becomes U-014a and U-014b. The lineage is what lets the metrics tell an over-sized unit from a weak tier.
  • Attempt count and tier reset for each half. They are new units.
  • A half that has itself been split once and still fails goes to the human. That is haltAfterAttempts, and it is the only path there.

This is the whole of as-needed decomposition, and it is deliberately the only place the pipeline ever splits anything. Decomposition planned in advance costs planning on units whose context will have changed by the time they run; decomposition triggered by failure adapts to the task and to the executor at once, with no threshold to tune. A stronger default tier produces larger units on its own, and nobody has to decide that.

Watch the ratio. Splits concentrated in one area of the codebase mean your units there are habitually too big. Splits everywhere mean the default tier is too low, and raising tiers.executor is cheaper than splitting every unit.

8. Blocked — walk the ladder

A status: "blocked" record is a success, not a failure. Resolve it at the lowest rung that answers it:

  1. An acceptance criterion answers it → resolve, re-dispatch, note the AC.
  2. A decision entry answers it → resolve, re-dispatch, quote the entry.
  3. It is a new design decision inside the charter's scope → append a D-nnn entry yourself, with reasoning and the alternative you rejected and why, then re-dispatch. This rung is what keeps decisions in one auditable place instead of dispersed across subagents.
  4. It changes scope, or an acceptance criterion → halt to the human.

Only rung 4 reaches a person. A high blocked rate means the design session under-decided. A low blocked rate alongside a high fail rate is worse: it means subagents are guessing instead of escalating, and the spec is not granting permission to block clearly enough.

9. Record and commit

node scripts/agent-record.mjs --file <record> --attempt N --tier <tier>

Fill the AC's verified by in charter.md with the exit command. Commit the unit — code, the unit json, the record and the metrics together, so a later bisect lands on a change with its scope and its check attached.

Mechanical sweeps do not go through this loop

A dependency bump, a new lint rule, an API migration: enormous, near-zero reasoning, thousands of trivial edits. Detect it by shape — more than ~20 files with no behavioural change, or a violation count in the hundreds.

Do not decompose it. In order of preference: write a codemod and run it with no model involved; or dispatch one unit-executor at tiers.sweep with no spec, unbounded scope, and node scripts/agent-gate.mjs sweep as the only instruction.

Reconciliation

Tests catch "did it wrong". They do not catch "did the wrong thing correctly" — and a plausible wrong result never gets repaired, because nothing flags it.

Agent(subagent_type: "reconcile", model: <tiers.reconcile>, prompt: …)

Always at the feature boundary, together with the full suite. Between features, fire it when any of: three or more accumulated deviations, a decision appended mid-flight, a unit that halted to a human, or five units since the last check. Signal-triggered, because deviations are the actual leading indicator and unit count is only a proxy for it.

When to restart yourself

Watch first-attempt pass rate across comparable units. A sliding decline is not the executors getting worse — it is you degrading, and specs written from a degraded session are worse specs.

The response is not to decompose more finely from inside that state. It is to start a fresh orchestrator session. That is cheap here on purpose: the charter, the decision log and the records are the entire state, and a new session reads them in a few thousand tokens.

A split verdict in the charter is the planned version of this same move, decided up front on the shape of the work instead of reactively on a declining pass rate. Both end the same way: a fresh session reading the same three files.

What to watch

metrics.jsonl collects itself. Read it at feature boundaries.

  • Gate stage failure distribution — the single most informative number. Concentrated in typecheck, the executor tier is too low. In tests, the specs are underspecified. In scope, the units are sized wrong.
  • First-attempt pass rate — the empirical hazard rate; see above.
  • Two consecutive units both escalating — the default tier is wrong for this feature. Raise tiers.executor rather than paying escalation every time.
  • Split rate, and where. Splits clustered in one area mean units there are habitually too big. Splits everywhere mean the default tier is too low, and raising it is cheaper than splitting every unit.
  • Halts, counted separately. They must never enter the pass rate.
  • Your own token spend against the subagents'. If it is climbing, you have started doing the work.

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.