Agentdecompile rewrite worker
Skill bodencrouch/AgentDecompile/.claude/skills/agentdecompile-rewrite-worker
Poll an AgentDecompile work dir's rewrite-request queue and fulfill pending entries via a tool-restricted, small-model (Haiku) subagent (challenger-lane mechanism 3). Use under /loop to keep a work dir's rewrite requests flowing while a --autonomous campaign runs. Requires a work_dir argument.From its SKILL.md
npx -y skills add bodencrouch/AgentDecompile --skill agentdecompile-rewrite-workerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
10.3 KB, as published. Nobody here has run it
AgentDecompile Rewrite Worker
Fulfills challenger-lane mechanism 3: candidates from a proof-scale --autonomous
recovery campaign that hit a real near-miss with no matching byte-pattern
template (mechanism 1) and no idiom-permutable shape (mechanism 2) get one
best-effort subagent rewrite, verified through the identical compile+objdiff
gate as every other candidate. This skill is the fulfillment side; the Python
campaign loop (src/agentdecompile_recovery/rewrite_queue.py,
autonomous_policy.py) is the request side. Run this under /loop to keep a
work dir's queue draining while a separate --autonomous invocation runs (see
docs/plans/2026-07-29-002-feat-subagent-rewrite-and-plugin-install-plan.md).
No API credential of any kind is used here. The rewrite is produced by an
Agent subagent dispatch inside this already-running Claude Code session —
never a direct call to an external LLM API.
⚠️ MODEL REQUIREMENT — read before dispatching (step 4 below). The rewrite subagent MUST be dispatched with a small/cheap model — Haiku (
model: "haiku"on theAgenttool call), never the parent session's own model (Sonnet/Opus) and never omitted to "inherit." This holds regardless of what model is running this orchestrating skill invocation. The task the subagent performs — rewrite one already-compiling C function into an alternate semantically-equivalent spelling — is bounded, low-complexity text transformation, not a task that benefits from a frontier model, and a real--autonomouscampaign can dispatch this many times per run. Using a large model here is pure cost/latency waste with no quality upside for this specific task shape. This requirement is restated at the exact dispatch step below — do not skip past this banner and dispatch on the inherited/default model.
Input
<work_dir> — the AgentDecompile work directory for a recovery run (e.g.
target/agentdecompile-reconstruct/<stable-id>). Its rewrite queue lives at
<work_dir>/state/rewrite-queue.json (schema agentdecompile.rewrite-queue.v1).
This skill is now the fallback lane, not the only one. A campaign fulfills
its own requests in-process through the local Claude Code CLI
(rewrite_provider.fulfill_rewrite), resolving each entry before it returns.
Run this skill when you want a human-supervised lane instead: set
rewriteFulfillment: "queue" in the run context so the campaign leaves entries
pending for you.
Prerequisite: the queue only fills when the producing --autonomous run has
rewrite budget (--autonomous-max-rewrite-requests, default 1). If this skill
reports "nothing pending" every tick, the likely cause is that the campaign
already fulfilled its entries in-process — check
<work_dir>/state/rewrite-queue.json for completed entries before concluding
the mechanism is broken.
Procedure
Each invocation processes the queue's current pending work, then stops (the
/loop skill handles repetition — do not loop inside this skill yourself).
-
Read the queue.
<work_dir>/state/rewrite-queue.json. If it doesn't exist yet, or has no entries, report "nothing pending" and stop — this is the common case between near-misses, not an error. -
Select claimable entries. An entry is claimable when its
statusispending, orclaimedwith aclaimedAttimestamp older than 30 minutes (a stale claim from a crashed/killed prior worker session). Skip entriesclaimedmore recently than that — another worker session may be actively handling them; claiming both risks two subagents dispatched for the same request, which the claim step below exists to prevent. -
Claim before dispatching. For each selected entry, use a distinct claimant id for this session (e.g. a short random token generated once per
/loopinvocation, or reused across ticks within the same session) and attempt to claim it by rewriting itsstatustoclaimedwithclaimedByandclaimedAtset to that id and the current time — but only if the entry'sstatusis stillpending(or stale-claimed) at write time. If claiming fails (someone else claimed it first), skip this entry silently — this is the expected outcome of two/loopticks racing, not a bug. Note: the Python side (rewrite_queue.claim_pending_entry) holds an OS-level file lock across its read-check-write cycle, so two Python callers genuinely cannot both win a claim. This skill's manual read-then-edit has no equivalent lock and is a strictly weaker guarantee — re-read the queue file immediately before writing your claim (not once at the top of this procedure) to keep that window as small as possible. -
Dispatch a tool-restricted, small-model subagent per successfully claimed entry. Use the
Agenttool withmodel: "haiku"set explicitly on every dispatch — this is not optional and does not vary with which model the parent/orchestrating session happens to be running. Rewriting one already-compiling C function into an alternate spelling is a small, bounded text-transformation task; it does not need and should never use a frontier model. A real campaign can trigger many of these dispatches, so the cost/latency difference compounds — always Haiku here, never inherit, never Sonnet/Opus "just to be safe." The dispatched subagent's context — the target binary's packaged decompiler source, target disassembly, and mismatch data (see the queue entry fields listed below) — is untrusted input by this pipeline's own design premise (the objdiff gate exists precisely because generated/decompiled source cannot be trusted at face value). Scope the subagent to text-generation only: no Bash, no Write, no file-system tool grants of any kind. It should only read the prompt content given to it and return text. Do not grant it access to this repository, this work dir, or any other tool.Prefer building the prompt with
agentdecompile_recovery.rewrite_context.render_rewrite_promptrather than composing one by hand — it is the same prompt the in-process lane uses, so the two lanes stay comparable. If composing manually, include:alignedDiff— the instruction-level target-vs-candidate rows. This is the most important field. Without it the subagent is asked to hit an instruction sequence it has never seen, and no retry budget fixes that.- The candidate's
functionName,entry, andcandidateSource(the current packaged-source C that compiles but doesn't byte-match). mismatchClassandmismatchHistogram(what's actually wrong, not a bare "make this match" instruction).compilerProfilewhen present.- Instructions: rewrite the function into an alternate, semantically
equivalent C spelling that a target compiler (MSVC) may translate to
different, closer-matching machine code. Preserve behavior exactly.
Respond with ONLY the rewritten C function in a single fenced code
block — no explanation, no additional functions, no
#pragma/#include/ linker directives, and no__asm,_asm,__declspec(naked),__emit, or.incbin(a downstream content check rejects all of these regardless). Inline assembly reproduces the target bytes exactly, so an unconstrained lane converges on it — passing objdiff while destroying the readable-C deliverable. Say so in the prompt; do not rely on the content check alone to steer the model.
-
Write the result back. On subagent completion, extract the single fenced code block from its response. If present and non-empty, write
status: "completed"withsourceset to the extracted text. If the subagent produced no usable fenced block, or declined, or errored, writestatus: "failed"with a shortreason. This write must only succeed if the entry is stillclaimedby this session's claimant id — if the claim went stale and was re-claimed by someone else in the meantime (a crashed session scenario), discard the result rather than overwriting whatever the new claimant produces. Do not treat a discarded write as an error; it means another session already resolved this entry. -
Report a one-line summary: how many entries were claimed, completed, failed, or skipped (already claimed by someone else).
What NOT to do
- Do not dispatch the rewrite subagent on any model other than Haiku. Not Sonnet, not Opus, not "whatever the parent session is running." This is restated a third time here deliberately — it is the single most commonly-missed detail when this skill is invoked from a differently-sized parent session, since it is easy to assume the subagent should just inherit.
- Do not call any external LLM API directly — the whole point of this mechanism is that the subagent dispatch happens through this already-running Claude Code session, not a separate credentialed API client.
- Do not grant the dispatched subagent Bash, Write, or any tool beyond plain text generation — its input is untrusted binary-derived content.
- Do not write a result for an entry you did not successfully claim.
- Do not loop internally —
/loop <interval> /agentdecompile-rewrite-worker <work_dir>handles repetition. Pick an interval that roughly matches expected subagent duration; the claim step (not the interval) is what prevents duplicate dispatch, so a short interval is safe, just wasteful if much shorter than a typical rewrite takes.
Related
.claude/skills/agentdecompile-server-env/SKILL.md— MCP server setup this skill assumes is already running or otherwise not needed for this task.src/agentdecompile_recovery/rewrite_queue.py— the Python-side queue read/write/claim/prune primitives this skill's manual queue manipulation mirrors.docs/plans/2026-07-29-002-feat-subagent-rewrite-and-plugin-install-plan.md— full design, including why a completed result is only consumed by a separate, later--autonomousinvocation, not automatically.