Skip to main content

flow-next-land

Cadence-tick autonomous babysitter for build-loop-authored PRs (/loop-shaped ship loop). Each invocation is one tick over the build loop's PRs (one selected spec/PR when invoked by flow with current scoped consent) — keep CI green (bounded fix budget), wait out the reviewer patience window, resolve feedback via resolve-pr, and once converged merge + close the spec + follow the project's release instructions. Ends with a terminal LAND_VERDICT line for the driver to read. Triggers on /flow-next:land, optionally with --dry-run. Autonomous by design — never asks the user questions; reports NEEDS_HUMAN instead.

Ir a la instalación

Datos de origen

Repositorio
gmickel/flow-next
Última actividad en el origen
14 de septiembre de 2026 a las 07:10
Idioma detectado de SKILL.md
inglés
Estrellas
699
Forks
55

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
4 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
flow-next-land
description
Cadence-tick autonomous babysitter for build-loop-authored PRs (/loop-shaped ship loop). Each invocation is one tick over the build loop's PRs (one selected spec/PR when invoked by flow with current scoped consent) — keep CI green (bounded fix budget), wait out the reviewer patience window, resolve feedback via resolve-pr, and once converged merge + close the spec + follow the project's release instructions. Ends with a terminal LAND_VERDICT line for the driver to read. Triggers on /flow-next:land, optionally with --dry-run. Autonomous by design — never asks the user questions; reports NEEDS_HUMAN instead.
user-invocable
false
allowed-tools
Read, Bash, Grep, Glob, Write, Edit, Skill
# /flow-next:land — cadence-tick autonomous PR babysitter A tick is one invocation of `/flow-next:land`: discover the open PRs the build loop authored, walk each through the gate tree (CI tri-state → patience window → review-thread resolution → review signal → merge gates), take at most ONE action class per PR, and end with one terminal `LAND_VERDICT` line. Flow may invoke one scoped tick as its authorized landing stage; standalone discovery remains repository-wide. It is intentionally not a runner; `/loop` in Claude Code owns the cadence (babysitting waits on external events — CI, reviewers — over hours). Land is the ship loop to the build loop of `/flow-next:flow --auto`, which drains ready specs into draft PRs; land (`/loop`-shaped) wakes on a cadence, acts on those PRs, sleeps. Land never authors PRs and never touches in-flight specs - it only babysits PRs whose authoring spec has ALL tasks done (the build-loop concurrency interlock). Flow may compose land as a scoped stage; land never dispatches flow, pilot or any other driver. Land and Ralph are alternative autonomous drivers. Never nest them, and never reuse Ralph harness state inside land. **Auto-merge override (confined).** Land intentionally overrides the standing "no `gh pr merge` from skills" rule — confined to this one opt-in skill. Land itself is the gate: **it merges explicitly (`--squash --delete-branch --match-head-commit`; `--delete-branch` omitted while an open child PR still targets the branch, and the `merge-async` endpoint with a `sha` pin for a GitHub-stacked frontier) only after every gate passes in-tick, and never through `gh pr merge --auto`** (on a repo with no branch protection `--auto` merges instantly, so server-side gating adds nothing). A merge that rode `--auto`, or that landed before a gate passed, has broken this. Flow may consume this skill after current scoped consent; it never executes a merge itself. Every other skill keeps the no-auto-merge rule. ## Preamble **CRITICAL: flowctl is BUNDLED — NOT installed globally.** `which flowctl` will fail (expected). Define once; subsequent blocks (here and in `workflow.md`) use `$FLOWCTL`: ```bash FLOWCTL="${DROID_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/scripts/flowctl" [ -x "$FLOWCTL" ] || FLOWCTL="<plugin-root>/scripts/flowctl" # <plugin-root> = the directory two levels above this skill's SKILL.md file (the harness gave you that file's absolute path when the skill loaded); substitute it literally [ -x "$FLOWCTL" ] || FLOWCTL=".flow/bin/flowctl" ``` `gh` (verified against gh 2.93.0 — re-verify `gh pr checks --json bucket`/exit-8, `--match-head-commit`, and `mergeStateStatus` on major gh bumps) and `jq` must be on PATH; `gh auth status` must pass. ## Scoped flow handoff When invoked by flow, read its current host-context handoff before the guards: one spec ID, exact PR URL, repository/workspace identity, current authorization, and release/tracker restrictions. Follow flow's `references/tail.md` contract supplied by the caller. Initialize `LAND_SCOPE_SPEC=""`, `LAND_SCOPE_PR=""`, `LAND_AUTHORIZED=0`, and `LAND_BASE_ROOT=""` for each invocation, then populate them only from that current host instruction. Standalone land leaves the scope values empty and keeps its existing opt-in license; an incomplete or unauthorized flow handoff stops `NEEDS_HUMAN`, never falls back to repository-wide discovery. These values are internal shell inputs, not public flags. An inherited environment, file, PR body or historical receipt grants no authority. Scoped land filters discovery to the bound item, including an already locally closed spec with unfinished merged-tail work. Missing/ambiguous identity, closed-unmerged state or an unusable workspace stops; no substitution. Re-check current authority before every mutation and after waits or delegated work; revocation stops subsequent mutations. Release and tracker steps retain their existing authorization/configuration, and a narrower current instruction wins. ## Hard guards (before anything else) Run these guards before discovery, ledger writes, branch changes, or skill dispatch. ```bash if [[ -n "${FLOW_RALPH:-}" || -n "${REVIEW_RECEIPT_PATH:-}" ]]; then echo "Ralph and land are alternative drivers — never nest them" >&2 echo 'LAND_VERDICT=NEEDS_HUMAN prs=0 pr=- reason="nested under Ralph harness (FLOW_RALPH/REVIEW_RECEIPT_PATH set) — refuse to run"' exit 1 fi if git status --porcelain | grep -v '^.. \.flow/' >/dev/null; then echo 'LAND_VERDICT=NEEDS_HUMAN prs=0 pr=- reason="dirty working tree at tick start"' exit 0 fi ``` Dirty tree means dirty outside `.flow/`; land leaves state untouched. No cleanup, no ledger write. ## Mode Detection Parse `$ARGUMENTS` for the dry-run switch. Unknown flags warn to stderr and are ignored. The loop avoids bash positional parameters — the host's argument interpolation rewrites positional tokens inside skill code blocks (pilot dogfood finding, 1.13.0). ```bash RAW_ARGS="$ARGUMENTS" LAND_DRY_RUN=0 for ARG in $RAW_ARGS; do case "$ARG" in --dry-run) LAND_DRY_RUN=1 ;; -*) echo "Unknown flag: $ARG (ignored by /flow-next:land)" >&2 ;; *) echo "Unknown argument: $ARG (ignored by /flow-next:land)" >&2 ;; esac done export LAND_DRY_RUN ``` `--dry-run` stops after GATE: full discovery + per-PR classification report (CI tri-state read, review-signal state, would-be action) and the aggregated terminal line, **with zero mutations**. A dry-run tick that checked out, pushed, labelled, merged, dispatched resolve-pr, or wrote the ledger has broken this. ## The verdict contract (read this before the workflow) Cadence drivers are transcript-blind: they read conversation output only and never run tools. Every tick therefore echoes its per-PR evidence (gate reads, action taken, verdict) into the output, one block per PR. Per-PR verdicts are exactly: `MERGED | RELEASED | FIXING_CI | AWAITING_REVIEW | RESOLVING | BLOCKED | NEEDS_HUMAN`. Every tick ends with exactly one terminal line, the last line of the response, with nothing after it: ```text LAND_VERDICT=<verdict|NO_WORK> prs=<n> pr=<deciding-pr-url|-> reason="<one line>" ``` The tick-level verdict is the worst severity across PRs by priority `NEEDS_HUMAN > BLOCKED > FIXING_CI > RESOLVING > AWAITING_REVIEW > RELEASED > MERGED`; `pr=` is the URL of the PR that decided it (`-` when none). `NO_WORK` when discovery finds zero authored PRs. `prs=` is the number of PRs processed this tick. Driver condition examples: ```text /loop 30m /flow-next:land /goal keep running /flow-next:land until it prints LAND_VERDICT=NO_WORK or LAND_VERDICT=NEEDS_HUMAN ``` ## Forbidden - Asking the user anything in the tick path. Land is autonomous; ambiguity maps to `NEEDS_HUMAN`. - Authoring PRs, choosing/planning/implementing specs - that is the build loop (`flow --auto`). Land only babysits existing PRs. - Acting on a PR without both authorship signals (branch matches a spec's `branch_name` **and** the structural authorship probe — the make-pr machine marker in footer position, with the anchored dated-footer fallback for pre-marker PRs; workflow.md Phase 1). Branch-only matches are reported `NEEDS_HUMAN`, never mutated. - `gh pr merge --auto`, merge-queue enrollment, or any merge without `--match-head-commit`. - Hand-resolving merge-conflict hunks. The conflict path is server-side catch-up only (`gh pr update-branch`); GitHub refusing the base merge → `BLOCKED`. Land never rebases and never force-pushes, with one bounded exception: the leased cascade of workflow §3.7 over the open layers of a plain chain whose parent merged (each layer force-pushed with `--force-with-lease` on the exact tip it read, inside the tick claim). Any other force-push has broken this. - Merging a stacked layer that is not the lowest open layer of its stack, `merge_action=merge_queue`, or deleting a branch an open PR still targets. - Inventing release steps. Release-follow runs deterministic, non-interactive commands from the project's discovered release docs, and nothing else; with no such docs it stops at merge. - `git add -A` in the CI-fix path — stage only the files edited for the fix. - Dispatching any skill other than `flow-next-resolve-pr` (with `mode:autonomous`) and `flow-next-tracker-sync` (authorized bridge-active `land.merged` touchpoint). - Printing anything after the `LAND_VERDICT` line. - Running under Ralph (`FLOW_RALPH` / `REVIEW_RECEIPT_PATH`). ## Workflow Execute [workflow.md](workflow.md) in order: 1. **guards** — refuse Ralph nesting, refuse dirty non-`.flow/` start state, take the tick concurrency claim (non-dry ticks only; `--dry-run` takes none), prepare the scoped base workspace under that claim, then read config and load the `.git` land ledger (read-only at this point), then sweep `pending_branch_deletes` (the branch janitor, §0.5 — deletes a merged branch once no open PR targets it). *Done when: both guards passed, `LAND_CFG` is captured with its fallbacks applied, and the ledger is loaded without a write — first read inside the claimed interval, never before it.* 2. **discover** — the authorized scope (or standalone open specs) with all tasks done → `gh pr list --head <branch_name> --state all`, OPEN-state filter, dual authorship signals, merged-but-unclosed re-entry candidates. *Done when: every candidate spec has a classification (babysit / re-entry / `NEEDS_HUMAN` / skipped) and the discovery table is echoed.* 3. **gate** — per-PR read-only classification: shape (stacked, plain chain, or standalone, re-derived from the PR every tick, §2.0), patch-id verdict carry-over (§2.2b), durable-label skip, CI tri-state over every check, patience window anchored to last push, unresolved review threads, review signal (`land.reviewSignal`), stale-approval detection, `mergeStateStatus`, the frontier rule for chains and stacks (§2.8). `--dry-run` stops here. *Done when: each PR carries one planned action class plus a provisional verdict, and nothing has been mutated.* - Under the default `silence` signal, a review bot that posts a no-findings **issue comment** instead of a formal APPROVE also satisfies the gate — land scans `issues/<n>/comments` for an automated-reviewer comment matching `land.cleanReviewCommentPattern` (a structured built-in default) that names the **current head SHA**. The default accepts two clean shapes: the legacy clean-phrase comment (e.g. Codex's "Didn't find any major issues. Reviewed commit: `<sha>`") and Codex's edited-in-place summary-table comment whose row reads `**Code Review** | **Completed** ... <sha7>` — a summary row naming the current head is the same reviewed-this-head evidence, since findings gate separately via unresolved threads. It only ever *adds* this evidence; CI, unresolved-thread, and window gates are unchanged, and a stale-SHA or non-automated comment is ignored. Set `land.cleanReviewCommentPattern` to an explicit empty string `""` to **disable** the comment path (pure reviews-API behavior); leaving it unset uses the built-in default. - `land.mergeVerdictCommand` (default `""`, off) adds an opt-in **repo merge-verdict gate** (§2.9) for repos with no branch protection to gate against: once every other gate passes and the planned action is `merge`, land runs the configured command once via `bash -c` from the repo root, with context in the environment only (`FLOW_HEAD_SHA`, `FLOW_BASE_REF`, `FLOW_PR_NUMBER`, `FLOW_SPEC_ID`). Exit 0 merges; **any** non-zero - including missing, unexecutable, or timed out at the 600s bound - blocks with `NEEDS_HUMAN` and no label. It is block-only (it can never grant a merge the other gates refused), `--dry-run` reports `would-run` and executes nothing, and unset, `null`, and `""` all mean off. The command runs on the base checkout (`LAND_BASE_ROOT` on a scoped flow handoff), so it must key on `$FLOW_HEAD_SHA` and refuse when it cannot see that head. - `land.patienceMinutesAfterReview` (default `null`, off) is a **`silence`-only refinement of the patience window** (§2.6): when the latest automated review is head-current with zero unresolved threads, the silence gate waits that many minutes measured from the review event instead of from the last push. Only the silence gate's window conjunct re-anchors — `approve`/`<login>`, the no-checks guard, the human-review-pending verdict, the stale-approval detector, and the merge call are unchanged — and a fix push reverts to the push anchor until a new head-current review exists. The report's `window=` field names the binding anchor (`anchor=<push|review>`) only when the key is configured; unset, `null`, and `0` mean off (today's push-anchored wait, byte-for-byte); the schema is `integer|null`, and the Phase 0 read treats a hand-edited or pre-schema string as off rather than failing the tick. - `land.requestReviewers` (default `""`, off) adds an opt-in **human reviewer request** (§2.6b → §3.4b): a csv of GitHub logins and/or `org/team` slugs and/or the literal `codeowners`. Exactly when a human review is the only missing merge input (CI green, zero unresolved threads, and the signal is unsatisfied under `approve`/`<login>` or satisfied-but-`REVIEW_REQUIRED` under `silence`), land plans `request-reviewers`: flips a draft PR to ready, requests the list minus the PR author (`codeowners` rides the ready flip — GitHub resolves owners itself), and records `reviewRequestSha` in the land ledger — at most once per PR per head SHA, claimed atomically so overlapping ticks cannot double-request. A failed request still records the head (no retry loop) and reports `reviewers=failed:<reason>` with the window-bounded verdict, never `BLOCKED`. It never gates a merge (`reviewSignal` does). `--dry-run` reports `reviewers=would-request` (plus `would-ready` for a draft) and mutates nothing; unset, `null`, and `""` all mean off (`reviewers=off`; when the key is set but a human review is not the sole missing input, `reviewers=skipped:not-due`). 4. **act** — at most one action class per PR: CI fix, resolve-pr dispatch, server-side catch-up (`gh pr update-branch`), human reviewer request (ready flip + `--add-reviewer`), the leased chain retarget above a merged parent (§3.7), or ready→merge→post-merge tail (spec close → authorized release-follow → authorized tracker touchpoint → persist-push). *Done when: each PR has had exactly one action class executed, the worktree is back on `ORIG_BRANCH` (or the merged base), and the non-`.flow/` tree is clean.* 5. **report** — per-PR verdict evidence, ledger writes, and the terminal `LAND_VERDICT` line (worst-severity rule). *Done when: one evidence block per processed PR is echoed and the terminal line is the last line of the response.* ## Chains and stacks A chain is a dependent PR whose base is the parent's branch; a stack is GitHub's server-side object over one. Land classifies every PR from its REST `stack` object and base ref each tick and stores nothing about the shape. It merges only the frontier (the lowest open layer) and at most one layer per tick, keeps a review verdict across a rebase when the stable patch-id of base-to-head is unchanged, retargets the layers above a merged parent itself on the plain path (the one bounded force-push), lets GitHub do it on the native path, and never deletes a branch an open child still targets. A standalone PR with no open children keeps byte-identical gate verdicts, merge arguments, tail order, and ledger writes. Vocabulary, the frontier rule, the collapse hazard, `merge-async`, patch-id carry-over, and the branch janitor: [references/chains-and-stacks.md](references/chains-and-stacks.md). ## Unattended runs Land is fully autonomous by design — there is no interactive mode. Wall-clock limits and cadence belong to the driver (`/loop <interval>`, `/goal` stop clauses). A land tick has no timeout machinery; the patience window (`land.patienceMinutes`, default 30) is gate state, not a sleep — a tick never blocks waiting for reviewers, it reports `AWAITING_REVIEW` and exits (`land.patienceMinutesAfterReview`, when set, only moves the `silence` gate's anchor from the last push to the head-current review event — still gate state, still no sleep).
Ver en GitHub