agentleFS
WarshoowWarshoow/afk.sh/skills/afk-preflight/SKILL.md

afk-preflight

Skill3 starsChanged 45 days agoMITView on GitHub

Rereads and re-slices the ready-for-agent batch before an afk run: freezes, uncheckable criteria, oversized or colliding tickets. `apply` (afk-app.sh only) applies the mechanical fixes itself.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 1 is distinctive, and 2 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.

  • 2

    Very specific

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

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

    Read from it, without recomputing: the frozen tickets, the waves (who runs at the same time as whom), the bases (who stacks on whom), and …

    line 33
  2. Distinctive:

    Every ticket of the batch against every row of this table.

    line 51
  3. Very specific:

    Read it off ./afk.sh -n (who runs in the same wave) crossed with the bodies (which files each one announces it touches).

    line 114

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

/afk-preflight

A badly written ticket does not cost five minutes, it costs MAX_ATTEMPTS × TIMEOUT of the night — and if it blocks the others, it costs their night too. This skill rereads the batch before the run and returns a list of corrections.

./afk.sh -n already gives the whole mechanism: waves, bases, stacks, frozen, effective gate per ticket. Read it from there; if you and the script disagree, the script is right. This skill judges the content of the tickets, which the script cannot do.

1 — Prerequisites

test -f .afk.env || echo "no .afk.env — run /afk-setup first"

No .afk.env → the gate will be a pnpm monorepo's, wrong everywhere else. Stop there.

2 — The plan

./afk.sh -n            # the whole ready-for-agent batch
./afk.sh -n 43 48 49   # or an explicit batch

Read from it, without recomputing: the frozen tickets, the waves (who runs at the same time as whom), the bases (who stacks on whom), and the Verify: / Timeout: / Model: / Effort: lines the tickets gave themselves.

3 — The bodies

gh issue view <n> --json title,body,labels -q '.title, .body'
gh api "repos/{owner}/{repo}/issues/<n>/dependencies/blocked_by" --jq '.[].number'

One ticket per call, for the whole batch. It is the raw material for everything else. The blockers are the native GitHub links first, the body's Blocked by section when there are none, as afk.sh reads them: /to-tickets (mattpocock-skills 1.3+) leaves the section out when it set the links.

4 — What to look for

Every ticket of the batch against every row of this table. Done when each pair has a verdict — most are "does not apply", and that is still a verdict.

What you seeWhat will happenFix
Frozen — blocker open outside the runthe ticket does not start, and neither do its dependantsthree cases: (a) the blocker is done but its ticket was never closed → close it; (b) it has an open PR → STACK_ON_OPEN_PR=1 is enough, nothing to do; (c) it really is still to do → add it to the batch, or take the dependant out
Stale Blocked by (blocker already merged)a freeze for nothingclose the blocker, or remove the line from the body
Acceptance criterion no gate can see ("the user sees a toast")"green" will mean "it compiles"either a test that proves it plus a Verify: line that runs it, or accept it — but then say so, do not discover it in the summary
Ticket crossing several apps with a Verify: shrunk to onethe local gate does not see the breakage, only CI will — after the PRwiden the Verify:, or remove it to fall back on the complete gate
Rework without a Timeout: (migration + code + tests + docs, or more than ~6 criteria)cut in the middle at TIMEOUT, twicepropose Timeout: 90m (the timeout(1) format)
Fuzzy scope ("improve X", "clean up Y")the agent goes where it likes, the review has nothing to compare againstrewrite the acceptance criteria as checkable things, or take the ticket out of the batch
Two tickets of the same wave on the same fileseach worktree starts from the base without seeing the other: it compiles on both sides and breaks at integrationserialise them with a Blocked by between the two
Ticket already covered by an open PRit will come out absorbed, at bestclose it, or leave it: absorbed is a clean result, not a failure
Mechanical ticket (rename, config, docs, version bump)it will run on the rework modelModel: sonnet in the body
Ticket whose previous run finished near the context window ("Context" column of .afk/summary.md)too big: quality degrades before the failure doescut it — §5

5 — Cut, serialise, number

The three fixes that touch the batch rather than a body. They hold for any already published ticket, whatever its origin — /to-tickets, a grilling, written by hand, or a batch from three weeks ago. Nothing to cut is the normal case: a batch out of /to-tickets is already in vertical slices of one session.

Cutting a ticket that does not fit in one session

