Commit Graph
61 Commits
Author SHA1 Message Date
Jonas Volman 1cc83929d2 Add rename-stable exact verdict sweeps 2026-09-02 15:58:58 -07:00
Jonas Volman 37ff481e1c Record Models BSS admission boundary 2026-09-02 15:19:41 -07:00
Jonas Volman 73ba65723e Document portable campaign gate probes 2026-09-02 08:28:17 -07:00
Jonas Volman b533182986 Snapshot Fable gate enhancements for salvage 2026-09-02 08:28:17 -07:00
Jonas Volman e92ba073c2 Support direct object admission audits 2026-09-02 05:21:39 -07:00
Jonas Volman b1f5f7421e Track object-level admission rejections 2026-09-02 05:18:51 -07:00
Jonas Volman 3f809b4b79 Harden player rumble closeout accounting 2026-08-31 23:49:49 -07:00
Jonas Volman f70e1987ec Audit stack memory pool retention scaffolding 2026-08-31 23:49:49 -07:00
Jonas Volman 2652deb5a4 Make treemap exactness fail closed on canonical parks 2026-08-31 20:43:20 -07:00
Jonas Volman 83e72959bb Harden treemap accounting across all objects 2026-08-31 18:25:51 -07:00
Jonas Volman 84bed49755 Fix semantic exact treemap display 2026-08-31 17:42:31 -07:00
Jonas Volman 9f63702601 Add provenance-safe symbol importer and correct CRC/LRA private names 2026-08-31 16:08:09 -07:00
Jonas VolmanandClaude Fable 5 ffb69dfbaf Fix the C1 sampler with a suspended launch; record two traps it exposed
c1_sampler2.py launches CL.Exe CREATE_SUSPENDED so the main thread handle is
owned outright - no Toolhelp, no OpenThread, which is what defeated the first
version - then tight-loops Suspend/Wow64GetThreadContext/Resume and
accumulates over N compiles. It works: 333,991 C1 samples for m6only.c vs
163,140 for the control over 6 runs each, showing C1 does ~2x the work when
the inline expression is present.

Two traps caught by verification, not assumed:
- int3-padding "function starts" are labels, not entry points; five
  top-ranked ones took zero breakpoint hits. Raw sampled EIPs are the valid
  targets.
- the top differential EIPs are hot shared parser code: breakpointing the
  five highest-excess raw EIPs fires in BOTH compiles at the 250-hit cap, so
  the "excess" is largely volume, not expression specificity.

dbg32 now prints hit counts with 8 hex digits instead of 1 (250 printed as
"a" before), so differential counting is possible at all.

Requirements for a next attempt recorded: count-only mode with a raised cap,
a work-matched control (same expression, non-commutative operators), and
call-target attribution instead of int3 boundaries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 ce3764d331 Add the C1 differential profiler and record why it does not sample yet
c1_sampler.py profiles m6only.c against m6none.c (identical headers and
locals, cross product removed) so header parsing cancels and expression
building stands out. It collects zero samples today, diagnosed rather than
assumed: OpenThread fails for all four threads, and the loop gets a single
pass before the sub-second compile exits, so Toolhelp-based sampling from
64-bit Python is far too coarse either way.

Fix for both recorded: launch CL suspended via CreateProcess to hold the
thread handle directly (no Toolhelp, no OpenThread), then tight-loop and
accumulate across many compiles - the approach the older acc_sampler used.
Cheaper alternative also recorded: a differential BREAKPOINT profile with
dbg32, which already fires on C1, trading many runs for a proven harness.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 da945c1a49 dbg32: plant breakpoints in any module; front end now reachable
Planting was hard-coded to C2.Dll at 0x10700000. It now matches the top 12
address bits of whichever module just loaded, so C1.Dll (0x10600000) and
C2.Dll breakpoints can be mixed in one dbg_bp.txt.

Measured on probes/m6only.c: C1.Dll loads before C2, four C1 breakpoints
plant, and two of them fire alongside a C2 control. The C front end runs
in-process and is debuggable with the same instrument - which is where the
frame walk pointed, having shown no C2 frame chooses between commutative
operands.

Scope recorded honestly: reaching C1 is not mapping it. C1 has none of the
anchors this file documents for C2, so locating the canonicaliser there is a
from-scratch effort over a 400KB .text, best started from a sampler profile
rather than guessed addresses.

Also records a discarded hypothesis: node[+0x34] is NOT a frame displacement
(two values matched member displacements by coincidence; across all 46
chain-consumer hits it decodes as pointers and unrelated constants). The
node-to-instruction correlation remains unsolved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 ae1a732c2e IR_LAYOUT: the frame walk ends - no lowering frame chooses the operand
The chain-carrying node is opcode 0x275; of 73 static creation sites exactly
one executes (0x10760f80), reached past two operand tests. The branch there
leads to an alternate path (0x10760e84) that DOES order two operands
explicitly - and it takes zero hits in this compile, measured against a
30-hit control on the same run. All 30 constructions go through the same
node maker 0x10763ac3 with the order already fixed by the caller.

