agentsclimarketplace

Harness loop

Skill niksavis/basicly/.agents/skills/harness-loop

One-command harness distribution for coding agents — a versioned YAML catalog projected into agent instructions, skills, and deterministic git gates.

Install
npx -y skills add niksavis/basicly --skill harness-loop

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 24 days oldThe repository was created 24 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Drive a unit of work through the basicly harness loop end-to-end (intake → classify → decompose → build → verify → ship → teardown → retro) using `basicly loop` + `br`, agent-agnostic across Claude/Codex/Copilot. Use when starting or resuming non-trivial development in a harness-enabled repo, when deciding what phase a tracked issue is in, or when coordinating the checkpoints, gates, and bounded rework the loop enforces.

SKILL.md

13.2 KB, as published. Nobody here has run it

<!-- Generated by `basicly skills-build` from skill.yaml. Do not edit; edit the source. -->

Harness Loop

Scope

Owns driving one tracked unit of work through the whole development loop with the basicly loop command group over the br (beads) tracker. The loop is agent-agnostic: the same commands drive it under Claude, Codex, or Copilot — the agent supplies the phase inputs (the work type, the child plan) and does the coding in the worktree; the engine records state, gates, and advances.

It is not for the mechanics each phase delegates to — those have their own skills: tool-br (create/claim/close issues), worktree-isolation (isolate a node's build), conventional-commits (format the commit), tool-git (staging, diffing). This skill sequences them; it does not replace them.

The tracker is the state — start by reading it

br is the single source of truth; the loop keeps no side-state, so it is resumable across restarts and across agents. Whatever happened last session, begin by reconstructing where a track is:

basicly loop status <issue>     # phase, worktree binding, gates, checkpoints, rework, ready/blocked

Pick the next actionable issue with br ready / br scheduler --json; basicly loop status then tells you which phase it is parked in and what it is waiting on.

Tracker state is zero-touch — the engine commits it, you never do

One tracker, everywhere: a loop-provisioned worktree shares the base checkout's .beads via br's git-ignored redirect file, so br commands (create, update, comments, gates) work identically from base or any worktree and always hit the one real DB/JSONL. There is no worktree tracker copy to diverge and nothing to reconcile at landing.

The engine makes the only tracker commits, at the three natural points:

  1. At provisioning, the claim (status, work type, classify approval) is committed before the worktree is created, so the claim is in git history from the moment work starts — a teammate who pulls sees it immediately.
  2. At landing, loop advance rolls the .beads/** dirt accumulated since (checkpoints, gate records) into one chore(beads) commit before merging. A base that is dirty with anything outside .beads/ still blocks — that is someone's uncommitted work.
  3. At ship, after br close, the engine commits the closing tracker state itself.

So: never git add .beads yourself for loop-tracked work, and never commit .beads/issues.jsonl on a harness branch (restore it if something staged it).

The base clean-tree check counts untracked files. Landing mutates the shared base checkout, so it runs git status --porcelain there with untracked paths included — unlike the worktree readiness check, which passes --untracked-files=no because git rebase does not abort on untracked files. So a stray untracked file in base blocks the landing exactly like a modified tracked one. Check base before every landing:

git -C <base-checkout> status --short

When the dirt is not yours — one shared base checkout with a second concurrent session in it is the usual cause — hold the branch until that session commits its own work, then land. Never git clean, git checkout -- or stash another session's files to unblock your merge; the branch waits, the other session's work does not survive being cleared.

Push cadence — tracker-only pushes are CI-free by design (paths-ignore .beads/**; the local commit-msg hooks are the deterministic floor), so the choice is purely about who is watching the remote:

  • Solo repo: push once per track, after ship — one CI run for the real change, none for the tracker noise.
  • Team repo (other agents or humans pull the same tracker): push each engine tracker commit as soon as it lands — especially the provisioning claim commit, so nobody starts work someone already claimed. Cross-machine races that still slip through are caught by br scheduler --stale-claim-hours and br coordination.

Advancing the loop — one command per phase boundary

Drive the loop with basicly loop run. It is one command per boundary, not per step: it advances until it needs an agent or a human, resolving every checkpoint it is authorized to resolve on the way. A leaf bead therefore takes two invocations, one at each boundary, plus one relay of the confirm code each:

basicly loop run <issue> --work-type task   # intake -> awaiting the agent's work
#   ... do the coding in the worktree and COMMIT it on the harness branch ...
basicly loop run <issue>                    # land, verify, ship, close

Without an interactive terminal it stops once per boundary with a one-time confirm code and reprints the whole command to re-run — relay the code on that command, not on a bare policy checkpoint --approve, or the checkpoint is approved and the loop stays parked. A covering autonomy grant (basicly policy grant, with --root <epic> on the run) resolves the checkpoint with no relay at all. Nothing here widens what may be self-approved: a TTY, a covering grant, or a relayed code are still the only three ways past a checkpoint.

Answering a confirm-code challenge

The challenge protects the human decision, not the keystrokes. So do not hand the command over and wait for someone to type it — that wastes a round trip and races the code's 15-minute TTL, and a ship code has expired mid-ask before. The protocol is:

  1. Show the exact command, including the code.
  2. Say what approving it does in one line — which bead, which checkpoint, and what happens next (a classify approval provisions a worktree; a ship approval merges, closes and tears down).
  3. Get an explicit yes. Silence, "sounds good" about something else, or an earlier approval of a different checkpoint is not one. Approval covers the one checkpoint in front of you, never the next.
  4. Then run it yourself.

Ask when the challenge appears, not after finishing other work — the code expires whether or not you are ready for it. If it has expired, re-run the command with no --confirm to mint a fresh one and ask again.

basicly loop advance <issue> [--work-type T] [--children plan.toml] [--mode M]

loop advance is the single-step form — reach for it to inspect one transition in isolation, or when a boundary stopped somewhere you want to step through by hand. Both exit non-zero when the track stopped short, so scripts and CI can branch on it.

The flags are the agent-supplied inputs a phase needs; pass the one the current phase is asking for (basicly loop status/advance names it as needs input).

Phases and what each one needs

A reference for what each phase is waiting on — not a checklist to type out. loop run performs every engine step in this table itself; what it cannot do is the agent's own column: propose the work type, write the child plan, do the coding, and commit it.

PhaseWhat advances itCommand
intakeagent proposes the br work typebasicly loop advance <id> --work-type {bug|chore|task|feature|epic} — records the type, then blocks for the classify checkpoint
classify (human checkpoint)approve, then the Definition-of-Ready gate must passbasicly policy checkpoint <id> classify --approve; check readiness with basicly policy dor <id>. Never guess which sections the DoR wants — basicly policy scaffold --type <work-type> prints the body with every required heading (a bug also owes ## Steps to Reproduce, an epic ## Success Criteria); fill the TODOs and pass it to br create -d / br update -d
decomposefeatures need an agent child plan; leaves (bug/chore/task) skip straight to buildbasicly decompose <feature> --plan plan.toml (or --children on advance); preview with basicly decompose <feature> --plan plan.toml --dry-run
decompose (human checkpoint)approve before fan-outbasicly policy checkpoint <id> decompose --approve
buildfan out one worktree per dependency-unblocked child (ranked by br scheduler, concurrency-capped), do the work, commit it on the branch, then land through the serial merge queuebasicly worktree list; do the coding; git commit the work on the harness branch (referencing the bead — conventional-commits); basicly loop advance <id> lands it
verifythe landing already ran verify and recorded the required gate; inspect it, then approve shipbasicly policy gate <id>; basicly policy checkpoint <id> ship --approve. Re-run gates (e.g. after rework) with basicly verify --mode full --issue <id> — from the base checkout only
shiptear down the worktree and close the issuebasicly loop advance <id> (runs teardown + br close)

Never record the verify gate by hand during build. The build→verify loop advance is the only step that merges the worktree back to base (_verify_and_land); it runs verify and records the gate itself. Recording the gate out-of-band (basicly verify --issue, br gate report verify) makes the derived phase jump to verify with the merge skipped, and the loop then ships and closes the bead with the code stranded on the harness branch. Let loop advance record it; re-run basicly verify --issue only after the landing has merged (e.g. rework), never before. Ship refuses to close a node whose worktree branch has not landed, as a deterministic backstop.

Commit the build's work on the branch before you advance. Landing rebases the harness branch, so the agent (or, in manual/handoff mode, you) must git commit the changes on the branch first — the loop never auto-commits the agent's work. Leaving the worktree dirty (or the branch with no commit) makes the landing block with "commit the work on <branch> before landing"; it no longer misreports it as a rebase conflict or spends a rework attempt on it (basicly-4psl).

Leaf types (bug/chore/task) build directly in their own worktree; features decompose into children and, once every child closes, land the child worktrees that are still live through the merge queue. A child driven through its own loop self-lands (its ship phase tears the worktree down), so the parent fan-in counts it as already merged instead of failing. See worktree-isolation for the sibling-worktree placement and provisioning rules the build phase relies on.

Gates: deterministic blocks, semantic advises

Deterministic checks (tests, lint, type, build) report a required gate via br gate report --status pass|fail; a failed required gate blocks advancement. AI-semantic verification reports a non-required gate — advisory, never blocking. Inspect the decision with basicly policy gate <id>.

Gates recorded from a loop-provisioned worktree are safe: its .beads redirects to the base checkout, so the record lands in the one real tracker. basicly verify --issue refuses only from a linked worktree without that redirect (a throwaway tracker copy — the record would be discarded at landing). During build you never need to record the gate manually anyway: the landing advance verifies the rebased tree in the worktree and records the required gate itself.

Blocked on a missing fact — don't guess

When a dispatched agent cannot resolve a required fact, it must not guess. Write .basicly/usage/needs-input.json ({"fact": ..., "detail": ...}) and stop — the loop blocks and surfaces the missing fact instead of landing a wrong answer.

Rework and escalation

A failed node enters a bounded rework loop (default n=2), tracked with gate results and comments — not a status change (br has no rework status). At the cap it escalates to a human. Inspect or record attempts with:

basicly policy rework <id> --gate verify [--record]

Any track can escalate a tier (carry work forward, re-hit only the decompose checkpoint) without restarting.

Ship and retro

Ship merges to the entry branch recorded at intake (default: main), tears down the worktree, and closes the issue. After an epic slice lands, capture a retro as tracker comments and file a br issue for each finding the user does not choose to ignore:

br comments add <epic-id> "Retro: <finding>"

One-shot vs task-by-task

Default is task-by-task (every checkpoint is a stop). One-shot mode collapses the middle (decompose) checkpoint for small, well-scoped work; the classify and ship checkpoints still hold.

Resuming after a switch

Because state lives in br (issue status, the worktree binding on external_ref, recorded gate results, checkpoint/rework comments), resuming — after a crash, or when switching from a rate-limited agent to another — is just re-reading it: basicly loop status <issue>, reconcile against live worktrees (basicly worktree list), and continue. Start on one agent, finish on another.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.