[{"data":1,"prerenderedAt":762},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fparity":135,"\u002Fdocs\u002Fparity-surround":758},[4],{"title":5,"path":6,"stem":7,"children":8,"page":134},"Docs","\u002Fdocs","docs",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130],{"title":10,"path":11,"stem":12},"AI harnesses: LLM tools, MCP servers and agents","\u002Fdocs\u002Fai-tools","docs\u002Fai-tools",{"title":14,"path":15,"stem":16},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002Farchitecture",{"title":18,"path":19,"stem":20},"Web \u002F native bridges","\u002Fdocs\u002Fbridges","docs\u002Fbridges",{"title":22,"path":23,"stem":24},"Broadcast channels and tests","\u002Fdocs\u002Fchannels-and-tests","docs\u002Fchannels-and-tests",{"title":26,"path":27,"stem":28},"CLI reference","\u002Fdocs\u002Fcli","docs\u002Fcli",{"title":30,"path":31,"stem":32},"Completeness: how far an answer reaches","\u002Fdocs\u002Fcompleteness","docs\u002Fcompleteness",{"title":34,"path":35,"stem":36},"Configuration","\u002Fdocs\u002Fconfiguration","docs\u002Fconfiguration",{"title":38,"path":39,"stem":40},"External systems","\u002Fdocs\u002Fexternal","docs\u002Fexternal",{"title":42,"path":43,"stem":44},"Generated, copied and vendored files","\u002Fdocs\u002Fgenerated","docs\u002Fgenerated",{"title":46,"path":47,"stem":48},"Installing and updating cg","\u002Fdocs\u002Finstall","docs\u002Finstall",{"title":50,"path":51,"stem":52},"Java","\u002Fdocs\u002Fjava","docs\u002Fjava",{"title":54,"path":55,"stem":56},"Kotlin","\u002Fdocs\u002Fkotlin","docs\u002Fkotlin",{"title":58,"path":59,"stem":60},"Known limitations","\u002Fdocs\u002Flimitations","docs\u002Flimitations",{"title":62,"path":63,"stem":64,"children":65},"MCP server","\u002Fdocs\u002Fmcp","docs\u002Fmcp",[66],{"title":67,"path":68,"stem":69},"code-graph MCP: sample outputs (real calls via the MCP Python SDK stdio client)","\u002Fdocs\u002Fmcp\u002Fsample_outputs","docs\u002Fmcp\u002Fsample_outputs",{"title":71,"path":72,"stem":73},"Rust, C and C++","\u002Fdocs\u002Fnative","docs\u002Fnative",{"title":75,"path":76,"stem":77},"Port gaps: cg parity","\u002Fdocs\u002Fparity","docs\u002Fparity",{"title":79,"path":80,"stem":81},"PHP","\u002Fdocs\u002Fphp","docs\u002Fphp",{"title":83,"path":84,"stem":85},"Planned changes","\u002Fdocs\u002Fplans","docs\u002Fplans",{"title":87,"path":88,"stem":89},"Platform-specific code","\u002Fdocs\u002Fplatforms","docs\u002Fplatforms",{"title":91,"path":92,"stem":93},"Protocol links","\u002Fdocs\u002Fprotocols","docs\u002Fprotocols",{"title":95,"path":96,"stem":97},"Python","\u002Fdocs\u002Fpython","docs\u002Fpython",{"title":99,"path":100,"stem":101},"Quick start","\u002Fdocs\u002Fquickstart","docs\u002Fquickstart",{"title":103,"path":104,"stem":105},"Graph schema","\u002Fdocs\u002Fschema","docs\u002Fschema",{"title":107,"path":108,"stem":109},"Attack surface","\u002Fdocs\u002Fsurface","docs\u002Fsurface",{"title":111,"path":112,"stem":113},"Swift","\u002Fdocs\u002Fswift","docs\u002Fswift",{"title":115,"path":116,"stem":117},"TypeScript \u002F JavaScript frameworks","\u002Fdocs\u002Fts-frameworks","docs\u002Fts-frameworks",{"title":119,"path":120,"stem":121},"How we validate","\u002Fdocs\u002Fvalidation","docs\u002Fvalidation",{"title":123,"path":124,"stem":125},"Validation log","\u002Fdocs\u002Fvalidation-log","docs\u002Fvalidation-log",{"title":127,"path":128,"stem":129},"Value facts and resolutions","\u002Fdocs\u002Fvalue-facts","docs\u002Fvalue-facts",{"title":131,"path":132,"stem":133},"Visual view","\u002Fdocs\u002Fviz","docs\u002Fviz",false,{"id":136,"title":75,"body":137,"description":752,"extension":753,"meta":754,"navigation":755,"path":76,"seo":756,"stem":77,"__hash__":757},"docs\u002Fdocs\u002Fparity.md",{"type":138,"value":139,"toc":742},"minimark",[140,148,158,165,170,187,237,241,251,392,399,406,412,501,519,555,559,614,618,621,668,671,698,711,723],[141,142,143,147],"p",{},[144,145,146],"code",{},"cg parity"," compares two graphs of the same app on two platforms (an iOS app in Swift \u002F SwiftUI\nand its Android port in Kotlin \u002F Compose). It lists types, functions, enum cases and constants\nof the source graph that have no counterpart in the target.",[149,150,156],"pre",{"className":151,"code":153,"language":154,"meta":155},[152],"language-text","$ cg index immuni-app-ios --db out\u002Fios.db && cg index immuni-app-android --db out\u002Fandroid.db\n$ cg parity --db out\u002Fios.db --against out\u002Fandroid.db\nparity: out\u002Fios.db -> out\u002Fandroid.db\n1378 source symbols: 193 matched (exact 157, normalized 36), 1180 missing, 5 unknown\n","text","",[144,157,153],{"__ignoreMap":155},[141,159,160,161,164],{},"Run both directions. ",[144,162,163],{},"--db A --against B"," lists what B lacks.",[166,167,169],"h2",{"id":168},"what-is-compared","What is compared",[171,172,173,177,184],"ul",{},[174,175,176],"li",{},"Types: class, struct, enum, protocol, interface, object, actor.",[174,178,179,180,183],{},"Members of matched types: methods, properties, enum cases, constants, Kotlin nested sealed\nobjects (",[144,181,182],{},"data object DeleteClick",").",[174,185,186],{},"Top-level functions and constants.",[141,188,189,190,193,194,197,198,201,202,205,206,209,210,213,214,217,218,201,221,224,225,201,228,201,231,201,234,183],{},"Left out, and counted in ",[144,191,192],{},"--json"," ",[144,195,196],{},"summary",": test and mock folders (",[144,199,200],{},"TestHelpers\u002F",", ",[144,203,204],{},"Mock*"," \u002F\n",[144,207,208],{},"Fake*"," \u002F ",[144,211,212],{},"Stub*","); Swift ",[144,215,216],{},"Has*"," service-locator protocols; extension and companion-object\nnodes (members stay on the type); overrides (",[144,219,220],{},"viewDidLoad",[144,222,223],{},"onCreate","); boilerplate (",[144,226,227],{},"body",[144,229,230],{},"init",[144,232,233],{},"hash",[144,235,236],{},"description",[166,238,240],{"id":239},"how-a-counterpart-is-found","How a counterpart is found",[141,242,243,244,246,247,250],{},"First match wins. ",[144,245,192],{}," records ",[144,248,249],{},"confidence",".",[252,253,254,266],"table",{},[255,256,257],"thead",{},[258,259,260,263],"tr",{},[261,262,249],"th",{},[261,264,265],{},"rule",[267,268,269,295,305,361,382],"tbody",{},[258,270,271,277],{},[272,273,274],"td",{},[144,275,276],{},"explicit",[272,278,279,280,201,283,286,287,290,291,294],{},"a comment above either declaration (",[144,281,282],{},"\u002F\u002F\u002F Port of: FooView",[144,284,285],{},"\u002F\u002F Android: FooScreen","), or ",[144,288,289],{},"--map renames.json"," (",[144,292,293],{},"{\"source\": \"target\"}",")",[258,296,297,302],{},[272,298,299],{},[144,300,301],{},"exact",[272,303,304],{},"same name, same category. Members need the same name inside the matched type",[258,306,307,312],{},[272,308,309],{},[144,310,311],{},"normalized",[272,313,314,315,318,319,209,322,209,325,209,328,331,332,335,336,331,339,342,343,345,346,349,350,353,354,201,357,360],{},"case and ",[144,316,317],{},"_"," folded; ",[144,320,321],{},"Default",[144,323,324],{},"Impl",[144,326,327],{},"Json",[144,329,330],{},"RequestModel"," and ",[144,333,334],{},"--strip-prefix"," words dropped; ",[144,337,338],{},"VM",[144,340,341],{},"Processor"," read as ViewModel; UI suffixes stripped only when both names have one; word order may differ; a SwiftUI type with ",[144,344,227],{}," matches a ",[144,347,348],{},"@Composable"," of the same stem; member ",[144,351,352],{},"get"," prefixes and event verbs (",[144,355,356],{},"deletePressed",[144,358,359],{},"DeleteClick",") dropped",[258,362,363,368],{},[272,364,365],{},[144,366,367],{},"fuzzy",[272,369,370,371,209,374,377,378,381],{},"one word shortened or pluralised (",[144,372,373],{},"ItemList",[144,375,376],{},"ItemListing","). One extra word is not a match. ",[144,379,380],{},"--no-fuzzy"," turns this off",[258,383,384,389],{},[272,385,386],{},[144,387,388],{},"moved",[272,390,391],{},"a member of three or more words, missing on the counterpart type, present on exactly one other target type",[141,393,394,395,398],{},"A nested type is looked for inside its owner's counterpart. Anywhere else it matches by exact\nname only, so a generic ",[144,396,397],{},"Keys"," does not meet an unrelated type.",[166,400,402,403,294],{"id":401},"structure-structure","Structure (",[144,404,405],{},"--structure",[141,407,408,409,183],{},"Off by default. With it, symbols still missing after the name rules are paired by what they use\n(",[144,410,411],{},"cg_code_graph\u002Fparity_structure.py",[252,413,414,424],{},[255,415,416],{},[258,417,418,421],{},[261,419,420],{},"feature",[261,422,423],{},"from",[267,425,426,451,461,471,481,491],{},[258,427,428,433],{},[272,429,430],{},[144,431,432],{},"l10n:\u003Ckey>",[272,434,435,201,438,201,441,201,444,447,448,450],{},[144,436,437],{},"Localizations",[144,439,440],{},"L10n",[144,442,443],{},"R.string",[144,445,446],{},"CommonStrings"," (case and ",[144,449,317],{}," folded)",[258,452,453,458],{},[272,454,455],{},[144,456,457],{},"str:\u003Ctext>",[272,459,460],{},"string literals of 5–80 characters",[258,462,463,468],{},[272,464,465],{},[144,466,467],{},"http:\u003Cpath>",[272,469,470],{},"HTTP paths, parameters folded",[258,472,473,478],{},[272,474,475],{},[144,476,477],{},"sym:\u003Ctarget>",[272,479,480],{},"calls already paired, renamed to the target's name",[258,482,483,488],{},[272,484,485],{},[144,486,487],{},"call:\u003Cname>",[272,489,490],{},"member names it calls (two words or more)",[258,492,493,498],{},[272,494,495],{},[144,496,497],{},"w:\u003Cstem>",[272,499,500],{},"stemmed words of its own name",[141,502,503,504,507,508,511,512,514,515,518],{},"Two symbols pair when they share a use and either two uses or two name words, the cosine of\ntheir features is at least 0.3, each is the other's best candidate, and the runner-up is below\n0.8 of the best. Category and UI-ness must agree. A ",[144,505,506],{},"Coordinator"," does not meet a ",[144,509,510],{},"State",";\n",[144,513,341],{}," meets ",[144,516,517],{},"ViewModel",". Compose previews are left out.",[141,520,521,522,524,525,528,529,532,533,536,537,540,541,544,545,548,549,552,553,250],{},"A word rewrite seen at least twice, and in two thirds of the pairs with that tail (\n",[144,523,506],{}," → ",[144,526,527],{},"Navigator","), is applied to the rest (",[144,530,531],{},"learned","). ",[144,534,535],{},"--no-learn"," turns that\noff. Inferred matches are an ",[144,538,539],{},"== INFERRED"," section (",[144,542,543],{},"summary.inferred","), never name matches.\n",[144,546,547],{},"--write-map FILE"," writes a ",[144,550,551],{},"--map"," to review; fed back, those rows become ",[144,554,276],{},[166,556,558],{"id":557},"buckets","Buckets",[252,560,561,571],{},[255,562,563],{},[258,564,565,568],{},[261,566,567],{},"bucket",[261,569,570],{},"meaning",[267,572,573,585,598],{},[258,574,575,578],{},[272,576,577],{},"missing",[272,579,580,581,584],{},"no counterpart. Grouped by folder (a Gradle ",[144,582,583],{},"src\u002Fmain\u002Fkotlin\u002F"," path by package)",[258,586,587,590],{},[272,588,589],{},"unknown",[272,591,592,593,597],{},"the file parsed with syntax errors (",[594,595,596],"a",{"href":31},"Completeness","), so it is not \"missing\"",[258,599,600,603],{},[272,601,602],{},"platform_only",[272,604,605,606,609,610,613],{},"tagged only for platforms the target graph does not build (",[594,607,608],{"href":88},"Platforms","), other than the source app's own platform. A tag on at least half the source symbols is the app itself, so that tag is compared like untagged code. A ",[144,611,612],{},"watchos","-only widget stays platform-only",[166,615,617],{"id":616},"how-far-to-trust-missing","How far to trust \"missing\"",[141,619,620],{},"A counterpart with a different name and a different shape is reported missing. Hand-checked\nsamples of 20 \"missing\" rows on Bitwarden (bitwarden\u002Fios, bitwarden\u002Fandroid):",[252,622,623,638],{},[255,624,625],{},[258,626,627,630,633,635],{},[261,628,629],{},"direction",[261,631,632],{},"symbols",[261,634,577],{},[261,636,637],{},"false \"missing\" in the sample",[267,639,640,654],{},[258,641,642,645,648,651],{},[272,643,644],{},"iOS → Android",[272,646,647],{},"3735",[272,649,650],{},"3048",[272,652,653],{},"6 \u002F 20",[258,655,656,659,662,665],{},[272,657,658],{},"Android → iOS",[272,660,661],{},"8177",[272,663,664],{},"7661",[272,666,667],{},"2 \u002F 20",[141,669,670],{},"The false rows fall into three groups:",[171,672,673,683,692],{},[174,674,675,676,679,680,250],{},"Behaviour under another name:\n",[144,677,678],{},"CompleteRegistrationProcessor.checkPasswordAndCompleteRegistration"," ↔\n",[144,681,682],{},"CompleteRegistrationViewModel.handleCallToAction",[174,684,685,686,679,689,250],{},"Moved and renamed: ",[144,687,688],{},"AuthService.getPendingLoginRequest",[144,690,691],{},"AuthRequestManager.getAuthRequestById",[174,693,694,695,250],{},"A SwiftUI subview written as a Compose function: ",[144,696,697],{},"GeneratorView.generatedValueView",[141,699,700,701,704,705,707,708,710],{},"The real gaps in those samples were platform-only code (watchOS, CryptoKit, Compose saved-state\nkeys) and shapes the other side models differently (a result type returned as ",[144,702,703],{},"Bool",", a\nper-screen dialog state). Read the list as \"no counterpart with a related name\". Use ",[144,706,551],{}," and\n",[144,709,334],{}," for systematic renames.",[141,712,713,714,716,717,719,720,250],{},"With ",[144,715,405],{}," (October 2026): Bitwarden inferred 101 and 124 matches; a sample of 20 was\nmostly right where the apps share a localization key, and a separate sample of 20 still-missing\nsymbols had no match either way. Element X Android → iOS inferred 91 (about 16\u002F20 right).\nElement X iOS → Android inferred 83; before the platform-tag fix, 3,551 of 4,184 iOS symbols\nwere ",[144,718,602],{}," because they are tagged ",[144,721,722],{},"ios",[141,724,725,727,728,201,731,201,733,201,735,201,737,707,740,250],{},[144,726,192],{}," returns ",[144,729,730],{},"matched",[144,732,577],{},[144,734,589],{},[144,736,602],{},[144,738,739],{},"learned_rules",[144,741,196],{},{"title":155,"searchDepth":743,"depth":744,"links":745},4,2,[746,747,748,750,751],{"id":168,"depth":744,"text":169},{"id":239,"depth":744,"text":240},{"id":401,"depth":744,"text":749},"Structure (--structure)",{"id":557,"depth":744,"text":558},{"id":616,"depth":744,"text":617},"cg parity compares two graphs of the same app on two platforms (an iOS app in Swift \u002F SwiftUI\nand its Android port in Kotlin \u002F Compose). It lists types, functions, enum cases and constants\nof the source graph that have no counterpart in the target.","md",{},true,{"title":75,"description":752},"-qMKpYt_rPVDsTHkC11bhpDj8qJqMgjEAPVRlDinB4c",[759,761],{"title":71,"path":72,"stem":73,"description":760,"children":-1},"What Rust, C, and C++ add beyond Install, CLI specs, and Graph schema: heuristic vs rust-analyzer \u002F scip-clang, the indexer flags, and the ids those pages do not spell out. Toolchain fit: cg doctor -h. Why a file stayed heuristic: cg coverage.",{"title":79,"path":80,"stem":81,"description":155,"children":-1},1792170234608]