So across encoder, fld-node creation, chain-head consumer and arithmetic
build, no frame applies a rule choosing between commutative operands; each
propagates an order established upstream. That is a measured explanation for
the ~65 inert source shapes, including every operand text order.

Explicitly NOT claimed as below-source-visibility: the same compiler
produced January's opposite order, so something upstream differs - in
expression-tree shape or in the context that drives canonicalisation, above
everything mapped here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 2568d158f4 IR_LAYOUT: the deciding frame takes the operand-chain head
At 0x10736518-0x1073653d, one frame back from fld-node creation: the code
reads the operand chain from [node+0x28], calls the accessor on the first
element and keeps it, calls the same accessor on the linked second element
and DISCARDS the result, then hands the first to the node builder. Confirmed
live at 0x1073652c over 46 hits - edi/ebx is the chain head, itself a 0x24e
node with a symbol pointer at +0x18 and the link at +0.

So this frame applies no rule: the head of the chain becomes the load. The
commutative operand role is decided by the chain ORDER, fixed upstream when
the arithmetic node's operands are linked.

That explains the source-side result: ~65 shapes inert, including every
operand text order, because commutative operands are canonicalised into the
chain before this point. Only a change to the chain order can move it.

Open: which chain element is which source operand for the tied instruction
(needs the per-hit correlation). Next target: the code that builds
[node+0x28].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 159a415c75 IR_LAYOUT: catch the fld operand-pointer write in lowering
Arming dbg_armreg at node CREATION (not at the encoder, which is too late by
construction) catches the write. Route: FP opcode constants are immediates,
so creation sites are findable statically; of 186 candidates for 0x24e
exactly one fires for probes/m6only.c - 0x10707995, called from 0x10736542
in the per-node codegen region.

The operand pointer is written by two sites sharing one idiom: operand
producer 0x10708c34 -> node constructor 0x107019f4 -> opcode into [node+4],
class/reg word into [node+0xa] copied from another node, then the operand
pointer into BOTH [node+0x18] and [node+0x1c] (def/use pair). Stores at
0x1070db1d and 0x10710332. 0x107019f4 independently confirms the node
constructor address recorded in the earlier POGO work.

Caveat recorded in full: the watched slot was recycled by the arena, so the
captured stores build a fresh 0x24d node reusing that memory rather than
provably the tied instruction's node. This maps the creation path and the
write, not the specific execution; correlating a site execution to the tied
fld needs a per-hit sweep or a value filter in dbg_armreg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 89016f5801 IR_LAYOUT: map the FP operand encoder's node view
Against probes/m6only.c: encoder entry 0x107455e6 reads the node opcode from
[ebp+4] and range-checks the 0x249-0x25a band, establishing ebp as the IR
node (breakpoint 0x107455fc, after ebp is loaded). Byte dispatch 0x107455ad
via the table at 0x107455c0, store at 0x107455da, then emit_bytes 0x10750023
-> 0x10781bbc -> inlined copy 0x10781c18, with the code-buffer descriptor in
ebx (+0x0c length, verified 0x18 as the tied fld was appended).

Corrects the standing note on [0x1088b788]: it is the per-instruction
STAGING cursor, not the code buffer, which is why it looked wrong for
integer code.

Node view: hits repeat with period 18; exactly three nodes per pass carry an
operand pointer at +0x18, and those point at per-variable symbol nodes one
0x60 stride apart. Field differential between the a- and b-referencing nodes
recorded, reproduced across two independent captures. Which field encodes
the operand role is NOT decoded - +0x34 is explicitly falsified as a pure
displacement by the result node.

Settled: the encoder only renders node fields, so arming a watchpoint at
encode time can never catch the operand choice being made. It is fixed
upstream in lowering.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 20fed6edaa dbg32: resolve watchpoint addresses at run time
DR0..DR3 are programmed when C2 loads, so dbg_wp.txt can only watch an
address known up front. Compiler-internal addresses are not: the arena base
shifts ~1MB per run, so IR nodes and the code buffer move (offsets stable,
base moves). Two new modes resolve the address while the compile runs:

  dbg_armwp.txt  "<hexpattern> @N +<hexoff> <len>" - at the Nth hit of bp0,
                 scan the debuggee for the pattern and watch match+off.
  dbg_armreg.txt "<reg> <hexoff> <hit> <len>" - at that hit, take the
                 register from the trapping context and watch reg+off.

Used against probes/m6only.c this pins the write of the tied instruction's
displacement byte and the whole emission chain: encoder store 0x107455da
(mov [edx],al) advancing the emit cursor [0x1088b788]; its owner 0x107455e6
reads the node opcode from [ebp+4] and range-checks edx-0x249<=0x11, which
confirms the FP opcode band AND that ebp is the IR node there; then
emit_bytes 0x10750023 -> 0x10781bbc -> inlined byte copy 0x10781c18.

