compiles_standalone() returned a bare False and the caller attributed EVERY failure to the
overlay-local type cap. The dominant real cause is undeclared FILE-SCOPE EXTERNS: the body
references extern decls living outside the extracted def block (func_80174CB0: 22 of them;
carrying them makes it compile cc1 rc=0).
- compiles_standalone now returns (ok, stderr); the skip is classified by actual cause:
"missing file-scope extern (CARRY-FIXABLE): <names>" vs "overlay-local TYPE (the real cap)".
- FLEET SIZING (--auto-from ov_SC01_077 --check-only): 7 skipped, ALL 7 carry-fixable, 0 genuine
type-cap. Three of them (0x80142B2C/0x801535F4/0x80155800) are on the Phase-21 backlog list whose
note ALREADY said "macro-extern-injection frees them x134 (~+0.3%)" -- never built, because the
mislabel told every later session they were the type wall. A wrong label cost ~4 phases.
- also: func_80174CB0's local Mtx_/Svec_ typedefs swapped for the canonical shared MATRIX/SVECTOR
(byte-identical layouts); ov_SC07_006 still BYTE-IDENTICAL 7ca772be.
- value behind the real fix: the 7 (~+0.3pp) + func_80174CB0 x138 (16,974 ins, ~+0.13pp), ~0 tokens.
- _carry_externs itself is SPEC'd but NOT built here: it writes 138 overlay files (§63 class) and
wants a fresh session with an R22 budget. func_80174CB0 (banked x1) is the test case.
- PROBE ANSWERED (the SESSION-17 open item): a0's first use is body-line 41, a1's is 28
-> use order ALREADY matched the target's birth order while birth order was inverted.
The §31 RC-1/RC-2/RC-3 first-use-order hypothesis is REFUTED for this class; decl order
is inert too. Both retired, do not re-buy.
- ROOT CAUSE (byte-read): gcc schedules the arg->pseudo entry copies as ordinary in-block
insns and hoists an unconstrained one to the earliest slot. Mine raced `move $s4,$a0` to
idx 2, which freed $a0 to become the early load temp (target: $v1) and left the target's
idx-12 load-delay slot unfilled. The "wrong temp reg", the mirrored `sw $sN`/`move $sN`
prologue and the +1 instruction were ONE defect in three costumes.
- THE LEVER (cookbook §67, written in-session per R30): an UNPINNED launder
`__asm__ __volatile__("" : "=r"(pv) : "0"(p));` placed at the statement where the target's
copy lands, later uses rewritten to pv. Zero instructions. Prerequisite: collapse redundant
pointer aliases first (the two-pseudo split made gcc serve the first use from the incoming
arg reg). Placement is the knob and is NOT linear -- sweep 3-4 anchors (3-statement plateau).
- 25 -> 16 by reading; permuter_ils (REGALLOC, 10x180s) 16 -> 14 in cycle 1 then x9 unchanged
(§66d-3: a repeat means stop). Its edit is semantics-preserving (hoists desc.y+0x10) and
cleared the idx 271/272 cluster. Seeds tracked: s18_func_8014D820_close{16,14}.c.
- MEASURED NEGATIVES recorded so they are never re-bought: pinning the laundered var to $s4
(pre-stages via $t0, 305 ins); pinning the reused temp t to $3 (287/303); an artificial
"r"(t) dependency (inert -- gcc still hoists); laundering after the beqz (305); dropping the
a2 pin (29); wholesale pos/desc reorder or sinking z0=ent->z (+1 ins).
- NOT banked (G3) -- residual 14 in 2 clusters: idx 21/22 scratch $v1 vs $a0, idx 84-98 the
desc.y/currentLocationId schedule. SCHEDULE-weighted ILS running from the close=14 seed.
- Also measured: func_80140958 260/260 54 - func_80176734 371/371 56 - func_80176218 328 vs
327, whose +1 is NOT §67 (it hoists a global address into an extra callee-saved $s6 that the
target rematerializes -> the §17 array-decay lever).
- Measured locally (no MCP): per-overlay stubs that are substantial AND uncached AND undrafted = what
an import would unlock. Best single overlay 6,062 ins (0.05pp); fleet total 67,116 ins (0.51pp).
- Task 5's greedy cover (+1.59pp for ov_SC06_018) was a snapshot of a CONSUMABLE and has been consumed
by the s14/s15 waves + permuter runs. What remains is overlay-unique tail across 87 overlays, each
needing a server restart + a human /mcp for ~0.01pp.
- Ranked: giants ~+1.3pp (seeds ready) > func_801463A0 ~+0.11pp > the ENTIRE prefetch ~+0.51pp at 87
human-gated imports. The prefetch is now the worst lever on the board.
- R14 on myself: a 3-line ls of two dirs made func_8014032C look never-attempted; the full glob found
6 drafts. The fleet figure (0 cached+never-drafted at live>=100) stands. Same failure as §66c, twice
in one session — prefer the glob over a hand-listed pair.
- Balanced-if diamond and a zero-ins memory barrier both leave it at exactly 100/36, unchanged.
Why: §H kills a fold ACROSS A JOIN; here both uses are adjacent statements in the same basic
block, so there is nowhere for a fresh cse table to start.
- State: a standalone MATCH (101 ins) exists with direct-symbol u16 decls, blocked ONLY by the
canonical "extern u8 D_80126BE0[]" living inside a DEFINE_func_* macro body (engine_core.h:19813).
Exits: (a) demacroize = x1 trap (+101 ins, forfeits x138), (b) change the shared decl = T2 /
§63 disaster class, (c) a C form that keeps u8[] and defeats the address CSE = the open question.
+13,938 ins if (c) lands. Do not re-buy (a) or the two antidotes.
- 3 falsified hypotheses, then MATCH (101 ins) with direct-symbol scalar decls. The length gap was
the target re-materializing "lui $at,%hi(sym)" per scalar store while array/struct forms let gcc
CSE the address into a register (1-ins stores) -> mine was exactly one instruction short.
- Remaining blocker NAMED: the TU's canonical decl is "extern u8 D_80126BE0[]" INSIDE a DEFINE_func_*
macro body (engine_core.h:19813), so the matching u16 form gives conflicting types in the real TU
(real cc1, via rtu_match --stderr-out).
- demacroize would clear it but banks x1 (+101 ins) and forfeits x138 — a trap, not a win. The right
exit is the §H CSE address-fold antidote (balanced if/else diamond, zero asm) so the canonical u8[]
decl stays and the bank propagates x138 (+13,938 ins). Both draft forms preserved.
- rtu MATCH (101 ins) vs gate reject, baseline intact -> divergence had to be in a relocation.
All 9 jal targets agreed; of 15 data symbols the target uses, the draft referenced 14 — missing
exactly D_80126BE8.
- CAUSE: the draft declared D_80126BE0_s / D_80126BE8_s — `_s`-suffixed aliases NO symbol table
defines, invented because D_80126BE0 was already declared at a different type in the same draft.
- MECHANISM CORRECTED (§65c refinement): rtu over-claims not merely because it is relocation-masked
but because it COMPILES WITHOUT LINKING — an unresolvable extern is invisible to it by construction.
Cheap general guard: diff the draft's symbol set against the target .s's %hi/%lo/jal set before
gating (one comm over two greps; found this in seconds).
- FIXED: real symbols referenced, duplicate u8[] decl dropped, store re-expressed via &. Residual is
now an ORDINARY near-miss (100 vs 101 ins, 36 mismatched, regalloc/fold) -> permuter fuel.
Draft preserved at .run/giants/s17_func_801463A0_symfix.c.
- Did it properly: per-TU provided set via cdecl.typedef_names(tu_path) (217/215 names; it takes a
PATH), strip_provided_typedefs dropped 2/2 typedef lines from each draft, then the DRIVER's ladder.
pass 1 banked 0/2; src/ restored exactly.
- The stack: func_80156670 S8 -> B8 -> conflicting types for D_801270A8 (a DATA extern);
func_80174CB0 MATRIX/SVECTOR -> conflicting types for func_80012ABC (a callee conflict
cast_call_sites did not clear). cc1 reveals only the first layer each time (§65).
- NEW STATIC-ORACLE BLIND SPOT (R34 earning its keep): func_80156670's data conflict is CC1-ONLY —
the static oracle says `none` while real cc1 fails. First cc1-only case measured (SESSION-16 was
36/36 agreement). A `static: none` verdict is not evidence a draft is clean.
- Stripped drafts kept at .run/perm_s17j/ so the next attempt starts 3 layers in. ~+0.4pp if solved.
- func_8012B4B8 (84) + func_80169228 (105) propagated via targeted --addr (--check-only first,
never --auto-from): 138 overlays byte-identical, 2 new dedup groups, ~+26,082 ins.
- R22 clean-fleet: check-all 140 passed, 0 failed of 140. Fleet fn-count 88.90 -> 88.98%.
- The 3 non-banks are diagnosed, not guessed (blocker_probe, both oracles agree): func_801463A0 is
a real-cc1 MATCH in its own TU that the gate still rejects (§65c rtu-vs-gate divergence, link-level);
func_80156670/func_80174CB0 carry "drop when banking" typedefs textually identical to the canonical
ones. Blockers STACK — stripping the cc1-named typedef exposed the next (S8->B8; MATRIX->a callee
conflict). Remedy named: strip ALL shared-provided typedefs, then run the DRIVER's ladder.
- func_80176734: 76 -> 57 in cycle 1, then flat x9 (converged). Completes the queue.
- Seeds TRACKED at .run/giants/s17_*.c — the allowlist covers .run/giants/*.c but NOT subdirectories,
so they go at the top level (the R20 trap: a subdir would have left them untracked and one
git clean from gone).
- Queue state: 80177940 BANKED x138 | 8014D820 25 (toolkit exhausted -> Fable5) | 80140958 56 |
80176734 57 | 80176218 271 (never run). ~+1.3pp instr if the four crack.
barrier-on-a1 25 (inert) | barrier-on-a2 25 (inert) | param-staging via pinned $s3/$s4 35 | staging+barrier 34.
Staging DID fix the register assignment (loads via $v1 like the target) while shuffling birth order, so
the two are separately steerable and no tried combination gets both. Residual reproduced independently:
gcc copy-propagates the $a3 pin, so mine loads through incoming regs where the target uses the copies.
Per-cycle 80/75/72/69/64/62/60/59, monotone, never repeating. The readable signal: a repeated best
score means DONE (func_8014D820: 25 x7 -> reader/Fable5); a still-falling last cycle means
BUDGET-LIMITED (buy more cycles, it is CPU not tokens). Read the series, not the final number.
- permuter_ils from the 27-waypoint: 27 -> 25 in cycle 1, then UNCHANGED for 7 cycles.
- Residual read: target emits $s3<-a1 first, $s4<-a0 twelfth; mine the reverse. Same mapping,
swapped BIRTH ORDER, cascading into prologue save order + load base regs. §17 register-ORDER class.
- A one-line scheduling barrier on a1 (after the decl block; before it is a C89 error) changed
NOTHING. Corroborates the drafting agent's swept-pins note. Seeds carried; do not re-spend CPU.
- The loop: permuter (§31 schedule, 900s -j12) 5 -> 1, closing the 4-ins INSN_LUID scheduler tie the
drafting agent had swept by hand and recorded as un-steerable; read the last instruction (andi vs
addu); fixed it from the byte-verified sibling func_801778A8's pinned plain-copy idiom; permuter
again from the corrected seed (cse profile, 1800s) -> MATCH.
- The diagnosis was byte-driven, not guessed: dropping the redundant & 0xf alone COLLAPSED the copy
(100 vs 101 ins, 52 mismatched), proving the target needs a distinct PINNED register.
- GATE: harvest_verify --chunk 1 -> verified 1 / failed 0, d19c9580 BYTE-IDENTICAL; stub gone from
source (checked by grep, not the report). R22 clean-fleet: check-all 140 passed, 0 failed of 140.
- NEGATIVE recorded: the pin does NOT transfer to func_8014D820 (pinning its temp t to $v1 -> 285
mismatched, 303 vs 304 ins). Its run improved 33 -> 27 and plateaued; seed kept for ILS.
- REFUTES the .run/giants README's "pycparser/permuter CANNOT ingest it as-is": p16_permute.setup's
b64-pragma pin carrier handles it (6 pins -> 6 carriers, 0 raw __asm__, target.o built, §31 profile).
Checked against the tool, not the note (R35) — the 3rd recorded wall this session to dissolve.
- Drift-check first (R14): all preserved drafts reproduce their recorded closeness exactly (5/33/76/116).
func_801670E4 (close=16) is ALREADY BANKED fleet-wide — the README is stale; it is not work.
- 900s @ -j12: 5 -> 1. The permuter closed the 4-ins INSN_LUID scheduler tie the drafting agent had
recorded as un-steerable after sweeping all 6 assign orders + pin combos by hand.
- Last instruction (andi vs addu) diagnosed from the byte-verified sibling func_801778A8, whose
"nib = uVar1;" plain-copy idiom (both vars hard-pinned) after the identical (x << 16) >> 28 shift
pair is what materializes the addu. Dropping my redundant & 0xf alone COLLAPSES the copy (100 vs
101 ins, 52 mismatched), so the target needs a distinct pinned register. Pinning n to $a2 ->
101/101 with 6 left, class ADDRESSING [permuter] -> handed back to the permuter from the
structurally-correct seed rather than hand-designed.
- FIX: run_permuter's cleanup pkill matched EVERY concurrent run (two permuters silently killed each
other); scoped to the run's own scratch dir -> concurrent giant grinding is now safe.
- build_wave_args --min-live 100: ov_SC07_006 37 candidates / 0 fresh; ov_SC06_018 163 / 33 fresh,
all reach-1. Fleet-wide (139 binaries, 983 cached Ghidra-C): cached & live>=100 = 141 -> 111 gated,
30 with a preserved draft, 0 never attempted. Only fresh cached fuel anywhere = 40 fns at live 1-4.
- So the queue's '6 drafters -> ~3 banks x138' economics have no fuel. Fresh high-reach fuel is
CREATED by a per-overlay Ghidra-C prefetch (Task 5's greedy cover, imports 2-8 = +0.59pp), which
needs an MCP restart + Drew running /mcp (R23/R29).
- TWO selection bugs in my own filter, caught before spending: (1) the exclusion set missed
.run/giants/ (would have re-bought ~2.6M tokens of characterized permuter-only work); (2) it then
counted .run/ghidra_c/*.c -- the Ghidra INPUT -- as drafts, making every pool read 'exhausted'.
- Nothing spent; no agents launched.
- THE FREE TEST (cookbook §66): reverted func_801778A8's bank to its INCLUDE_ASM stub (stub state
rebuilds BYTE-IDENTICAL 7ca772be — a faithful revert proves itself; needs `make extract` first,
the R22 corollary) and re-banked it THROUGH recover_integration.py --commit --r22.
pass1 1/1 -> exact restore -> pass2 1/1 -> commit commit:0928 -> R22 140/140 -> report.json.
Bank confirmed from SOURCE (stub gone), never the report (§55b trap 4). EQUIVALENCE: git diff vs
the pre-revert commit = ONE blank line (mine) -> the driver reproduced SESSION-16's state exactly.
- DEFECT 1 (SAFETY, found by reading before firing): PROPAGATION is a fleet-tier write
(dedup_propagate --auto-from -> src/shared/engine_core.h + up to 138 overlay .c) that was both
UNDECLARED and the DEFAULT, so --max-tier binary still permitted the widest write in the toolchain.
assert_write_set cannot catch it (it runs before the gate; under --commit git status is clean).
FIXED up front: propagate now requires --max-tier fleet AND --r22, and is REFUSED after a
demacroize stage (those banks are x1 by construction; --auto-from would re-macroize and undo them).
Both refusals negative-control-tested, exit 1. The "standing hazard" is now a refusal.
- DEFECT 2 (METRIC): gate_stage scraped the fleet % via a progress.py label that no longer exists ->
fp=None -> 50 gate commits recorded "fleet None%". Now reads FLEET instr-weighted (legacy fallback
+ loud stderr warning if neither matches); parses 79.6.
- STALE DIGEST (R14): docs/progress.fleet.md at HEAD disagreed with HEAD's own source by 45 in the
dedup-shared column — generated during the §65g local_type trial whose edits were then reverted.
Regenerated (reproduced identically in-gate + standalone); headline %s unaffected.
- cookbook §66/§66a/§66b distilled in-session (R30); SETUP.md gains the missing recover_integration
row (R21 debt). tools-health OK: corpus 0/0, cdecl green, audit-binaries 140 citizens, lint OK,
dedup-check 1879/0. Fleet unchanged 79.6% instr / 67.7% distinct / 88.86% fn-count.
Records that recover_integration.py's SUCCESS path (pass 2, --commit, r22(), --report) has NEVER
executed -- the end-to-end run banked 0. Names the free, agent-free test that exercises it: revert one
of the 14 banks and re-bank it through the driver before pointing it at a fresh wave.
- 0 of 4 banked; reverted; make check BYTE-IDENTICAL; nothing landed.
- Ordering bug found+fixed: uniquifying the draft's type also renames it inside the draft's own
`extern <T> D_x;` decls, trading `redefinition of struct T` for `conflicting types for D_x`. With
uniquify moved BEFORE the reconcile one compiles -- and then DIFFs 48/53, because the data
reconcile's cast-at-use changes real codegen when the body depends on its own struct layout.
- func_8014C4AC: rtu MATCH but the gate returned a REAL final SHA != locked, i.e. the de-macroize edit
itself shifted a macro's OWN already-matched function. The §63 failure mode relocated somewhere the
per-binary gate catches it for free. MEASURED BOUNDARY: de-macroize is byte-neutral 14 of 15.
- Rule recorded: read the FINAL SHA, not the verified count -- `None` = no image (compile/link break),
a real hash != locked = the TU edit moved bytes. Different faults, different fixes.
- Two consecutive honest negatives (T8, T9): the EXISTING transforms stop at 14/36 (39%). §65f/§65g so
the next session does not re-buy this.
The () skip is confirmed blind to RETURN-type conflicts (func_801376E8 normalizes 0). The other two
targets produced edits that broke the build outright (final SHA None, not a byte-DIFF) -- consistent
with §57a's SURGICAL-ONLY classification: NSD edits the TU file, so a bad edit poisons the group and
cannot be bisected per-member. Reverted; make check BYTE-IDENTICAL; tree clean; nothing landed.
The self_decl_tu class stays OPEN and needs its own diagnosis session. Measured recovery holds at 14/36.
Extended, not replaced: it already owned exact snapshot/restore, split-aware grouping and the two-pass
gate-all -> restore -> re-stage-winners protocol. A new driver would be a 7th snapshot impl (R33).
- --draft-dir (repeatable): consume a WAVE dir instead of the backlog (unreliable closeness,
overlay-specific drafts). Strict ^func_[0-9A-Fa-f]{8}\.c$ filter -- the wave dirs carry scratch
(_b.c, try2.c, scratch/) and run_gate globs *.c blindly.
- --run-id: all scratch under .run/recover/<id>/, and run-local verified_out/failed_out passed into
run_gate -- closes §55b trap 4 (the accumulating .run/harvest_verified.txt phantom bank), which the
cookbook still lists as "still armed".
- --stages with the new demacroize stage; --max-tier; --r22; --probe-only; --report.
- TIERS ENFORCED not documented: stages declare T0/T1/T2, the driver MEASURES the write set
(git status before/after) and ABORTS if a stage writes outside its blast radius (§61d). A fleet-tier
stage is refused without --max-tier fleet AND --r22. Both refusals negative-control-tested.
- stub_map now derives from corpus.stubs (R33, coverage-asserting) instead of a private regex that
could silently return a short map; banked_from_source() is the sole bank oracle for reporting.
- End-to-end on the remaining 22: excluded 26 already-banked by name, demacroize ran on 12, banked 0,
restored exactly (src/ clean), 14/14 prior banks intact. A clean negative -- it does not manufacture
banks. Those 22 need normalize_self_decls / draft type-uniquify wired next.
- func_8012F40C banked (the callee-conflict variant): relaxing demacroize from "the draft's own
function" to "any decl the DRAFT declares incompatibly" reaches macros that declare a CALLEE
differently than the draft does (RotTransPers/RotTransSV). 14 banks total, R22 140/140.
- THE ONE FAILURE, kept honest: func_8012F49C was rtu-MATCH but the whole-binary gate REJECTED it.
rtu_match is relocation-masked, so a wrong call TARGET is invisible to it -- and this was a callee
case, exactly where the mask hides the error. Trust rtu MATCH for self-decl corrections, distrust it
for callee ones (§65c). Reverted its edits and re-banked only the winner rather than leave
byte-neutral churn on matched code (§57a-4).
- DISTILLED IN-SESSION (R30/R16/R31/R21): cookbook §65 + §65a-§65e (blast-radius tiers; the
de-macroize escape and the §20 refutation; the rtu-vs-gate divergence; the existing-ladder baseline;
two-oracle practice); decision-log entry with the HONEST multiple (~2.3x, not the projected 3.7x,
and it lands on distinct-code not the display number); calibration.md measured table; SETUP.md rows
for blocker_probe + demacroize PLUS the three the inventory was missing (lift_types, uniquify_type,
fix_header_decl-as-retired).
- Carried and NAMED, not dropped: 10 match_one-MATCH drafts still blocked by stacked classes, and the
11 `near` drafts which are unfinished drafts, not recovery fuel.
S0 measured all 36 stranded drafts in 9.2s, two oracles agreeing 36/36.
- POPULATION CORRECTED (R14): the audit's "~92% byte-correct" is a whole-wave figure; among the
STRANDED residue match_one says 24/36 MATCH / 11 near / 1 ERR = 67%. The 11 near are unfinished
drafts, not integration problems -- and they are exactly the ones that compile and DIFF.
- BLOCKERS (they STACK; cc1 reveals only the first): self_decl_hdr=21, callee_decl=19, data_decl=16,
self_decl_tu=5, local_type=5. Per function by MAX tier: T0=6, T1=26, not-integration=4.
- T3 BASELINE, measured free: the existing draft-side ladder clears callee_decl 19->3 and data_decl
16->0 yet converts 1 of 36 to compiling, which then DIFFs -- §61d verbatim. The wave's gate
orchestration was NOT broken; the ladder simply cannot reach this population.
- NEW tools/demacroize.py: the conflicting extern lives INSIDE a DEFINE_func_* macro BODY, so it
exists only where instantiated. Expanding those instantiations in the overlay's OWN TU, correcting
only the conflicting decl to the draft's byte-true sig (never dropping it, §57a-1), dissolves the
conflict with nothing written outside src/ov_SC07_006/. This is §63's own unexplored
"per-overlay-local decl" -- and it refutes §20's "the DEF-conflict class is byte-proven
unrecoverable by text transform" for the per-overlay case.
- MEASURED on the 14 clean candidates: 13 MATCH / 1 DIFF in the real TU.
- END-TO-END: func_8012CC88 banked whole-binary BYTE-IDENTICAL (stub gone per grep, not per report);
R22 clean-fleet 140 passed / 0 failed of 140 -> the T1 blast-radius claim validated empirically
(the difference from fix_header_decl, which broke 139/140 from the same per-binary green light).
- GATE A: 32/36 real decl errors (>=12) and 13/36 rtu-MATCH simulated (>=12). PASS.
Price stated honestly: a de-macroized bank is x1 -- full distinct-code credit, ~1/138 of instr.
Task 16 (the integration-recovery pass) T1. The SESSION-15 audit measured the wave bottleneck as
INTEGRATION (~92% of drafts byte-correct, ~27% bank); 36 stranded byte-correct reach-138 drafts are
the fuel. Before building any recovery, measure the REAL blocker per draft.
- tools/rtu_match.py: --stderr-out (atexit flush, covers every sys.exit path) + \n in //@EDIT
replacements (T6 needs a multi-line macro expansion). The inline tail is truncated and these TUs
emit hundreds of benign warnings -- on the first real run it was 100% warnings while the actual
errors sat ~180 lines earlier (the §58 red-herring, one level down).
- tools/blocker_probe.py (NEW, read-only, two oracles R34): static (cdecl.compatible -- never text
equality, which is what made the deleted scanner report u8-vs-unsigned-char as a conflict) and
real cc1 via rtu_match (ONE compile implementation, R33). Leads with the DISAGREEMENT table.
- DELETED .run/diag_plumbing.py (R3 tooling under tools/; R33 net -1 scanner).
- Two build-forced corrections: (1) cdecl.tu_scope runs real cpp, so it already expands instantiated
DEFINE_func_* macros -- the macro scan's job is ATTRIBUTION (tu-text vs shared-header macro body:
different transforms, same T1 tier), byte-checked against engine_core.h:7533 for func_80161374;
(2) blockers STACK and cc1 reveals only the first, so a function's tier is the MAX over blockers.
- Smoke test 3 fns: oracles agree 3/3. src/ untouched (write-set asserted). Not yet population
evidence -- that is T2 / KILL GATE A.