[{"data":1,"prerenderedAt":1055},["ShallowReactive",2],{"navigation_docs":3,"-contributing-adding-a-feature":172,"-contributing-adding-a-feature-surround":1050},[4,30,100,134],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":29},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,14,18,21,25],{"title":11,"path":12,"stem":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction",{"title":15,"path":16,"stem":17},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":5,"path":19,"stem":20},"\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start",{"title":22,"path":23,"stem":24},"Build from source","\u002Fgetting-started\u002Fbuild-from-source","1.getting-started\u002F4.build-from-source",{"title":26,"path":27,"stem":28},"Troubleshooting","\u002Fgetting-started\u002Ftroubleshooting","1.getting-started\u002F5.troubleshooting",false,{"title":31,"icon":32,"path":33,"stem":34,"children":35,"page":29},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96],{"title":37,"path":38,"stem":39},"Interface","\u002Fguide\u002Finterface","2.guide\u002F01.interface",{"title":41,"path":42,"stem":43},"Workspace","\u002Fguide\u002Fworkspace","2.guide\u002F02.workspace",{"title":45,"path":46,"stem":47},"Collections","\u002Fguide\u002Fcollections","2.guide\u002F03.collections",{"title":49,"path":50,"stem":51},"HTTP requests","\u002Fguide\u002Fhttp-requests","2.guide\u002F04.http-requests",{"title":53,"path":54,"stem":55},"Variables","\u002Fguide\u002Fvariables","2.guide\u002F05.variables",{"title":57,"path":58,"stem":59},"Authorization","\u002Fguide\u002Fauthorization","2.guide\u002F06.authorization",{"title":61,"path":62,"stem":63},"Scripts and tests","\u002Fguide\u002Fscripts-and-tests","2.guide\u002F07.scripts-and-tests",{"title":65,"path":66,"stem":67},"Collection runner","\u002Fguide\u002Fcollection-runner","2.guide\u002F08.collection-runner",{"title":69,"path":70,"stem":71},"Import and export","\u002Fguide\u002Fimport-export","2.guide\u002F09.import-export",{"title":73,"path":74,"stem":75},"Code snippets","\u002Fguide\u002Fcode-snippets","2.guide\u002F10.code-snippets",{"title":77,"path":78,"stem":79},"gRPC","\u002Fguide\u002Fgrpc","2.guide\u002F11.grpc",{"title":81,"path":82,"stem":83},"WebSocket","\u002Fguide\u002Fwebsocket","2.guide\u002F12.websocket",{"title":85,"path":86,"stem":87},"Cookies, proxy and certificates","\u002Fguide\u002Fcookies-proxy-certificates","2.guide\u002F13.cookies-proxy-certificates",{"title":89,"path":90,"stem":91},"Settings","\u002Fguide\u002Fsettings","2.guide\u002F14.settings",{"title":93,"path":94,"stem":95},"Keyboard shortcuts","\u002Fguide\u002Fkeyboard-shortcuts","2.guide\u002F15.keyboard-shortcuts",{"title":97,"path":98,"stem":99},"Privacy and security","\u002Fguide\u002Fprivacy-and-security","2.guide\u002F16.privacy-and-security",{"title":101,"icon":102,"path":103,"stem":104,"children":105,"page":29},"Reference","i-lucide-square-terminal","\u002Freference","3.reference",[106,110,114,118,122,126,130],{"title":107,"path":108,"stem":109},"Command line","\u002Freference\u002Fcli","3.reference\u002F1.cli",{"title":111,"path":112,"stem":113},"Automation tools","\u002Freference\u002Fautomation-tools","3.reference\u002F2.automation-tools",{"title":115,"path":116,"stem":117},"Scripting API","\u002Freference\u002Fscripting-api","3.reference\u002F3.scripting-api",{"title":119,"path":120,"stem":121},"Dynamic variables","\u002Freference\u002Fdynamic-variables","3.reference\u002F4.dynamic-variables",{"title":123,"path":124,"stem":125},"UI control channel","\u002Freference\u002Fui-control-channel","3.reference\u002F5.ui-control-channel",{"title":127,"path":128,"stem":129},"Workspace format","\u002Freference\u002Fworkspace-format","3.reference\u002F6.workspace-format",{"title":131,"path":132,"stem":133},"Feature status","\u002Freference\u002Ffeature-status","3.reference\u002F7.feature-status",{"title":135,"icon":136,"path":137,"stem":138,"children":139,"page":29},"Contributing","i-lucide-git-pull-request","\u002Fcontributing","4.contributing",[140,144,148,152,156,160,164,168],{"title":141,"path":142,"stem":143},"Contributing overview","\u002Fcontributing\u002Foverview","4.contributing\u002F1.overview",{"title":145,"path":146,"stem":147},"Development","\u002Fcontributing\u002Fdevelopment","4.contributing\u002F2.development",{"title":149,"path":150,"stem":151},"Architecture","\u002Fcontributing\u002Farchitecture","4.contributing\u002F3.architecture",{"title":153,"path":154,"stem":155},"Known gaps","\u002Fcontributing\u002Fgaps","4.contributing\u002F4.gaps",{"title":157,"path":158,"stem":159},"Adding a feature","\u002Fcontributing\u002Fadding-a-feature","4.contributing\u002F5.adding-a-feature",{"title":161,"path":162,"stem":163},"Assets and clean-room","\u002Fcontributing\u002Fassets-and-clean-room","4.contributing\u002F6.assets-and-clean-room",{"title":165,"path":166,"stem":167},"Releasing","\u002Fcontributing\u002Freleasing","4.contributing\u002F7.releasing",{"title":169,"path":170,"stem":171},"Writing the documentation","\u002Fcontributing\u002Fdocumentation","4.contributing\u002F8.documentation",{"id":173,"title":157,"body":174,"description":1043,"extension":1044,"links":1045,"meta":1046,"navigation":1047,"path":158,"seo":1048,"stem":159,"__hash__":1049},"docs\u002F4.contributing\u002F5.adding-a-feature.md",{"type":175,"value":176,"toc":1030},"minimark",[177,181,200,220,225,261,265,271,365,426,437,441,448,518,522,536,660,674,677,710,716,721,725,734,738,741,808,811,815,820,831,835,856,890,902,916,919,944,948,951,1026],[178,179,180],"p",{},"A feature is done when it works end to end and every layer has its proof. The order is fixed:",[182,183,184,188,191,194,197],"ol",{},[185,186,187],"li",{},"Engine API.",[185,189,190],{},"Automation tool with an end-to-end test.",[185,192,193],{},"UI.",[185,195,196],{},"Parity entry with evidence.",[185,198,199],{},"Documentation page update.",[201,202,203,204,211,212,214,215,219],"note",{},"This page is the short form of ",[205,206,210],"a",{"href":207,"rel":208},"https:\u002F\u002Fgithub.com\u002Fzuramai\u002Fpostguy\u002Fblob\u002Fmain\u002FAGENTS.md",[209],"nofollow","AGENTS.md"," sections 3, 4 and 5. Read ",[205,213,149],{"href":150}," first. Frontends reach the engine only through ",[216,217,218],"code",{},"crates\u002Fengine",", and nothing below L7 may depend on egui.",[221,222,224],"h2",{"id":223},"_1-engine-api","1. Engine API",[226,227,228,251,258],"ul",{},[185,229,230,231,234,235,234,238,234,241,234,244,234,247,250],{},"Put the behaviour in the engine, or in the crate below it that owns the concern (",[216,232,233],{},"http",", ",[216,236,237],{},"grpc",[216,239,240],{},"ws",[216,242,243],{},"interop",[216,245,246],{},"script",[216,248,249],{},"store",", and so on).",[185,252,253,254,257],{},"Return errors through the crate's error type and ",[216,255,256],{},"?",".",[185,259,260],{},"The UI and the automation tool must share this one implementation.",[221,262,264],{"id":263},"_2-automation-tool","2. Automation tool",[178,266,267,268,257],{},"Every user-facing feature must be callable without the GUI. Tools live in ",[216,269,270],{},"crates\u002Fautomation\u002Fsrc\u002Ftools.rs",[226,272,273,321,328,331,338,341,358],{},[185,274,275,276,279,280,283,284,287,288,291,292,234,295,234,298,301,302,305,306,309,310,305,313,316,317,320],{},"Add a ",[216,277,278],{},"ToolDef"," to the table returned by ",[216,281,282],{},"tools()",". It has ",[216,285,286],{},"name"," (",[216,289,290],{},"snake_case","), ",[216,293,294],{},"title",[216,296,297],{},"description",[216,299,300],{},"input_schema"," and the ",[216,303,304],{},"read_only"," and ",[216,307,308],{},"destructive"," flags. Declare required and optional arguments with the ",[216,311,312],{},"req(...)",[216,314,315],{},"opt(...)"," helpers in the ",[216,318,319],{},"schema!"," macro.",[185,322,323,324,327],{},"Add the matching arm to ",[216,325,326],{},"dispatch(...)",". Unknown tools and unknown arguments are refused before any state changes.",[185,329,330],{},"Errors must say what was wrong and what is allowed.",[185,332,333,334,337],{},"Send every path argument through the session, so ",[216,335,336],{},"--root"," confines it. A path outside the root gets the same refusal whether or not it exists, including paths reached by nested dispatch.",[185,339,340],{},"Write atomically. Never discard unsaved work silently. Cap anything echoed to an agent (bodies are capped at 1 MiB).",[185,342,343,344,347,348,305,351,354,355,257],{},"Add an end-to-end test in ",[216,345,346],{},"crates\u002Fautomation\u002Ftests\u002F"," (see ",[216,349,350],{},"tools.rs",[216,352,353],{},"engine_tools.rs"," there). The CLI side is exercised in ",[216,356,357],{},"apps\u002Fpostguy-cli\u002Ftests\u002F",[185,359,360,361,364],{},"Check it yourself with ",[216,362,363],{},"postguy-cli",":",[366,367,372],"pre",{"className":368,"code":369,"language":370,"meta":371,"style":371},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","cargo run -p postguy-cli -- tools\ncargo run -p postguy-cli -- run --script steps.json --root DIR\n","sh","",[216,373,374,399],{"__ignoreMap":371},[375,376,379,383,387,390,393,396],"span",{"class":377,"line":378},"line",1,[375,380,382],{"class":381},"sBMFI","cargo",[375,384,386],{"class":385},"sfazB"," run",[375,388,389],{"class":385}," -p",[375,391,392],{"class":385}," postguy-cli",[375,394,395],{"class":385}," --",[375,397,398],{"class":385}," tools\n",[375,400,402,404,406,408,410,412,414,417,420,423],{"class":377,"line":401},2,[375,403,382],{"class":381},[375,405,386],{"class":385},[375,407,389],{"class":385},[375,409,392],{"class":385},[375,411,395],{"class":385},[375,413,386],{"class":385},[375,415,416],{"class":385}," --script",[375,418,419],{"class":385}," steps.json",[375,421,422],{"class":385}," --root",[375,424,425],{"class":385}," DIR\n",[201,427,428,429,434,435,257],{},"AGENTS.md and the ",[205,430,433],{"href":431,"rel":432},"https:\u002F\u002Fgithub.com\u002Fzuramai\u002Fpostguy\u002Fblob\u002Fmain\u002Fcrates\u002Fautomation\u002FREADME.md",[209],"automation README"," refer to an \"Adding a tool\" section. That README currently has no such heading. This page and the existing tests are the reference. Tool tables for users are in ",[205,436,111],{"href":112},[221,438,440],{"id":439},"_3-ui","3. UI",[178,442,443,444,447],{},"Implement the interface in ",[216,445,446],{},"crates\u002Fui-egui",". These rules apply to every UI change:",[226,449,450,453,456,466,469],{},[185,451,452],{},"Never add a repaint loop.",[185,454,455],{},"Never run I\u002FO, parsing, formatting, searching or scripts on the UI thread.",[185,457,458,459,462,463,465],{},"Use Lucide icons from ",[216,460,461],{},"assets\u002Ficons\u002F"," and Poppins only (see ",[205,464,161],{"href":162},").",[185,467,468],{},"Check undo\u002Fredo and dirty tracking, save fidelity and session restore.",[185,470,471,472,500,503,504,234,507,305,510,513,514,305,516,257],{},"Look at the result:",[226,473,474,494],{},[185,475,476,477,480,481,484,485,234,488,305,491,465],{},"Launch ",[216,478,479],{},"postguy --control FILE",". Use ",[216,482,483],{},"postguy-cli ui --control FILE screenshot --out x.png"," (plus ",[216,486,487],{},"inspect",[216,489,490],{},"command",[216,492,493],{},"set",[185,495,496,497,257],{},"Or take a headless shot with ",[216,498,499],{},"cargo run -p postguy-ui-egui --example shot",[501,502],"br",{},"The control channel refuses ",[216,505,506],{},"click",[216,508,509],{},"key",[216,511,512],{},"type"," today. See ",[205,515,123],{"href":124},[205,517,153],{"href":154},[221,519,521],{"id":520},"_4-parity-entry","4. Parity entry",[178,523,524,525,528,529,257],{},"Every user-facing feature has a ",[216,526,527],{},"[[feature]]"," entry in ",[205,530,533],{"href":531,"rel":532},"https:\u002F\u002Fgithub.com\u002Fzuramai\u002Fpostguy\u002Fblob\u002Fmain\u002Fparity\u002Fpostman-features.toml",[209],[216,534,535],{},"parity\u002Fpostman-features.toml",[537,538,539,552],"table",{},[540,541,542],"thead",{},[543,544,545,549],"tr",{},[546,547,548],"th",{},"Field",[546,550,551],{},"Meaning",[553,554,555,584,606,621,634,647],"tbody",{},[543,556,557,571],{},[558,559,560,234,563,234,565,234,568],"td",{},[216,561,562],{},"id",[216,564,294],{},[216,566,567],{},"area",[216,569,570],{},"tier",[558,572,573,574,577,578,305,581,257],{},"Identity. Areas are A collections, B environments-and-variables, C http, D grpc, E websocket, F automation, G imports-and-exports, H ui-shell, I platform-packaging. Tiers are ",[216,575,576],{},"P0"," to ",[216,579,580],{},"P3",[216,582,583],{},"N\u002FA",[543,585,586,591],{},[558,587,588],{},[216,589,590],{},"status",[558,592,593,234,596,234,599,602,603,257],{},[216,594,595],{},"planned",[216,597,598],{},"partial",[216,600,601],{},"shipped"," or ",[216,604,605],{},"na",[543,607,608,613],{},[558,609,610],{},[216,611,612],{},"notes",[558,614,615,616,618,619,257],{},"What is missing. Mandatory honesty for ",[216,617,598],{},". A reason for ",[216,620,605],{},[543,622,623,628],{},[558,624,625],{},[216,626,627],{},"commands",[558,629,630,631,257],{},"Registry ids that must exist in ",[216,632,633],{},"crates\u002Fengine\u002Fsrc",[543,635,636,641],{},[558,637,638],{},[216,639,640],{},"tools",[558,642,643,644,257],{},"Tool names that must exist in ",[216,645,646],{},"crates\u002Fautomation\u002Fsrc",[543,648,649,654],{},[558,650,651],{},[216,652,653],{},"evidence",[558,655,656,657,257],{},"Passing tests as ",[216,658,659],{},"path\u002Fto\u002Ffile.rs::test_name",[226,661,662,667],{},[185,663,664,666],{},[216,665,601],{}," requires cited tests whose paths and names exist.",[185,668,669,305,671,673],{},[216,670,595],{},[216,672,605],{}," entries must not cite evidence.",[178,675,676],{},"Run the check:",[366,678,680],{"className":368,"code":679,"language":370,"meta":371,"style":371},"cargo xtask parity            # validate and report\ncargo xtask parity --partial  # list partial entries\n",[216,681,682,696],{"__ignoreMap":371},[375,683,684,686,689,692],{"class":377,"line":378},[375,685,382],{"class":381},[375,687,688],{"class":385}," xtask",[375,690,691],{"class":385}," parity",[375,693,695],{"class":694},"sHwdD","            # validate and report\n",[375,697,698,700,702,704,707],{"class":377,"line":401},[375,699,382],{"class":381},[375,701,688],{"class":385},[375,703,691],{"class":385},[375,705,706],{"class":385}," --partial",[375,708,709],{"class":694},"  # list partial entries\n",[178,711,712,713,715],{},"\"Shipped\" means it exists and is tested, not that it is \"as good as another tool\". Say in ",[216,714,612],{}," what is still missing. Also make sure no other entry just became untrue.",[178,717,718,719,257],{},"The same facts show to users on ",[205,720,131],{"href":132},[221,722,724],{"id":723},"_5-documentation","5. Documentation",[178,726,727,728,731,732,257],{},"Update the matching page under ",[216,729,730],{},"docs\u002Fcontent\u002F"," in the same pull request as any user-facing change. See ",[205,733,169],{"href":170},[221,735,737],{"id":736},"testing","Testing",[178,739,740],{},"Review every change at four zooms. Do it while you make the change, not at the end.",[537,742,743,753],{},[540,744,745],{},[543,746,747,750],{},[546,748,749],{},"Zoom",[546,751,752],{},"Check",[553,754,755,781,789,797],{},[543,756,757,760],{},[558,758,759],{},"Clause",[558,761,762,763,766,767,770,771,234,773,776,777,780],{},"Checked arithmetic, ",[216,764,765],{},"get()"," instead of ",[216,768,769],{},"[i]",", char-boundary slicing, the right error through ",[216,772,256],{},[216,774,775],{},"\u003C"," against ",[216,778,779],{},"\u003C=",", 0-based against 1-based seams, capped allocations.",[543,782,783,786],{},[558,784,785],{},"Function",[558,787,788],{},"Is it total? Name an input that panics. Walk empty, zero, max, malformed and cyclic inputs. Is the return type honest?",[543,790,791,794],{},[558,792,793],{},"File or module",[558,795,796],{},"Two sources of truth, dead or duplicated code, smallest public surface, doc comments still true.",[543,798,799,802],{},[558,800,801],{},"Project",[558,803,804,805,807],{},"Layering, undo\u002Fredo and dirty tracking, save fidelity, session restore, ",[216,806,336],{}," confinement, a matching tool, a parity note that just became untrue.",[178,809,810],{},"Tests mirror the zooms: property, unit, crate integration, end to end. Scale the zoom to the change.",[812,813,814],"tip",{},"Prove a test fails before the fix by actually reverting the fix. A test nobody has seen fail is not evidence.",[816,817,819],"h3",{"id":818},"hermetic-tests","Hermetic tests",[178,821,822,823,826,827,830],{},"Tests never touch the internet. Use the loopback servers in ",[216,824,825],{},"crates\u002Ftestkit"," (a dev-dependency, never shipped): HTTP, TLS, an OAuth token endpoint, gRPC with our own ",[216,828,829],{},"echo.proto",", WebSocket and a proxy.",[221,832,834],{"id":833},"fuzzing","Fuzzing",[366,836,838],{"className":368,"code":837,"language":370,"meta":371,"style":371},"cargo xtask fuzz --time 300\n",[216,839,840],{"__ignoreMap":371},[375,841,842,844,846,849,852],{"class":377,"line":378},[375,843,382],{"class":381},[375,845,688],{"class":385},[375,847,848],{"class":385}," fuzz",[375,850,851],{"class":385}," --time",[375,853,855],{"class":854},"sbssI"," 300\n",[178,857,858,861,862,865,866,869,870,234,873,234,876,234,879,234,882,234,885,305,888,257],{},[216,859,860],{},"fuzz"," mutates committed seed files under ",[216,863,864],{},"fuzz\u002Fseeds\u002F",". It runs these targets in child processes through ",[216,867,868],{},"postguy-cli fuzz-target",": ",[216,871,872],{},"url",[216,874,875],{},"vars",[216,877,878],{},"curl",[216,880,881],{},"data",[216,883,884],{},"openapi",[216,886,887],{},"har",[216,889,246],{},[226,891,892,895],{},[185,893,894],{},"A panic, a fatal signal or a hang is a finding.",[185,896,897,898,901],{},"Findings are saved under ",[216,899,900],{},"fuzz-out\u002Ffindings\u002F",", which is git-ignored.",[178,903,904,905,908,909,912,913,257],{},"Optional flags: ",[216,906,907],{},"--time SECONDS",", and ",[216,910,911],{},"--seed N"," for a reproducible run. CI runs it nightly with ",[216,914,915],{},"--time 900",[178,917,918],{},"To turn a finding into a regression test:",[182,920,921,928,931,938,941],{},[185,922,923,924,927],{},"Read the saved input and the ",[216,925,926],{},"why"," in the finding's info file.",[185,929,930],{},"Reduce the input to a small synthetic sample. Never commit corpus-derived files.",[185,932,933,934,937],{},"Write a test that feeds it to the failing function and asserts a clean ",[216,935,936],{},"Err"," or a handled result.",[185,939,940],{},"Run the test and watch it fail (panic) before the fix.",[185,942,943],{},"Fix, run it again, then commit the fix and the test together.",[221,945,947],{"id":946},"never-crash-rules","Never-crash rules",[178,949,950],{},"A malformed file, a hostile response, a bad tool argument, a corrupt settings file or a full disk must produce an error the user can act on. It must never crash and never lose work. This outranks feature work.",[226,952,953,979,989,995,1002,1016,1023],{},[185,954,955,956,959,960,234,963,234,966,234,969,234,972,602,975,978],{},"Non-test code uses ",[216,957,958],{},"Result",". No ",[216,961,962],{},"unwrap()",[216,964,965],{},"expect()",[216,967,968],{},"panic!",[216,970,971],{},"unreachable!",[216,973,974],{},"todo!",[216,976,977],{},"unimplemented!"," unless provably infallible, with a comment saying why.",[185,980,981,982,985,986,257],{},"No ",[216,983,984],{},"unsafe",". The workspace sets ",[216,987,988],{},"unsafe_code = \"forbid\"",[185,990,991,992,994],{},"Treat every input-derived number as hostile. Use ",[216,993,765],{},", checked or saturating arithmetic, and cap allocations sized by the input.",[185,996,997,998,1001],{},"Bound recursion with seen-sets or depth limits (JSON, ",[216,999,1000],{},"$ref",", proto messages, variable references, redirects).",[185,1003,1004,1005,1008,1009,1012,1013,257],{},"Entry points that run untrusted input (scripts, importers, commands, file import and export) keep a last-resort ",[216,1006,1007],{},"catch_unwind"," guard. Keep ",[216,1010,1011],{},"panic = \"unwind\"",". Never set ",[216,1014,1015],{},"panic = \"abort\"",[185,1017,1018,1019,1022],{},"A clean crate carries ",[216,1020,1021],{},"#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]",". New crates start with it.",[185,1024,1025],{},"Every crash fix comes with a small synthetic regression test that panicked before the fix.",[1027,1028,1029],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":371,"searchDepth":401,"depth":401,"links":1031},[1032,1033,1034,1035,1036,1037,1041,1042],{"id":223,"depth":401,"text":224},{"id":263,"depth":401,"text":264},{"id":439,"depth":401,"text":440},{"id":520,"depth":401,"text":521},{"id":723,"depth":401,"text":724},{"id":736,"depth":401,"text":737,"children":1038},[1039],{"id":818,"depth":1040,"text":819},3,{"id":833,"depth":401,"text":834},{"id":946,"depth":401,"text":947},"The path from engine API to automation tool, UI and parity entry, and how to test, fuzz and review it.","md",null,{},true,{"title":157,"description":1043},"1pYPyMcmiSyTjdslNXQFJA0dN20wZobLwkAyEN_YpYU",[1051,1053],{"title":153,"path":154,"stem":155,"description":1052,"children":-1},"Ranked open gaps, the feature investigation matrix and what has been closed.",{"title":161,"path":162,"stem":163,"description":1054,"children":-1},"Which assets Postguy may ship, how to attribute them, where behaviour may come from, and the commands that enforce it.",1793179614653]