Settles the question the mapping was for: the encoder only renders node
fields, so the operand role is already fixed in the node graph before it
runs and the decision is upstream in lowering. dbg_armreg on the node's
operand pointer is the way in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 e5adcc3709 Drop debugger run artifacts from the probe commit
dbg_run1.txt and dbg_scan.txt are per-run output, not source; the README
records the measurements taken from them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 f3284264e9 Map the C2 FP emit path against the micro_m6 tie
Single-function target m6only.c isolates the cross-product operand tie.
Measured: the FP path runs through byte emitter 0x107455e6 (called from
0x10744452) with edi holding a live IR node; opcode at node[+4] (0x24e),
operand pointer at node[+0x18], member leaves one 0x60 stride apart. The
assembled function is findable in the arena by pattern scan - prologue at
buffer+0 and the tied fld at buffer+0x18 - so the deciding bytes are
addressable at run time. Node/buffer offsets are deterministic; only the
arena base shifts per run.

Negatives recorded: all previously-mapped FP decision sites (0x10745628,
0x10744304, 0x10735135) take zero hits here - they were mapped from an
ai_debug compile and are path-specific. And the emitter's hits are NOT
1:1 with FP instructions (4 of 12 displacement positions match), so an
earlier node differential keyed on hit order was invalid and is discarded.

Next instrument: runtime-resolved watchpoints in dbg32, watching the
displacement byte at buffer+0x1a to get the operand encoder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:32 -07:00
Jonas VolmanandClaude Fable 5 bed9ca0ad4 Preserve the c2 probe lab for the commutative-order residual
micro.c::micro_m6 is a 96-byte reproduction of the cross-product operand
tie; probe_cross.c reproduces the full caller context. probelab.py compiles
either with the unit's real flags and disassembles one function, so the
next session can iterate in seconds instead of minutes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 15:51:07 -07:00
Jonas Volman 11ca9bb2f5 Correct thread ownership and recover camera names 2026-08-31 12:46:57 -07:00
Jonas Volman 3fafed8727 Park credible unclassified residuals honestly 2026-08-31 03:54:13 -07:00
Jonas Volman fdc63baec0 tools: add conservative fake-match source scanner 2026-08-30 20:52:51 -07:00
Jonas Volman 4941e5b987 Close Shell Xbox aligned data ownership 2026-08-29 20:42:36 -07:00
bnunu fd9c8eb095 Publish Units, HS, and campaign tooling progress
Carry forward three Units reconstruction advances, complete hs_library_external at 36/36 target-owned functions and 3824/3824 padded bytes, and admit it as Matching.

Also harden parked-function validation for assembly transcriptions and enable MSVC header dependency tracking. Full 568-object builds and all 205 tooling tests pass; the parked manifest has zero stale or invalid entries.
2026-08-28 08:17:11 -07:00
Jonas Volman b3b04dabc2 Port modern COFF and classifier tooling 2026-08-27 23:45:12 -07:00
Jonas Volman f30927ffeb Match item acceleration and restore probe walking 2026-08-27 23:06:25 -07:00
Jonas Volman b97d95fe79 Recover recorded animation playback wrappers 2026-08-27 20:18:09 -07:00
Jonas Volman 3c66472617 Publish local reconstruction tool suite 2026-08-27 09:29:47 -07:00
Jonas Volman d7aa6ce2ca Publish object-matching audit tools 2026-08-27 07:57:59 -07:00
Jonas Volman 31c2ba4144 Handle same-address function aliases in regression gate 2026-08-13 08:31:38 -07:00
Jonas Volman 1bf72e846d Match UI widget event handler functions object 2026-08-13 05:40:42 -07:00
Jonas Volman 64f068c27c Rank strict object closeout candidates 2026-07-29 16:13:28 -07:00
Jonas Volman 251d2ca783 Support semantic aliases in regression gate 2026-07-29 15:39:58 -07:00
Jonas Volman ce213d213a Add fail-closed shape transfer candidate executor 2026-07-29 14:00:55 -07:00
Jonas Volman 1626c093c5 Match plasma energy XDK wrappers 2026-07-21 13:18:56 -07:00
Jonas Volman 93baf254c5 Add reviewed XDK COMDAT adjudication gate 2026-07-21 12:04:38 -07:00
Jonas Volman f8e8e6b6fb Complete objects object and harden progress accounting 2026-07-19 12:30:45 -07:00
Jonas Volman a32e704bef Add fail-closed translation unit regression gate 2026-07-18 20:46:17 -07:00
Jonas Volman 7f3e114e06 Verify compiler-local label continuations 2026-07-18 18:24:40 -07:00
Jonas Volman 84414a1a04 Credit exact data in guarded incomplete units 2026-07-18 18:19:51 -07:00
Jonas Volman f2d0c47e95 Revoke object completion on semantic rejection 2026-07-18 18:05:47 -07:00
Jonas Volman 3b5f48f3b5 Add fail-closed codegen blocker classifier 2026-07-18 16:55:57 -07:00
Jonas Volman 6a372b627c Add fail-closed PDB 2.00 evidence extractor 2026-07-18 16:34:11 -07:00
Jonas Volman ca0d54a6ac Preserve pairwise COFF symbol equality 2026-07-18 13:25:54 -07:00
Jonas Volman 55db3f40ce Harden COFF non-code relocation matching 2026-07-18 13:05:10 -07:00
Jonas Volman 46f03e1827 Handle payloadless COFF BSS sections 2026-07-18 11:46:09 -07:00