harness-tier
CLAUDE.md10 starsChanged 31 days agoApache-2.0View on GitHub
This repo is the Claude Code plugin itself, not a consumer of it. Usage: README.md (core idea + install) · USAGE.md (per-topic index into docs/usage/), every file with a Korean twin that doc-sync keeps in step. Component authoring specs (agent/hook/skill frontmatter) come from the official docs as SSOT, never model knowledge: skills · plugins-reference · hooks · permissions. allowed-tools pre-approves tools, it does not restrict — enforced at point of use by .claude/rules/skill-frontmatter.md and tests/skills/. vway-kit is the internal sister…
In this repository21 other files it gives its agents.
- commitSkill
- design-apiSkill
- design-architectureSkill
- design-erdSkill
- design-sdsSkill
- design-srsSkill
- design-tableSkill
- doc-syncSkill
- flow-initSkill
- flowSkill
- flow-uninstallSkill
- harness-authoringSkill
- harness-deploymentsSkill
- harness-initSkill
- harness-insightSkill
- integrationSkill
- performanceSkill
- playwright-scaffoldSkill
- prose-reviewSkill
- release-commitSkill
- wiki-initSkill
The file
Files
CLAUDE.md
This repo is the Claude Code plugin itself, not a consumer of it. Usage:
README.md (core idea + install) · USAGE.md (per-topic index into
docs/usage/), every file with a Korean twin that doc-sync keeps in step.
Component authoring specs (agent/hook/skill frontmatter) come from the official docs as
SSOT, never model knowledge: skills ·
plugins-reference ·
hooks ·
permissions.
allowed-tools pre-approves tools, it does not restrict — enforced at point of use by
.claude/rules/skill-frontmatter.md and tests/skills/.
vway-kit is the internal sister repo — not a consumer install and not an older name: the same
disciplines and gate scripts, maintained separately, propagating in neither direction. A session
here runs the installed vway-kit, so a discipline fixed here does not govern the work that
fixed it, and reflecting a fix there is its own task.
Commands
uv run python -m evals.run --dry-run --all # session count + wall-clock, no model calls
uv run python -m evals.run # measure skills whose description changed
uv run python -m evals.outcome # measure the outcome armA falling eval number re-measures that skill to confirm it, doubling its sessions over what
--dry-run advertised. ShellCheck every *.sh change in WSL: a shell bug hides as FAIL-OPEN
on the Windows hook runtime. A .sh checks out LF; other text files are CRLF in the worktree.
Conventions
- English in the repo — docs, commit messages, comments/docstrings, test assertion messages.
Korean stays only where load-bearing: text the repo quotes rather than authors, the strings a
test compares against it, and fixtures whose non-ASCII bytes ARE the case — translated, the
test stays green and stops exercising anything. Untracked
docs/superpowers/stays Korean. - Write only what the code can't say —
rules/doc-style.md; for a commit body,rules/commit-discipline.md; for generated harness artifacts,rules/harness-rules.md5-2. - Dogfood new CI — a workflow-rendering feature also lands in this repo's own
.github/workflows/, every job with a tighttimeout-minutes. Exempt: a template whose subject does not exist here (a REST service, a browser front end, a deployment target). - A test file past 500 lines becomes a folder
tests/<what it covers>/, every file under the cap, with an__init__.py— without it, the day two packages share a basename, pytest aborts the session. A file under the cap stays flat. - The dev host is Windows, CI is ubuntu —
core.autocrlf=true, and.gitattributespins only*.sh(LF) and*.cmd(CRLF): every other tracked text file is CRLF in the worktree, LF in the blob. Never digest a tracked file's raw bytes (localpytestgreen, CI red, in silence); normalize CRLF inside every new digest. Check shell, PATH, shebangs, file modes and path separators in WSL before a push./flow-initcopies byte-for-byte, so a.shlands in the host LF; the host's own checkouts then follow itscore.autocrlf. - Mutation-test a fix, and assert the mutation applied — a no-op edit reads as verified. Apply
it in Python with
assert old in text, neversed -i; revert withgit checkout --from an already-clean tree. Assert the baseline is green where the battery runs, or every mutation reports as caught; a battery that carries rows forward says which it dropped for a moved anchor, since the edit under review moves them and the rest still sweeps clean. Mutate POSIX-only guards in WSL, and diff collected node ids around a mechanical test edit. A/B a claim that a gate over- or under-blocks against the released tag, over a command matrix, before acting on it.
Folder structure
agents/, skills/ are auto-discovered, and hooks/claude/hooks.json is declared in
plugin.json: adding a component is a new file. Consumers install the plugin branch, a
plugin-only tree .github/scripts/plugin_dist.py builds at release; a file the plugin reads at
runtime that its SHIP list misses is absent there (tests/test_plugin_dist.py).
.claude-plugin/ plugin manifest · marketplace entry pinned to the plugin branch; .codex-plugin/ · .agents/ mirror this for Codex
.claude/ this file and dev-only rules for this repo: authoring guidance, and what loads rules/ here — never ships
agents/ subagents the skills dispatch
hooks/ SessionStart · PostToolUse · Notification scripts (claude/hooks.json) — the commit gate is not one; Codex runs the pair from the host's .codex/hooks.json
skills/ one directory per slash command
rules/ shipped SSOTs: tier discipline (+ on-demand parts), harness generation, prose
scripts/ gate + setup scripts; the host copy lists are flow_init_setup.py COPY_FILES/HARNESS_COPY_FILES; harness/<name>/ holds each harness's own installer
github/ consumer workflow templates /flow-init and /wiki-init render; .github/ is this repo's own CI
templates/ design-doc templates /flow-init seeds once into the host (host-owned after)
tests/ pytest over scripts/ and over the shipped skill and rule files
evals/ skill measurement (invocation, outcome), incl. codex_probe/ — NOT shipped: commit as test:/chore:
docs/ usage/ consumer guide (English + .ko twins, shipped) · superpowers/ design records and reference notes (Korean, gitignored, local only)Architecture
- Installed outside the host (in a cache) → dual paths.
${CLAUDE_PLUGIN_ROOT}reads,${CLAUDE_PROJECT_DIR}writes. Never write into the plugin directory. Host writes group under.claude/harness-tier/, except files whose location an external tool forces. - The commit gate is registered in the host's
settings.json, not the plugin's hooks.json, for deny-enforcement reliability.settings.jsoncannot resolve${CLAUDE_PLUGIN_ROOT}, so/flow-initcopies the gate scripts and policy into the host (Codex:.codex/hooks.json). - Script propagation is one-way — SOURCE (
scripts/,flow-tiers.yaml) → cache → host copies. Fix only the SOURCE —/flow-initoverwrites a host copy on its next re-sync. - Policy stays environment-free —
flow-tiers.yamlis plugin-owned and immutable in a host, and itsmerge_strategynames flows only byflow-config.brancheskey. - A consumer-facing
.mdchange (rules, skills) commits asfeat/fix—docs/choretrigger no release, and only aplugin.jsonversion bump reaches a consumer. rules/risk-tiers.mdis the tier-discipline SSOT, injected at SessionStart beside adoc-style.mdsummary (injected for Codex always, for Claude only while no leftover copy from an older/flow-initremains in the host); the split-out files are read on demand. Editing it or the hook that injects it costs everyhook_assistedskill a live re-measure. A rate moves with where text sits beside## Principle's mandate, not with how much, even on a byte-identical description: leave that section alone, move whole sections, and leave no "moved to X" stub — a pointer-only section can cost more than the text it replaced. Compare a rate only to a baseline of the same model and--reps— a plain--allalready matches.- Three verification layers, independent: the host's
.pre-commit-config.yaml; the flow gate (PreToolUse, agent-session commits and merges only — terminal commits and CI bypass it); and CI, which closes that blind spot. Per-gate mechanism:rules/gate-mechanics.md. PR mode takes a flow's merge out of the hook's sight (rules/promotion.mdPR workflow). - Ask a review agent for a literal
VERDICT: PASS/VERDICT: FAILline — an ambiguous report reads as a pass, and the marker then records a review that never happened. - Skills are measured —
tests/skills/checks the file is well-formed,evals/that it is reached (stale when its description or a fixture its cases run in moves) and, in the outcome arm, executed, whose fingerprint covers the body and every fixture input: a body edit costs a re-measure the invocation check never shows.
Invariants (break these and the gate is silently neutralized)
Preserve these in scripts/* and hooks/*.sh; code, tests and skills cite them by number.
- FAIL-OPEN — a transient internal error lets the gate pass, so a broken gate never
permanently blocks commits. Three fail-closed exceptions:
- Exception 1:
python3≥ 3.8 or PyYAML missing or outdated → the runner blocks. - Exception 2: the policy loads with its
tiers, the config loads or is absent, notiermarker exists, and the config names the branch neither staging nor production →flow_gate_checkblocks the unclassified commit. A missing or broken policy, or a broken config, fails open: the test is "works reliably", not "the file exists". - Exception 3: a
git merge, or agit pullthat names a branch without rebasing, whose flags violate its flow'smerge_strategyrow — a missingrequireflag or a presentforbidflag, nothing else — is blocked, decided from the command string alone, so no internal error can misfire it. Anything uncertain fails open, as does a command whose merges all run elsewhere; one merge naming no directory beside one that does keeps the whole command judged, behind acda deliberate over-block.
- Exception 1:
- Windows encoding — the hook's Python runs in a cp949 locale, where a Korean
print()or a UTF-8open()can FAIL-OPEN and let a commit that should be blocked through. Keep thePYTHONUTF8=1·force_utf8_io()·encoding="utf-8"defenses. - Block = exit 2 + a reason on stderr — emit the JSON
permissionDecisiontoo; exit 2 decides. - No
iffield on the settings.json gate hook — it suppresses the hook per build. Filter in the runner's stdin self-filter instead. /flow-initis idempotent — match-then-skip on every addition it makes to a host file.- Worktree re-designation stays FAIL-OPEN — the commit path re-points
ROOTto the worktree the commit runs in, read from the command, else from the hook's cwd; anything uncertain falls back to main, the resolver never guesses between directories the command's invocations name, and re-designation must never newly block. One exception: a command whose commit tree cannot be pinned to one place is gated anyway, since whichever tree it resolves to, its being clean says nothing — invocations naming different directories, an untrackablecd/pushd/popdhop (a subshell counts) before a bare commit other than the leading prefix, a-Cvalue still carrying shell expansion or a glob, or a commit the directory readers never see to resolve — one inside a script handed to an interpreter, or one a quote, backslash or ANSI-C escape spells (com''mit,c\ommit,$'\x63ommit'). Same-repo identity is--git-common-direquality, never a path prefix. Keep the uncertain set small. Cases:scripts/_harness_paths.py. A merge whose target the command never names, in a command that names and moves to no directory, reads that branch from the hook's cwd through the same resolver: Exception 3's verdict, not a re-designation, so it may block. - One authority for what a
gitinvocation is — the classifier decides; the runner's stdin filter only decides whether to spawn it, and stays coarser: a spelling one of them alone accepts is the gate off in silence. Quoting, escapes, comments and heredoc bodies are read in one place, and every rule is located on that mask (the anchoredcdprefix excepted). Quoted text and heredoc bodies are data only until something runs them: any exemption from reading them as a command must err toward over-gating, andgitnever earns one. A missed commit is the one direction this may never fail in;tests/skills/pins real invocations and mere mentions. Skills spellgit commit,git mergeandgit pullflags literally — the hook reads them unexpanded. Exemption and heredoc rules:scripts/_harness_paths.py.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

