feat(repipe): standing brief — be an interface, not an oracle - #366
Merged
Conversation
171 of the corpus's 250 challenges carry at least one obfuscation class and 57 are code-virtualised. Hostile binaries are exactly where a decompiler's automatic answer is wrong, so the interesting question this loop asks is not "why did kuna guess wrong" but "why could the agent not TELL it the right answer". That is now a standing instruction to both halves of the loop. Testers are told to file a missing INTERFACE whenever they catch themselves thinking "kuna should have known this" -- because the useful form of that complaint is almost always "kuna should have let me say so": define a function boundary, override a jump table, declare a blob as data with a type, steer structuring, fix a prototype, make a rename persist. They are told to check `kuna catalog --json` first, since an option that already exists is a discoverability problem rather than a missing interface -- and worth reporting as such. The prompt now also names the challenge's own obfuscation classes, because "this one is virtualised and string-encrypted" changes which interface is worth asking for. Builders are told to EXPOSE before they invent. kuna-console registers ~37 intervention-shaped commands -- map function, map address, map param/return, override prototype/flow/jumptable, force goto/datatype/varnode, name varnode, rename, retype, parse line/file, comment instruction, structure blocks, analyze range -- and NONE is reachable from the `kuna` binary; `kuna decompile` only ever emits `option` and `kassert` lines. Three very different jobs hide behind "add an interface" and they cost wildly different amounts: 1. it already works in the console and is merely unexposed -- wiring, the common case, and verifiable in one decomp_dbg invocation before any code; 2. it answers `engine integration not yet ported` -- `global add`, `dump` and `callgraph build` are confirmed examples -- which is real engine work and takes the [PROPOSAL] route rather than a half-port; 3. there is no decision point at all -- then it is a phases.toml option, not a subcommand, because a new judgement call ships behind a named flag. Two rules keep the result usable by the thing it is for. A durable assertion beats a one-shot flag: the model is assert(phase, anchor, type, value, strength) consulted on every re-run, and an agent that renames forty functions and loses them on the next invocation has gained nothing. And machine-readable in, machine-readable out -- assertions as a file or repeatable flags, JSON beside the human form. smoke.sh 71/71, make check-spec OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The corpus is deliberately hostile — 171 of its 250 challenges carry at least one obfuscation class, 57 are code-virtualised. Hostile binaries are exactly where a decompiler's automatic answer is wrong, so the interesting question this loop asks is not "why did kuna guess wrong" but "why could the agent not tell it the right answer?"
That is now a standing instruction to both halves of the loop.
Testers file a missing interface whenever they catch themselves thinking "kuna should have known this" — because the useful form of that complaint is almost always "kuna should have let me say so". Define a function boundary, override a jump table, declare a blob as data with a type, steer structuring, fix a prototype, make a rename persist. They check
kuna catalog --jsonfirst: an option that already exists is a discoverability problem, not a missing interface, and that is worth reporting too. The prompt now names the challenge's own obfuscation classes, because "this one is virtualised and string-encrypted" changes which interface is worth asking for.Builders expose before they invent.
kuna-consoleregisters ~37 intervention-shaped commands —map function,override jumptable,force goto,force datatype,parse line,retype,structure blocks… — and none is reachable from thekunabinary. Three very different jobs hide behind "add an interface":decomp_dbginvocation before any code is written;engine integration not yet ported(global add,dump,callgraph buildconfirmed) → real engine work,[PROPOSAL]route, not a half-port;phases.tomloption, not a subcommand, because a new judgement call ships behind a named flag.Two rules keep the result usable by the thing it is for:
assert(phase, anchor, type, value, strength), consulted on every re-run. An agent that renames forty functions and loses them on the next invocation has gained nothing.smoke.sh 71/71,make check-spec OK. No Rust touched.🤖 Generated with Claude Code