General-purpose coding policy for Baruch's AI agents
91
97%
Does it follow best practices?
Impact
91%
1.78xAverage score across 18 eval scenarios
Advisory
Suggest reviewing before use
Structured workflow for shipping code: PR creation, automated policy review, merge, and cleanup. Process each step in order — do not skip ahead, and do not stop between steps; the skill runs end-to-end from git push through merge + cleanup verification in a single agent session.
main/master)evals/ → rules/plugin-evals.md and skills/eval-authoring/SKILL.md; auto-loaded prose in rules/ or skills/ → rules/context-writing-style.md; new scripts → rules/script-delegation.md and rules/testing-standards.md)because, therefore, since, etc. per rules/context-writing-style.mdouter-boundary-process-contract token per rules/error-handling.mdmax_score weight sums (must sum to 100) per skills/eval-authoring/SKILL.mdjq '[.checklist[].max_score] | add' <criteria.json> must print 100, and the weights must not be uniformly distributed (per skills/eval-authoring/SKILL.md)bash -n <script> must exit 0 on shell scriptsgit push -u origin <branch>gh pr create:
<type>(<scope>): <imperative summary>**Author-Model:** <model-id(s) space-separated, or `human`>
## Summary
<what changed and why — 1-3 bullet points>
## Test plan
- [ ] <verification steps>rules/author-model-declaration.md. Use the exact model ID you're running under (e.g., claude-opus-4-7, gpt-5.4), human for a hand-authored PR, or every contributing model space-separated for mixed authorship.When this step is wrapped in a reusable script (e.g., release.sh that other devs run unattended), see the script-wrapping gates at:
skills/release/SCRIPTING.mdProceed immediately to Step 3.
Decide the bump per semver. Patch is the default and is handled automatically by tesslio/patch-version-publish — only update the manifest version for minor or major.
Opening the PR, or pushing further commits to an existing PR, automatically triggers the paired gh-aw policy reviewers (OpenAI + Anthropic, cross-family by author-model). The workflows are bound to the pull_request event (opened / synchronize / reopened / edited); a plain git push to a non-PR branch does NOT fire them. See the trigger / self-gating / authorship mechanics at:
skills/release/GH_AW_DETAILS.mdAlso request Copilot. Copilot is a deliberate second reviewer with a different lens — gh-aw enforces rules/*.md compliance, Copilot reads for doc accuracy, cross-step consistency, and ambiguity. Both reviewers gate the merge:
skills/release/request-copilot-review.sh <owner> <repo> <pr-number>Proceed immediately to Step 5.
Block until the PR reaches a merge-gate-relevant terminal state. The watcher polls poll-pr-reviews.sh at a script-owned interval up to a script-owned budget and watches exactly the fields the Step 7 merge gate reads — each gating bot's latest review state (resolved by bot login), CI status, and merge state. Do not hand-roll a poll loop, and do not wrap the watch in an invented wall-clock timeout (see rules/ci-safety.md "Always Watch CI"):
skills/release/watch-pr-reviews.sh <owner> <repo> <pr-number>It returns the full poll-pr-reviews.sh snapshot plus a watch object — {"result": ..., "attempts": N, "elapsed_seconds": N}. The interval/budget constants and the result contract are the script's, not restated here (rules/script-as-black-box.md — see the header's result matrix). Branch on .watch.result:
ready (exit 0) — mergeable, CI success/none, both gating bots posted, none requested changes. Read every non-empty reviews.*.body (a COMMENTED verdict with zero inline comments still carries a body per rules/reviewer-feedback-reading.md), then proceed to Step 6.changes_requested (exit 0) — a gating bot requested changes. Go to Step 6, address it, push; the next push re-fires the review, so re-run the watcher.ci_failure (exit 0) — a check failed. Fix it (Step 6), push, re-run the watcher.dirty (exit 0) — the branch conflicts with main and GitHub skipped the pull_request: workflows. Rebase onto current main, resolve, force-push, then re-run the watcher — the push re-fires the missed workflows.pending_at_budget (exit 1) — a signal never arrived within the budget (a reviewer that never posted, CI stuck pending). Inspect which field is still none/pending in the returned snapshot. If the gh-aw review check ran but posted nothing, gh run view --log-failed; do not retry via GraphQL — gh-aw is event-triggered. Re-run the watcher to keep waiting once the cause is understood.reviews.*.body and every inline comment body before judging any item — a COMMENTED state or zero inline comments is not a license to skip the body (see rules/reviewer-feedback-reading.md)Fixed in <sha> (literal phrase; Done / Accepted and fixed do not satisfy)Declining — <reason with cited evidence> (em dash —, not hyphen or period)pull_request: synchronize); Copilot needs a manual re-request each push via skills/release/request-copilot-review.sh (same args as Step 4).APPROVED, or COMMENTED with its body read and no blocking items, and every thread has a reply.Only proceed when:
.watch.result as ready — its exit-0 readiness conjunction (mergeable, CI success/none, both gating bots posted, no CHANGES_REQUESTED); the field predicate is the watcher's, not restated here (rules/script-as-black-box.md — see skills/release/watch-pr-reviews.sh header). ready already requires each gating bot's state to have left none, so a reviewer that never ran cannot satisfy the gate vacuously, ANDreviews.*.body in the returned snapshot has been read in full — a COMMENTED state with zero inline comments is not a license to skip the body (see rules/reviewer-feedback-reading.md), ANDinline_comments count has a Fixed in <sha> or Declining — <reason> reply per Step 6 (verify by listing the PR's review comments — the poll script tracks counts, not reply state, so the operator confirms thread closure).A COMMENTED review never gates the merge on its state alone — but its body must be read before merge, zero inline comments included. With inline comments, it is mergeable once every thread also has a reply.
Once these conditions hold, merge automatically — the green gates are the approval. Do not pause to ask a human whether to merge.
Clear superseded review gates first. A policy bot cannot APPROVE (github-actions[bot] gets HTTP 422), so a clean re-review lands as a COMMENT that does NOT supersede the bot's earlier CHANGES_REQUESTED in GitHub's merge gate — the stale request keeps merge_state.status at BLOCKED. Dismiss every such superseded review before merging:
skills/release/dismiss-stale-reviews.sh <owner> <repo> <pr-number>Run it once Step 5's poll shows every bot's latest verdict clean. It emits a JSON summary of what it dismissed and what it left active, exits non-zero on API failure, and is idempotent on re-run. Which reviews it dismisses and which it leaves is the script's decision contract — see skills/release/dismiss-stale-reviews.sh header, not restated here (rules/script-as-black-box.md).
Before merging, capture the registry baseline so the post-merge check has something to compare against:
PRE=$(tessl plugin info <workspace>/<plugin> | grep "Latest Version" | awk '{print $NF}')Pick the right cleanup path based on where you ran the skill from.
(A) From the base checkout (no additional worktree):
# Merge
gh pr merge <N> --merge --delete-branch
# Update local
git checkout main && git pull --ff-only
# Clean up local branch
git branch -d <branch>
# Prune stale remote refs
git remote prune origin(B) From an additional worktree (per rules/agent-worktree-isolation.md):
# Merge (running from inside the worktree is fine)
gh pr merge <N> --merge --delete-branch
# Return to the base checkout, fast-forward main
cd <path-to-base-checkout>
git checkout main && git pull --ff-only
# Tear down the worktree — directory + `.git/worktrees/` metadata
git worktree remove <path-to-worktree>
# Now safe: branch is no longer checked out anywhere and is fully merged
git branch -d <branch>
# Prune stale remote refs
git remote prune originOrder in (B) is mandatory: git branch -d refuses to delete a branch that is checked out in any worktree, so the git worktree remove step must come before git branch -d. Reversing the order produces a "checked out at <path>" error and leaves a stranded branch.
After merge — per rules/ci-safety.md's Always Watch CI duty extended through release:
Verify the merge landed on main (git pull --ff-only succeeds; git log -1 --oneline shows the merge commit)
Watch the publish workflow to a terminal state. Bind to the merge commit SHA + the push event, never to "latest on main". The publish workflow may take several seconds to be enqueued after merge, so the run-id lookup polls until the run is listed (2s interval, 30s budget):
merge_sha=$(gh pr view <N> --json mergeCommit --jq '.mergeCommit.oid')
run_id=$(skills/release/resolve-publish-run.sh <owner> <repo> "$merge_sha" "<publish-workflow-name>" | jq -r '.database_id')
gh run watch "$run_id"No --exit-status on the watch: the publish-landed conjunction below reads the run conclusion explicitly, so letting --exit-status propagate a non-zero exit would short-circuit set -e wrappers before the conjunction runs.
gh pr view returns the specific merge commit for this PR, unaffected by parallel merges. The resolver filters on headSha == $merge_sha AND event == push so manual workflow_dispatch runs sharing the SHA are excluded; it also retries on enqueue latency so the immediate post-merge gh run list doesn't race the publish workflow's enqueue and surface as "no run found". Output is {"database_id": N} per rules/script-delegation.md — extract with jq -r '.database_id'. The watch is a timing precondition for the conjunction below, not the gate
Confirm the publish landed via the conjunction check — conjuncts 1 and 2 (resolved run's conclusion == success AND registry's Latest Version > PRE). Capture the emitted current version for the moderation check that follows:
# Gate on the exit code — only a clean conjunction (rc 0) may proceed to
# the moderation step. A non-zero rc (publish did not land, or a tool
# error) stops the release here; do not fall through to moderation.
landed=$(skills/release/verify-publish-landed.sh <workspace> <plugin> "$PRE" "$run_id") \
|| { echo "Publish not confirmed — $(jq -r '.reason // "see stderr"' <<<"$landed")" >&2; exit 1; }
CURRENT=$(jq -r '.current' <<<"$landed")Output is exit-code-dependent: rc 0/1 emits the JSON envelope {"ok": bool, "reason": "...", "run_conclusion": "...", "pre": "...", "current": "..."} on stdout (parse it for the finding); rc 2 emits the stderr diagnostic (tool-state errors: run still in flight, gh/tessl unreachable). Exception: the missing-jq guard at rc 2 emits a minimal JSON envelope on stdout (the script can't use jq to format JSON when jq itself is absent) so wrappers that always parse stdout still see a parseable failure. Do not compare against a specific expected version. See rules/ci-safety.md for full release-contract semantics and failed-publish recovery
Once conjuncts 1 and 2 hold, confirm moderation cleared — conjunct 3. A freshly published version can be install-blocked until its moderation state reaches pass; poll with exponential backoff (the script owns the backoff constants and the cleared/blocked decision):
skills/release/verify-moderation-cleared.sh <workspace> <plugin> "$CURRENT"Exit 0 = moderation cleared. Exit 1 = blocked or still-pending at budget exhaustion — an unconfirmed release; surface it and do not report success. Exit 2 = tool-state error (tessl unreachable, jq missing). Never report the release confirmed until this clears. See rules/ci-safety.md for the full three-conjunct contract
Report the outcome: merged PR URL, version published, registry + moderation confirmation
When this step is wrapped in a reusable script (e.g., merge-and-cleanup.sh that other devs run unattended), see skills/release/SCRIPTING.md for the gates the script must enforce.
Finish here — the skill is complete.
.tessl-plugin
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
rules
skills
adopt-fork-pr
eval-curation
install-reviewer
migrate-to-plugin