bin/ Authoring Guide¶
Reference for any skill/scaffolding step deciding bin/ script vs inline code, language choice, structure.
Two audiences:
- Check 33 auto-fix — HIGH verdict: reference for extraction method
foundry:manage create skill— reference when scaffolding new skill needing code blocks, prevents inline blocks needing later extraction
See also: bin/ Script Principles in plugins/README.md — authoring motivation.
Language Policy (canonical — reproduced verbatim from plugins/CLAUDE.md)¶
bin/— optional: standalone executables (.sh,.py) auto-added to BashPATHby Claude Code; invoked via${CLAUDE_PLUGIN_ROOT}/bin/<script>inside skills- Language policy —
bin/: Python default (minimum 3.10); bash only for enumerated cases: (1) plugin install-path resolution, (2)$ARGUMENTSparsing where bash regex shorter and quoting-safe, (3)find | sort | headpipelines with no business logic- Python scripts: type hints, module docstring,
if __name__ == "__main__"guard; ruff-format 120-char line length (pre-commit enforced); aggregate related print output into singleprint()using\n/\t; pure functions (no I/O, no subprocess, no env-var reads) →doctestin docstring; anything with I/O/subprocess/argv →pytestwithcapsys/monkeypatchintests/alongsidebin/ - bin/ scope: deterministic transforms only (parse args, resolve paths, compute one value); decision flow, branching prompts, agent-dispatch logic stays in SKILL.md prose
- Complexity escalation (bin/ scripts only — not inline blocks): existing or new
bin/bash script that hits any trigger → convert to Python (see Complexity Escalation section); triggers: (1) 3+if/elifbranches, (2) nested conditionals, (3) loop with conditional body, (4) multiplesed/awkpatterns in one pipeline, (5) multiple distinct error-handling paths - Reference design:
plugins/codemap-py/bin/(typed, docstrings,__name__guards, dataclass serialization boundaries)
- Python scripts: type hints, module docstring,
- Language policy — inline blocks in SKILL.md: bash default; Python only when bash version requires JSON parsing, multi-line string manipulation, or numeric computation (and note:
Bash(python:*)not in allow list — inline Python triggers approval prompt every invocation)
Cross-OS Compatibility¶
bin/ scripts run macOS, Linux, Windows (WSL/git-bash). Prefer Python over bash beyond the three allowed bash cases — Python portable by design, bash not.
Bash: banned constructs (GNU-only or platform-divergent):
| Construct | Problem | Use instead |
|---|---|---|
grep -P |
PCRE — GNU only; macOS BSD grep rejects | grep -E or Python re |
sed -i (no arg) |
GNU accepts; BSD requires sed -i '' |
Python pathlib.write_text |
readlink -f |
BSD lacks -f |
Python Path.resolve() |
date -d |
GNU only | Python datetime |
find -printf |
GNU only | Python os.walk |
sort -V (version sort) |
GNU/recent BSD only | Python packaging.version |
Python: portability rules:
- Use
pathlib.Pathfor all path operations — neveros.path.sepstring surgery - Never
os.system()— usesubprocess.run(..., check=True) - Add
LC_ALL=Cto subprocess env callingsort/grep— stable locale-independent output - Test with
tmp_pathfixture (pytest) — never hard-code/tmp/orC:\Temp
Silent-Failure Bash Idioms¶
Two traps producing no error, no output — the command "succeeds" while the check it powers never fires. Both found live in shipped skills; neither caught by shellcheck.
1. $(cmd) || echo N where cmd prints on failure. grep -c prints 0 and exits 1 on zero matches, so fallback fires too — substitution captures "0\n0". Later [ "$v" -eq 0 ] then errors; failed test exits non-zero, so any && action hanging off it skips — warning suppressed exactly when the condition it tests is true.
v=$(grep -c PAT "$f" 2>/dev/null || echo 0) # ✗ file exists, zero matches → v="0\n0"
v=$(grep -c PAT "$f" 2>/dev/null) || v=0 # ✓ correct in both the zero-match and missing-file cases
Missing-file case works either way (grep prints nothing, fallback clean) — why the bug reads harmless and survives review. Applies to any counter printing a valid result on non-zero exit; wc not affected (no print-and-fail).
2. Glob patterns held in a variable. Tool shell may be zsh — unlike bash, applies neither word-splitting nor filename generation to unquoted $VAR. for f in $_SKILL_GLOB iterates once over literal pattern string, matches nothing; same line under bash expands normally.
G="plugins/*/skills/*/SKILL.md"; for f in $G; do ... # ✗ zsh: 1 literal iteration, 0 files
while IFS= read -r f; do ... done < <(find plugins -path "*/skills/*/SKILL.md") # ✓ identical in both shells
Keep variables holding plain paths, never patterns; enumerate with find piped into while IFS= read -r. Note find -path "*/agents/*.md" recurses (* matches /) where glob */agents/*.md doesn't — add ! -path "*/agents/*/*" for flat scope.
Extraction Gate¶
Before writing any inline code block, apply Prose check first (§Prose over Code, Case 3). Prose precision-equivalent and shorter → write prose, stop. Else apply this gate. All three must pass — any fails, stay inline.
Gate conditions (all three must pass):
- G1 (Size): block > 100 tokens — else overhead ≥ savings
- G2 (Independence): no branch on prior LLM decision that cannot become an explicit arg
- G3 (Identity): has computational meaning outside orchestration prose
Score — sum applicable weights when gate passes:
| Dimension | Weight |
|---|---|
| Testable (deterministic I/O, writable pytest/shellcheck test) | +2 |
Reuse (same logic used in 2+ .md files) |
+2 |
| Token drain (block > 300 tokens) | +2 |
| Lintable (shellcheck/ruff directly applicable) | +1 |
| Run frequency (executes >1× per skill invocation) | +1 |
| Standalone debuggable (runnable with no SKILL.md context) | +1 |
| Reasoning complexity (3+ conditional branches, nested conditionals, or non-trivial regex/arithmetic) | +2 |
Verdict:
| Score | Verdict | Action |
|---|---|---|
| Any gate fails | HOLD | Inline is correct choice |
| 0–1 | LOW | Inline acceptable |
| 2–3 | MEDIUM | Prefer bin/ script |
| ≥4 | HIGH | Write as bin/ script — do NOT write inline |
Prose over Code (Token Compression)¶
Prefer plain language, table, or schema over code block when prose precision-equivalent and shorter in tokens. Applies at authoring time and retrospectively.
Exempt (fenced code blocks in .md files): examples, templates, blocks carrying exact syntax for copy-paste or reproducible execution.
Precision-equivalent means prose expresses logic with 100% precision and 100% reproducibility: every input produces same output from prose as from code, no ambiguity. Holds for: routing/switch logic with fixed, bounded, enumerable input set (mode flags, classification labels, small enum dispatch). Does NOT hold for: free-form inputs, numeric ranges, regex pattern matching, file-system state checks, or logic whose edge cases can't be fully enumerated in plain language. Uncertain → keep code.
Tests/linting on a bin/ script are anti-regression tools — NOT reason to keep a script fully replaceable with plain language. Delete script and tests when precision-equivalent prose possible.
Case 1 — inline fenced code block in any .md file¶
Replace with prose/table/schema when all REPLACE conditions apply AND no KEEP condition applies:
| Condition | REPLACE | KEEP |
|---|---|---|
| Variable only referenced in prose conditions (never in a later shell command) | ✓ | — |
| Variable consumed by a later shell command or drives file I/O / cache state | — | ✓ |
| Cases bounded, mutually exclusive, no shell/subshell semantics | ✓ | — |
| Prose form is precision-equivalent (see definition above) | ✓ | — |
Token test (apply only when all REPLACE conditions hold): tokens(block) > tokens(prose/table/schema) → replace.
Replace: manage/SKILL.md EDIT_TRIVIAL classifier — only in prose conditions, no shell consumer → 2-row table.
Keep: STALE=$([ ! -f "$INDEX" ] || [ -n "$(find "$INDEX" -mmin +60 -print 2>/dev/null)" ] && echo true || echo false) — STALE consumed by downstream shell command; find -mmin + 2>/dev/null not precision-equivalent in prose.
Case 2 — existing bin/ script¶
bin/ scripts enforce reproducibility and stay as executables. Deletion candidate only when ALL hold:
- Logic is precision-equivalent (see definition above) — routing/switch with bounded input set; NOT free-form or range inputs
- If test file exists (
tests/test_<name>.pyortests/test_<name>_sh.py): evidence precision was non-obvious at authoring time. Before deleting, verify prose covers every non-happy-path test scenario — any test case producing ambiguous prose answer → keep script. Delete test file only after verification passes. - No cross-plugin consumers (not listed in
Known cross-plugin utilitiesor any<!-- file: ... consumers: ... -->header) - Single consumer — called from exactly one
.mdfile within the plugin; verify withgrep -rn "<script-basename>" plugins/*/skills/ plugins/*/agents/ - Token test:
tokens(call-site description in .md) > tokens(equivalent prose in .md)— strict savings required
Linting on script isn't a blocker. Tests aren't a veto — but document precision cases the author considered non-obvious. Verify prose covers every test scenario before deleting; delete test file with script after verification.
When all hold: delete script (and its test file if present), replace call-site with prose, run check_orphaned_bin.py (must exit 0).
Case 3 — new code at authoring time¶
Prose check runs first, before the Extraction Gate. Ask: would one sentence, a table, or a schema express this with equal precision and fewer tokens? Yes → write prose; stop. No → proceed to Extraction Gate (G1/G2/G3).
Decision Flowchart¶
- Prose check first: would one sentence, a table, or a schema express this with precision-equivalent content and fewer tokens? Yes → write prose; stop here. No → continue.
- Writing a code block in SKILL.md? Apply gate (G1/G2/G3).
- Any gate fails? Inline is correct — stop here.
- Gate passes. Score positive dimensions.
- Score < 2? Inline acceptable — stop here.
- Score 2–3? Prefer bin/ (MEDIUM verdict); use language policy to pick bash vs Python.
- Score ≥ 4? bin/ required (HIGH verdict); use language policy; write tests.
- Wire into consumer — before commit: edit consumer SKILL.md, replace inline twin with
"${CLAUDE_PLUGIN_ROOT}/bin/<script>" …; runpython "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/check_orphaned_bin.py"; must exit 0.
A consumer never reaches into another plugin's
bin/.${CLAUDE_PLUGIN_ROOT}must resolve to the consuming plugin — script must exist in that plugin's ownbin/. Script two plugins both need is duplicated: addpropagate_shared.pyMANIFEST entry (canonical in owning plugin), copies stay byte-identical. Precedent:find-polluter.py, canonical in foundry, copied tocc_develop/bin/—develop:debugpreviously derived$_FOUNDRY_BINpath from resolver output, so flaky-test isolation silently vanished on develop-only install. Rule + rationale:plugins/CLAUDE.md§Self-Contained_shared; audit Check 27 fails new reach-ins.
Caller Pattern¶
How to invoke bin/ scripts from .md files:
# timeout enforced via annotation
RESULT=$("${CLAUDE_PLUGIN_ROOT}/bin/<script-name>.sh" arg1 arg2 2>/dev/null || echo "fallback-value") # timeout: 5000
# timeout enforced by --timeout default inside script
RESULT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/<script-name>.py" arg1 arg2)
Script Output Routing¶
Rule: match output channel to downstream consumer.
| Output needed for | Script writes | Skill reads via |
|---|---|---|
Shell command arg ("$VAR") |
${TMPDIR:-/tmp}/<skill>-<name>-${CSID} file |
IFS= read -r VAR < "${TMPDIR:-/tmp}/<skill>-<name>-${CSID}" |
| Prose condition / display only | ${TMPDIR:-/tmp}/<skill>-<name>-${CSID} file |
Read tool or plain prose |
| Single value, same bash block | stdout | VAR=$(python script.py ...) |
| Several values across later blocks | bin/state.py set <ns> K=V … |
eval "$(python … bin/state.py load <ns>)" |
Multi-value DATA output: write to TMPDIR files — never eval stdout.
Shell variables set in one Bash tool call don't persist to next separate call — survive only within single invocation. TMPDIR files survive across all invocations. Script returning 2+ values (e.g. PROJ + INDEX) must write each to own file, exit 0/1. Skill checks exit code; downstream steps cat what they need.
Preferred idiom for cross-block persistence: bin/state.py. Instead of hand-rolling per-skill temp file + reload, use tested helper — python "${CLAUDE_PLUGIN_ROOT}/bin/state.py" set <namespace> RUN_DIR="$RUN_DIR" SCOPE="$SCOPE" in producing block, then eval "$(python "${CLAUDE_PLUGIN_ROOT}/bin/state.py" load <namespace>)" at top of each consuming block. Values single-quote-escaped, keys must be shell identifiers matching ^[A-Za-z_][A-Za-z0-9_]*$ (set exits 2 on unsafe key; load skips one) — eval injection-safe. Include run-unique component in <namespace> (timestamp/run-id) when concurrent sessions of same skill could collide. check_bash_persistence recognizes this as valid reload — eval "$(…)" form suppresses cross-block-loss finding.
Scope: rule applies to DATA output (returning computed values to skill). Shell-setup eval — e.g.
eval "$(python parse-skill-flags.py ...)"injectingFLAG_*=...assignments into calling shell — different pattern, remains valid.
Naming convention: ${TMPDIR:-/tmp}/<plugin>-<script-slug>-<value-name>-${CSID} (terminal session-scope suffix — see rules/claude-config.md §TMPDIR Sentinel Scoping). Script with more than one consumer (e.g. shared resolve-shared.py) — calling skill passes unique prefix: --out-prefix <skill>-<run-id>; script writes <prefix>-proj-${_CSID}, <prefix>-index-${_CSID}. Never hardcode prefix in shared script — consumers collide.
# script — owns output routing; prefix passed by caller when multi-consumer
import os, sys, tempfile
from pathlib import Path
_CSID = os.environ.get("CSID") or os.environ.get("CLAUDE_CODE_SESSION_ID") or "shared"
tmpdir = os.environ.get("TMPDIR") or tempfile.gettempdir()
prefix = sys.argv[1] # e.g. "codemap-integration"
Path(f"{tmpdir}/{prefix}-proj-{_CSID}").write_text(proj)
Path(f"{tmpdir}/{prefix}-index-{_CSID}").write_text(index)
sys.exit(0)
# skill — exit-code check only; no parsing
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
python "${CLAUDE_PLUGIN_ROOT:-plugins/myplugin}/bin/resolve.py" "myplugin-resolve" ... # timeout: 5000
# only when value feeds shell command
IFS= read -r INDEX < "${TMPDIR:-/tmp}/myplugin-resolve-index-${CSID}" 2>/dev/null || INDEX=""
python scan.py --index "$INDEX" # timeout: 30000
# downstream prose — when value used only for display or condition
Read ${TMPDIR:-/tmp}/myplugin-resolve-index-${CSID}. If empty: print ✗ and stop.
Anti-patterns — data output:
# ✗ eval for data — fragile, needs shlex discipline; vars die at next Bash call anyway
eval "$(python resolve.py ...)"
# ✗ tab-delimited read — vars die at next Bash tool call
IFS=$'\t' read -r PROJ INDEX < <(python resolve.py ...)
# ✗ non-atomic — two calls may see different state; one invocation should write both files
PROJ=$(python resolve.py --field proj)
INDEX=$(python resolve.py --field index)
Timeout Policy¶
Every bin/ executable called from SKILL.md with # timeout: N comment must enforce timeout at runtime — not just a hint to Claude Code's Bash tool:
Bash scripts — use # timeout: N annotation; do NOT wrap with timeout S shell command:
# ✓ — Claude Code kills Bash tool after N ms; annotation is correct
RESULT=$("${CLAUDE_PLUGIN_ROOT}/bin/<script>.sh" args 2>/dev/null || echo "fallback") # timeout: 5000
# ✗ timeout S inside $() redundant with # timeout: N — not allow-listed (permission prompt), same threshold + fork overhead
RESULT=$(timeout 5 "${CLAUDE_PLUGIN_ROOT}/bin/<script>.sh" args 2>/dev/null || echo "fallback") # timeout: 5000
Note: timeout S IS valid for scripts invoked outside Claude Code (CI pipelines, standalone shell, pytest helpers). In SKILL.md context only: use # timeout: N.
Python scripts — add --timeout SECS argparse argument; scripts doing subprocess/network I/O must pass it to every blocking call. --timeout optional at call site — default value must equal N ÷ 1000 (from calling SKILL.md # timeout: N annotation). Shell timeout S wrapper not required for Python scripts; argparse default enforces budget internally:
# ✓ — --timeout default enforces budget; no shell wrapper needed
RESULT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/<script>.py" args) # timeout: 5000
# ✓ — explicit override for different budget
RESULT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/<script>.py" --timeout 30 args) # timeout: 30000
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(...)
# default= must match # timeout: N at the call site (N ÷ 1000)
parser.add_argument("--timeout", type=int, default=5,
help="Max subprocess wait in seconds (default: 5).")
args = parser.parse_args(argv)
result = _subprocess_call(timeout=args.timeout)
...
def _subprocess_call(timeout: int = 5) -> str:
try:
return subprocess.check_output([...], timeout=timeout, ...)
except subprocess.TimeoutExpired:
return "" # or raise, depending on caller contract
Pure-transform scripts (arg parsers, path resolvers without subprocess) — no timeout parameter needed; they cannot block.
ms → s reference (for --timeout arg in Python scripts): 5000 ms = 5 s; 6000 ms = 6 s; 15000 ms = 15 s; 600000 ms = 600 s.
Python Script Skeleton¶
Closed option sets (severity, mode, status, kind, action) must be named
(str, Enum)— never bare strings compared inline.argparsederiveschoices=from enum so CLI and type can't drift; convert at boundary, pass enum inward. Full rule +EnumvsLiteraltable:rules/python-code.md§Closed Option Sets.
Minimum required structure for any new Python bin/ script:
#!/usr/bin/env python
"""script-name.py — one-line description.
Usage:
python "${CLAUDE_PLUGIN_ROOT}/bin/<script-name>.py" <required-arg> [--flag]
"""
from __future__ import annotations
import argparse
import sys
# ... imports
def pure_function(x: str) -> str:
"""One-line summary.
Args:
x: description.
Returns:
description.
Examples:
>>> pure_function("input")
'output'
"""
...
def main(argv: list[str] | None = None) -> int:
"""CLI entry point. Returns exit code."""
parser = argparse.ArgumentParser(...)
...
return 0
if __name__ == "__main__":
sys.exit(main())
Tests go in <plugin-root>/tests/test_<script-name>.py — alongside bin/, not inside it. No __init__.py. Plugin layout:
plugins/cc_foundry/
bin/
script_name.py ← underscore names (see naming rule below)
tests/
test_script_name.py ← here, not bin/tests/
Naming rule — underscores, not hyphens. Python can't import hyphenated filenames via import statement; script-name.py requires importlib boilerplate. Underscore names (script_name.py) allow direct import — simpler tests, no extra machinery.
conftest.py (one per plugin tests/ directory — centralises bin/ path setup for all test files in that plugin):
"""Pytest configuration — adds bin/ to sys.path for all tests."""
from __future__ import annotations
import sys
from pathlib import Path
_BIN_DIR = Path(__file__).resolve().parent.parent / "bin"
if str(_BIN_DIR) not in sys.path:
sys.path.insert(0, str(_BIN_DIR))
.resolve()— resolves symlinks; path is absolute and canonical- Guard
if str(_BIN_DIR) not in sys.path— prevents duplicate entries when pytest reimports conftest
Individual test files — import directly, no sys.path manipulation needed:
Bash Script Skeleton¶
For the three allowed cases only (see language policy above):
#!/usr/bin/env bash
# script-name.sh — one-line description.
# Usage: script-name.sh [arg]
# Exit codes: 0 = success, 1 = not found
set -euo pipefail
...
Bash Script Testing¶
Naming: test_<basename_normalized>_sh.py in tests/ alongside bin/. Normalize: dashes → underscores, drop .sh, append _sh suffix. _sh suffix permanently distinguishes bash tests from Python tests with same base name.
Example: resolve-shared-path.sh → test_resolve_shared_path_sh.py.
Self-contained helper — each test file defines own SCRIPT path and sh() helper; no conftest.py changes needed for bash tests:
import os, subprocess
from pathlib import Path
import pytest
SCRIPT = Path(__file__).parent.parent / "bin" / "script-name.sh"
def sh(*args: str, env: dict | None = None, cwd: str | None = None) -> subprocess.CompletedProcess:
e = {**os.environ, **(env or {})}
return subprocess.run(["bash", str(SCRIPT), *args], capture_output=True, text=True, env=e, cwd=cwd)
Three mandatory tests per script:
- Missing/wrong args → non-zero exit
- Invalid input (path traversal
.., special chars, non-integer where integer expected) → exit 2 + stderr message - Happy path with isolated
HOMEviatmp_path(prevents cache-dir reads from real~)
Template:
def test_missing_args() -> None:
assert sh().returncode != 0
def test_invalid_input_traversal() -> None:
r = sh("../evil", "skills/_shared")
assert r.returncode == 2
assert "invalid" in r.stderr
def test_happy_path(tmp_path: Path) -> None:
env = {"HOME": str(tmp_path)}
r = sh("foundry", "skills/_shared", env=env)
assert r.returncode == 0
assert "skills/_shared" in r.stdout
HOME isolation — always pass HOME=str(tmp_path) for scripts doing cache lookups. Never rely on real ~/.claude/ in tests.
Integration marking — scripts requiring real git repo with history, gh auth, or network calls use explicit decorators on each test or an existing test class:
@pytest.mark.skipif(not os.getenv("RUN_INTEGRATION"), reason="requires real git/gh env — set RUN_INTEGRATION=1")
class TestIntegration:
"""Group tests requiring the explicitly enabled integration environment."""
# Add the integration test methods here.
Apply decorators to an existing class for grouped integration tests, or to individual tests for mixed files (arg-validation unit + happy-path integration).
Integration-requiring conditions: git describe, git log on real history, gh auth/API, network calls.
Audit enforcement — Check 34 (/audit plugins) verifies every bin/*.sh has corresponding tests/test_<name>_sh.py. Missing test files flagged as MEDIUM severity.
Complexity Escalation¶
Applies to bin/ scripts only — inline SKILL.md blocks stay bash (inline Python triggers approval prompt every invocation). Extracted bin/ bash script growing past a simple linear transform → convert to Python before complexity compounds.
Escalation triggers — any one fires → convert:
| Trigger | Example |
|---|---|
3+ if/elif branches |
if [[ $x == a ]]; then ... elif [[ $x == b ]]; ... (3rd branch = trigger) |
| Nested conditionals | if ...; then if ...; fi; fi |
| Loop with conditional body | for f in ...; do if ...; then ...; fi; done |
Multiple sed/awk patterns |
sed -e 's/a/b/' -e 's/c/d/' — 2nd -e is trigger |
| Multiple distinct error paths | 2+ separate exit N calls at different failure points |
Conversion steps:
- Identify bash script in
bin/meeting a trigger - Rewrite as Python using the Python Script Skeleton above — preserve CLI interface (arg names, exit codes, stdout contract)
- Add
pytesttest file intests/test_<script_name>.py— cover all branches that triggered escalation plus happy path - Replace invocation in source SKILL.md (Bash block or prose reference) with
python "${CLAUDE_PLUGIN_ROOT}/bin/<script_name>.py" ... - Delete old
.shfile - Delegate to foundry:linting-expert (ruff + mypy) and foundry:qa-specialist (edge-case matrix) per Quality Agents section
Check 33 / --efficiency mode: Phase A bin/-extraction check raises complexity-escalation findings as medium severity when trigger conditions detected in existing bin/ bash script. HIGH or MEDIUM verdict triggers conversion, not just extraction.
Quality Agents¶
After writing any bin/ script, delegate to these agents:
foundry:linting-expert — after implementation, before handover:
ruff check+ruff format— style, imports, security, 120-char linesmypy— type annotation correctness- Note:
bin/scripts useprint()for output — intentional, not stray. Add"bin/**" = ["T20"]to[tool.ruff.lint.per-file-ignores]inpyproject.toml
foundry:qa-specialist — for test coverage review and edge-case matrix:
- Public API surface:
main(), all exported pure functions - Edge cases: empty input, bad args, missing files, unsupported markers
- Parametrize where 3+ cases share same structure
Resilience Replication Marker¶
Blocks replicating across files by design (per-plugin resilience, cross-plugin fallbacks) must be marked to suppress Check 33 / --efficiency false positives.
Canonical marker — first line of the fenced block content:
Marker must be the first content line inside the fence (not preceding it). Curator and Check 33 Phase 2 recognize both the structured marker and prose annotations matching "intentional resilience replication" — the structured form is a conventional token (not yet wired into bash quick-scans; recognized by curator prompt).
Example:
# audit-skip: resilience-replication
AGENT_DEADLINE_S=${AGENT_DEADLINE_S:-900}
APPLY_DEADLINE_S=${APPLY_DEADLINE_S:-600}
When to use: block appears in 2+ plugin files with only constant differences AND isn't a bin/ extraction candidate — e.g. agent-deadline constants, plugin-availability checks, unsupported-flag resilience boilerplate. See plugins/CLAUDE.md §Fallback / Resilience Infrastructure for design rationale.
Integration with foundry:manage create skill¶
When foundry:manage create skill <name> scaffolds a new SKILL.md, include this instruction:
Before writing any fenced code block, run
cat "$_FOUNDRY_SHARED/bin-authoring-guide.md"via Bash tool and apply extraction gate. Write bin/ script directly if verdict MEDIUM or HIGH. Any bin/ script returning 2+ values: apply §Script Output Routing — write each value to${TMPDIR:-/tmp}/<skill>-<name>-${CSID}file; neverevalstdout.
Integration with Check 33 Auto-Fix¶
When Check 33 surfaces HIGH findings, reference this doc for:
- Language choice (bash vs Python) — see Language Policy section
- Caller pattern to replace the inline block with — see Caller Pattern section
- Test location (
bin/tests/)
Surgical edit constraint — when replacing an inline block in a source .md file, modify ONLY the target block. Do NOT edit surrounding prose, frontmatter, other code blocks, check tables, or other content. Incidental issues noticed → record in extraction summary; don't fix inline. After each file edit, run git diff HEAD -- <file>, verify only target-block lines appear in diff; revert and re-apply if non-target lines changed.