The signs, in order of reliability: the "Context" column of a previous run close to the window; the ticket crosses several apps of the monorepo while its gate only sees one; more than ~6 acceptance criteria; a title containing "and". A longer Timeout: fixes nothing: the budget is not what is missing, the room is. A ticket cut in the middle burns MAX_ATTEMPTS × TIMEOUT and returns a half-written branch.

Each piece keeps a complete slice — schema, API, screen, tests — otherwise the gate cannot judge it on its own and the ticket becomes a half-ticket nothing verifies. The pieces are serialised with Blocked by in the order they get built: afk then stacks the branches and each one inherits the previous one's work.

The original never stays in the batch: either it loses its label and serves as a parent, or it gets closed pointing at its pieces. Otherwise it starts again the next night and redoes the work of its own children.

gh issue create -t "<piece title>" -l ready-for-agent -F - <<'EOF'
## What to build
…
## Acceptance criteria
- [ ] …
## Blocked by
- #<previous piece>, or "None"
EOF
gh issue edit <original> --remove-label ready-for-agent   # parent: out of the batch
gh issue comment <original> --body "Cut into #a #b #c for an afk run."

Serialising two tickets writing into the same files

Two tickets of the same wave each start from a base that does not contain the other: both are green, and the breakage only shows at integration — or not at all, when both create the same path with two APIs each right on its own side (defect 25). The fix is a Blocked by on whichever of the two can wait, not a merge: the second one then starts from the first one's branch and sees its work. We only merge them when neither verifies without the other.

Read it off ./afk.sh -n (who runs in the same wave) crossed with the bodies (which files each one announces it touches).

Handing out the numbers before the run

Two branches claiming the same ADR, migration or RFC number are each green on their own side and no gate will see it (defect 22) — the integration pass flags it, but after the PRs. So a number is handed out in the body, before the run:

ls docs/adr | tail -3            # the last one taken
ls apps/*/migrations | tail -3

Then, in each ticket concerned: "this ticket's ADR is 0042, not the next free one". Two tickets never get the same one.

6 — Prove every Verify: line before proposing it

Prove each one by the rule of /afk-setup step 4 (../afk-setup/SKILL.md): timeout 180, then read rc there — rc=124 is the watch trap.

Prove the command the script will actually run, not the one the ticket looks like it writes: ./afk.sh -n prints it, extracted. Two forms pass — the bare command, and the command in code followed by prose, where only the span counts. A value ending in : is ignored and the ticket falls back on VERIFY_CMD; if the -n shows no Verify: line where the ticket writes one, that is why.

7 — Give the verdict

A table, one ticket per line: goes as is / to fix / to cut / to take out of the batch, with the reason in one line. Then the concrete fixes, ready to paste:

gh issue edit <n> --body-file -    # corrected body
gh issue edit <n> --remove-label <ready-for-agent>   # take it out of the batch

What happens to them depends on how you were invoked:

  • /afk-preflight (a human): propose, and wait for approval before any edit, label, ticket created or closed. A ticket body is trust surface: its Verify: and Timeout: lines are executed as-is by the run. An uncheckable criterion gets a proposed wording; the human decides. Finish with the launch command suited to the batch, for the human to run:

    nohup ./afk.sh -j 3 43 48 49 &
  • /afk-preflight apply (only afk-app.sh's loop, where nobody is awake to approve a table): apply the fixes yourself, within the limits of the next section, then give the table anyway.

Apply mode — what it may change

What you may apply on your own, because it is mechanical and ./afk.sh -n proves it:

  • cut a ticket that does not fit in one session, into the pieces step 5 describes;
  • serialise two tickets writing into the same files, with a Blocked by;
  • hand out the ADR and migration numbers before the run;
  • fix a Timeout:, a Verify: proven in step 6, a Blocked by pointing at a blocker already merged and closed.

What you may not apply, whatever it costs: rewriting an acceptance criterion. That is the judgement docs/spec.md reserves for /afk-spec, and a criterion rewritten by whoever is going to fill it is the exact failure the afk-spec tag exists to prevent. A ticket whose criteria no gate can check is therefore taken out of the batch:

gh issue comment <n> --body "preflight: <the criterion> is not checkable by a gate — out of this wave"
gh issue edit <n> --remove-label <ready-for-agent>

It will come back through /afk-wave on a later wave, or by hand. An emptied batch is a result: afk-app.sh stops on it and says so.

Re-run ./afk.sh -n after your edits and check it agrees with what you intended. It is the script that is right. Then finish with the step 7 table, in the session's output: it is the only trace the morning will have of what you changed.

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.