1@README.md 2 3- **Linux/x86_64 only, on purpose.** No `target_lexicon`, no per-OS branches 4 in `src/main.rs` - this ports the *logic* of dioxus-cli's `patch.rs`, not 5 its full cross-platform surface. Adding another OS means adding the real 6 branch (Mach-O headers, Windows stub asm, …), not guessing at one. 7- **TLS symbols are handled by copying init bytes, not by refusing them.** 8 `create_undefined_symbol_stub`'s `SymbolKind::Tls` arm copies the base 9 binary's own `.tdata` bytes (`CachedSymbol::address`/`size` are the OFFSET 10 and length into that section, not a virtual address - the one symbol kind 11 here `aslr_offset` does not apply to) into a fresh TLS symbol in the patch, 12 porting `patch.rs`'s ELF branch (`patch.rs:1163-1226` in the dioxus 13 checkout). **This was not a theoretical risk**: proof against the real 14 window (`apps/native`) hit it immediately, on a plain recompile with NO 15 source changes to `packages/panels` at all - moving `logic`/`ui`'s bodies 16 into free functions shifted codegen-unit boundaries enough that a 17 thread-local internal to `std` or `tokio` came out newly-undefined in the 18 fresh link. `apps/hotdemo` never exercises this (no tokio, a two-crate 19 dependency graph) - do not treat it passing as evidence this branch is 20 unneeded for anything bigger. What is still genuinely unhandled: a symbol 21 that is TLS in the NEW code but has no counterpart in the base binary's 22 cache at all (nothing to copy init bytes from) - that still exits loudly, 23 correctly, since there is nothing to port it from. 24- `patch.sh`'s crate name comes from the target label's own suffix 25 (`//apps/hotdemo:hotdemo` -> `hotdemo`), and that name has to match: the 26 log file (`run/<crate>.log`), the `--out-dir XIPL/extras/<crate>` buck2 27 produces, and the patch-json path the running binary watches 28 (`run/<crate>.patch.json`) all derive from it. A target whose crate name 29 differs from its label's tail (an alias, an unusual `crate` attr) needs 30 `patch.sh` taught about the difference, not a rename to force the 31 convention. 32- Re-run `research/subsecond-patch-build.md` §7's measurements (the 33 `XIPL/extras` path shape, the `-Clink-dead-code` symbol-count diff) if this 34 is ever pointed at a different buck2 prelude version - both are read from 35 the prelude's `.bzl`/measured against a real build, not documented 36 upstream API. 37- **Never remove `-Csave-temps=true`/`-Clink-dead-code` from 38 `apps/native:native`'s own `BUCK` rule, even though `main.rs` has no 39 patch points.** `patch.sh` reads that object off disk (never rebuilding 40 it) as the "main" sentinel `subsecond::apply_patch` looks up by name in 41 every patch's own link - see README's "the executable is never rebuilt" 42 section. Removing the flags "cleans up" a real dependency, silently: 43 `hotpatch` fails loudly ("the patch has no 'main' symbol") the next time 44 anyone patches `apps/native`, not when the flags are removed. 45- **A tip's first-party dependencies are walked TRANSITIVELY 46 (`all_first_party_deps_of`), not one level.** `apps/native:native` -> 47 `apps/native:app` -> `packages/panels` is two hops; a one-level walk finds 48 `app` and stops, so a `packages/panels` edit builds correct fresh objects 49 that never reach `hotpatch` - the patch "succeeds" and silently keeps 50 running the OLD panels code via the undefined-symbol stub. No error 51 anywhere; this is the same family of silent failure as the TLS trap above, 52 found the same way (proving against the real window, 2026-09-20). Adding 53 another hop to the dependency graph needs no patch.sh change - the walk 54 is already general - but REMOVING the transitive walk to "simplify" it 55 reintroduces this exact bug. 56- **A dependency is checked with `has_save_temps` BEFORE it is built, not 57 after.** Building it first to find out costs real time for nothing: 58 `packages/mcp` depends on `packages/panels`, so a panels edit invalidates 59 mcp's own (proc-macro-heavy) compile too, for a result that was always 60 going to be thrown away (~10s measured 2026-09-20, before this check 61 moved earlier in `patch.sh`'s dependency loop). 62- **`--base` is `/proc/$PID/exe`, never a path `buck2 build` just produced.** 63 Asking buck2 to build `//apps/native:native` for `--base` is what forces 64 the relink this whole design exists to avoid the moment `app` has 65 diverged from what shipped in the last real build of the executable - 66 `/proc/$PID/exe` is the OS's own answer to "what is this pid actually 67 running", free and correct by construction, whether or not buck2's 68 on-disk copy at that path has since changed underneath it.