一键导入
arch-audit
Periodic audit of src/benchflow/ shape (names, boundaries, file sizes, stability mix) — propose structural reorg opportunities, don't execute
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Periodic audit of src/benchflow/ shape (names, boundaries, file sizes, stability mix) — propose structural reorg opportunities, don't execute
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Review Benchflow or SkillsBench task-run trajectories and integration-test Benchflow code changes. Use this skill whenever the user asks to audit traj health, failed or timed-out runs, healthy pass/fail/timeout status, no-skill leakage, skill loading, reward hacking, verifier isolation, metadata completeness, token usage, timing, Daytona-vs-Docker parity, path/root handling, coverage gaps, Docker/Daytona failures, or release-readiness of benchmark data.
Run agent benchmarks, create tasks, analyze results, and manage agents using BenchFlow. Use when asked to benchmark an AI coding agent, run a benchmark suite, create tasks, view trajectories, or compare agent performance.
Run agent benchmarks, create tasks, analyze results, and manage agents using BenchFlow. Use when asked to benchmark an AI coding agent, run a benchmark suite, create tasks, view trajectories, or compare agent performance.
Adopt, convert, verify, and publish upstream benchmarks as BenchFlow benchmarks. Use when asked to port a benchmark, create a BenchFlow adapter, write or review benchmarks/<name>/benchflow.py, run parity, route a benchmark through L1/L2/L3, or decide whether a benchmark should run natively, be translated, or run as-is.
Review benchflow documentation for drift, staleness, duplication, and alignment
Manage a BenchFlow release end-to-end — choose the channel (public vs internal-preview vs release-candidate), stage and publish it safely, and run the pre-tag audit gates. Use when the user says "release", "cut a release", "release candidate", "rc", "internal tag", "publish to PyPI", "prerelease", "tag v0.x", or asks how releases/versions/channels work here. Complements `launch-prep` (which mechanically prepares a public cut); this skill owns the channel decision, the RC-without-merging-to-main flow, and the audit gates.
| name | arch-audit |
| description | Periodic audit of src/benchflow/ shape (names, boundaries, file sizes, stability mix) — propose structural reorg opportunities, don't execute |
| user-invocable | true |
Find structural reorg opportunities: vague filenames, orphan tiny files, stability-mixed merges, oversize files. One layer above /code-cleanup — that skill edits inside files; this one reshapes which files exist.
Do not auto-apply. Report ranked candidates; the user approves. Reorgs have import-graph consequences that need human judgment.
/arch-audit — full src/benchflow/ sweep/arch-audit <subtree> — scoped (e.g. src/benchflow/agents/, src/benchflow/cli/)In: file-level structure — names, boundaries, merges, splits, package grouping, __init__.py re-exports, import depth.
Out: line-level edits (/code-cleanup), public API design, dependency upgrades, test strategy, registry-entry additions (those are one-line contributions, not structural).
Reusable scripts live in scripts/ — paths below are relative to the skill root, run from there or prefix with .claude/skills/arch-audit/. They encode edge cases (private-underscore convention, __init__.py barrels, test exclusion, __all__, re-exports, string-typed imports). Python 3.12+, stdlib ast only.
Primary:
scripts/manifest.py [--no-cache] — one ast + git log pass over non-test src/benchflow/**/*.py. Emits JSON with {file, loc, commits_6mo, churn_ratio, exports[], importers[], barrel_importers[], importer_selectors{}}. Cached under scripts/.cache/<sha>[-dirty-<hash>].json. Source for Rules 1, 2, 5 — do not per-file-loop when manifest has the answer.Per-file (for what manifest doesn't cover):
scripts/dominant_symbol.py <file> — Rule 1 ≥70% exemption. Emits VERDICT: dominant=X (N%) / NONE / INSUFFICIENT_IMPORTERS (<3) / NO_IMPORTERS.scripts/churn_ratio.sh <file>... — TSV ratio<tab>commits<tab>loc<tab>path. Uses --follow; manifest's churn_ratio doesn't. Required for Rule 3.scripts/co_edit_matrix.py <file> — Rule 4 symbol co-edit clustering via git log --numstat + AST line-range mapping. Emits TSV pairs ≥20% or # status: (file_renamed / insufficient_commits / too_many_symbols / no_clusters).scripts/split_costs.py <file> --half-a=names --half-b=names — emits {shared_types, shared_helpers, importer_payoff, importers} for a proposed 2-way split. Required for every split finding. If it fails or can't be run, Pass 1 must suppress the finding entirely — do not emit a split proposal Pass 2 has no data to evaluate.Spot-check: scripts/tiny_files.sh, scripts/importers.py, scripts/exports.py — redundant when manifest is fresh; use for ad-hoc or post-rename sanity.
Parallelize per-file helpers with xargs -P 8 (read-only, safe).
Each has command + threshold + decision. Thresholds are heuristics — note them in findings.
Scan non-test sources: SRC=$(find src/benchflow -name '*.py' -not -name 'conftest.py' -not -path '*/tests/*').
Source: manifest exports[]. A module is vague if both:
exports[] against importer_selectors; unselected exports don't count). Value export = FunctionDef/AsyncFunctionDef/ClassDef/module-level assignment whose name doesn't start with _ and isn't excluded by a __all__ carve-out. Drop TypeAlias/Protocol/TypedDict/NamedTuple entirely — even with runtime behavior, they rarely drive vagueness. andBefore flagging, run scripts/dominant_symbol.py. Only dominant=X (≥70%) exempts. Every other VERDICT (NONE, INSUFFICIENT_IMPORTERS, NO_IMPORTERS) means no exemption applies — emit the finding. INSUFFICIENT_IMPORTERS is not a "skip this file" signal; it means the exemption check is unreliable, so fall back to the mechanical step-1+2 trip and emit.
Rule 1 is independent of Rule 4 — a Rule 4 skip doesn't exempt Rule 1.
No "cohesive around X" prose overrides — mechanical check decides.
Private modules (leading underscore like _sandbox.py, _env_setup.py) are NOT exempt. Underscore means "package-private API surface"; it does not mean "cohesive by convention." Rule 1 still fires.
Source: manifest loc < 100. Must satisfy one:
importers.length >= 2, ORsubprocess.run specifically so tests can patch("benchflow.X.run"); inspect source), ORbarrel_importers.length > 0 OR file itself is an __init__.py barrel (only re-exports).Otherwise inline at sole caller. 1 importer does NOT satisfy (a) — that's the fold signal.
Skip __init__.py with __all__ and/or re-exports only — those are barrels, exempt by (d).
Before any merge, scripts/churn_ratio.sh <a> <b>. If ratio >3× → veto (mixed stability = blame noise, review friction). Label sides "hot" / "cold" in the finding.
Caveat: --follow tracks single-rename chains only; squash-merge repos (benchflow uses squash-merge on PRs to main) under-count. Signal, not proof — a ratio of 2.5× in a squash-merge repo should be treated as closer to 4×.
Applies only to modules >500 LOC. Verify with wc -l first. Current candidates in benchflow: _sandbox.py (~757), sdk.py (~706), job.py (~582). Probably process.py (~379), viewer.py (~378) are under threshold but borderline — skip unless they cross 500.
scripts/co_edit_matrix.py <file>.no_clusters → leave the file. file_renamed → extend with git log --follow or skip. insufficient_commits / too_many_symbols → skip. boundary_drift_hunks: N → reduce confidence.Don't downgrade to "manual inspection required" — silence beats a weak claim.
no_clusters fallback: if file >500 LOC with ≥3 importers and Rule 4 is silent, check importer_selectors. Disjoint selector sets = importer-driven cleave (e.g., sdk.py imported as SDK by one set of callers and as SetupPhase/VerifyPhase helpers by another). Surface as needs_signoff; don't mechanize (facades / __init__.py re-exports look disjoint by design).
Source: manifest importers.length + barrel_importers.length.
5 importers: codemod +
ty check src/+.venv/bin/python -m pytest tests/in same PR.
__init__.py barrels exempt from Rule 2, count toward Rule 5 — rename behind a barrel still needs codemod if the symbol is imported directly (from benchflow.sdk import SDK bypasses the benchflow/__init__.py barrel for tree-shaking agents).Extra hub: src/benchflow/__init__.py is benchflow's public API surface. Any symbol re-exported there (check __all__ or direct from .X import Y) counts as >5 importers by default — external consumers aren't visible to the codemod.
If $SRC has <20 files or <3000 LOC, one Explore agent runs all rules end-to-end. Benchflow (~39 files / ~9k LOC) is above this threshold — default to multi-agent split by subtree.
One agent per subtree, all five rules. Splitting Rules 1+2 from Rule 3 means wasted merges Rule 3 vetoes. Suggested split for a whole-repo /arch-audit:
src/benchflow/ top-level (all *.py not in subpackages)src/benchflow/agents/src/benchflow/acp/ + src/benchflow/cli/Run scripts/manifest.py once first — data source for Rules 1/2/5. Only per-file-loop for what manifest lacks: scripts/dominant_symbol.py, scripts/co_edit_matrix.py, scripts/churn_ratio.sh. Parallelize with xargs -P 8.
Primary output: JSON, one object per line. If a rule can't produce a finding (e.g. Rule 4 file_renamed), emit no row. A Rule 4 skip doesn't suppress other rules.
Do not pre-filter with semantic prose. "Single-importer facade pattern" / "semantically coherent around SDK phases" / "extension point" are exactly the rationales Pass 2 exists to attack — let it do its job. Dominant-symbol ≥70% is the only prose-based suppression.
Do pre-filter on rationale quality. One-importer Rule 1 findings with no concrete workflow rationale (no named future PR, no test-isolation gain, no mock-graph win) default to rationale_weak: true + importer_payoff: none — and those must not be emitted. If you can't name a concrete win in one sentence, the finding is aesthetic and Pass 1 drops it. The 40–60% Pass 2 kill target assumes Pass 1 has already suppressed the single-importer noise; if you forward every mechanical trip, Pass 2 drowns.
Schema:
{
"file": "src/benchflow/foo.py",
"rule_id": 2,
"evidence_cmd": ".claude/skills/arch-audit/scripts/importers.py src/benchflow/foo.py",
"evidence_output": "src/benchflow/bar.py",
"proposed_change": "fold into src/benchflow/bar.py",
"loc": 57,
"importers": ["src/benchflow/bar.py"],
"churn_6mo": 3,
"co_edit_cluster": null,
"split_costs": {
"shared_types": [],
"shared_helpers": [],
"importer_payoff": "high | medium | none",
"rationale": "one sentence: what concrete PR becomes easier?",
"rationale_weak": false
}
}
Populating split_costs:
shared_types/shared_helpers: from split_costs.py, else manual AST check.importer_payoff: 1 importer → none — suppress the finding unless rationale names a concrete workflow win. 2–3 importers → medium — require a concrete rationale or suppress. 4+ with disjoint importer_selectors → high.rationale: must name a concrete future PR or bug-fix pattern ("splitting _sandbox.py lets the path-lockdown tests stop importing user-setup fixtures and cuts the tests/test_sandbox_hardening.py mock graph in half"). "Narrative clarity," "isolated tests" (generic), "cognitive load," "extension point" → rationale_weak: true → suppress. The bar is: can you name the specific PR or test file this unblocks? If not, don't emit.Do not skip. Pass 2's value is attacking weak proposals, not confirming strong ones. Spawn one Explore agent with this prompt verbatim:
You are a skeptical reviewer of arch-audit findings. Default REJECT unless proposals survive concrete mechanical attacks. Each finding ends SHIP / SKIP / NEEDS-REWORK / NEEDS-SIGNOFF.
Run attacks in order, stop at first kill:
Pass 1 data integrity: split proposal with missing
split_costs.pyoutput, merge proposal with missingchurn_ratio.sh, or Rule 4 finding with missingco_edit_matrix.py→ flag as a Pass 1 bug and drop the finding. Do not grade semantics on missing data; do not emit NEEDS-REWORK (that reads as a semantic verdict). Note it separately so the user knows Pass 1 needs re-running, not that the proposal is fixable.Rule 3 veto (merges): recompute
churn_ratio.sh. Threshold is 3× — if you typed 5× or 8×, re-read the skill.Aesthetic rationale: if
rationale_weak: trueORimporter_payoff: none→ SKIP. Demand a concrete PR pattern.Shared-types trap (splits):
shared_typesnon-empty → 2-way split forces 3rd types module. NEEDS-REWORK.Shared-helpers trap (splits):
shared_helpersnon-empty → duplicated helpers or cross-imports. NEEDS-REWORK unless helpers move cleanly.Semantic-marker exemption (Rule 2 folds): if top 15 lines have a module docstring or block comment explaining the boundary (keywords:
boundary,variant,unguarded,scoped,isolate,bridge,shim) → SKIP.Entry-point trap (renames): check
pyproject.toml[project.scripts],[project.entry-points], and direct imports bysrc/benchflow/cli/,src/benchflow/__init__.py, andsrc/benchflow/sdk.py. If hit → NEEDS-SIGNOFF.Registry-surface trap: check if the file contains or is imported by
agents/registry.py/agents/providers.py. These are the documented extension points — any rename invalidates external registration code and needs user-docs update. NEEDS-SIGNOFF.Cycle/barrel trap:
importers.pyoutput showing# barrel:lines via__init__.py; verify proposed splits don't import each other through a barrel.Test colocation:
tests/test_<name>.pymust move with source without fixture orconftest.pyrestructuring. If the file has a paired test file, name it and check forconftest.pydependencies.All attacks fail → SHIP with counterfactual rationale verbatim. No hedging.
Expect 40–60% kill rate. <20% → re-run with stronger framing. >80% → Pass 1's rationale_weak filter is too loose.
Three buckets:
Include PR sequence respecting Rule 5.
Do NOT edit. On approval:
/code-cleanup.grep -rl 'from benchflow.X' | xargs sed -i ...) + ty check src/ + .venv/bin/python -m pytest tests/ in one PR. "Draft PR 1" means diff plan, not commits.Monthly or per-major-feature. Signal comes from accumulated drift, not single-commit noise. Benchflow has three files already past the Rule 4 threshold (_sandbox.py, sdk.py, job.py) — those are the current top candidates.
__init__.py re-exports, and registry surfaces.split_costs, not new rules.rationale_weak: true.split_costs.py — unchecked shared types/helpers become 3-way splits or cross-import tangles._sandbox.py / _env_setup.py look mergeable by name but carry the repo's most security-sensitive code; the underscore prefix is about API surface, not cohesion.