[{"data":1,"prerenderedAt":492},["ShallowReactive",2],{"navigation_docs":3,"-decisions-0021-the-rulebook-is-contributing-md":223,"-decisions-0021-the-rulebook-is-contributing-md-surround":487},[4,26,96,105,202],{"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],{"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,"icon":98,"path":99,"stem":100,"children":101,"page":25},"AI and agents","i-lucide-bot","\u002Fai","3.ai",[102],{"title":97,"path":103,"stem":104,"icon":98},"\u002Fai\u002Fagents","3.ai\u002F1.agents",{"title":106,"icon":107,"path":108,"stem":109,"children":110},"Decisions","i-lucide-scale","\u002Fdecisions","4.decisions",[111,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198],{"title":112,"path":108,"stem":113,"icon":46},"All decisions","4.decisions\u002Findex",{"title":115,"path":116,"stem":117},"0001. kyo-ui is the DSL","\u002Fdecisions\u002F0001-kyo-ui-is-the-dsl","4.decisions\u002F0001-kyo-ui-is-the-dsl",{"title":119,"path":120,"stem":121},"0002. jatatui renders the cells","\u002Fdecisions\u002F0002-jatatui-renders-the-cells","4.decisions\u002F0002-jatatui-renders-the-cells",{"title":123,"path":124,"stem":125},"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":127,"path":128,"stem":129},"0004. Public Kyo APIs only","\u002Fdecisions\u002F0004-public-kyo-apis-only","4.decisions\u002F0004-public-kyo-apis-only",{"title":131,"path":132,"stem":133},"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":135,"path":136,"stem":137},"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":139,"path":140,"stem":141},"0007. Compiler flags from sbt-tpolecat","\u002Fdecisions\u002F0007-compiler-flags-from-sbt-tpolecat","4.decisions\u002F0007-compiler-flags-from-sbt-tpolecat",{"title":143,"path":144,"stem":145},"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":147,"path":148,"stem":149},"0009. tui4s-use and tui4s-widgets, cross-built","\u002Fdecisions\u002F0009-use-and-widgets-cross-built","4.decisions\u002F0009-use-and-widgets-cross-built",{"title":151,"path":152,"stem":153},"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":155,"path":156,"stem":157},"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":159,"path":160,"stem":161},"0012. The documentation is example-first","\u002Fdecisions\u002F0012-documentation-is-example-first","4.decisions\u002F0012-documentation-is-example-first",{"title":163,"path":164,"stem":165},"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":167,"path":168,"stem":169},"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":171,"path":172,"stem":173},"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":175,"path":176,"stem":177},"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":179,"path":180,"stem":181},"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":183,"path":184,"stem":185},"0018. pini4s is a vendored Git submodule","\u002Fdecisions\u002F0018-pini4s-as-a-vendored-submodule","4.decisions\u002F0018-pini4s-as-a-vendored-submodule",{"title":187,"path":188,"stem":189},"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":191,"path":192,"stem":193},"0020. Release from the Actions form","\u002Fdecisions\u002F0020-release-from-the-actions-form","4.decisions\u002F0020-release-from-the-actions-form",{"title":195,"path":196,"stem":197},"0021. The rulebook is CONTRIBUTING.md","\u002Fdecisions\u002F0021-the-rulebook-is-contributing-md","4.decisions\u002F0021-the-rulebook-is-contributing-md",{"title":199,"path":200,"stem":201},"0022. The logo is text","\u002Fdecisions\u002F0022-the-logo-is-text","4.decisions\u002F0022-the-logo-is-text",{"title":203,"icon":204,"path":205,"stem":206,"children":207,"page":25},"Project","i-lucide-compass","\u002Fproject","5.project",[208,213,218],{"title":209,"path":210,"stem":211,"icon":212},"Roadmap","\u002Fproject\u002Froadmap","5.project\u002F1.roadmap","i-lucide-map",{"title":214,"path":215,"stem":216,"icon":217},"Contributing","\u002Fproject\u002Fcontributing","5.project\u002F2.contributing","i-lucide-git-pull-request",{"title":219,"path":220,"stem":221,"icon":222},"Security","\u002Fproject\u002Fsecurity","5.project\u002F3.security","i-lucide-shield",{"id":224,"title":195,"body":225,"description":480,"extension":481,"links":482,"meta":483,"navigation":484,"path":196,"seo":485,"stem":197,"__hash__":486},"docs\u002F4.decisions\u002F0021-the-rulebook-is-contributing-md.md",{"type":226,"value":227,"toc":469},"minimark",[228,233,237,241,244,248,290,294,372,376,405,409,441,445],[229,230,232],"h2",{"id":231},"status","Status",[234,235,236],"p",{},"Accepted.",[229,238,240],{"id":239},"date","Date",[234,242,243],{},"2026-10-20.",[229,245,247],{"id":246},"context","Context",[249,250,251,259,272],"ul",{},[252,253,254,258],"li",{},[255,256,257],"code",{},"AGENTS.md"," held 873 lines (821 lines that are not blank). It mixed two kinds of text: the rules (the toolchain, the commands, the rules for code, the purity rules, the docs, the versions and the release process) and the narrative of how the runner works (the modules, the keys, the components, the layers, the viewports and the text flow).",[252,260,261,262,265,266,268,269,271],{},"GitHub shows ",[255,263,264],{},"CONTRIBUTING.md"," to a first contributor: the page of a new issue and of a new pull request links to it. ",[255,267,264],{}," was only a short form that sent the reader to ",[255,270,257],{},".",[252,273,274,275,277,278,281,282,285,286,289],{},"Agent tools read ",[255,276,257],{},". Claude Code reads ",[255,279,280],{},"CLAUDE.md",", which holds one line, ",[255,283,284],{},"@AGENTS.md",", and it follows such ",[255,287,288],{},"@"," imports.",[229,291,293],{"id":292},"decision","Decision",[249,295,296,299,307,310,319,332,352,358,361],{},[252,297,298],{},"Three files at the root of the repository.",[252,300,301,303,304,306],{},[255,302,264],{}," is the rulebook, for humans and for AI agents. It starts with a quick path: set up, check a change, write docs, the release notes, the marks, the bench, report a problem. Each part links to its full section. The full sections follow. They moved from ",[255,305,257],{}," with the same text and the same marks: \"Toolchain\", \"Daily commands\", \"UI architecture and API design\", \"Rules for code\", \"Purity\", \"Docs\", \"Benchmarks\", \"Dependencies and versions\", \"Branch and tag rules\", \"Compatibility and versioning\" (it was \"Compatibility\") and \"Releasing\".",[252,308,309],{},"\"Compatibility and versioning\" adds two procedures: how to choose the next version of a module, and the pull request after a release.",[252,311,312,315,316,318],{},[255,313,314],{},"ARCHITECTURE.md"," holds the section \"What tui4s is\" of ",[255,317,257],{},", with the same text: the module table and how the runner works. A change of behaviour changes it in the same pull request.",[252,320,321,323,324,327,328,331],{},[255,322,257],{}," is short (under 60 lines). It tells an agent to read the two other files, and it imports them with the lines ",[255,325,326],{},"@CONTRIBUTING.md"," and ",[255,329,330],{},"@ARCHITECTURE.md",". It holds the rules for agents only: the marks, no terminal UI in the shell of an agent, one sbt process for each build root, the human gate of a release, no force push, no model name, ASD-STE100, the file to update for a change of behaviour or of process, and the skills.",[252,333,334,335,337,338,340,341,337,343,345,346,348,349,351],{},"The import chain: ",[255,336,280],{}," (",[255,339,284],{},"), then ",[255,342,257],{},[255,344,326],{},", ",[255,347,330],{},"). Claude Code loads the three files. Another agent reads ",[255,350,257],{},", and its first sentence names the two other files.",[252,353,354,355,357],{},"No sentence is lost. A script compared each line of the old ",[255,356,257],{}," that is not blank with the three files. Only the old title, the old intro, the old title \"Compatibility\" and the docs row of the module table (with its mark) changed on purpose.",[252,359,360],{},"The page \"Contributing\" of the docs site is the quick path, with links to the three files on GitHub. It does not copy the rules.",[252,362,363,364,366,367,369,370,271],{},"A reference that names a rule of today names ",[255,365,264],{}," or ",[255,368,314],{},". A reference in an older record or in a mark that tells the past keeps ",[255,371,257],{},[229,373,375],{"id":374},"alternatives-considered","Alternatives considered",[249,377,378,388,399],{},[252,379,380,387],{},[381,382,383,384,386],"strong",{},"One file, ",[255,385,264],{},", with everything"," (option a). Rejected: a human who fixes a typo scrolls past the architecture.",[252,389,390,398],{},[381,391,392,394,395,397],{},[255,393,257],{}," as the source and ",[255,396,264],{}," as the short form"," (option c, the state before this record). Rejected: the rulebook was invisible to humans on GitHub.",[252,400,401,404],{},[381,402,403],{},"The docs site as the only rulebook"," (option d). Rejected: an agent needs the rules in the checkout, also offline.",[229,406,408],{"id":407},"consequences","Consequences",[249,410,411,414,417,420,426,435],{},[252,412,413],{},"Good: GitHub shows the rulebook to a first contributor, and the quick path comes first.",[252,415,416],{},"Good: the narrative of the runner has its own file, so a change of behaviour has one clear place to document.",[252,418,419],{},"Good: an agent gets the same rules as a human through the import chain, plus the rules for agents only.",[252,421,422,423,425],{},"Bad: three files instead of one. A change must find the right file; ",[255,424,257],{}," tells which file a change of behaviour or of process updates.",[252,427,428,429,431,432,434],{},"Bad: an agent tool that does not follow ",[255,430,288],{}," imports reads only the short ",[255,433,257],{},". It must read the two files that the first sentence names.",[252,436,437,438,440],{},"Bad: the older records keep ",[255,439,257],{}," where they tell the past, so a reader can see both names.",[229,442,444],{"id":443},"references","References",[249,446,447,457],{},[252,448,449,345,451,345,453,345,455,271],{},[255,450,264],{},[255,452,314],{},[255,454,257],{},[255,456,280],{},[252,458,459,345,463,345,466,271],{},[460,461,462],"a",{"href":160},"ADR 0012",[460,464,465],{"href":176},"ADR 0016",[460,467,468],{"href":192},"ADR 0020",{"title":470,"searchDepth":471,"depth":471,"links":472},"",2,[473,474,475,476,477,478,479],{"id":231,"depth":471,"text":232},{"id":239,"depth":471,"text":240},{"id":246,"depth":471,"text":247},{"id":292,"depth":471,"text":293},{"id":374,"depth":471,"text":375},{"id":407,"depth":471,"text":408},{"id":443,"depth":471,"text":444},"CONTRIBUTING.md is the rulebook for humans and for AI agents; ARCHITECTURE.md tells how the runner works; AGENTS.md is short, holds the rules for agents only, and imports the two other files.","md",null,{},true,{"title":195,"description":480},"3bqf06d_17sWFAujVcLUlpXBJPuqh35UWMpBZQhHa-4",[488,490],{"title":191,"path":192,"stem":193,"description":489,"children":-1},"A release starts from the form of the workflow Release on main; every check runs before a tag exists; one approval of the environment publishes all the modules of the run in the order of the dependencies; CHANGELOG.md is the one source of the release notes.",{"title":199,"path":200,"stem":201,"description":491,"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.",1792528757750]