[{"data":1,"prerenderedAt":289},["ShallowReactive",2],{"navigation_docs":3,"-docs-reference-decisions":59,"-docs-reference-decisions-surround":286},[4,25,40],{"title":5,"path":6,"stem":7,"children":8,"page":24},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",[9,14,19],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":15,"path":16,"stem":17,"icon":18},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F1.getting-started\u002F2.installation","i-lucide-download",{"title":20,"path":21,"stem":22,"icon":23},"Using Porter","\u002Fdocs\u002Fgetting-started\u002Fusing-porter","docs\u002F1.getting-started\u002F3.using-porter","i-lucide-terminal",false,{"title":26,"path":27,"stem":28,"children":29,"page":24},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002F2.architecture",[30,35],{"title":31,"path":32,"stem":33,"icon":34},"Overview","\u002Fdocs\u002Farchitecture\u002Foverview","docs\u002F2.architecture\u002F1.overview","i-lucide-layers",{"title":36,"path":37,"stem":38,"icon":39},"Receiver internals","\u002Fdocs\u002Farchitecture\u002Freceiver","docs\u002F2.architecture\u002F2.receiver","i-lucide-smartphone",{"title":41,"path":42,"stem":43,"children":44,"page":24},"Reference","\u002Fdocs\u002Freference","docs\u002F3.reference",[45,49,54],{"title":46,"path":47,"stem":48,"icon":23},"Commands","\u002Fdocs\u002Freference\u002Fcommands","docs\u002F3.reference\u002F1.commands",{"title":50,"path":51,"stem":52,"icon":53},"Wire format","\u002Fdocs\u002Freference\u002Fwire-format","docs\u002F3.reference\u002F2.wire-format","i-lucide-binary",{"title":55,"path":56,"stem":57,"icon":58},"Decisions","\u002Fdocs\u002Freference\u002Fdecisions","docs\u002F3.reference\u002F3.decisions","i-lucide-file-text",{"id":60,"title":55,"body":61,"description":279,"extension":280,"links":281,"meta":282,"navigation":283,"path":56,"seo":284,"stem":57,"__hash__":285},"docs\u002Fdocs\u002F3.reference\u002F3.decisions.md",{"type":62,"value":63,"toc":265},"minimark",[64,79,82,179,184,189,196,200,207,211,218,222,233,237,242,249,258],[65,66,67,68,78],"p",{},"Non-obvious, reversible-but-significant decisions are recorded as ADRs in\n",[69,70,74],"a",{"href":71,"rel":72},"https:\u002F\u002Fgithub.com\u002FTerrorSquad\u002Fporter\u002Ftree\u002Fmain\u002Fdocs\u002Fadr",[73],"nofollow",[75,76,77],"code",{},"docs\u002Fadr\u002F",".",[65,80,81],{},"Add a new numbered record when you change the wire format, the fountain PRNG or\ndegree table, the isolate\u002Fthreading model, disk persistence semantics, or a\nlanguage or runtime choice.",[83,84,85,101],"table",{},[86,87,88],"thead",{},[89,90,91,95,98],"tr",{},[92,93,94],"th",{},"#",[92,96,97],{},"Decision",[92,99,100],{},"Status",[102,103,104,116,126,136,147,161],"tbody",{},[89,105,106,110,113],{},[107,108,109],"td",{},"0001",[107,111,112],{},"Flutter receiver worker isolate",[107,114,115],{},"Accepted",[89,117,118,121,124],{},[107,119,120],{},"0002",[107,122,123],{},"Fountain (LT-code) vs. sequential chunk encoding",[107,125,115],{},[89,127,128,131,134],{},[107,129,130],{},"0003",[107,132,133],{},"Disk hydration design",[107,135,115],{},[89,137,138,141,144],{},[107,139,140],{},"0004",[107,142,143],{},"Sender language — TypeScript → Rust",[107,145,146],{},"Accepted (QR-display sender only)",[89,148,149,152,158],{},[107,150,151],{},"0005",[107,153,154,157],{},[75,155,156],{},"mobile_scanner"," stays pinned at the vendored fork (7.2.0)",[107,159,160],{},"Accepted (known gap)",[89,162,163,166,176],{},[107,164,165],{},"0006",[107,167,168,171,172,175],{},[75,169,170],{},"porter join"," ported to Rust; ",[75,173,174],{},"nodejs\u002F"," and all JS deleted",[107,177,178],{},"Accepted (resolves 0004's defer)",[180,181,183],"h2",{"id":182},"in-brief","In brief",[185,186,188],"h3",{"id":187},"_0001-worker-isolate","0001 — Worker isolate",[65,190,191,192,195],{},"Decoding ran on the UI isolate and froze the app during a 109 MB transfer.\nA per-call ",[75,193,194],{},"compute()"," was rejected because the decode state must persist across\nthousands of calls; one long-lived worker owns it instead.",[185,197,199],{"id":198},"_0002-fountain-coding","0002 — Fountain coding",[65,201,202,203,206],{},"A QR slideshow has no back-channel. Sequential encoding stalls on a\nconsistently-missed frame; fountain removes the positional dependency at the\ncost of per-symbol decode overhead. Both are implemented and sender-selectable —\nthe leading ",[75,204,205],{},"F"," token disambiguates.",[185,208,210],{"id":209},"_0003-disk-hydration","0003 — Disk hydration",[65,212,213,214,217],{},"Chunk filenames are the ground truth for what has been received, because\ndebounced ",[75,215,216],{},"metadata.json"," writes can lag the actual files. Hydration records\nwhat exists without reading it; an earlier eager implementation exhausted memory\non real transfers.",[185,219,221],{"id":220},"_0004-rust-sender","0004 — Rust sender",[65,223,224,225,228,229,232],{},"\"Install Node to send a file\" is friction an air-gapped tool should not impose.\nRust gives a single static binary and ",[75,226,227],{},"ratatui","\u002F",[75,230,231],{},"crossterm"," for the interactive\ncontrols. Go was considered and lost on the TUI ecosystem.",[185,234,236],{"id":235},"_0005-pinned-scanner-fork","0005 — Pinned scanner fork",[65,238,239,241],{},[75,240,156],{}," is vendored at 7.2.0 with a local patch adding macOS\nexternal-camera selection. Upstream is at 7.4.0; re-diffing risks the feature\nthe fork exists for, for mostly-irrelevant fixes. Recorded as a gap.",[185,243,245,246],{"id":244},"_0006-porting-join","0006 — Porting ",[75,247,248],{},"join",[65,250,251,252,254,255,257],{},"Joining is the last step of an air-gapped transfer, so it runs on exactly the\nclass of machine that motivated ADR-0004. ",[75,253,248],{}," is pure local file\nconcatenation plus a SHA-256 check — no networking, no rendering, no wire-format\nsurface — so porting it allowed ",[75,256,174],{}," to be deleted entirely.",[65,259,260,261,264],{},"One deliberate behavioural difference: stray files sharing a ",[75,262,263],{},".part"," prefix are\nskipped rather than concatenated in.",{"title":266,"searchDepth":267,"depth":267,"links":268},"",2,[269],{"id":182,"depth":267,"text":183,"children":270},[271,273,274,275,276,277],{"id":187,"depth":272,"text":188},3,{"id":198,"depth":272,"text":199},{"id":209,"depth":272,"text":210},{"id":220,"depth":272,"text":221},{"id":235,"depth":272,"text":236},{"id":244,"depth":272,"text":278},"0006 — Porting join","The architecture decision records, and where to find the full text.","md",null,{},{"icon":58},{"title":55,"description":279},"TJvi6CXXbXFruq2ZdCpT9hl7J5BiyeLVM3Z7Rb4QQDA",[287,281],{"title":50,"path":51,"stem":52,"description":288,"icon":53,"children":-1},"Normative description of what a Porter QR frame contains.",1786360986984]