Repo profile — read
.claude/repo-profile.mdfirst. This skill is repo-agnostic; arc is the reference implementation. Use the profile'srepo_slug,verification_entry,kb_issue,plugin_root(where issue-graph's scripts live), and toolchain wherever this doc shows an arc default. Arc's own provenance for the lessons below is not inlined here (fuller case narratives, where they exist, are under.claude/case-law/).
Handle an issue thoroughly: read the issue + the referenced repo docs/code + existing comments + compare against the already-landed implementation/code/intent, produceevidence-backedfindings, and land them back on the issue as a comment (not buried in some conversation). Cover five categories:
- Doc-review: human-originatednew designdiscussed/reviewed in the issue (look for drift, independent findings, reframe). Lightweight, discussion-oriented; output = review comment + split suggestions.
- Doc-audit:existing legacy docsin the repo are audited one by one (re-verify against code, run tests, give one of the 5 categories of conclusions).Boundedunits, invest in tiers by value.
- System-audit(comprehensive code audit): the issue requires asubsystem / cross-platform parity / the runtime itselfto be comprehensively code-audited (e.g. "is the Swift/Kotlin implementation lagging behind the Node/CF reference?").Unboundedtask,full execution is the contract— see "★ System-audit" below.
- Research (research type): the issue requiresresearching the intersection of an external system/technology with our system(e.g. "research the intersection of perkeep and DID space").Produces only a comment, never changes repo code— see "★ Research" below.
- Idea (idea type): the issue is aninternal proposal/idea(e.g. "provide a DID Space + MCP endpoint to the agent in the loop") — may be feasible, may not be feasible, may be too vague, may contradict the existing design.The first step is to clarify, not to execute; output = assessment comment + clarifying questions,never change repo code, never open a spin-off— see "★ Idea" below.
The five categories share the same engine (read → compare against reality → land evidence-backed comments), butthe investment tier and output form differ: doc-review is light, doc-audit is tiered by value,system-audit must be exhaustive, research involves deep investigation on both sides but the artifact lands only as a comment, idea is assessed against the existing architecture but the artifact lands only as a comment (the "save tokens" set belowdoes not apply to the investigation depth of system-audit and research/idea)。
How to determine the type: issue anchored to asingle doc = doc-review / doc-audit; the issue says "comprehensive audit", "review the entire runtime / whether cross-platform is consistent", "requires a full test run", "open issues for gaps/bugs found" = system-audit; title contains
[research]/ body is "research X and our Y", "investigate whether X suits us" = research; title containsidea:/ body self-describes as "this is an idea, first we need to analyze feasibility and value" / is a piece ofproposal-natureconcept (often with the original Slack/discussion text attached, no acceptance criteria, no clear spec) = idea. When unsure about audit-type, follow the high standard of system-audit (better to over-invest than to be cursory);when unsure whether it's "an instruction or an idea", treat it as an idea(the cost of clarifying first is far lower than executing a vague idea as an instruction in the wrong direction).
Output language and writing conventions (follow
comment_language, faithfulness, expressiveness, elegance). All team-facing outputs—issue comment, spin-off issue title and body,PR description body, evaluation/verification reports—must all use the body language specified by the repo profile'scomment_language(arc default: Chinese, the team's reading language); code identifiers, paths, commands,path:line, test outputstay as-is(do not translate code).PR and commit titles followcomment_language's title conventions—full Conventional Commits (type(scope): description, arc default titles are entirely in English, and the description after the colon is also in English, no mixing); issue titles (including spin-off) follow the body language (arc default: Chinese).Pursue faithfulness, expressiveness, and elegance, without padding: too much content is itself a reading burden—give a one-sentence conclusion first, then the minimum but sufficient evidence, and do not elaborate just to appear comprehensive; every assertion must be backed by evidence (documentation / codepath:line/ real test output,UI-related must include screenshots); long logs are collapsed into<details>, not spread out and flooding the screen.
Usage
/agentloop:issue-review <issue-number-or-url> [--dry-run]
<issue-number-or-url>— the GitHub issue to handle (read withgh)--dry-run(old name--no-poststill compatible)—only produces output for the user to see,does notpost/modify comments,does notautomatically open spin-off issues, does not touch labels,does not lock(used when a person wants to preview first). For semantics see the plugin README's Dry-run contract。
Examples
/agentloop:issue-review 115 # doc-review:评审一篇新设计
/agentloop:issue-review 120 # doc-audit:审计一篇存量老文档
/agentloop:issue-review 756 # idea:先 clarify + open 评估一个提案
/agentloop:issue-review 120 --dry-run
When to Use
- An issue is discussing/reviewing a document in the repo (
planning/、docs/、intent/), and needsverifiableAI handling. - A human reviewer has already left comments, and you want anindependent perspective that can find problems the human did not mention.
- You are building an "agent loop that automatically handles issues" and need a reusable action with traceable artifacts.
Not applicable: review of a pure code PR (use /code-review / /review); purely local documents that do not go through issues (use /agentloop:design-review <path>)。
★ Concurrency lock (acquire at the start of each run, always release at the end)
Multiple actors will touch the same issue at the same time: scheduled issue-sweep(cron), multiple people doing local manual /agentloop:issue-review, local agents. Without coordination,duplicate reading + verification + running tests + duplicate comments(wasting tokens), and in severe cases duplicate PRs. The two labels each handle one thing:
| label | Meaning | Who adds/removes | Who respects |
|---|---|---|---|
agent:hold |
Human reserved = terminal-state freeze—"do not take irreversible actions (close/merge) without my feedback",not "ignore it"(applies to issues/PRs) | only humans add, only humans remove; agents never remove automatically.The only exception (arc#2914): when this skill produces a conclusion list of the "recommend closing" type,automatically addto the issues named in the list (see below ★ "recommend closing" type conclusion list)—removal is still human-only。 | issue-sweep / pr-sweep freeze terminal-state actions(never close/dedup-close/merge), butnew human comments/new commits still trigger review + response as usual(human feedback is the highest-priority input); only skip when there is no new input.issue-review / pr-review Explicit manual invocation only warns, does not block(if a human names it, it must be handled) |
agent:processing |
In-progress mutex(advisory, with TTL 30min) | agent acquires at start, releases at wrap-up | Any run that seesa freshlock will SKIP;expired(the previous runner crashed), then grabs the lock and redoes it |
Across issue/PR boundaries:
agent:holdcommon to both — "human reserved" is a reservation independent of object type (GitHub labels are shared at the repo level), with the same semantics on both sides:freeze the terminal-state actions (close/merge), but do not freeze responses— new human comments are handled as usual,pr-reviewexplicit invocation only warns, does not block (see the respective SKILL).agent:processing(TTL mutex)is used only for issues: on the PR side, concurrent deduplication is carried bypr-sweep's own deterministic branchclaude/issue-<N>+ the claim check before opening a PR + the disposition label, and does not reuse this lock.
Positioning must be honest:agent:processing is advisory (saves duplicated work), not a perfect distributed lock— in this repository, humans and AI share the same account/possibly the same token, label-add is idempotent, and two machines starting at the same instant can still have residual races.The real hard deduplication is still issue-sweep 's existing "deterministic branch claude/issue-<N> + claim check before opening a PR", and this layer is left untouched as the fallback.agent:processing merely moves collisions from "only discovered at wrap-up" forward to "short-circuited at start," saving the prior reading/verification/testing.
Terminal-state actions without a branch fallback (comment+close types, such as ★parent rollup) have another hard mutex: claim-comment fencing. Branch collisions cannot catch them, and labels have no CAS — use issue-graph 's claim.ts(comment id total-order arbitration, write-then-read, earliest unexpired claim wins):
bun <plugin_root>/skills/issue-graph/scripts/claim.ts --issue <N> --action rollup # exit 0=赢/3=输(输了自删claim退出)
# …执行动作(动手前最后重读一次目标状态)…
bun <plugin_root>/skills/issue-graph/scripts/claim.ts --release <claimId> # 完成必调;崩溃靠TTL 30min兜底
Naming disambiguation: in this skill,
in-progressthiswordalready means "multi-round continuation comment disposition" (round-aware relay), so the mutexis named separately asagent:processing, do not reusein-progress。
acquire (at the very start of Step 0, before reading the thread):
N=<issue>; TTL_MIN=30
# 缺 label 自建(幂等,best-effort)
gh label create agent:hold --color D4C5F9 --description "人类保留:自动化别碰,只人摘" 2>/dev/null || true
gh label create agent:processing --color FBCA04 --description "处理中互斥锁(advisory,TTL 30min)" 2>/dev/null || true
labels=$(gh issue view "$N" --json labels --jq '.labels[].name')
# agent:hold —— 人类保留:显式手工调用只提示(sweep 才真跳过)
grep -qx 'agent:hold' <<<"$labels" && echo "⚠️ #$N 带 agent:hold(人类保留);显式调用继续。"
# agent:processing —— 互斥锁:新鲜则 SKIP,过期则抢
if grep -qx 'agent:processing' <<<"$labels"; then
since=$(gh api --paginate repos/{owner}/{repo}/issues/$N/timeline \
--jq '[.[]|select(.event=="labeled" and .label.name=="agent:processing")]|last|.created_at')
now=$(date -u +%s)
then=$(date -u -j -f "%Y-%m-%dT%H:%M:%SZ" "$since" +%s 2>/dev/null || date -u -d "$since" +%s)
age_min=$(( (now - then) / 60 ))
if [ "${age_min:-9999}" -lt "$TTL_MIN" ]; then
echo "🔒 #$N 正被处理中(since $since, ${age_min}min<${TTL_MIN}) — SKIP"; exit 0
fi
echo "♻️ #$N 锁已过期(${age_min}min) — 抢锁重做"
fi
gh issue edit "$N" --add-label agent:processing # 加锁
release (at wrap-up, done on both success and failure):
gh issue edit "$N" --remove-label agent:processing
--dry-rundoes not acquire/does not release(does not make any outward write); it only prints a notice when it finds the lock already held.- ★ The escalation point from interpretation→execution = go through Step 0 again. After a session starts with "help me look at/explain this" (dry-run semantics, no lock), the user midway says "fix it/implement it" —at the moment of escalation to execution, you must first acquire the lock before acting, and must not start work directly while carrying the lock-free state of the dry run (real-world lesson: this once caused duplicate implementation by a concurrent agent).
- Long-task lock renewal: for executions expected to exceed the TTL (30min) (implementation + verification + PR), re-run
gh issue edit <n> --add-label agent:processingevery ~20min (label-add is idempotent, and the timeline refreshes the labeled timestamp), otherwise the lock will still expire midway and be grabbed. - If it crashes/is killed without release → the lock automatically lapses via the TTL (30min), and the next run grabs the lock and redoes it, so it will not be stuck forever.
- If you manually want long-term exclusive ownershipof a certain item: the humanfirst adds
agent:hold(sweep permanently bypasses it), and removes it after handling — a stronger and more explicit reservation than a temporary lock.
★ Round awareness + token saving (do this first on every call)
Do not blindly rerun everything in full. An issue gets processed over multiple rounds; the cost of later rounds should be far lower than the first round. First read the thread (gh issue view <n> --comments, cheap), and determine the round:
| Round | Signal | What to do |
|---|---|---|
| First round (cold start) | No prior AI review/audit comment | First triage the value, then invest according to tier(see below): for clearly obsolete ones, only lightly confirm; only for genuinely live ones do the full thing (cross-check the code + run tests) |
| Later rounds (warm start) | Existing AI conclusions + human opinions | Do not redo: read the thread, treat prior evidence as established fact, and follow the human opinions to the next step |
Even for a cold start, tier by value; do not jump straight into a full build / full test:
- First cheaply determine the category: read the frontmatter (
superseded/superseded_by/deprecated)+ls/grepand scan whether the corresponding code is still there.For those clearly already obsolete / no longer valuable(explicitly superseded, approach replaced, corresponding code already removed) → only do alight confirmation: usegrep/ls/git logto establish that "the code really is gone / has been superseded", and then you can give thedeprecated,Do not build, do not run the test suite, do not go item by item throughpath:line。 - Only when you judge that it is "really alive"(possibly drifted/partial/current, details matter) do you go full: item by item through
path:line+ actually run tests. - In one sentence:Investment is proportional to the documentation's value. Doing a full audit of a dead document that is going to be deleted is itself a waste.
⚠️ The above "tier by value / light confirmation / save tokens" only constrains doc-review and doc-audit. System-audit does not follow this— see below.
★ System-audit (comprehensive code audit) — full execution is the contract
When the issue requiresa comprehensive code audit(subsystem / cross-platform parity / the runtime itself), "save tokens" gives way to "do not miss anything".Sloppy = failure. Iron rules:
- No light confirmation, no drawing conclusions from frontmatter. Every parity claim must be
path:lineestablished (present / absent / drifted), and both sides must be checked (the reference implementation side vs the target implementation side). - Tests must actually be run; if tests are missing, add them. The issue usually explicitly says "there must be a complete test run" — run everything that can be run, and record the exact commands + pass/fail;if it cannot be run, state the reason clearly(see the Deployment Environments listed in the repo profile for platform toolchain gaps; the arc example: no Xcode/Android SDK in the sandbox → Swift/Kotlin tests
describe.skip/cannot compile), and fall back tostatic cross-checking + conformance suiteas a stopgap,do not pretend you ran it。The discipline for judging "cannot be run" is the same as Step 4: first really try + first fix the setup (compiling native dependencies and linking the CLI do not count as environmental limitations); only count it if you actually hit a hard toolchain gap, and paste the exact error — do not make excuses in advance. - Decompose first, then audit. Break a large audit intosubsystem units(core / aup / session / each provider ...), cross-check each unit, and do not blur them together. Give evidence independently for each unit.
- gap/bug/security — open an issue on the spot (reasonable granularity), no need to wait for confirmation. One issue per type of gap; bug and security each get their own (
security+P0). The audit comment summarizes the matrix + a one-liner pointing to each spin-off. - Output = current-state matrix (reference × target, element-by-element ✅/⚠️/❌ + evidence) + test results + gap list + list of issues opened. This is the deliverable for "report the current state", not a status label.
Model / orchestration (System-audit)
- Don't use a weak model for the overall synthesis just to save money. The main controller (synthesis + opening issues + judging whether parity claims are genuine) uses astrong model (Opus);Auditing bounded sub-elements after decomposition can be delegated to Sonnet(read one subsystem's code on both sides + run one test + give structured findings), butkey semantic surfaces(core semantics, protocol/validation, security degradation) stay with Opus.
- Parallelize where you can: subsystems are independent of each other, so fan out with subagents (one agent per subsystem, returning structured parity findings), and the main controller aggregates. This is both faster and lets each go deeper —more complete than a single-threaded sequential scan, not cheaper。
- One line:doc-audit picks Sonnet because it's bounded; system-audit is the opposite — prefer Opus + fanning out multiple agents to do it thoroughly.
Cross-repo / reference×target consistency audit (a common form of system-audit)
Many system-audits are "audit whether A correctly consumes B's abstraction" — e.g. "does the downstream repo follow protocol-first and correctly reuse the upstream core abstraction", "is some platform implementation behind the reference runtime" (arc examples: "is aside AFS-first + using ARC AUP", "are the Swift/Kotlin implementations behind the Node/CF reference"). The audited artifact is in the target repo, the reference implementation is in the reference repo,both repos checked out locally at different paths. Discipline:
- First define reference and target, and read both sides. reference = authoritative abstraction/protocol source of truth (
<reference-repo-path>, arc examples:platforms/swift、platforms/kotlin、providers/runtime/ui、packages/aup, AFS core); target = the code under audit (<target-repo-path>, arc examples: asideios/android/.aup/)。Every parity claim must cite both sides:path:line: is the target actually "consuming the reference's abstraction" or "parallel-rebuilding its own set". ghAll with--repo <owner/repo>。 The audit issue, verdict comment, spin-off issue, and label all land in the target's repo(where the issue lives); the reference repo is read-only, don't open issues in it. Across repos,repos/{owner}/{repo}the placeholder resolves to the repo at the current cwd,don't rely on it, write it out explicitly--repo。- Core lens: "genuinely used" vs "not used thoroughly" must be layered, don't judge in binary. The common form isshell reused, flesh not reused: the renderer/interface is generic ✅, but what feeds it (UI tree / data) is, on each platform,hand-built/parallel-rewritten ❌. A precise conclusion ("it is a genuine AUP renderer, but every screen hand-builds AUPNode in native, doesn't load the canonical
.aup, three parallel sets will inevitably drift") is far more valuable than "violates AUP".First affirm the part done right, then precisely locate which layer the violation is in. - Single Source of Truth (SSOT) determination is the core output of this type of audit. Does the same interface/capability have "one canonical definition rendered/consumed by each side," or N parallel implementations (JSON + Swift + Kotlin…)? Listthe overlap matrix of units with the same nameto substantiate it.
- Cross-repo root cause tracing + staged fix. The target's violations oftenhave their root cause in a capability gap in the reference(e.g., "hot read bypasses AFS" has its root cause in "ARC AFS lacks a reactive/watch API"). The spin-off must clearly statetwo stages:reference-side capability addition (may require filing in reference repo a separate issue) + target-side adoption.
- When a fix needs a direction, frame the issue as "confirmed gap + pending directions A/B/C," don't presuppose. Once the current state (violation) is substantiated, open a tracking issue (the system-audit contract requires opening one), but list the unification/fix options asoptions for a human to decide, don't choose for them (echoing the spin-off's "needs-decision does not presuppose"). For pure marketing pages/things requiring human qualitative judgment (e.g., bespoke landing HTML), leave a verdict comment, don't auto-open an issue.
- Platform-specific toolchain tests will most likely not run—honestly downgrade. For the specific platform see the repo profile's Deployment Environments(arc example: Xcode (Swift)/gradle+Android SDK (Kotlin) are usually missing in the sandbox); first genuinely try + first do setup, and if you hit a hard blocker,paste the exact command + error(arc example:
gradle.propertieshardcoded JBR, composite build expecting a sibling repo layout that doesn't match, missingcompileSdk), fall back tostatic comparison + reading test sourceto substantiate the structure,explicitly mark which layer was skipped, never pretend to have run it. Conclusions are based on definite facts of the code structure, not dependent on tests passing. - After batch-opening spin-offs, you must verify title↔body↔label alignment. Capturing the issue number in a loop is prone to misalignment (the first create misses a number → everything shifts), and subsequent body backfilling will hitthe wrong issue. After openingdump each body's first line and compare against the title, and upon finding a misalignment immediately
gh issue editfix it + create the missed ones. Better to spend one extra step verifying.
Shared KB (hot-start repo topology, avoids repeated exploration)
There is a pinned knowledge base issue(repo profile's kb_issue, arc default label doc-audit-kb), and the body is repo topology hints (where subsystems are, test commands, major migrations, meta facts).At the start of each run, read it first for a hot start, and at the end append newly learned things back:
- Read the KB body before starting work(
gh issue view <kb_issue>,read only the body—comments are the raw append stream, don't read them all) to get hot-start facts—don't grep from scratch again for "where is the CLI / what is the test command / which major migrations." - hints are not truth: trust it toquickly locate, butcheaply re-verify(code changes). If you read a wrong entry (e.g., "X is in
packages/cli" but it has actually migrated) → edit the KB body to fix that line + leave a comment saying what was changed. A stale hint is worse than none. - append at the end: new topology / command / migration / meta facts discovered in this round are added to the corresponding subsection of the KB body, with "last confirmed commit/date".
- Scope: the KB only holds topology / commands / migrations / meta;notthe audit ledger (ledger =
gh issue list --label doc-audit)。 - During parallel batch processing(not yet enabled): agents onlyappend comments, and a consolidation step folds them into the body, avoiding body write conflicts; during sequential auditing, edit the body directly.
Memory MCP (optional, when already configured)
If the MCP tool list of the runtime environment contains an AFS namespace (such as afs_read / afs_write / afs_search, from a connected ARC instance MCP endpoint), add two steps in Step 0:
Recall before warm start (do it in parallel with reading the KB):
afs_search /user/memory 关键词:<issue 相关术语 / 路径 / 子系统>
Add the retrieved content (observations / patterns / principles) to the warm-start context—on equal footing with KB hints: "locate quickly, cheap to re-verify with code".
After processing, store (append, do not overwrite existing entries): Write timing—any of the following discovered in this round:
- Non-obvious code constraints(why a function is unusable in a certain scenario, hidden side effects, hook execution order)
- Team decisions(why A was chosen over B, the historical reason for a field's naming)
- Revert reasons(the real reason a PR was rolled back, to prevent repeating it next time)
- Cross-issue patterns(root-cause patterns of recurring bugs of the same kind)
Write in three layers (granularity from small to large):
observation: concrete facts +path:line(smallest granularity, closest to the code)pattern: patterns generalized from multiple observations ("the root cause of X-type issues is usually Y")principle: inferred working principles ("before doing Z, you must first check W")
Path:afs_write /user/memory/<memory_namespace>/<namespace>/<id>(memory_namespace see repo profile Agent Tooling, arc defaults to arc-loop); caller identity is automatically isolated (different loop agents do not interfere with each other).
MCP not configured = skip this section, and all other behavior of the skill remains completely unchanged.
Three hard rules for warm start (the gate for saving tokens):
- The issue thread is cumulative state. Previously verified evidence (
path:line, test pass/fail counts) is by defaulttrusted, not re-derived—unless "the file changed" or "a human questioned this item". - Do not rebuild, do not rerun the whole test suite, do not reread all documentation. Only when "the target code changed / a human explicitly asked for re-checking" should you rerunthat onetest and rereadthat section。
- Use cheap commands to determine "whether it changed":
git log --oneline --since="<上条 comment 时间>" -- <unit 路径>. If untouched → the previous evidence holds, go directly to the next step.
The human comment is the direction for subsequent rounds, but not an imperial edict. It confirms/rejects a conclusion, offers new facts (such as "this protocol is actually for reverse injection"), or points to the next step—prioritize following it, butdo not blindly obey:
- real problems the human did not mentiondo not drop because of this—point them out where they should be pointed out (he may not have covered everything).
- The human comment isa question / uncertainty(with "?", "is it", "I'm not sure"), treat it asa question to be answered, not a command to be executed—give an evidence-backed reply, and when necessary admit you're also unsure and lay out options for the person to decide.
- Multiple comments / from different peoplewhen, list them one by one,reconcile disagreements; don't just listen to the last one or the loudest one. If there's a conflict, lay it out for the person to make the call, don't quietly pick one yourself.
The output of subsequent rounds is often not "another full review" but atargeted next step(confirm some conclusion / resolve some gap / draft a crystal / answer a question).
★ Research (research-type issue)—investigating the intersection of an external system × our system
The issue asks to research anexternal project/technology(open-source system, protocol, competitor) andour system's intersection, feasibility, or reference value. A paradigm is investigating the perkeep × did-space intersection. This is the in-repo variant of deep research:the biggest difference is that we're inside a repo (a knowledge base or product code), so we can go code-level deep, rather than just reading the other side's marketing page.
Iron rules (the key differences from other categories):
- Never modify this repo's code. The output = an evidence-backed research comment (+ label), not a PR, not a file. Derivative work like skill improvements is a separate matter, not mixed into the research deliverable.
- By default, only leave a comment + external resource links, no downloading or saving. Clone external repos to the scratchpad and discard after use.Only when the issue explicitly says to collect data and save it in the repo, only then open a dedicated directory in
research/<task-slug>/to collect what's worth saving (still via PR, signed by a human). - Both sides must be code-level, no reading only the README. External side: shallow clone to the scratchpad, read architecture docs + key source packages, conclusions carry in-repo relative paths (with line numbers where possible) + official doc links; our side: read this repo's code/intent/planning, conclusions carry
path:line。fan out two subagents in parallel (one per side), and the main controller synthesizes—both sides gather evidence independently, to prevent preconceptions. - External project health must be checked:
git logthe last 12 months' commit curve, the latest release, whether core authors have been active recently, license,gh api repos/<owner>/<repo>'s pushed_at/stars. Intersection conclusions depend strongly on the other side's vitality (a dead project and a just-revived project yield completely different conclusions), and this is often the source ofindependent findings(e.g., discovering perkeep revived in 2025-10, its first release in 7 years). - Honesty first, against "using for the sake of using". The issue owner often brings their own caution ("we can't use X just for the sake of using it"), and the research conclusion must dare to say "this direction is not recommended"; each intersection point should note the real beneficiary and preconditions.
- Deliverable structure(comment, in Chinese): TL;DR directly answers the specific questions raised by the issue, item by item → a side-by-side architecture comparison table (both sides substantiated by code) → points of conflict → intersection pointstiered(⭐ recommended / ◐ pending or for reference only / ✗ not recommended, with a reason for each) → next-step options for the person to decide (no presuppositions, no automatically opening a spin-off—the conclusion of research is naturally needs-decision; only after a human picks a direction is it split into self-contained feature issues) → external resource link list.
- Label:
research+needs-human-confirm; the concurrency lock proceeds as usual (agent:processing). The issue stays open awaiting a human decision on direction. - Investment tier: research depth is not skimped on (the subagents on both sides each go in full), butthe verification layer differs—research does not run this repo's test suite (there is no implementation to be accepted), and evidence = source citations from both sides + official documentation + project activity data.
- ★ Only pure research concludes with needs-human-confirm (#1947 feedback, 2026-07-19). When an issue simultaneously carries aclear end-state goal(in the form of expressions like "an unshakable goal" or "ultimately it should…"), research is only phase 0: after the research comment lands,immediately switch to the feature pipeline(split the sub-issue graph + native edges + testable end-state acceptance written into the parent issue; do whatever can be done), and it must not be frozen with "options awaiting a decision".Decision items must be mutually exclusive forks—non-mutually-exclusive work items are dependency ordering; list them as phases and execute directly; choices that can be decided by engineering judgment (API shape, implementation path) are decided by the agent itself with rationale recorded in the PR/issue; only what is truly uncertain (irreversible forks, aesthetics, priorities) needs a human, and use a "recommendation + objection window with default execution" (disagree by calling a halt in the issue) rather than blocking and waiting. Packaging work decomposition as decision items to hand to a human = trading a decision for workload; prohibited. (Same origin and same criterion as ★Idea iron rule 9—#1947/#1949 feedback on the same day; if one is changed, the other and the corresponding two rows in the issue-sweep table must be synchronized.)
Subsequent round: after a human picks a direction (e.g. "do A"), split into self-contained feature issues according to the option (following the self-contained recipe of "partial → split remaining work"), or switch to the /agentloop:design-review → /agentloop:build-phases pipeline; if the human is merely asking follow-up questions, edit in place/append a comment to answer.
★ Idea (idea-type issue)—clarify first, open evaluation, do not treat as an instruction
The issue is aninternal proposal/idea—the author themselves marks it as "possibly feasible, possibly infeasible, possibly too vague, and possibly contradictory to existing things". A paradigm example is proposals like "provide loop agent with DID Space + MCP endpoint".The biggest handling risk for this type of issue is not being insufficiently deep, but doing the wrong kind of thing: treating an idea as an instruction and directly starting to implement something whose direction is undecided and whose boundaries are unclear.
Iron rules (key differences from the other four types):
- Do not treat as an instruction; treat as a proposal. The first step isunderstanding and restating(restate the idea in your own words, decompose it into independently evaluable value propositions) rather than splitting tasks. Put the restatement at the very front of the comment—it gives people a cheap correction point ("you understood it wrong" is a hundred times cheaper than "you did it wrong").
- Never modify repo code, open a PR, or open a spin-off. The conclusion of an idea is naturally needs-decision; before the direction is set, opening issues/writing code is all presupposition. Deliverable = one evidence-based evaluation comment + label.
- Open evaluation, genuinely investigate all three directions: ① Feasible and valuable—compare against the code to find "how much of the foundation already exists" (a common surprise: the building blocks already exist, and the idea only lacks wiring); ② Infeasible / value unclear—the gap comes with
path:linenailed down, not glossed over as "should be fine"; ③ contradicts the existing design——name the contradicting object (which mechanism/discipline/in-flight design), lay out the tension instead of quietly picking a side.Every assertionpath:lineis nailed down, and the grounding discipline is on par with auditing. - Honesty first, dare to pour cold water. What the idea author (often the founder/architect) wants is a feasibility analysis, not agreement. "This half of the value proposition has a real engineering-effort gap" is more valuable than "good idea"; at the same time,first affirm the parts that genuinely hold up, then point out the gaps (same layered judgment as system-audit).
- Insufficient information → list specific clarifying questions, ask the person to fill them in next round, don't force a plan. The questions must bespecific enough to make a call("Is the scope shared or per-repo?" "Does auth accept a shared owner token?"), not open-ended "what do you think?". Each question explainswhy it blocks what follows(what design fork it affects). Keep the issue open, converge over multiple iterations.
- Output structure(comment, in Chinese): restate understanding (decompose the value proposition) → current-state comparison table (what the foundation already has,
path:line) → real gaps (what must be filled to land it, with evidence) → tension/contradiction check (with existing mechanisms, with in-flight design, topological forks) → value assessment by tier (⭐/◐/✗, given per claim, not a single binary verdict overall) → context that needs human input (specific clarifying questions) → next-step options (A/B/C, not presupposed). - Label:
idea+needs-human-confirm; concurrency lock as usual (agent:processing). Keep the issue open pending a human decision. - Effort tier: assessment depth is not spared (nail down each claim against the code), but theverification layer differs——an idea doesn't run the test suite (there is no implementation to accept), so evidence = source references in this repo + existing design docs + the original text of relevant discussions.
- For an idea whose requirements are already clear → don't produce a decision menu (Robert's correction, #1949/#1947, 2026-07-19). When the author has already stated the goal clearly and only the path/details are undetermined, the assessment must not turn "decisions that can be given a safe default" into multiple-choice questions——that is indirectly making a person cut scope for the AI, and after the person chooses, the agent easily "thinks everything is done after solving a few specific problems". Correct form: ① any decision that can be given asafe defaultis chosen directly and annotated "proceed on this basis, point it out if you disagree" (ratchet, same as Step 5.5); ② the output must be accompanied by afinal acceptance checklist(aligned with the issue's original goal, verifiable item by item)——it is the sole condition for closing the parent issue (what rollup checks against), and "all child issues closed ≠ done"; ③ after the person confirms the direction,immediately decompose it in fullinto self-contained spin-offs + writing edges (at this point iron law 2's "don't open spin-offs" is lifted), and phasing is a priority order, not a reduction; ④ only genuinely uncertain items (resource-level investment, irreversible actions, timing of external dependencies) are left for the person to decide, and they do not block other workstreams. Criterion: if the decision items arenot mutually exclusive, then they are not decision items but a dependency order——schedule them directly into the plan for execution. (Same source and same criterion as ★Research iron law 9——feedback from #1947/#1949 on the same day; change one and you must synchronize the other place and the corresponding two rows in the issue-sweep table.)
Difference from Research: research investigatesexternal systemsIntegration point with this system (two-sided subagent, checking the other side's project activity); idea evaluationinternal proposal(one-sided, but the focus is on "comparing against the existing architecture to find what exists/gaps/contradictions" + "turning vague points into decidable questions"). An idea may embed a research need ("use X to do this")—then nest the two-sided discipline of research inside the evaluation.
subsequent rounds: the human answered the clarifying questions/settled the direction → break down a self-contained feature issue according to the selected item, or switch to /agentloop:design-review to produce the design; the human rejects → suggest close (the human closes it, the agent does not act); the human follows up → edit in place/append a comment to answer.after multiple rounds an idea often converges into a feature/design issue—from that moment it is no longer handled as an idea, switch to the discipline for the corresponding type.
★ Parent rollup (closing out a parent issue whose children are all closed)—the authorized exception to automatic close
Trigger:issue-sweep Step 0.5's graph-scan reports rollupCandidates(open parent issue ∧ all native sub-issues already closed), or a human names it.This is the only explicit exception to this skill's iron rule of "never automatically close", and requires repo owner authorization—it fixes the existing disease of "all children done, parent issue left open waiting for someone to bump it". close is reversible (can be reopened), and the risk level is noise, not damage.
Process (order is mandatory):
- Idempotency check: issue already closed → end; already has
<!-- rollup-done -->marker comment → end. - fencing lock acquisition:
claim.ts --issue <N> --action rollup(see ★concurrency lock). Lost → end (another machine is doing it).agent:holdthe parent issue of does not do rollup close(hold = human reserves the final state, see concurrency lock table), only writes a summary comment without closing. - Verify acceptance: read the parent issue's acceptance criteria/question list/body intent, and map each one to the landing evidence in the child issue/PR (
path:line, PR links, test output).Before acting, reread the issue state one last time (closed/new human comment → abandon the action and follow the new input first). ★ Full test gate for large issues (decided by Robert 2026-07-20, source #1947): for feature epics with multiple phases / a sub-issue graph / final acceptance,before close there must be a complete end-to-end scenario test on a real surface—not just green unit tests per PR, but designing multiple types of scenarios (positive + honesty negative samples + boundaries) in the real target environment (real device / real browser / live daemon), running each case, attaching screenshot/output evidence for each case, and posting the report to the issue as stable-numbered checkboxes (e.g. FM-01…) for item-by-item verification; the test plan itself is posted first and marked as a closing acceptance clause. If this layer is missing → do not close, fill in the tests first (this is the default composition of rollup, no need to wait for a reminder). Record failures truthfully: wiring bug → spin-off; platform/model limitation → note it and ask for human acknowledgment, do not loosen the criteria to make it green. Small single-PR fixes are not subject to this gate. - Summary comment(in Chinese,
> 🤖 AI Agentheader +@ <hostname>): item-by-item coverage table + one-sentence conclusion for each child issue + residual gap (if any). End with<!-- rollup-done -->marker (idempotency key). - Disposition: fully covered →
gh issue close <N> -r completed; residual gap → list them andleave open (If what remains is a bounded task, split off a self-contained spin-off following "partial → split" and write the edge). Research/idea-type parent issues are likewise synthesized and then closed — the conclusion has already landed in the child issue/comment, and the parent is merely wrapping up. - release claim:
claim.ts --release <claimId>; while carryingagent:ready, also remove (the consumer removes it after processing — producers that close will also have it cleared next round, but anything left open must be removed now, otherwise the queue view keeps showing "actionable," misleading people and other workers).
★ For lists of "recommended close"-type conclusions → immediately attach at the time of landing agent:hold(arc#2914)
Anyconclusive batch disposition listproduced by this skill
— in scenarios such as doc-audit summaries, ★ parent rollup synthesis comments,
one-off full backlog audits, etc., where a table/list listsmultiple issuesand gives conclusions such as "recommended close" /
"recommended merge" / "recommended delete" thatrequire human review before they can be executed—at the very moment this list lands
(posted to an issue body or comment), you must attach toevery single issue named in the list
agent:hold:
for n in <清单里点名的每个 issue 号>; do
gh issue edit "$n" --add-label agent:hold
done
(If the label does not exist, first create it idempotently per the ★ concurrency lock acquire section's gh label create agent:hold ... || true .)
Why you cannot rely on a textual promise in the body alone (arc#1863 lesson): #1863 was a one-off 138-issue full
backlog audit, and at the end of the body it explicitly stated "the 'recommended close' column was not closed on our behalf this time; it is enough for a person to scan the table and then batch-close." — that natural-language promise was not accompanied by any structured signal. The next unattended sweep treated the
12 issues named in that text as directly executable instructions and closed them, bypassing the human-confirmation gate declared here (on later review it mostly held up,
but that was luck, not design — see arc#2914).agent:hold is issue-sweep Step 1's existing deterministic mechanism of "Then
drop the reserved/locked ones," which is already respected —use it to carry the promise of "awaiting human review,"
rather than expecting the next sweep to parse natural-language qualifiers in the issue body. This complements issue-sweep
Step 2's corresponding rule: Step 2 ensures that even if a named issue is unexpectedly missed for agent:hold, the list
itself will not be consumed as instructions — independent human confirmation is required.
After human review, remove the label: approve → the person closes it themselves (or removes agent:hold and then goes through the normal sweep process);
reject → remove agent:hold and leave an explanation.The agent never automatically removes this label(same as the general rule for the ★ concurrency lock
table:agent:hold only humans add and only humans remove; this section is the sole "automatic add" exception, and it does not include "automatic remove").
Doc-from-Issue lifecycle (the process this skill sits in)
Human-originated documentationstarts from an issue, is discussed until it can be committed, and is then committed into the repo like code. Two layers:
| Layer | Role | Nature |
|---|---|---|
| Issue = raw / working layer | All input + AI expansion + AI review/audit (this skill) | Mutable, can be dirty, cumulative, AI-assisted;never enters the repo |
| Repo = crystal / crystallization layer | Minimalist documentation for which a human is word-for-word responsible, committed via PR, with a backlink to the issue for provenance | Like code; a person is responsible for every character. |
One-way direction: dirty flows toward refined; refined does not flow back to pollute (to change = start a new round).Provenance is an append-only chain:doc → 本轮 issue → 上轮 issue → …, closed issues remain permanently reachable.
The human / AI boundary (drawn by "reversibility of consequences," not by "whether it is outward")
The agent shouldhave judgment and act on its own, not ask for instructions on everything. Do reversible, traceable operations directly; only stop and wait for a human for big moves / irreversible ones.
- Do automatically, without asking(act with judgment): post/edit comments, add/adjust labels, assign assignee, judge and mark
status, maintain the "living crystal" draft; andanything that should be a separate issue, just open it—issues discovered during review that are clearly independent of this document (security vulnerabilities, unwired dead code, definite bugs),automatically open a new issue(with label/milestone/assignee set up + bidirectional backlinks),without asking the user。 - Needs human confirmation (only big moves / irreversible): deleting content or files, moving directories, PR merge,close issue, final decisions that change architectural direction. These hang on
needs-human-confirmwaiting for a human—reason: this is where consequences are borne; AI has no consequences. - Iron rule: output always carries evidence;Neverautomatically merge / close issues / delete files / modify document frontmatter.The only explicit exception for close = ★ parent rollup(all children closed + fencing mutual exclusion + acceptance check fully covered, close is reversible) and
issue-sweep's "PR merged but not auto-closed" cleanup.
Doc-audit process (auditing existing old documents)
Existing intent/ planning/ cleanup, document by document.Do not move directories(moving directories breaks the issue↔document path key and cuts git history); only use frontmatter status marking + backlink issues; the only physical change is deprecated -type file deletion.
5 status enum values (controlled vocabulary, replacing the 30+ kinds of random marking in history)
status: |
Meaning | Issue destination |
|---|---|---|
planned |
Valuable, not yet implemented | open(tracker; dedup existing issues/roadmap before creating) |
partial |
Implemented, but incomplete ("needs triage" signal) | open; gap is path:line confirmed → automatically split into an independent self-sufficient spin-off afterremove this label, switch to residual status (residual drift→drifted; no residual→current+ awaiting human close); gaps that are still speculative/undetermined are left as comments for human confirmation. See "partial → split remaining work" |
drifted |
Implemented, but document drift (described interface surface ≠ shipped surface) | Triaged by document category(2026-07-17 Robert decided, #187 batch): planning//intent/ → archive, do not fix the body—after ship they are historical artifacts, the source of truth has moved to code + living docs, and fixing them will inevitably drift again (counterexample: #243 drifts once per fix round). Archive = put a historical tombstone banner at the top (see "historical archive" below), first extract the valuable design rationale into docs/guides//README re-archive; close issue when tombstone PR merges.docs/ living guide → fix docs → convert to current |
current |
implemented, docs accurate | closed + audit record |
deprecated |
deprecated | closed; save content to issue first → human confirmation → separate PR to delete file |
(in-flight new designs use draft, not one of the 5 audit categories.)
Naming / classification conventions
- Milestone = directory batch: naming and classification follow the repo profile's Milestone Conventions(arc default:
Doc Audit: intent//Doc Audit: planning//Doc Audit: docs/), clear them one by one to prevent issue explosion. - Label:
doc-audit(meta, all hung on) +status:<x>(this round's conclusions hung on) +needs-human-confirm(suggestions given, awaiting human confirmation to close/delete). - Title:
[<area>] <doc-name> — doc audit, e.g.[intent] session-protocol — doc audit。 - Idempotency key: issue body first line
<!-- doc-audit-key: <doc-path> -->; before creating, firstgh issue list --searchsearch for it to prevent duplicate creation. - Assignee (let the right people review): assign the issue to two kinds of people——
- Doc creator(available when creating the issue): the author of the doc's first commit.
sha=$(git log --reverse --format=%H -- <doc-path> | head -1); gh api repos/{owner}/{repo}/commits/$sha --jq .author.login - Committer of the implementation code(grabbed in passing after locating
path:lineduring review): taken from the implementation file's recent commits, deduplicated.gh api "repos/{owner}/{repo}/commits?path=<impl-file>&per_page=5" --jq '.[].author.login' gh issue edit <n> --add-assignee <login>。If assignment fails / not a collaborator, skip and note it, don't block. the same person is assigned only once.
- Doc creator(available when creating the issue): the author of the doc's first commit.
Doc-side frontmatter contract (written by the human-signed PR at resolve time)
status: current # 受控词表,grep ^status: 一把筛
audit: "#<N>" # 回链审计 issue(issue body 反指文档路径,双向)
verified: 2026-06-24 # current 时记确认日期
historical archive (drifted planning/intent resolve paths)
For old docs without YAML frontmatter, the tombstone is a top banner (grep doc-status: historical to filter them all):
<!-- doc-status: historical (archived <date>, doc-audit #N) -->
> ⚠️ **Historical** — 实现期 planning/intent 文稿,已归档(doc-audit [#N](.../issues/N))。
> 内容以写作当时为准,**不再随代码更新**;与现行代码的已知漂移明细见上述 audit issue。
> 现状以代码与 living docs(`docs/`、各包 README)为准。
The main doc uses a full banner; sibling docs in the same directory (tasks/plan/review) use a one-line simplified version pointing back to the main doc.Don't delete files, don't move directories—— the tombstone preserves links from back-references (counterexample: #253 wanted to delete context-builder, but 2 active docs linked to it). Drift detailsnot copied into the doc, stay in the audit issue (single source of truth). After archiving, the unit exits the scope of subsequent doc-audit scans.
Lifecycle
create(一篇=一 issue,挂 milestone+doc-key) → review(冷启动:对照代码+跑测试,见下) → human 给意见(comment) → resolve(热启动:按 human 意见起草修复/crystal) → 人确认 → close。
Bulk-create issues (streamlined; completed during review)
When bulk-converting existing docs to issues,the create step is deliberately streamlined, no deep reading: each issue only contains doc-key + directory/main doc link + frontmatter status + the doc's own anchor line + a generic audit task template. The purpose is just to let peoplequickly browse and give a preliminary judgment, not analyze on the spot.The deep overview is left to be filled in during the actual review.
- Idempotency: before create, use
doc-audit-keyto search once, skip if it already exists——repeatable, never creates duplicates. This is the record of "which docs have been turned into issues", no extra file needed. - Coverage tracking: ledger = the set of doc-audit issues; coverage =
(所有单元) − (已存在 doc-key); milestone provides visible aggregation. - Legacy collections(flat directories from before the per-feature convention, e.g.
specs//bugs//*.legacy/):first do 1 directory = 1 issue rough audit(whether the whole is legacy), then during review, split per-file if needed. - The audit phase does not need to modify the issue body:Put the conclusion + evidence in verdict comment (keep the body concise; the comment follows right below and is clear enough).Only in the resolve phase, or when the body has become clearly misleading after multiple rounds, (optionally) update the body— don't burn extra tokens per article just to update the body.
Batch review orchestration (model / rate limit / concurrency)
When running tens to hundreds of articles together,the orchestration layer outside the skillhas four lessons that must be followed:
- Pick the most suitable model; don't inherit Opus by default. doc-audit is abounded task(read 1 article + skill + KB + grep code + possibly 1 test + classify into 5 categories + write comment) → use Sonnet;no Opus, no 1M context(a single agent's context is far below 200k).
needs-human-confirmas a fallback; the occasional Sonnet deviation will be caught by a human.Reserve Opus on demand for a few difficult/controversial articles(e.g. security spin-off re-review) and rerun them separately. The cost difference is ~5×. - Rate limiting: GitHub "content creation" is a hard constraint (≤500/h, ≤80/min). In batch POSTs, the bulk is comments, so:
- each agent posts only 1 verdict comment;
- at large batch sizes, agents do not each post a KB comment(otherwise POSTs double) — new topology facts go into the agent's return line,and the KB is folded centrally by a single point (the main control);
- spin-off only when there is truly an independent real issue;
- when gh hits a 403 secondary limit → back off and retry (≤3 times), and if it still fails mark it
RATE-LIMITED, do not error out the whole article (can be resumed and filled in later); - Estimate: N articles ≈ N POSTs; make sure it's < 500/h; if N is very large, split into segments/reduce concurrency to stretch out the time.
- Concurrency = the balance between throughput × rate limit. ~10–14 concurrency × ~2–3min per agent ≈ ~4–5 POST/min (~250–300/h), stably under the rate limit; don't blindly crank up concurrency and trigger the 80/min burst.
- Single-point editing of the KB body. Parallel agents only read the KB, do not write the body; new facts are folded uniformly by the main control after each segment/batch (see "Shared KB").Only interactive sessions may use Workflow orchestration (batch runs should be resumable, so failures/rate limits can be continued);unattended routines must never use Workflow, never use AskUserQuestion— by
issue-sweep's bounded worker pool use agent fan-out that requires no confirmation; only fall back to serial inline when the runtime does not support it. Questions awaiting a decision still go into a comment as usual.
Spin-off issue (opened automatically, without asking)
During review/audit you often run intoreal issues independent of this document's status(security vulnerabilities, dead code that isn't wired up and whether it should stay, clear bugs). Theseshould not be buried in the audit comment, andshould not wait for the user to nod——directly open a separate issue: with an appropriate label, assign the relevant code committer, cross-link both ways with the audit issue, and mention in one sentence in the audit comment that "spun off to #N". Opening an issue is reversible and traceable, so it counts as "do automatically".
- Only open automatically for "clear / confirmed" issues: bugs/vulnerabilities with solid evidence, or ones a human has already approved opening.Questions still unresolved / for A-B-C options not yet decided, do not open an issue first—leave it in a comment for someone to decide, and open it once decided.
- Once opened, the native edge must be written (write-edge discipline): in addition to the
<!-- spinoff-of: #N -->marker on the first line of :body, alsobun <plugin_root>/skills/issue-graph/scripts/link.ts --parent <N> --child <新号>(idempotent). The marker is provenance,only the native edge enters deterministic graph computation(close-kick / rollup); not writing the edge = when this spin-off closes it will never kick back to the parent issue. - Fix-on-discovery escalation(aligned with
pr-review★ fix on discovery): defects in a spin-off that satisfy the four gates (evidence confirmed · fix is unambiguous and bounded · not security · no direction decision needed)—especially UI defects visible at a glance in a screenshot—fix on the spot and open a fix PR at the same time as opening the issue(before/after screenshots + verification); the issue serves only as a tracking backlink, and is not left for the "next round / another agent". - Use a controlled vocabulary for priority(to prevent label drift, same as with status):
P0(urgent / security) ·P1·P2·P3(low priority); for security types additionally addsecurity. If these labels are missing, create them, butuse only this set of terms, do not create any morepriority:high/urgentand other variants.
partial → split out the remaining work (handling of the main conclusion of status:partial)
The Spin-off above is about review findingsencountered incidentallyindependent problems.This section covers a different scenario: when the audit'smain conclusion is exactly partial(the main body has landed, with a few bounded subtasks left undone), the correct action is todecompose the remaining work into independent, dependency-free, self-contained implementation issues—do not just list the gaps in a comment and wait for someone.
Trigger (once evidence is confirmed, split automatically, no asking): if the gap has path:line confirmed to be genuinely unfinished (e.g. "grep this.emit providers/iot/frigate/ → 0 hits"), split automatically.Gaps that are still speculative / with A-B-C options undecided are not split, leave a comment for someone to decide, and split once decided (the same principle as Spin-off).
Splitting discipline:
- First distinguish "unfinished tasks" vs "completed but documentation drift"—only split the former.
- Unfinished feature tasks(the code genuinely was not written) → split into a feature spin-off.
- Completed but the documentation was not updated retroactively(test counts outdated, checkboxes not ticked, decisions marked "pending" that are actually already decided) → this isthis audit's own resolve(fix the documentation via a human-signed PR),do not split an issue, otherwise it creates noise. State clearly in the audit comment that these items are left for resolve.
- Granularity: independently completable, no step dependencies. A unit that one person can complete independently without depending on another = one issue (e.g. one each for different providers / different APIs).Neversplit out chained issues of the form "B can only be done after A is done".
- feature spin-off ≠ doc-audit:do not attach
doc-auditlabel、do not attachthe audit milestone (this is an implementation task, not a documentation audit); usefeature+ priority (controlled vocabulary). Use an implementation tone in the title, e.g.[frigate] emit events into AFS EventBus。 - Every spin-off must be self-contained(so that an agent looking only at the issue can start working), fixed recipe:
- Goal:one sentence + current-state evidence (
grep/path:lineproving what is missing). - Background:one sentence identifying the system it belongs to.
- Reference implementation:an already landed paradigm of the same kind
path:line(just copy it), including key signatures / conventions. - Concrete tasks + Naming/path conventions(aligned with the paradigm).
- Acceptance criteria(checkable; include concrete test commands + paste pass/fail).
- Optional research:back-reference the original audit issue #N + related spec—mark it asoptionalresearch, not a required prerequisite.
- Goal:one sentence + current-state evidence (
- Bidirectional backlinks + native edge:spin-off body first line
<!-- spinoff-of: #N ... -->+ Optional research references #N; the original issue gets a comment listing the split-out #X/#Y (table: scope + independence) + remaining resolve actions.Each split-out spin-off alsolink.ts --parent <N> --child <#X>writes a native edge(edge-writing discipline, close-kick/rollup depends on it). - Immediately after splitting, remove
status:partial, replace it with the residual true state (otherwise it misleads human review).status:partialis a **"needs triage" signal**;path:lineonce all confirmed gaps are routed to tracking issues, it will make a human misjudge that this issue still has unhandled implementation gaps. Removing label / changing label is reversible → do it automatically:- This issue still has residual(typical: doc drift—"done but docs not updated") → change to
status:drifted(open; resolve is routed by the status table:planning/intent→ historical archive,docs/→ fix docs and convert tocurrent; both are landed via a human-signed PR → close). - No residual at all(all gaps tracked + no drift) → change to
status:current(or no status) + keepneeds-human-confirm, as an "audit complete, awaiting human final close" signal. - Splitting ≠ done, but "this issue's partial work has been fully triaged" = done—the difference is: the home of the remaining implementation work has moved to the spin-off, and this issue only has doc resolve left (or nothing).
- Still never automatically close / modify frontmatter(those are irreversible human actions); the final resolve (write frontmatter + fix doc + close) is done via a human-signed PR. Labels belong to AI (reversible), frontmatter belongs to humans (signed).
- This issue still has residual(typical: doc drift—"done but docs not updated") → change to
How It Works (cold-start first round)
┌────────────────────────────────────────────────────────────┐
│ 0. 读 thread,判轮次。后续轮 → 走上面"轮次感知",别全量重跑 │
│ │
│ 1. 读 issue 全貌(body + 全部 comments,含 human 意见) │
│ │
│ 2. 读被处理文档 + 引用的 spec/design / 对标范式 │
│ │
│ 3. ★ 对照已落地实现/代码/intent(最关键) │
│ 逐条声明 → grep/read 定位 `path:line`,或标 NOT FOUND │
│ │
│ 4. ★ 真跑测试(doc-audit 必做) │
│ 找到相关测试 → 跑 → 记录确切命令 + pass/fail │
│ │
│ 5. 出结论:逐条验证表 + 测试结果 + gap + 推荐 status,带证据 │
│ │
│ 6. 落 comment(中文),挂 status + needs-human-confirm 标签 │
│ 不 close、不删文件、不改 frontmatter │
└────────────────────────────────────────────────────────────┘
Implementation Instructions
Step 0 — acquire concurrency lock + determine round + read KB warm start (do this first, it determines whether you save effort)
Acquire the concurrency lock first(see "★ Concurrency lock"): already held by a fresh agent:processing → SKIP and exit; otherwise lock (--dry-run do not lock). The parallel issue-sweep orchestrator only allocates slots,does not pre-lock for workers; workers acquire immediately on their own when they get here. Then read the shared KB (gh issue view <kb_issue> body) for a repo topology warm start, do not explore from scratch. Then gh issue view <n> --comments: there are prior AI conclusions + human opinions → take the "round-aware" warm-start path,skipThe full steps below repeat; only do the next step specified by the human; otherwise follow cold-start Steps 1–6 (cold start is also tiered by value).Wrap-up: a normal single-issue call appends/corrects the topology facts newly learned this round into the KB body; when acting as a parallel issue-sweep worker, do not directly modify the KB body; return the structured KB delta to the controller for unified folding. Both modes require this worker to release the lock (Step 7)。
Step 1 — Read the full issue
gh issue view <n> --json title,body,author,labels,state,milestone + --comments. Note down: document paths, referenced specs/paradigms, key commits,all human/AI comments(human comments have the highest priority).
Step 2 — Read the document + referenced items
Read the full text of the document being processed + the specs/design it references / the paradigms it claims to align with (e.g. docs/architecture/did-space.md)。
Step 3 — ★ Cross-check against already-landed implementation/code/intent
This is the key to distinguishing "reads correctly" from "actually already landed / direction reversed / interface surface drifted". Do not compare only between documents — check the real code:
find . -path ./node_modules -prune -o -iname "*<topic>*" -print
grep -rniE "<关键路径或符号>" -l . | grep -vi node_modules
ls intent/<topic>/ ; sed -n '1,80p' intent/<topic>/INTENT.md
Each claim → locate path:line or mark NOT FOUND. Note: historical documents commonly have TASK.yaml marked done but INTENT.md/plan.md not updated in turn → status frontmatter is generally untrustworthy; you must re-verify against the code, and never trust status.
Step 4 — ★ Actually run the tests (doc-audit / verification named in acceptance criteria)
Find the relevant tests (pnpm --filter <pkg> test / bun test <path>),actually run, and recordthe exact command + real pass/fail countsin the conclusion.
The targeted
bun test <path>above is for confirminga certain doc-audit claim(you only want that one test's output as evidence) — keep it lightweight; do not run the full gate for one claim.The set below applies only when the issue is a feature/task, or the acceptance criteria or the human names a verification method.
When acceptance / the human names verification — "cannot run in this environment" is a conclusion to be proven, not a presupposed excuse. Usethe repository's own blessed skill, do not hand-roll commands and then hand-fill numbers:
- Structural PR gates (build / lint / types / tests / architecture) go through
/agentloop:verification。 to run<verification_entry>,numbers are measured by the script, not hand-filled。do notrunpnpm build/bun testyourself and then hand-write "759 pass" — that is exactly the anti-pattern of hand-rolled commands + hand-filled counts, and also the/agentloop:verificationnon-determinism to be eliminated. Seeverificationskill + CLAUDE.md「Self-Verification」。 - Integration e2e named in acceptance criteria (blocklet render / mount / serve) goes through
/e2e-verify(that repository's companion; see Companion Skills in the repo-profile; if none, stub or skip this step) — try first, then draw conclusions. It itselfpnpm build+ boot two runtime(dev_server_node+dev_server_edge, see the repo profile) —edge side =<dev_server_edge>starts a local environment, needs no cloud account, and does not touch the online environment; so edge-parity / runtime type verification can be done locally, and must never be judged as "requires a cloud environment" and deferred — that is wrong. Do not treat "don't hammer the online environment" as "cannot be verified locally";<cli_binary>missing/stale, run<cli_setup_command>first (e2e-verify itself also requires this)./agentloop:verification、/e2e-verify、<cli_setup_command>Youcan absolutely call—— If you haven't actually run it, writing "requires daemon / cannot execute in this environment" = failure,and you also can't substitute unit tests for a named e2e。 - Missing dependencies = one extra setup step, not "can't run". Native plugins not compiled (e.g. better-sqlite3 →
npx node-gyp rebuild), CLI not linked, not built —— do the setup first and then run it, don't treat it as an environment limitation. - Only a genuine hard limitation counts as "can't run": the sandbox simply doesn't have that toolchain (the platform toolchains listed in the repo profile Deployment Environments , arc examples: no Xcode → Swift, no Android SDK → Kotlin, no Playwright MCP → Tier B real browser for e2e-verify),and you've actually hit the wall。
dev_server_edgeis not in this category——it's the local environment, and it never counts as "can't run". In that case, postthe exact command + the exact error, fall back to whatever part can run (/agentloop:verificationscripts / other tiers / static comparison), andexplicitly annotate which layer was skipped(e.g.Tier B skipped/no-playwright)。 - Never pretend you ran it, never hand-fill numbers. If you didn't run it, say you didn't run it; if you ran it, paste the real output of the skill / script.
Step 5 — Draw conclusions
- Item-by-item verification table:claim →
path:lineor NOT FOUND. - Test results:command + pass/fail.
- gap list + phase completeness(doc-audit)。
- Recommended status(one of the 5 doc-audit categories) or graded findings(doc-review:🔴 regression/wrong direction · 🟡 genuine increment · 🟢 already-landed restatement · ⚪ deletable).
- reframe(if applicable): when the document as a whole is aimed at the wrong layer/reopens a closed question, just say "what should really be produced this round".
- The value is inindependent discovery, not in restating the human.
Step 5.5 — needs-human-confirm hard prerequisite (issue #1860)
Before tagging needs-human-confirm , ask once:Can I name a safe default action? Yes → escalation is forbidden; on the spot, per ratchet (default allow, tighten if problems arise, same as pr-review Step 5.5) perform that action and leave a trace; if not, only then is it a genuine judgment call, and only then does it deserve the needs-human-confirm tag going through the structured decision block of Step 6. This hard prerequisite must bebefore the tagging action, not filled in after tagging.
Step 6 — Post the comment (where the artifact belongs)
Write in the body language specified by comment_language (arc default: Chinese), and mark AI identity and read/run scope at the top:
> 🤖 AI Agent Audit @ <hostname> · runner:<runner> · skills@<hash>[ · engine:<kind>[/<model>]]。读取:<文档+代码+测试>。运行:<测试命令>。每条发现附可复现证据。
The entire header line must be generated by a single-point script(<agent_identity_script>; the four-dimensional provenance of environment/attribution/skills/engine can't be replaced by a date, placeholder, or hand-assembly——especially stop hardcoding "Claude Code()" by hand; the script brings out the real engine per ARC_AGENT_ENGINE/ARC_AGENT_MODEL , and running under Codex with a hardcoded one would falsely claim to be Claude), append the read/run scope at the end of the line:
bash <agent_identity_script> --header "Audit" --skill issue-review
# → "> 🤖 AI Agent Audit @ vm · runner:<name> · skills@a2298a3b"
For runner parsing priority, skills hash semantics, and prefix predicate discipline, see "Agent Comment Format" in the root CLAUDE.md.
gh issue comment <n> --body-file <draft.md> # 新发现 = 新 comment
gh issue comment <n> --edit-last --body-file <draft.md> # 改写/补充既有结论(如翻译)= 原地编辑,不新发
gh issue edit <n> --add-label "status:<x>,needs-human-confirm"
- New discovery = new comment; updating an existing conclusion (translating, adding evidence, responding to the human) = edit that comment in place, don't pile up duplicate comments.
- The two hard acceptance checks for screenshot evidence(anti-recurrence rules for the broken-image incident; issue #3010 added a third): ① UploadOnly walk
<ui_upload_script>(agent_identity_scriptAgent Tooling in the same section, arc defaults to<ui_upload_script>;ASSET_CONTEXT=issue-<N>), script exit 3 = local script inconsistent with origin/<default_branch> (stale checkout, the exact root cause of the incident) →git checkout origin/<default_branch> -- <ui_upload_script>then rerun, not allowed toALLOW_STALE_UPLOADER=1bypass; ② any image URL to be embedded in a comment mustcredential-free curl 200 (camo anonymous perspective; the script already has this spot check built in)—a non-200 URL will definitely break the image when embedded, forbidden to send; ③ the deterministic fallback when both uploader channels are unavailable (exit 2) is the browser's native attachment upload(open the issue/PR comment box in a browser logged into GitHub → file chooser attachment → GitHub attachment CDNuser-attachments/user-images.githubusercontent.comURL → screenshot before submitting to confirm it rendered, not a broken link; for full steps seeui-verifySKILL's Step 3fallback subsection)—— there is no longer this path of "MCP direct upload"(the old wording was incorporated and removed with #1037, MCP binary writes cause double base64 corruption, #1079). No matter which channel is used, an upload/publish failure must never be written as "verification completed" or "screenshot pending"——the comment must explicitly mark "screenshot publish failed, evidence missing" (consistent with theui-verify/pr-sweepofBLOCKEDsemantics), and must not be masked with neutral wording. - By default automatically post/edit, automatically open spin-off issues, automatically apply labels, no need to ask first(the agent has judgment).
--dry-runis an explicit opt-out: use it only when the user wants to preview first (do no outward writes). - Audit-phase artifacts = verdict comment + labels, leave the body untouched(the body stays lean, the comment follows right below, already easy for people to read); body completion is left to the resolve phase and is optional.
Step 7 — release concurrency lock (mandatory at wrap-up)
When processing ends (success, skip, or error all count), remove agent:processing:gh issue edit <n> --remove-label agent:processing。agent:hold untouched(that is a human reservation, only a human removes it).--dry-run If no lock was added then no removal is needed. A missed removal is not fatal—the TTL of 30min automatically expires it.
Key Principles
-
First determine the round + tier by value, don't waste tokens. The issue thread is cumulative state; later rounds trust previously verified evidence, and only do fresh verification on the parts that "changed/were questioned".Cold start is also tiered: clearly abandoned ones get only light confirmation (no build, no tests, no item-by-item path:line), full audit is reserved only for documents that are truly alive and whose details matter. Investment is proportional to document value.
-
Human comments are direction, not imperial decree. Give priority to following them, but tolerate that they may be incomplete, may be questions, may conflict among multiple people: still point out real problems the human didn't cover; if it's a question then answer rather than blindly obey; if multiple comments come from different people, reconcile them one by one and lay out the conflicts for the human to decide—don't quietly choose for them.
-
Artifacts land in the issue, not in the conversation. One processing run completed = the issue gains a comment that the next round can pick up, rather than someone gaining a bit of impression in their head.
-
Every finding must have reproducible evidence.
path:line/ grep hit / real test output /ghoutput. No evidence = don't write. -
Comparing against already-landed implementations is the top priority; doc-audit must actually run tests. Documentation being self-consistent ≠ consistent with reality;
statusFrontmatter is generally untrustworthy. The most valuable findings are "already implemented / the direction is wrong / the interface surface has drifted", and they are substantiated with test results. -
The value lies in independent discovery, not in restating the human reviewer.
-
Draw the boundary of autonomy by reversibility of consequences; judgment is required. Post a comment / add a label / assign / open issues that should be opened directly—— reversible and traceable actions are done automatically, without asking. Only major actions or irreversible operations such as deleting content or files, moving directories, merging/closing issues, or changing architectural direction are hung on
needs-human-confirmawaiting a person.Neverauto-merge/close/delete files/change frontmatter (the only exception to close = ★parent rollup, with authorization). Opening a spin-off must write a native edge (link.ts)。 -
Do not start a new stove beside an existing home. Before drafting any new crystal, first confirm whether this content is already carried by an existing intent/planning/provider; layer the increment on top of the existing source of truth and explicitly point to it.
-
Do not move directories. For the existing-content audit, only modify frontmatter
status+ backlink issue;deprecatedonly then delete files (content first safely enters an issue + human confirmation + a separate PR). Moving directories breaks the issue↔path key and git history. -
Warm-start with the shared KB; do not repeat exploration. First read the repo profile's
kb_issue(pinned knowledge base issue) to get the repo topology; hints are not truth, trust + cheap re-check, correct what you read if wrong; append new facts at the end. This prevents every agent from foolishly rediscovering the same set of topology. -
The remaining work of a partial must be split; once split, immediately remove the label.
status:partialWhen the main body has landed but bounded subtasks remain undone, automatically split the unfinished tasks substantiated bypath:lineintoindependent, dependency-free, self-containedfeature spin-offs (for the recipe see "partial → split remaining work");completed but with documentation driftare not split (that is the resolve of this audit).Once all gaps are routed, immediately removestatus:partial(it is a "pending triage" signal; keeping it would mislead human review), and replace it with the residual true state: remaining drift →status:drifted; no residue →status:current/no status +needs-human-confirm(awaiting final human close). Labels are reversible and may be adjusted automatically by AI; close / frontmatter go through a human-signed PR. -
Acquire the lock before starting work; always release at the end. Multiple actors (cron sweep + multiple people doing local manual work) concurrently processing the same issue wastes tokens repeatedly and duplicates comments.
agent:processing(TTL 30min advisory lock) atissue-reviewacquire it at the very start of work——if fresh then SKIP, if expired then grab——moving collisions from "discovered only at the end" earlier to "short-circuited at the start";agent:holdis a human reservation (automation permanently bypasses it; only a human removes it). The lock is advisory,hard deduplication still relies onissue-sweep's deterministic branching + claim check as a fallback。--dry-rundoes not touch the lock. -
Acceptance / human-named verification is a contract; "this environment cannot run it" must be proven first. Structural gating goes through
/agentloop:verification(pre-pr.ts, numbers are measured by scripts, not filled in by hand); acceptance-named integration e2e goes through/e2e-verify(<cli_binary>if missing/stale, first run<cli_setup_command>) — you can fully invoke these skills; if dependencies are missing, first do setup (compile native plugins, link CLI, build); only when you actually hit a hard toolchain gap (the platform toolchains listed in the repo profile Deployment Environments , e.g. arc: no Xcode/Android SDK/Playwright) does it count as "can't run", and you must paste the exact error + explicitly mark which layer was skipped.Don't substitute unit tests for the named e2e, don't hand-roll commands and hand-fill numbers, don't preemptively make excuses, don't pretend you ran it. -
When producing a design proposal, the grounding discipline is as strict as during audit: objective, precise, factual. issue-review doesn't only audit existing docs — it's also often used to produce a new proposal for a feature/design issue produce a new proposal(issue-sweep feature row). When producing a design, keep the same discipline: ① every assertion about thecurrent state(architecture, storage backend, API, file layout, existing behavior) must be
path:linebacked up —code is the sole authority, and when it conflicts with the referenced planning/docs, code prevailsand point out that the docs are outdated; ② everynumber(latency/throughput/size/count/limit) must either bemeasured(with command + output), orexplicitly marked as an unverified estimate, otherwise delete it —made-up latency/performance numbers are the most frequent hallucination, and when they conflict with the measurements the human gave in the issue, the measurements prevail; ③ clearly distinguish as-is (verified) from proposed (newly added). A fabricated backend/layout makes all subsequent phases build on a wrong foundation. Before the proposal is posted back to the issue it must pass/agentloop:design-review(its fact + number grounding is a HARD GATE); don't hand-post an unaudited design.
★ sweep-trace instrumentation (round-awareness criterion / L2 observability layer)
Every comment this skill sends to an issue(review verdict / ★Research evidence-based comment / ★Idea assessment comment / ★parent rollup synthesis —any one of them, not just the verdict) musthave appendedat the end a one-line sweep-trace HTML comment (invisible to humans, grep-able):
<!-- sweep-trace: {"ver":1,"issue":N,"gate":"review","val":"<val>","run":"<ISO8601>","runner":"<runner>","skills":"<hash>"} -->
This is not just observability — it is the criterion for issue-sweep round awareness. sweep relies onmachine markers(sweep-trace / Generated by [Claude Code] footer / Bot author) to distinguish "agent verdict (skip)" from "human input (respond)",not on > 🤖 header— because humans and agents use the same <agent_identity_script> generated header, with byte-for-byte identical format (live case arc#1722: a hand-pasted instruction was treated as an agent verdict and skipped for 19h).If this skill's comment lacks a trace, issue-sweep will misjudge it as "unhandled human input" → repeated handling/repeated commenting every round(the reverse effect in arc#1722 is exactly this gap). The identity header and the runner:…·skills@… linedo not countas machine markers (humans have them too).