From ca07373e44e19e0c8357ac49e460c90d87fcc22c Mon Sep 17 00:00:00 2001 From: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com> Date: Tue, 13 Oct 2026 15:45:55 +0800 Subject: [PATCH] docs(website): improve model essay transitions and narrative flow Connect the reconstruction cases to the questions about specialization, retrieval and feedback-driven search. Replace fragmented sentence sequences with explicit causal links and smooth the progression into oracle design and the proposed comparison. Validation: website.py check, formatting, preserved source links and evidence figures, and eight desktop/mobile light/dark layout checks at both preview paths. --- .../reverse-engineering-models/index.html | 486 ++++++++++-------- 1 file changed, 262 insertions(+), 224 deletions(-) diff --git a/website/public/blog/reverse-engineering-models/index.html b/website/public/blog/reverse-engineering-models/index.html index a3bbb712a..0ec0f9a6f 100644 --- a/website/public/blog/reverse-engineering-models/index.html +++ b/website/public/blog/reverse-engineering-models/index.html @@ -222,21 +222,25 @@ Since August 2026, I have been exploring how much reverse engineering an agent can carry out with access to a program and a way to check its work. Most of my experience comes from - reconstructing games, especially Touhou. The projects have also - become a record of what different models could make progress on. + reconstructing games, especially Touhou. As I have changed models, + the repositories have kept a record of what each session managed + to recover.
- Looking back through that record, there are functions that later - models closed after earlier sessions had left them unresolved. The - source changes make those breakthroughs more interesting than a - progress percentage does. + Much of that work aims at exact reconstruction: we compile the + maintained source under a pinned historical toolchain and check + whether it reproduces the target function. That gives us something + concrete to examine when a later model closes a function that + earlier work left unresolved. The source changes show what made + the breakthrough possible.
- One TH09 attack function was a byte short. Much of the logic was - already in place. The stack frame had the right size. But three - temporary vectors occupied different slots from the original, and - the compiled function still did not match. + In one TH09 attack function, much of the logic was already in + place, but the compiled candidate remained a byte short. Although + its stack frame had the right size, three temporary vectors + occupied different slots from the original. Matching the overall + size of the workspace had concealed a difference inside it.
A @@ -244,54 +248,61 @@ href="https://github.com/N0zoM1z0/th09/commit/de63c0f9121963f3a6b1ab5471c4878625fd3425" >GPT-6-Sol checkpoint - recorded that residual after testing several ordinary source - arrangements. Later, + recorded this mismatch after testing several ordinary source + arrangements. When GPT-6.1-Sol found a useful lifetime hypothesis. + >GPT-6.1-Sol returned to the problem, it found a useful hypothesis about how long those temporary + values needed to stay alive.
- The function calculated three vectors and copied each into an - animation's position. C++ keeps a returned temporary alive until - the end of the expression using it. Expressing the real operations - together kept those values alive together. The compiler could no - longer reuse the same storage for all three. + Each vector was returned from a calculation and copied into an + animation's position. Because C++ keeps a returned temporary alive + until the end of the expression using it, grouping the real + operations into one expression kept the three values alive + together. The compiler could no longer reuse the same storage for + all of them.
- A separate, real collision workspace also needed to keep its own - storage. With that source arrangement, the seventh targeted - candidate in the closing session matched. A cold build confirmed + That recovered the distinct temporary slots, but one still shared + storage with a real collision workspace used later. Keeping that + workspace at function scope separated it from the returned values. + With both changes in place, the seventh targeted candidate in the + closing session matched. A cold build confirmed the complete 1,436-byte function and all 44 encoded fields. Here, an exact reconstruction means that the maintained source, - compiled under the pinned historical toolchain, reproduces the - checked target function. + >.
- It was a useful discovery followed by several targeted tests. The - final result depended on both. + What interests me is how the discovery and the tests worked + together. The lifetime hypothesis gave the agent a new direction; + compiler feedback helped it refine that hypothesis into a source + arrangement that matched.
- Another TH09 function had a different obstacle. + A second TH09 function shows why that new direction can matter. + Here, the obstacle was how several branches shared their final + work. GPT-6.1-Sol's earlier work - reproduced two diagnostic regions, but the complete candidate was - 1,510 bytes against a 1,491-byte target. The way its branches - shared a continuation still differed. + reproduced two diagnostic regions, yet the complete candidate + remained 1,510 bytes against a 1,491-byte target. Those matching + regions did not resolve the way the branches joined up.
GPT-6-Astra changed the surrounding control-flow graph. Completion and frame processing became complementary branches, - followed by one common frame increment and return. In that - context, the compiler produced the required block sharing. The - entire 1,491-byte function matched, and a + >, making completion and frame processing complementary branches + followed by one common frame increment and return. Once the + compiler saw the branches in that context, it produced the + required block sharing. The entire 1,491-byte function matched, + and a recompile replay was accepted
A different representation made a different result - possible.Changing the representation opened a more productive search + space. - That is one reason I take general model capability seriously. An - agent can spend a long time trying variations within a source - structure that is keeping it stuck. + Both cases give me a reason to take general model capability + seriously: an agent can keep trying local variations for a long + time before finding a better way to express the surrounding work.
- These histories also contain accumulated work. Later sessions - inherited source and recorded failed experiments. They show the - discoveries and how we checked them. A controlled comparison would - tell us how much came from changing the model. + At the same time, the later sessions started with earlier source + and recorded failures. That accumulated work was part of their + advantage. The history lets us inspect the discoveries and their + checks; a controlled comparison would help separate the effect of + the model from the experience it inherited.
- Even so, the cases leave me with a question. How much of this work - needs a model with broad reasoning ability? How much could a model - learn from repeated experience with this particular kind of code? + This is where the question becomes interesting to me. Some of the + progress came from finding a new representation, while much of the + remaining work involved testing source forms against a familiar + compiler. How much needs broad reasoning ability, and how much + could a model learn through repeated experience with that compiler + and code?
- Touhou is an interesting place to ask. Much of the game code comes - from the same author, ZUN. That gives us a reasonable expectation - of recurring habits. The repositories contain more concrete - examples: related loops, helper functions and source arrangements - have supplied useful hypotheses across games. + Touhou gives us a concrete reason to expect that experience to + help. Much of the game code comes from the same author, ZUN, so + recurring habits are a reasonable starting assumption. The + repositories back that up with useful examples: related loops and + helper arrangements have supplied hypotheses across games.
- The compiler contributes its own habits. Under a particular - version and set of options, small differences in source can - produce repeatable differences in machine code. + Those source patterns become more specific when we include the + compiler. Under a particular version and set of options, small + changes in source can produce repeatable differences in machine + code. Some of those differences are surprisingly obscure.
- TH095 gave us a wonderfully awkward example:
+ In TH095, for example,
even the identifier backing a real local variable could change
where VC7.1 put it on the stack. Moving the declaration alone did not solve the layout. An
- earlier background function had already exposed the relevant
- identifier bucket, and that experience became useful in
+ >. Moving the declaration alone did not solve the layout, but an
+ earlier background function had exposed a useful identifier
+ bucket. That gave us a more promising hypothesis for
the reconstruction of Supervisor::LoadDat.
- Selecting the known backing identifier for the real file-size - variable put it and the character buffer in the required homes. - The buffer remained its genuine 128 bytes. All 151 bytes of the - function and its 15 relocations matched. + Reusing the known backing identifier for the real file-size + variable put it and the character buffer in the required homes, + without changing the buffer's genuine 128-byte size. With that + layout, all 151 bytes of the function and its 15 relocations + matched.
- That is narrow knowledge. A general model has little reason to - arrive with a detailed repertoire of one old compiler's local - allocation behavior. A specialist could encounter it repeatedly. - It could learn which source variations are worth testing first. + This is the sort of narrow detail a general model may not know + when it arrives. A specialist trained on this compiler could + encounter many such cases and learn which source variations are + worth testing first.
- In many of these final matching problems, we already understand - the behavior. The remaining question is which ordinary source form - this compiler turns into these instructions. That gives - specialization a specific job: propose plausible forms, then let - the target decide which survive. + The opportunity is especially clear in final matching problems + where we already understand the behavior. We are then asking which + ordinary source form this compiler turns into the observed + instructions. Specialization could help the model propose those + forms more efficiently, while the target still determines which + hypotheses survive.
- There are limits to how narrowly we can define the repertoire. - TH08 uses VC7. TH095 and TH09 use VC7.1. TH04 uses Turbo C++ in a - segmented DOS environment. Its + The useful patterns would have to retain their context, though. + TH08 uses VC7, while TH095 and TH09 use VC7.1. TH04's segmented + DOS environment uses Turbo C++, and its player reconstruction - needed another set of source-lifetime and linker-order hypotheses. - Shared authorship gives us a prior; each target tells us whether - that prior applies. + needed a different set of lifetime and linker-order hypotheses. + Shared authorship gives us a prior, but each target tells us + whether it applies. Distinguishing those contexts is part of what + a specialist would need to learn.
- Before training anything, there is an obvious place to look: the - repository. In the + Before deciding to teach those patterns through model training, I + would look at the knowledge we already keep in the repository. In + the previous essay, I wrote - about it becoming the project's working memory. Compiler lessons - belong there too. + about it becoming the project's working memory. That memory + includes compiler lessons, along with the source and failed + experiments that made them useful.
- An agent can retrieve a known result. It can inspect the source - that produced it and read which alternatives failed. That changes - its starting point without changing its weights. + By retrieving that record, an agent can start with a known result + and inspect how we reached it. It can also avoid alternatives that + have already failed in the same context. The starting point + improves without changing the model's weights.
- A TH09 + For the 373-byte TH09 enemy-spawn function, a GPT-6-Luna-max checkpointGPT-6-Luna-max session - makes this worth taking seriously. It closed a 373-byte - enemy-spawn function using an ordinary loop with branch-local - failure handling. TH08's corresponding source family supplied the - hypothesis. TH09's own evidence established its bounds and calls, - and two cold builds confirmed the complete match. + drew a hypothesis from TH08's corresponding source family. That + earlier source suggested an ordinary loop with branch-local + failure handling. TH09's own evidence supplied the bounds and + calls, and two cold builds confirmed the complete match.
“The model did not know that compiler quirk” and “the model could not use it” are different problems. - Supplying a fact may solve the first. Generating a useful source - candidate with that fact may still need practice. Choosing what to - try after a failed compile is another skill again. + Retrieval may solve the first, but turning that fact into a useful + candidate still takes work. And if the candidate fails, the model + must decide what the result means for its next attempt. Knowing + the relevant pattern is only the beginning of that process.
- I would want a smaller general model with good retrieval in any - comparison. Otherwise, we might credit fine-tuning for an - advantage that came from giving one model a better library of - experience. + For that reason, I would include a smaller general model with good + retrieval in any comparison. Giving it the same library of + experience would help us identify what training adds: better + candidate generation, better decisions after feedback, or both.
- In agentic reconstruction, the model proposes an explanation. The - program and its checks determine whether that explanation - survives. A failed candidate can be useful when it helps - distinguish the remaining possibilities. + Those decisions after feedback are what I would most like to + study. In agentic reconstruction, the model proposes an + explanation and tests it against the program. Even when the + candidate fails, the result can narrow the remaining possibilities + and suggest a more useful next experiment.
- This makes the temporary-vector example especially interesting to - me. The final source contains the successful arrangement. It does - not contain everything the search taught us. + Consider the temporary-vector example again. Its final source + shows the arrangement that worked, but the route to that source + contains more information. Each of the following experiments + helped identify what still needed to change.