Harness pr ops
Portable, evidence-driven agent development harness for Codex, Claude Code, and generic Agent Skills. Active beta v0.1.2.
npx -y skills add GhostlyGawd/recursive-harness --skill harness-pr-opsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 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
Use while DRIVING a harness change onto trunk — opening/merging PRs, especially several at once (a roadmap or /retro batch), or the moment a guard unexpectedly BLOCKS a git/gh/bin-harness command mid-flow. Encodes the operating mechanics the enforcement guards + GitHub impose that aren't obvious until they bite: stacked-PR merge order, running locked-path commands cleanly, and what to expect at the human gate. Pairs with harness-pr (the PR template), windows-host-paths (token mechanics), worktree.
SKILL.md
8.1 KB, as published. Nobody here has run it
Operating a harness change through the guards
The PR content rules live in harness-pr + harness-authoring. This is the
mechanics of getting the change to land without fighting the guards or GitHub —
the footguns that cost re-work the first time you hit them. Each rule has a receipt.
Standing grants — check BEFORE re-asking a settled point
Before ANY AskUserQuestion / "over to you" hand-back about approval mid-flow, run
"$HARNESS/bin/harness" approve --list. An active standing grant covering the scope
means the point is SETTLED: proceed (record marker grants against it verbatim), do
not re-ask. When the user gives blanket words ("full approval for everything",
"you're approved on X"), record them immediately: approve --standing --scope "<what kind of work>" --grant "<their verbatim words>" — that is what makes the
user-model's standing-grant test (evidence 4) mechanical instead of remembered.
FLOORS ALWAYS OUTRANK: guard-weakening and destructive/irreversible actions need
fresh explicit words no matter what --list shows.
receipt: roadmap item 2 (proposals/resolved/P-2026-039-product-ux-roadmap.md); the re-ask friction fired 3x on 2026-06-27 and again 2026-07-05.
Stacked PRs — retarget the child BEFORE deleting the base
When PR-B is stacked on PR-A's branch (B's base = A's branch), merging A with
gh pr merge A --delete-branch deletes the branch B targets. GitHub does NOT
reliably retarget B — it auto-CLOSES B with a dangling base, and a closed PR
whose base branch is gone cannot be reopened or rebased (gh pr edit --base
and gh pr reopen both fail). You must recreate it as a new PR.
Do instead, in order: merge A → gh pr edit B --base main (retarget while B is
still open) → then merge/delete. Or simplest: merge A without --delete-branch,
retarget B, merge B, then delete both branches. Prefer not to stack at all when the
PRs touch different files (branch each off origin/main independently).
receipt: session edd67875, 2026-06-28 — merged #200 with
--delete-branch; its stacked child #201 auto-closed un-reopenably and had to be re-created as #203.
After retargeting the child to main post-SQUASH-merge, expect gh pr update-branch
to FAIL ("Cannot update PR branch due to conflicts"): the squash rewrote the base's
history, so files both branches touched become add/add conflicts. Recover locally:
git fetch origin && git merge origin/main; for files where the child is strictly
newer (progress logs, loop state) take the branch tip via git show HEAD:<file> > <file> (NOT git checkout --ours — the dirty-revert guard blocks checkout/restore
path forms), confirm zero <<<<<<< markers, commit the merge; then PROVE no content
drift — git diff <pre-merge-tip> HEAD --stat must be empty — and push; CI re-runs.
receipt: session 4acb66e4, 2026-07-02 — #220 squash-merged; stacked #221's update-branch conflicted add/add on two loop-state files; resolved locally to the branch tip,
git diff da71709 HEAD --statclean, CI green, merged.
Run locked-path commands on their OWN Bash call
The enforcement-layer guard blocks a Bash command when a working-tree-mutating /
file-write token co-occurs with a locked absolute-root path substring (…/bin/harness,
…/hooks/…, …) — it then reads the locked path as a WRITE target even when you only
EXECUTE it read-only. The triggering tokens are git checkout / git restore, rm /
mv / cp / tee / sed -i, a > / >> redirect, open(…,'w') — NOT git merge
or git commit (those are allowed alongside a locked path; verified empirically). Safe
habit: run a locked-path command (bin/harness predict/outcome/…) as its OWN call, never
chained after a git checkout/restore or a file write.
receipt: session edd67875 —
git checkout main && git fetch && git merge … && python …/bin/harness outcome …was blocked ("'bin' is enforcement-layer"); thegit checkoutwas the trigger (a baregit merge … && python …/bin/harness …is NOT blocked). Splittingbin/harnessonto its own call ran clean.
A locked-layer build that adds test files: wire ci.yml in the SAME approve cycle
When an enforcement-gated change ALSO adds tracked test_*.py (a new file or whole new package),
test_ci_coverage.py requires each to be wired into .github/workflows/ci.yml (or excused in
INTENTIONALLY_UNWIRED) — and ci.yml is itself locked (.github/). So the ci.yml wiring is a
SECOND locked edit. Discover it UP FRONT and batch it into the same bin/harness approve →
edit-all-locked-files → --revoke cycle as your primary locked edit, instead of finding it after
the first commit and paying a second approve/revoke round-trip. Run python3 tests/test_ci_coverage.py
locally as part of pre-push validation so the requirement surfaces before CI, not after.
receipt: session 89bd318f, 2026-06-30 — an
bin/harnessdelegation landed first; only then didtest_ci_coveragereveal 7 newfleet/test_*.pyneeded wiring into the (locked)ci.yml, costing a second approve cycle. Excusedfleet/test_mcp.py(needs themcpSDK CI lacks).
The human gate is the EXPECTED terminus of locked-layer work — don't forecast auto-land
A change touching the locked layer (hooks/ lint/ evals/ bin/ .github/ autonomy.json settings.json templates/) does NOT auto-merge. Even auditor-APPROVED, the binding gate
is the human PR merge (harness-pr step 6); the agent must not self-merge. Likewise a
proposed enforcement gate may be redesigned NON-locked, and /run-evals may be
proportionately WAIVED for an additive read-only change. So when you predict such a task,
the calibrated expectation is "stops at the human gate / redesigned / eval-waived," NOT
"lands this session." Over-forecasting clean completion missed TWICE in one session
(predictions 9e2786ec, 5309dd57 — both enforcement-hooks/harness-authoring, the
session's lowest-hit categories).
Already documented elsewhere — go there, don't re-derive
- Guard-bypass tokens must LEAD the command (
HARNESS_TRUNK_LEASE_OK=1no-ops behind acd …or any non-leading position; cwd already persists, so never prefixcd): skillwindows-host-paths§A (Manifestation A). - A commit message / PR body that NAMES the enforcement marker trips the prose-scan
on inline
-m/heredoc text — write it to a file and usegit commit -F FILE/gh pr create --body-file FILE: skillharness-authoring§"Mentioning the enforcement marker in a commit/PR body". - Branch hygiene (return to trunk +
--ff-onlyrefresh after a PR):harness-prstep 7.
Merging under branch protection
main requires the lint-and-test check on the CURRENT head AND an up-to-date branch.
After any merge lands, sibling PRs go BEHIND; gh pr merge then fails "Required status
check … is expected." Per PR: gh pr update-branch N → gh pr checks N --watch →
gh pr merge N. Do NOT reach for --admin to skip this — the up-to-date re-run is the
gate working, and bypassing CI on the harness is the reward-hack the kernel forbids.