brainstorming
Refine feature and sprint intent into a useful specification. Capture scope, observable criteria and material choices without…
Prepare a declared release target, or preview it with --dry-run. Derive its version and require authorization before publication.
Claude Code
$ npx -y skills add arbiterForge/codeArbiter --skill release --agent claude-code
Codex
$ npx skills add arbiterForge/codeArbiter --skill release -a codex -y
Cursor
$ npx skills add arbiterForge/codeArbiter --skill release -a cursor -y
Gemini CLI
$ npx skills add arbiterForge/codeArbiter --skill release -a gemini-cli -y
GitHub Copilot
$ npx skills add arbiterForge/codeArbiter --skill release -a github-copilot -y
OpenCode
$ npx skills add arbiterForge/codeArbiter --skill release -a opencode -y
Windsurf
$ npx skills add arbiterForge/codeArbiter --skill release -a windsurf -y
name: release description: Prepare a declared release target, or preview it with --dry-run. Derive its version and require authorization before publication. argument-hint: "[target] | --dry-run"
The single permitted path to a version tag. Routed to when the user invokes `/release [target]`. Derive the bump from the commit log, update the changelog, tag — nothing more.
**One command, any number of declared targets.** A project declares one or more release targets in `$PROJECT_ROOT/.codearbiter/release-targets.md` (grammar and parser contract: `{{PLUGIN_ROOT}}/hooks/_releaselib.py`'s module docstring). `/release` takes the target's name as its only argument. When `$TARGET` is omitted and the declared file names exactly one target, that target is used — a single-target project's bare `/release` behaves exactly as it always has. When more than one target is declared, `$TARGET` is required; STOP and ask rather than guessing which one a bare invocation meant. **Resolve the omitted-single-target case mechanically, never by assumption** (MEDIUM, adversarial review 2026-07-31: `tag-prefix` itself takes `$TARGET` as a REQUIRED positional argument and has no way to express "the implicit one", so naming it here was not itself enough — the mechanical step that turns an omitted target into a concrete name before `tag-prefix` is ever called has to be spelled out too): run `"$PY" "{{PLUGIN_ROOT}}/hooks/_releaselib.py" list-targets` first — the sanctioned enumeration, through the same tested grammar `tag-prefix` already reads, rather than a by-eye scan of the delimiter block. Exactly one printed line confirms which name `$TARGET` is; more than one is the multi-target STOP above, restated by the tool rather than assumed. There is deliberately no second command per target: N commands would be N public surfaces to govern, catalog, and carry, for one operation whose only difference is which declared row it reads.
Every phase below is written once, against that row. Nothing in this skill is per-target prose.
**Execution-shell contract.** Every fenced `sh` command and every inline shell fragment in this workflow runs inside one POSIX-compatible shell session. On Windows, resolve and enter Git for Windows' own `bash.exe` before the interpreter step below; MUST NOT paste the `sh` snippets into PowerShell and treat PowerShell's exit status as their verdict. A native PowerShell session may be used only to locate and launch Git Bash, for example by resolving `git.exe`, taking its installation root, and invoking `bash.exe --noprofile --norc` from that installation's `bin` directory. Reject WSL aliases and WindowsApps stubs because they execute in a different filesystem. If no POSIX-compatible shell is available, STOP; do not translate the workflow ad hoc into a second command language.
**Interpreter convention, stated once and applying to every helper invocation in this file** (A-3.6). `python3` is not universally present — a Windows consumer commonly has `python` on PATH and no `python3` at all, and a literal `python3` spelling fails on every invocation at once there.
**Resolve the interpreter ONCE, by presence, before the first invocation:**
PY=python3; { command -v python3 >/dev/null 2>&1 && python3 --version >/dev/null 2>&1; } || PY=python
PYTHONDONTWRITEBYTECODE=1; export PYTHONDONTWRITEBYTECODE
PYTHONUTF8=1; PYTHONIOENCODING=utf-8; export PYTHONUTF8 PYTHONIOENCODING
{{IF:claude}}PROJECT_ROOT=${CLAUDE_PROJECT_DIR:-$(pwd)}{{ELSE}}PROJECT_ROOT=$(pwd){{END}}
cd "$PROJECT_ROOT" || { printf 'STOP — cannot enter the resolved project root.\n' >&2; exit 1; }**`command -v` alone is not enough** (LOW, #584): a Windows host commonly ships a `python3` *App Execution Alias* stub at `%LOCALAPPDATA%\Microsoft\WindowsApps\python3` that satisfies `command -v python3` with no Python actually installed — running it opens the Microsoft Store and exits non-zero. Only actually RUNNING it (`python3 --version`) tells the truth; `command -v` merely tells you a name resolves on `PATH`. `python3` wins whenever both it and `python` are genuinely present — the resolve-once order above tries it first and only falls back to `python` when it is absent or the stub — so a host with both interpreters gets the one this convention exists to prefer, not an arbitrary pick.
Set `PYTHONDONTWRITEBYTECODE` and resolve then enter `$PROJECT_ROOT` before the first invocation as shown. The host-conditional root uses Claude's harness pointer when available and the session cwd on Codex/Pi. It applies to every helper below and prevents a read-only or dry-run inspection from creating `__pycache__` beside a vendored helper. Every helper invocation below is then spelled `"$PY" "{{PLUGIN_ROOT}}/hooks/<script>" <args>` literally, one spelling throughout — including the inline `"$PY" -c "…"` snippets. Two spellings for one thing invites reading the difference as meaningful (blind exercise run 14 flagged exactly that when only three steps used `"$PY"` and fifteen still said `python3`).
**Both quotes are load-bearing, and the second one is the easier to lose** (HIGH-1, blind exercise run 16). Quoting only the interpreter — `"$PY" {{PLUGIN_ROOT}}/hooks/<script>` — leaves the script path exposed to word splitting, and a plugin root containing a space is an ordinary Windows install (`C:\Users\First Last\.claude\plugins\…`, since an account name with a space is unremarkable). On such a host the path splits at the space, Python is handed a truncated filename, and EVERY step of this lane fails at once: target resolution, `last-tag`, `classify-window`, `check-manifests`, `classify`, `notes-match`. The operator's only diagnostic is `can't open file '…\First'`, which names nothing recognisable. The same applies to any `$PROJECT_ROOT`-rooted path passed as an argument. Payload pathspecs are not an exception: load their line-delimited records into positional parameters and expand `"$@"` as specified under Targets.
**MUST NOT spell them `p
Open-source governance and hard gates for AI coding agents across Claude Code, Codex CLI, and Pi.
Refine feature and sprint intent into a useful specification. Capture scope, observable criteria and material choices without…
Create a verified local Git commit when committing changes is requested. Not for explaining commit history, drafting a message…
Inspect context drift and refresh selected source-backed documents under existing authorization.
Build source-backed project context through bounded inspection, optional agents, and record-level knowledge writes.
The banned-primitive gate. Routed to when changed code hashes, signs, encrypts, derives keys, generates security-relevant…
Investigate an unexplained defect or unexpected behavior without changing application code. Use for root-cause diagnosis and an…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.