[{"data":1,"prerenderedAt":397},["ShallowReactive",2],{"navigation_docs":3,"-decisions-0023-sample-crowded-reactive-regions":231,"-decisions-0023-sample-crowded-reactive-regions-surround":392},[4,26,100,109,210],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F1.installation","i-lucide-download",{"title":16,"path":17,"stem":18,"icon":19},"The first app","\u002Fgetting-started\u002Ffirst-app","1.getting-started\u002F2.first-app","i-lucide-play",{"title":21,"path":22,"stem":23,"icon":24},"The first test","\u002Fgetting-started\u002Ffirst-test","1.getting-started\u002F3.first-test","i-lucide-flask-conical",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[32,37,42,47,52,57,62,67,72,77,81,86,91,96],{"title":33,"path":34,"stem":35,"icon":36},"Components","\u002Fguide\u002Fcomponents","2.guide\u002F01.components","i-lucide-component",{"title":38,"path":39,"stem":40,"icon":41},"Inputs and forms","\u002Fguide\u002Finputs-and-forms","2.guide\u002F02.inputs-and-forms","i-lucide-text-cursor-input",{"title":43,"path":44,"stem":45,"icon":46},"Scrolling and viewports","\u002Fguide\u002Fscrolling","2.guide\u002F03.scrolling","i-lucide-scroll-text",{"title":48,"path":49,"stem":50,"icon":51},"Overlays and layers","\u002Fguide\u002Foverlays","2.guide\u002F04.overlays","i-lucide-layers",{"title":53,"path":54,"stem":55,"icon":56},"Styles and theme","\u002Fguide\u002Fstyles","2.guide\u002F05.styles","i-lucide-palette",{"title":58,"path":59,"stem":60,"icon":61},"Composables","\u002Fguide\u002Fcomposables","2.guide\u002F06.composables","i-lucide-puzzle",{"title":63,"path":64,"stem":65,"icon":66},"Widgets","\u002Fguide\u002Fwidgets","2.guide\u002F07.widgets","i-lucide-blocks",{"title":68,"path":69,"stem":70,"icon":71},"The assistant","\u002Fguide\u002Fassistant","2.guide\u002F08.assistant","i-lucide-message-square",{"title":73,"path":74,"stem":75,"icon":76},"The same app on the web","\u002Fguide\u002Fweb","2.guide\u002F09.web","i-lucide-globe",{"title":78,"path":79,"stem":80,"icon":24},"Testing","\u002Fguide\u002Ftesting","2.guide\u002F10.testing",{"title":82,"path":83,"stem":84,"icon":85},"Running and packaging","\u002Fguide\u002Fpackaging","2.guide\u002F11.packaging","i-lucide-package",{"title":87,"path":88,"stem":89,"icon":90},"The terminal contract","\u002Fguide\u002Fterminal","2.guide\u002F12.terminal","i-lucide-square-terminal",{"title":92,"path":93,"stem":94,"icon":95},"Benchmarks","\u002Fguide\u002Fbenchmarks","2.guide\u002F13.benchmarks","i-lucide-gauge",{"title":97,"path":98,"stem":99},"Diagnose input latency","\u002Fguide\u002Fdiagnostics","2.guide\u002F14.diagnostics",{"title":101,"icon":102,"path":103,"stem":104,"children":105,"page":25},"AI and agents","i-lucide-bot","\u002Fai","3.ai",[106],{"title":101,"path":107,"stem":108,"icon":102},"\u002Fai\u002Fagents","3.ai\u002F1.agents",{"title":110,"icon":111,"path":112,"stem":113,"children":114},"Decisions","i-lucide-scale","\u002Fdecisions","4.decisions",[115,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206],{"title":116,"path":112,"stem":117,"icon":46},"All decisions","4.decisions\u002Findex",{"title":119,"path":120,"stem":121},"0001. kyo-ui is the DSL","\u002Fdecisions\u002F0001-kyo-ui-is-the-dsl","4.decisions\u002F0001-kyo-ui-is-the-dsl",{"title":123,"path":124,"stem":125},"0002. jatatui renders the cells","\u002Fdecisions\u002F0002-jatatui-renders-the-cells","4.decisions\u002F0002-jatatui-renders-the-cells",{"title":127,"path":128,"stem":129},"0003. Pin Kyo 1.0.0-RC7 and JDK 25","\u002Fdecisions\u002F0003-pin-kyo-rc7-and-jdk-25","4.decisions\u002F0003-pin-kyo-rc7-and-jdk-25",{"title":131,"path":132,"stem":133},"0004. Public Kyo APIs only","\u002Fdecisions\u002F0004-public-kyo-apis-only","4.decisions\u002F0004-public-kyo-apis-only",{"title":135,"path":136,"stem":137},"0005. A SOFT frame contract and an own watcher loop","\u002Fdecisions\u002F0005-soft-frame-contract-and-own-watcher-loop","4.decisions\u002F0005-soft-frame-contract-and-own-watcher-loop",{"title":139,"path":140,"stem":141},"0006. Purity: edge files, lint and a pure painter","\u002Fdecisions\u002F0006-purity-edge-files-and-lint","4.decisions\u002F0006-purity-edge-files-and-lint",{"title":143,"path":144,"stem":145},"0007. Compiler flags from sbt-tpolecat","\u002Fdecisions\u002F0007-compiler-flags-from-sbt-tpolecat","4.decisions\u002F0007-compiler-flags-from-sbt-tpolecat",{"title":147,"path":148,"stem":149},"0008. The artifact split: runner, app, testkit and core","\u002Fdecisions\u002F0008-artifact-split-runner-app-testkit-core","4.decisions\u002F0008-artifact-split-runner-app-testkit-core",{"title":151,"path":152,"stem":153},"0009. tui4s-use and tui4s-widgets, cross-built","\u002Fdecisions\u002F0009-use-and-widgets-cross-built","4.decisions\u002F0009-use-and-widgets-cross-built",{"title":155,"path":156,"stem":157},"0010. The flagship assistant is the blueprint of a real app","\u002Fdecisions\u002F0010-the-flagship-assistant-as-blueprint","4.decisions\u002F0010-the-flagship-assistant-as-blueprint",{"title":159,"path":160,"stem":161},"0011. The web target: a standalone Scala.js app and one theme","\u002Fdecisions\u002F0011-web-target-standalone-scalajs-and-one-theme","4.decisions\u002F0011-web-target-standalone-scalajs-and-one-theme",{"title":163,"path":164,"stem":165},"0012. The documentation is example-first","\u002Fdecisions\u002F0012-documentation-is-example-first","4.decisions\u002F0012-documentation-is-example-first",{"title":167,"path":168,"stem":169},"0013. Benchmarks in the repository, with their own build","\u002Fdecisions\u002F0013-benchmarks-in-repo-with-own-build","4.decisions\u002F0013-benchmarks-in-repo-with-own-build",{"title":171,"path":172,"stem":173},"0014. Release per module, by tag, as 0.1.0-RC1","\u002Fdecisions\u002F0014-release-per-module-tags-and-rc1","4.decisions\u002F0014-release-per-module-tags-and-rc1",{"title":175,"path":176,"stem":177},"0015. Packaging: the AOT cache in the start scripts, native-image as an option","\u002Fdecisions\u002F0015-packaging-aot-cache-and-native-image","4.decisions\u002F0015-packaging-aot-cache-and-native-image",{"title":179,"path":180,"stem":181},"0016. Process: lean mode and agent roles","\u002Fdecisions\u002F0016-process-lean-mode-and-agent-roles","4.decisions\u002F0016-process-lean-mode-and-agent-roles",{"title":183,"path":184,"stem":185},"0017. Deferred: templates, mouse, the kitty keyboard protocol and Windows","\u002Fdecisions\u002F0017-deferred-templates-mouse-and-kitty","4.decisions\u002F0017-deferred-templates-mouse-and-kitty",{"title":187,"path":188,"stem":189},"0018. pini4s is a vendored Git submodule","\u002Fdecisions\u002F0018-pini4s-as-a-vendored-submodule","4.decisions\u002F0018-pini4s-as-a-vendored-submodule",{"title":191,"path":192,"stem":193},"0019. Upstream issues are drafts that the user posts","\u002Fdecisions\u002F0019-upstream-kyo-issues-as-drafts","4.decisions\u002F0019-upstream-kyo-issues-as-drafts",{"title":195,"path":196,"stem":197},"0020. Release from the Actions form","\u002Fdecisions\u002F0020-release-from-the-actions-form","4.decisions\u002F0020-release-from-the-actions-form",{"title":199,"path":200,"stem":201},"0021. The rulebook is CONTRIBUTING.md","\u002Fdecisions\u002F0021-the-rulebook-is-contributing-md","4.decisions\u002F0021-the-rulebook-is-contributing-md",{"title":203,"path":204,"stem":205},"0022. The logo is text","\u002Fdecisions\u002F0022-the-logo-is-text","4.decisions\u002F0022-the-logo-is-text",{"title":207,"path":208,"stem":209},"0023. Sample crowded reactive regions","\u002Fdecisions\u002F0023-sample-crowded-reactive-regions","4.decisions\u002F0023-sample-crowded-reactive-regions",{"title":211,"icon":212,"path":213,"stem":214,"children":215,"page":25},"Project","i-lucide-compass","\u002Fproject","5.project",[216,221,226],{"title":217,"path":218,"stem":219,"icon":220},"Roadmap","\u002Fproject\u002Froadmap","5.project\u002F1.roadmap","i-lucide-map",{"title":222,"path":223,"stem":224,"icon":225},"Contributing","\u002Fproject\u002Fcontributing","5.project\u002F2.contributing","i-lucide-git-pull-request",{"title":227,"path":228,"stem":229,"icon":230},"Security","\u002Fproject\u002Fsecurity","5.project\u002F3.security","i-lucide-shield",{"id":232,"title":207,"body":233,"description":385,"extension":386,"links":387,"meta":388,"navigation":389,"path":208,"seo":390,"stem":209,"__hash__":391},"docs\u002F4.decisions\u002F0023-sample-crowded-reactive-regions.md",{"type":234,"value":235,"toc":374},"minimark",[236,241,245,249,252,256,285,289,316,320,341,345,362,366],[237,238,240],"h2",{"id":239},"status","Status",[242,243,244],"p",{},"Accepted.",[237,246,248],{"id":247},"date","Date",[242,250,251],{},"2026-10-28.",[237,253,255],{"id":254},"context","Context",[257,258,259,268,279,282],"ul",{},[260,261,262,263,267],"li",{},"ADR 0005 gives each region its own watcher loop. The loop uses ",[264,265,266],"code",{},"Signal.nextWith",".",[260,269,270,271,274,275,278],{},"A derived signal built with ",[264,272,273],{},"combineLatest"," still runs one ",[264,276,277],{},"Async.race"," per change inside Kyo. Issue #8 records that limit.",[260,280,281],{},"The settlement fixture mounts one derived region per status row. At 128 rows, input stayed near 250 ms. That was the CI gate then. At 512 rows, input waited for seconds. Thread dumps showed the Kyo evaluator draining effect remainders, not a stalled inbox.\n",[260,283,284],{},"One capacity waiter reduced the 512-row delay and then missed keys and failed shutdown. That experiment stays a draft.",[237,286,288],{"id":287},"decision","Decision",[257,290,291,298,301,304,307,310],{},[260,292,293,294,297],{},"An input frame reads the first 16 reactive children of each parent. It also reads every bound region, every ",[264,295,296],{},"Foreach",", and a sampled region that holds the focus.\n",[260,299,300],{},"A parent with 2 reactive children or fewer gives each of those children a watcher fiber.\n",[260,302,303],{},"A parent with 3 reactive children or more gives those children no watcher fiber. The runner counts the children before it forks, so it does not start those fibers. A later mount stops a fiber that an earlier smaller mount left in place. A background frame reads the current value of 8 of those regions. The idle runner waits at most 16 ms for the next sample.\n",[260,305,306],{},"A span that only wraps a signal counts as one row of the element that contains the span. The span is not a separate parent for this count. The element is crowded when every child is one such row and there are more rows than the input read (16). A shorter list keeps one watcher on each span. A mixed element keeps one watcher on each span.\n",[260,308,309],{},"When input is already queued, the runner paints that input before the next background frame.",[260,311,312,313,315],{},"Bound regions and ",[264,314,296],{}," regions keep their watchers. The 1 s repair tick stays.",[237,317,319],{"id":318},"alternatives-considered","Alternatives considered",[257,321,322,329,335],{},[260,323,324,328],{},[325,326,327],"strong",{},"Wake one admission waiter."," It cut the 512-row delay in one run and then dropped keys and failed to shut down. Rejected.",[260,330,331,334],{},[325,332,333],{},"Drop the input pull of every reactive region, including small screens."," That breaks the armed-region check on an input frame. Rejected.",[260,336,337,340],{},[325,338,339],{},"Keep one watcher on every region and shorten settlement only."," Settlement already has a 16 ms budget. Layout and the watcher races sit outside that budget. Rejected.",[237,342,344],{"id":343},"consequences","Consequences",[257,346,347,350,353,356,359],{},[260,348,349],{},"A parent with 2 reactive children or fewer keeps the ADR 0005 watcher behavior.\n",[260,351,352],{},"A crowded parent samples its reactive children. A homogeneous list of more than 16 signal rows is one crowded parent. A shorter list, and a mixed element, keep one watcher per span.\n",[260,354,355],{},"The first 16 reactive children of a crowded parent still change on the input frame.\n",[260,357,358],{},"A sampled region can show its new value on a later frame. Input text and the focused region stay on the input frame.",[260,360,361],{},"The CI input gate is 300 ms for the continuous 128-region workload. A deadline-only miss may run three more times. A missing key, incorrect text, or a failed shutdown fails at once. This record does not claim a 100 ms bound.\n",[237,363,365],{"id":364},"references","References",[257,367,368],{},[260,369,370,371,267],{},"ADR 0005. Issue #8. ",[264,372,373],{},"tui4s.internal.ReactiveBudget",{"title":375,"searchDepth":376,"depth":376,"links":377},"",2,[378,379,380,381,382,383,384],{"id":239,"depth":376,"text":240},{"id":247,"depth":376,"text":248},{"id":254,"depth":376,"text":255},{"id":287,"depth":376,"text":288},{"id":318,"depth":376,"text":319},{"id":343,"depth":376,"text":344},{"id":364,"depth":376,"text":365},"An input frame reads 16 reactive children per parent. A parent with more than 2 forks no reactive watcher.","md",null,{},true,{"title":207,"description":385},"defivf7nalV4we62PcNsJuGboeC_QbHM7h0SEDqVcqE",[393,395],{"title":203,"path":204,"stem":205,"description":394,"children":-1},"The ASCII logotype of the maintainer is the logo of tui4s, and its 4 is the isomark. One script makes all the logo assets from the text file, and CI checks them.",{"title":217,"path":218,"stem":219,"description":396,"icon":220,"children":-1},"The planned and deferred features of tui4s, each with its GitHub issue.",1793293486489]