For agents, on top of README.md, which they read first.
- Linux/x86_64 only, on purpose. No
target_lexicon, no per-OS branches insrc/main.rs- this ports the logic of dioxus-cli'spatch.rs, not its full cross-platform surface. Adding another OS means adding the real branch (Mach-O headers, Windows stub asm, …), not guessing at one. - TLS symbols are handled by copying init bytes, not by refusing them.
create_undefined_symbol_stub'sSymbolKind::Tlsarm copies the base binary's own.tdatabytes (CachedSymbol::address/sizeare the OFFSET and length into that section, not a virtual address - the one symbol kind hereaslr_offsetdoes not apply to) into a fresh TLS symbol in the patch, portingpatch.rs's ELF branch (patch.rs:1163-1226in the dioxus checkout). This was not a theoretical risk: proof against the real window (apps/native) hit it immediately, on a plain recompile with NO source changes topackages/panelsat all - movinglogic/ui's bodies into free functions shifted codegen-unit boundaries enough that a thread-local internal tostdortokiocame out newly-undefined in the fresh link.apps/hotdemonever exercises this (no tokio, a two-crate dependency graph) - do not treat it passing as evidence this branch is unneeded for anything bigger. What is still genuinely unhandled: a symbol that is TLS in the NEW code but has no counterpart in the base binary's cache at all (nothing to copy init bytes from) - that still exits loudly, correctly, since there is nothing to port it from. patch.sh's crate name comes from the target label's own suffix (//apps/hotdemo:hotdemo->hotdemo), and that name has to match: the log file (run/<crate>.log), the--out-dir XIPL/extras/<crate>buck2 produces, and the patch-json path the running binary watches (run/<crate>.patch.json) all derive from it. A target whose crate name differs from its label's tail (an alias, an unusualcrateattr) needspatch.shtaught about the difference, not a rename to force the convention.- Re-run
research/subsecond-patch-build.md§7's measurements (theXIPL/extraspath shape, the-Clink-dead-codesymbol-count diff) if this is ever pointed at a different buck2 prelude version - both are read from the prelude's.bzl/measured against a real build, not documented upstream API. - Never remove
-Csave-temps=true/-Clink-dead-codefromapps/native:native's ownBUCKrule, even thoughmain.rshas no patch points.patch.shreads that object off disk (never rebuilding it) as the "main" sentinelsubsecond::apply_patchlooks up by name in every patch's own link - see README's "the executable is never rebuilt" section. Removing the flags "cleans up" a real dependency, silently:hotpatchfails loudly ("the patch has no 'main' symbol") the next time anyone patchesapps/native, not when the flags are removed. - A tip's first-party dependencies are walked TRANSITIVELY
(
all_first_party_deps_of), not one level.apps/native:native->apps/native:app->packages/panelsis two hops; a one-level walk findsappand stops, so apackages/panelsedit builds correct fresh objects that never reachhotpatch- the patch "succeeds" and silently keeps running the OLD panels code via the undefined-symbol stub. No error anywhere; this is the same family of silent failure as the TLS trap above, found the same way (proving against the real window, 2026-09-20). Adding another hop to the dependency graph needs no patch.sh change - the walk is already general - but REMOVING the transitive walk to "simplify" it reintroduces this exact bug. - A dependency is checked with
has_save_tempsBEFORE it is built, not after. Building it first to find out costs real time for nothing:packages/mcpdepends onpackages/panels, so a panels edit invalidates mcp's own (proc-macro-heavy) compile too, for a result that was always going to be thrown away (~10s measured 2026-09-20, before this check moved earlier inpatch.sh's dependency loop). --baseis/proc/$PID/exe, never a pathbuck2 buildjust produced. Asking buck2 to build//apps/native:nativefor--baseis what forces the relink this whole design exists to avoid the momentapphas diverged from what shipped in the last real build of the executable -/proc/$PID/exeis the OS's own answer to "what is this pid actually running", free and correct by construction, whether or not buck2's on-disk copy at that path has since changed underneath it.