andon-loop
Runs or resumes an evidence-grounded hardening loop over a repository's value stream (its stages and the wires between them), closing one gap per stage and refusing to advance past a broken or unproven wire. Use when the user wants to harden a repo, run the andon loop, resume the ledger, scan for gaps and fix them in order, or iterate a multi-stage codebase closing gaps while proving each handoff before moving on. Not for applying a single authorized phase from MODERNIZATION_BRIEF.md -- use befund-transform-execute for that, then return here (or to andon-verify) for the proof.
- License 许可
- MIT
- 最近更新
- 2026-11-02
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- andon-loop
- description
- Runs or resumes an evidence-grounded hardening loop over a repository's value stream (its stages and the wires between them), closing one gap per stage and refusing to advance past a broken or unproven wire. Use when the user wants to harden a repo, run the andon loop, resume the ledger, scan for gaps and fix them in order, or iterate a multi-stage codebase closing gaps while proving each handoff before moving on. Not for applying a single authorized phase from MODERNIZATION_BRIEF.md -- use befund-transform-execute for that, then return here (or to andon-verify) for the proof.
- allowed-tools
- Read, Write, Edit, Bash(python3 -B "${CLAUDE_PLUGIN_ROOT}/scripts/andon_core.py":*), Bash(python3 -B "${CLAUDE_PLUGIN_ROOT}/scripts/build_symbol_index.py":*), Glob, Grep, Agent
- argument-hint
- [stage-or-gap-filter]
03 SKILL.md 正文
andon-loop
Orchestrates Phases 0-6 below over the OKF ledger. This skill is the sole
writer to the ledger. andon-propose and andon-verify only ever return
structured results for you (the orchestrator) to persist -- never call them
expecting them to write files.
Every phase below names the exact andon_core.py subcommand that performs
the mechanical check. Treat a non-zero exit code or "allowed": false in its
JSON output as a hard stop, not a suggestion: do not re-derive the decision
in prose, and do not proceed past it without the specific explicit-user-input
the phase describes.
SCRIPTS below means ${CLAUDE_PLUGIN_ROOT}/scripts/andon_core.py.
Phase -1: settings gate (every invocation, before anything else)
python3 SCRIPTS enforce-enabled <repo_root>
If this exits non-zero, the settings file has enabled: false. Print the
error message verbatim and stop -- do not run Phase 0 or any later phase,
do not read the repo, do not touch the ledger. This is not a soft suggestion;
the script raised, so you halt.
If it succeeds, its JSON settings object gives you output_dir,
ledger_dir, authorization_level, skip_verification, gap_source, and
befund_output_dir for every phase below (defaults documented in
${CLAUDE_PLUGIN_ROOT}/references/okf-ledger-schema.md apply when the
settings file is absent -- the script already applied them, just use the
returned values).
Phase 0: topology detection
If gap_source is befund-brief (ingest mode), skip all heuristic
steps below and check the prerequisite in code first:
python3 SCRIPTS check-ingest-prereqs <repo_root> <gap_source> <befund_output_dir>
If this exits non-zero, MODERNIZATION_BRIEF.md or transform_brief_summary.json
is missing from befund_output_dir. Stop and tell the user to run
befund:befund-transform-brief first -- never silently fall back to
self-scan; that silent fallback is exactly the failure mode this check exists
to prevent. If it succeeds, take the stream from the brief's phases (already
leaf-first / Kahn-sorted) with confidence befund-backed, and go straight
to Phase 1 using those stages.
Otherwise (gap_source: self-scan, the default), detect stages and wires:
- Prefer dispatching the
befund:stage-mapperagent if thebefundplugin is installed. Confidence:befund-backed. - If unavailable, degrade to a built-in heuristic:
Globfor manifest files (package.json,pyproject.toml,Cargo.toml,go.mod,Gemfile, ...) and cluster by directory. Confidence:heuristic(flag this in the stage docs you write in Phase 1 -- theconfidencefield is a required, first-class key on every stage doc, never a prose caveat). - A repo with exactly one package is valid as a single stage with no
inter-stage wire. Confidence:
single-package. - If the user declared an explicit stream (stage list) in their request, that overrides detection entirely.
Phase 1: ledger init or resume
python3 SCRIPTS init-or-resume <repo_root> <ledger_dir>
If resumed: false, this already created ledger_dir/{stages,gaps,evidence}
and an empty log.md. Immediately write one type: stage doc per detected
stage using write-doc (below) -- order and confidence are required
fields, not optional metadata.
If resumed: true, its JSON gives you stages, gaps, evidence, and a
reconstructed cursor -- derived from the first status:open gap doc in
stage order, or {"state": "converged, no open gaps"}. Never guess the
cursor yourself; this script's reconstruction is the only source of truth
(ledger-cursor-reconstruction-from-gaps).
To write any OKF doc (stage, gap, or evidence), always go through:
python3 SCRIPTS write-doc <repo_root> <ledger_dir> <relative_path> '<fields_json>' [--body TEXT]
<relative_path> is relative to <ledger_dir> itself, e.g. stages/s1.md,
gaps/g1.md, evidence/ev1.md -- the script joins it onto ledger_dir
before validating, matching the on-disk layout
ledger_dir/{stages,gaps,evidence}/*.md.
This validates write-scope (rejects traversal/absolute/outside-ledger paths) and the OKF schema (rejects a doc missing a gating field) before touching disk. If it exits non-zero, the doc was not written -- fix the fields, don't retry with a workaround.
Phase 2: scan the cursor's stage for gaps
Scan only the cursor's current stage -- never re-scan completed stages
every pass. In self-scan mode look for: failing tests, wires with no
evidence doc or a red/unknown one, TODOs, schema drift, dead handoffs. In
ingest mode, gaps come from the brief's Work Items for this phase instead
(pre-classified: code-idiom/lint/ui-audit/zeugnis findings become kind:bug,
architectural Merge/Split/layering decisions become kind:wire,
documented-absent behavior becomes kind:feature; carry file:line and the
fix-owner agent name into the gap doc; the phase's Behavior Contract becomes
the wire's verification contract; Advisory notes go on the stage doc's body,
never converted into auto-fixable gaps).
Classify each gap with exactly one kind (bug, feature, or wire) and
write it with status: open via write-doc. select-next-gap enforces
priority when more than one gap is found:
python3 SCRIPTS select-next-gap '<json array of {kind, on_constraint, blast_radius, slug}>'
Priority is fixed in code: on_constraint:true first, then wire before bug
before feature, then smallest blast radius as tiebreak. Do not eyeball a
"more important-looking" gap instead.
Phase 3: propose
Dispatch the andon-propose skill with the selected gap, the stage doc, and
any linked gap/evidence docs. It returns a proposal (fix description, files
touched, chosen andon-verify strategy + rationale, and exactly one
blast-radius tag). Record the proposal onto the gap doc via write-doc
(this re-validates the blast-radius tag as part of schema validation -- a
proposal with zero, two, or an undefined tag is rejected, not coerced).
Stop condition 2 check, before doing anything else with this proposal:
python3 SCRIPTS check-stop-conditions --verdict unknown \
--blast-radius <tag> --authorization-level <settings.authorization_level>
If this exits non-zero, the blast radius exceeds the configured
authorization level. Halt and ask the user to either explicitly confirm
raising authorization (--confirm-authorization-raise on the recheck) or
explicitly skip this gap. Do not apply the fix in the meantime.
Phase 4: verify
Before dispatching, resolve or build the shared symbol-index snapshot. Read
analysis/andon/current.json; if missing or its source_fingerprint no
longer matches, run
python3 -B "${CLAUDE_PLUGIN_ROOT}/scripts/build_symbol_index.py" --repo-path . --plugin-name andon
(single-flight lock makes concurrent callers safe -- see
references/parallel-safe-research-protocol.md). For a repo well under
~50 tracked files the build overhead may not be worth it -- skip this and
tell andon-verify no snapshot is available.
Dispatch the andon-verify skill with the wire, its contract, the proposed
fix, and (when resolved) the snapshot path as additional evidence context.
Also pass the gap doc's recorded verify_strategy / verify_strategy_rationale
(from Phase 3) as read-only audit context only -- andon-verify still routes
the wire itself via its own classifier and must never skip or default to the
proposed strategy. Record both strategies verbatim in the evidence doc (e.g.
"proposed strategy: X, actual routed strategy: Y") so a mismatch is visible
in the ledger. It returns a verdict (green/red/unknown) plus evidence
content -- you persist it via write-doc into evidence/, never
andon-verify itself. Pass its tier_ceiling through unchanged: for
strategy e, write-doc refuses a doc without one or with a tier
stronger than it.
Run the full stop-condition check now that you have a real verdict and tier:
python3 SCRIPTS check-stop-conditions --verdict <verdict> \
--blast-radius <tag> --authorization-level <settings.authorization_level> \
[--tier <1|2|3>] [--non-overridable]
- Non-zero +
condition_1_red_verdict: halt. Do not advance past this wire. It may only advance later on an explicit user re-run with new evidence, or an explicit user override/defer of the gap. - Non-zero +
condition_3_tier1_non_overridable: halt, permanently, for this evidence. There is no flag on this script that waives it, by construction -- do not attempt to route around it by re-running with different arguments or asking the adjudicator to reconsider. - Success: close the gap (
status: closed,resolved_by: [[evidence/<slug>]]) viawrite-doc.
Sub-cycle backtracking: if the fix touched a contract an upstream wire depends on,
python3 SCRIPTS track-subcycle <repo_root> <ledger_dir> <wire_id> <requested_upstream_depth>
effective_upstream_depth is clamped to at most 2 stages back, regardless of
what you requested -- never re-verify further upstream than that. If
escalate: true (this wire has now reopened 3+ times), stop sub-cycling
it: record the escalation as the active constraint in log.md instead of
looping again. Every sub-cycle attempt gets its own log.md entry
(append-log ... sub-cycle ...), win or lose.
Phase 5: advance cursor, log the pass
python3 SCRIPTS append-log <repo_root> <ledger_dir> pass '<fields_json>'
Required fields: stage, wire, gap, strategy, verdict, next_cursor,
cycle, pass_number. This appends -- it never rewrites log.md; the hook
in hooks/ will independently refuse a Write that would overwrite an
existing log.md, so there is no path to "fixing" a bad entry by rewriting
the file. Advance the cursor to the next stage; wrap to the first stage past
the last one.
Phase 6: convergence check
At each pass boundary (cursor wraps to the first stage), tally
gaps_closed_this_pass from the pass log entries appended since the last
pass boundary, and build the wire-status array from each inter-stage wire's
latest evidence-doc verdict -- the same derivation andon-status/SKILL.md
already documents (its stream-table step: "each wire's status is derived
from its latest evidence doc"); do not re-derive that rule here, just apply
it:
python3 SCRIPTS check-convergence <gaps_closed_this_pass> '<json array of wire statuses>'
Only when converged: true (zero gaps closed this pass AND every inter-stage
wire is green) do you declare "Cycle N converged" and append a
cycle-converged log entry (passes, cycle fields required). Otherwise,
start the next pass in the same cycle.
Reference
See ${CLAUDE_PLUGIN_ROOT}/references/okf-ledger-schema.md for the doc schema
and settings defaults, and ${CLAUDE_PLUGIN_ROOT}/references/andon-rule.md
for the three stop conditions in full. Do not duplicate that content here --
read it when a decision needs it.
04 同仓库更多 Skills
toy-check
A skill that checks things in the repository and reports what it finds.
demo-check
Reports which generated files changed since the last generation run. Use when the user asks what drifted. Read-only; never edits a file.
demo-check
Reports which generated files changed since the last generation run. Use when the user asks what drifted. Read-only; never edits a file.
demo-check
Reports which generated files changed since the last generation run. Use when the user asks what drifted. Read-only; never edits a file.
demo-check
Reports which generated files changed since the last generation run. Use when the user asks what drifted. Read-only; never edits a file.
zirkel-verify-assumptions
Checks exactly ONE named assumption against real evidence in at most 3 steps and reports one outcome: confidence raised (>=90), reading changed, or still unresolved. Use to resolve a single load-bearing uncertainty — typically a blocking entry surfaced by zirkel-clarify-scope: "verify this one assumption", "is it actually true that X", "check this before we rely on it". For multiple uncertainties, invoke once per uncertainty — the step budget is never shared.