[{"data":1,"prerenderedAt":6482},["ShallowReactive",2],{"navigation":3,"api-navigation":184,"\u002Flearn\u002Ftutorials\u002Fproduction-patterns":206,"docyard:crossref-index":6481},[4,8,155,174,180],{"title":5,"path":6,"stem":7},"Getting Started","\u002Fgetting-started","1.getting-started",{"title":9,"path":10,"stem":11,"children":12},"Learn","\u002Flearn","2.learn",[13,15,66,99,133],{"title":9,"path":10,"stem":14},"2.learn\u002Findex",{"title":16,"path":17,"stem":18,"children":19},"Tutorials","\u002Flearn\u002Ftutorials","2.learn\u002F1.tutorials\u002Findex",[20,21,26,30,34,38,42,46,50,54,58,62],{"title":16,"path":17,"stem":18},{"title":22,"path":23,"stem":24,"icon":25},"Why Laco?","\u002Flearn\u002Ftutorials\u002Fwhy-laco","2.learn\u002F1.tutorials\u002F01.why-laco","i-lucide-notebook",{"title":27,"path":28,"stem":29,"icon":25},"First Steps with Laco","\u002Flearn\u002Ftutorials\u002Ffirst-steps","2.learn\u002F1.tutorials\u002F02.first-steps",{"title":31,"path":32,"stem":33,"icon":25},"Lazy Call and Partial","\u002Flearn\u002Ftutorials\u002Flazy-call-and-partial","2.learn\u002F1.tutorials\u002F03.lazy-call-and-partial",{"title":35,"path":36,"stem":37,"icon":25},"Hyperparameters and Interpolation","\u002Flearn\u002Ftutorials\u002Fhyperparameters-and-interpolation","2.learn\u002F1.tutorials\u002F04.hyperparameters-and-interpolation",{"title":39,"path":40,"stem":41,"icon":25},"Loading, Saving, and the CLI","\u002Flearn\u002Ftutorials\u002Floading-saving-cli","2.learn\u002F1.tutorials\u002F05.loading-saving-cli",{"title":43,"path":44,"stem":45,"icon":25},"Nested Configs and Containers","\u002Flearn\u002Ftutorials\u002Fnested-configs-and-containers","2.learn\u002F1.tutorials\u002F06.nested-configs-and-containers",{"title":47,"path":48,"stem":49,"icon":25},"Typed Groups and Schemas","\u002Flearn\u002Ftutorials\u002Ftyped-groups-and-schemas","2.learn\u002F1.tutorials\u002F07.typed-groups-and-schemas",{"title":51,"path":52,"stem":53,"icon":25},"Pipeline Configs","\u002Flearn\u002Ftutorials\u002Fpipeline-configs","2.learn\u002F1.tutorials\u002F08.pipeline-configs",{"title":55,"path":56,"stem":57,"icon":25},"Tasks and the App Loop","\u002Flearn\u002Ftutorials\u002Ftasks-and-app-loop","2.learn\u002F1.tutorials\u002F09.tasks-and-app-loop",{"title":59,"path":60,"stem":61,"icon":25},"Tracing","\u002Flearn\u002Ftutorials\u002Ftracing","2.learn\u002F1.tutorials\u002F10.tracing",{"title":63,"path":64,"stem":65,"icon":25},"Production Patterns","\u002Flearn\u002Ftutorials\u002Fproduction-patterns","2.learn\u002F1.tutorials\u002F11.production-patterns",{"title":67,"path":68,"stem":69,"children":70},"Concepts","\u002Flearn\u002Fconcepts","2.learn\u002F2.concepts\u002Findex",[71,72,76,80,84,88,92,95],{"title":67,"path":68,"stem":69},{"title":73,"path":74,"stem":75},"Config as Python","\u002Flearn\u002Fconcepts\u002Fconfig-as-python","2.learn\u002F2.concepts\u002F1.config-as-python",{"title":77,"path":78,"stem":79},"Lazy Construction","\u002Flearn\u002Fconcepts\u002Flazy-construction","2.learn\u002F2.concepts\u002F2.lazy-construction",{"title":81,"path":82,"stem":83},"Lie-Typing","\u002Flearn\u002Fconcepts\u002Flie-typing","2.learn\u002F2.concepts\u002F3.lie-typing",{"title":85,"path":86,"stem":87},"Interpolation","\u002Flearn\u002Fconcepts\u002Finterpolation","2.learn\u002F2.concepts\u002F4.interpolation",{"title":89,"path":90,"stem":91},"Typed Groups","\u002Flearn\u002Fconcepts\u002Ftyped-groups","2.learn\u002F2.concepts\u002F5.typed-groups",{"title":59,"path":93,"stem":94},"\u002Flearn\u002Fconcepts\u002Ftracing","2.learn\u002F2.concepts\u002F6.tracing",{"title":96,"path":97,"stem":98},"App Loop","\u002Flearn\u002Fconcepts\u002Fapp-loop","2.learn\u002F2.concepts\u002F7.app-loop",{"title":100,"path":101,"stem":102,"children":103},"How-To Guides","\u002Flearn\u002Fhow-to","2.learn\u002F3.how-to\u002Findex",[104,105,109,113,117,121,125,129],{"title":100,"path":101,"stem":102},{"title":106,"path":107,"stem":108},"Override Configs","\u002Flearn\u002Fhow-to\u002Foverride-configs","2.learn\u002F3.how-to\u002F1.override-configs",{"title":110,"path":111,"stem":112},"Safe Loading","\u002Flearn\u002Fhow-to\u002Fsafe-loading","2.learn\u002F3.how-to\u002F2.safe-loading",{"title":114,"path":115,"stem":116},"Custom Resolvers","\u002Flearn\u002Fhow-to\u002Fcustom-resolvers","2.learn\u002F3.how-to\u002F3.custom-resolvers",{"title":118,"path":119,"stem":120},"Lint and Strict Mode","\u002Flearn\u002Fhow-to\u002Flint-and-strict","2.learn\u002F3.how-to\u002F4.lint-and-strict",{"title":122,"path":123,"stem":124},"Publishing a reproducible app with laco app","\u002Flearn\u002Fhow-to\u002Flaco-app","2.learn\u002F3.how-to\u002F5.laco-app",{"title":126,"path":127,"stem":128},"Reproduce an Experiment","\u002Flearn\u002Fhow-to\u002Freproduce-experiment","2.learn\u002F3.how-to\u002F6.reproduce-experiment",{"title":130,"path":131,"stem":132},"Migrate from argparse","\u002Flearn\u002Fhow-to\u002Fmigrate-from-argparse","2.learn\u002F3.how-to\u002F7.migrate-from-argparse",{"title":134,"path":135,"stem":136,"children":137},"Examples Curriculum","\u002Flearn\u002Fexamples","2.learn\u002F4.examples\u002Findex",[138,139,143,147,151],{"title":134,"path":135,"stem":136},{"title":140,"path":141,"stem":142},"Foundation Examples","\u002Flearn\u002Fexamples\u002Ffoundations","2.learn\u002F4.examples\u002F1.foundations",{"title":144,"path":145,"stem":146},"Building Blocks","\u002Flearn\u002Fexamples\u002Fbuilding-blocks","2.learn\u002F4.examples\u002F2.building-blocks",{"title":148,"path":149,"stem":150},"Typed-Group Variants","\u002Flearn\u002Fexamples\u002Ftyped-variants","2.learn\u002F4.examples\u002F3.typed-variants",{"title":152,"path":153,"stem":154},"End-to-End Pipelines","\u002Flearn\u002Fexamples\u002Fpipelines","2.learn\u002F4.examples\u002F4.pipelines",{"title":156,"path":157,"stem":158,"children":159},"Resources","\u002Fresources","3.resources",[160,162,166,170],{"title":156,"path":157,"stem":161},"3.resources\u002Findex",{"title":163,"path":164,"stem":165},"Integrations","\u002Fresources\u002Fintegrations","3.resources\u002F1.integrations",{"title":167,"path":168,"stem":169},"Migration guide: Laco 0.x → 1.0","\u002Fresources\u002Fmigration-0.x-to-1.0","3.resources\u002F2.migration-0.x-to-1.0",{"title":171,"path":172,"stem":173},"Laco vs hydra-zen","\u002Fresources\u002Flaco-vs-hydra-zen","3.resources\u002F3.laco-vs-hydra-zen",{"title":175,"path":176,"stem":177,"children":178},"API Reference","\u002Fapi","4.api\u002Findex",[179],{"title":175,"path":176,"stem":177},{"title":181,"path":182,"stem":183},"Lazy Configuration for Python","\u002F","index",[185,188,191,194,197,200,203],{"title":186,"path":187},"cli","\u002Fapi\u002Fcli",{"title":189,"path":190},"compat","\u002Fapi\u002Fcompat",{"title":192,"path":193},"handler","\u002Fapi\u002Fhandler",{"title":195,"path":196},"keys","\u002Fapi\u002Fkeys",{"title":198,"path":199},"language","\u002Fapi\u002Flanguage",{"title":201,"path":202},"ops","\u002Fapi\u002Fops",{"title":204,"path":205},"utils","\u002Fapi\u002Futils",{"id":207,"title":63,"body":208,"description":6475,"extension":6476,"meta":6477,"navigation":6478,"path":64,"seo":6479,"stem":65,"__hash__":6480},"content\u002F2.learn\u002F1.tutorials\u002F11.production-patterns.md",{"type":209,"value":210,"toc":6432},"minimark",[211,215,248,251,254,335,396,401,415,418,577,589,593,611,624,960,965,1138,1141,1146,1413,1425,1432,1452,1455,1477,1814,1817,1901,1904,1910,1961,1966,1974,1996,2003,2176,2179,2417,2420,2427,2463,2476,2488,2495,2512,2523,3017,3020,3062,3065,3072,3095,3109,3116,3129,3138,3347,3350,3434,3437,3441,3451,3470,3477,3487,3506,3940,3943,4114,4117,4123,4131,4459,4462,4468,4478,4684,4687,4691,4705,5287,5290,5729,5732,5942,5945,5949,5952,5956,5981,5985,5998,6002,6030,6034,6082,6086,6293,6297,6300,6420,6422,6428],[212,213,63],"h1",{"id":214},"production-patterns",[216,217,218,222,223,226,229,230,234,235,238,239,241,244,245],"p",{},[219,220,221],"strong",{},"Series:"," laco tutorial notebooks",[224,225],"br",{},[219,227,228],{},"Prerequisites:"," All prior notebooks (",[231,232,233],"code",{},"01.why-laco.ipynb"," through ",[231,236,237],{},"10.tracing.ipynb",")",[224,240],{},[219,242,243],{},"Dependencies:"," ",[231,246,247],{},"torch",[249,250],"hr",{},[216,252,253],{},"This final notebook consolidates everything into the patterns you'll actually use in production:",[255,256,257,261,271,277,287,294,300,320,323,326],"ol",{},[258,259,260],"li",{},"The complete laco mental model: all six constructs in one reference table",[258,262,263,264,267,268],{},"Experiment reproducibility with ",[231,265,266],{},"laco.save"," \u002F ",[231,269,270],{},"laco.load",[258,272,273,276],{},[231,274,275],{},"LACO_STRICT_NODES"," for catching attribute-access bugs during development",[258,278,279,282,283,286],{},[231,280,281],{},"laco-lint"," and the ",[231,284,285],{},"LACO001"," lint code",[258,288,289,290,293],{},"The ",[231,291,292],{},"migrate_target"," hook for renaming classes across releases",[258,295,296,299],{},[231,297,298],{},"laco.compat",": auto-install backward-compatibility shims",[258,301,302,303,306,307,310,311,310,314,310,317],{},"Advanced ",[231,304,305],{},"L.Group"," patterns: ",[231,308,309],{},"bind_strict",", ",[231,312,313],{},"L.use",[231,315,316],{},"mode=\"extend\"",[231,318,319],{},"L.delete",[258,321,322],{},"A full production config pattern",[258,324,325],{},"What to read next",[258,327,328,329,331,332],{},"Series summary: the full learning path from ",[231,330,233],{}," to ",[231,333,334],{},"11.production-patterns.ipynb",[336,337,342],"pre",{"className":338,"code":339,"language":340,"meta":341,"style":341},"language-python shiki shiki-themes material-theme-lighter github-light github-dark","import laco\nimport laco.language as L\nimport torch.nn as nn\n","python","",[231,343,344,357,378],{"__ignoreMap":341},[345,346,349,353],"span",{"class":347,"line":348},"line",1,[345,350,352],{"class":351},"sVHd0","import",[345,354,356],{"class":355},"su5hD"," laco\n",[345,358,360,362,365,369,372,375],{"class":347,"line":359},2,[345,361,352],{"class":351},[345,363,364],{"class":355}," laco",[345,366,368],{"class":367},"sP7_E",".",[345,370,198],{"class":371},"skxfh",[345,373,374],{"class":351}," as",[345,376,377],{"class":355}," L\n",[345,379,381,383,386,388,391,393],{"class":347,"line":380},3,[345,382,352],{"class":351},[345,384,385],{"class":355}," torch",[345,387,368],{"class":367},[345,389,390],{"class":371},"nn",[345,392,374],{"class":351},[345,394,395],{"class":355}," nn\n",[397,398,400],"h2",{"id":399},"section-1-the-complete-laco-mental-model","Section 1: The complete laco mental model",[216,402,403,404,407,408,411,412,368],{},"The core of laco is a set of constructs that lie to your type checker. Each one presents itself as an ordinary Python object at IDE\u002Fpyright time, but produces a ",[231,405,406],{},"DictConfig"," (or related sentinel) at runtime. This is the ",[219,409,410],{},"lie-typing contract"," documented throughout ",[231,413,414],{},"laco.language",[216,416,417],{},"Here is the complete reference table:",[419,420,421,440],"table",{},[422,423,424],"thead",{},[425,426,427,431,434,437],"tr",{},[428,429,430],"th",{},"Construct",[428,432,433],{},"Static type (IDE sees)",[428,435,436],{},"Runtime value",[428,438,439],{},"Primary use case",[441,442,443,464,487,507,526,548],"tbody",{},[425,444,445,451,456,461],{},[446,447,448],"td",{},[231,449,450],{},"L.call(T)(**kw)",[446,452,453],{},[231,454,455],{},"T",[446,457,458],{},[231,459,460],{},"DictConfig{ _target_: T, **kw }",[446,462,463],{},"Lazy construction of any object",[425,465,466,471,476,481],{},[446,467,468],{},[231,469,470],{},"L.partial(fn)(**kw)",[446,472,473],{},[231,474,475],{},"functools.partial[T]",[446,477,478],{},[231,479,480],{},"DictConfig{ _partial_: true, **kw }",[446,482,483,484,238],{},"Deferred construction (e.g. optimizer needing ",[231,485,486],{},"model.parameters()",[425,488,489,494,499,504],{},[446,490,491],{},[231,492,493],{},"L.just(obj)",[446,495,496],{},[231,497,498],{},"type(obj)",[446,500,501],{},[231,502,503],{},"DictConfig{ _target_: laco.ops.identity, value: obj }",[446,505,506],{},"Embed an existing in-memory value in a config tree",[425,508,509,514,518,523],{},[446,510,511],{},[231,512,513],{},"L.required[T]()",[446,515,516],{},[231,517,455],{},[446,519,520],{},[231,521,522],{},"omegaconf.MISSING",[446,524,525],{},"Mandatory field with no default — must be overridden before instantiate",[425,527,528,533,539,545],{},[446,529,530],{},[231,531,532],{},"L.chosen(G)",[446,534,535,538],{},[231,536,537],{},"G","'s element type",[446,540,541,544],{},[231,542,543],{},"\"${package}\""," interpolation string",[446,546,547],{},"In-schema reference to whichever group entry is selected",[425,549,550,559,565,574],{},[446,551,552,555,556,238],{},[231,553,554],{},"@L.configurable"," (inside ",[231,557,558],{},"L.trace",[446,560,561,564],{},[231,562,563],{},"Callable[P, R]"," (unchanged)",[446,566,567,569,570,573],{},[231,568,406],{}," node (not a live ",[231,571,572],{},"R","!)",[446,575,576],{},"Trace-based config capture — reads like normal Python",[216,578,579,582,583,585,586,368],{},[219,580,581],{},"The contract in one sentence:"," every laco construct makes the IDE believe you have a live Python object, while actually giving you a serializable ",[231,584,406],{}," that can be saved, overridden, swept, and eventually materialized into the real object by ",[231,587,588],{},"laco.instantiate",[397,590,592],{"id":591},"section-2-experiment-reproducibility","Section 2: Experiment reproducibility",[216,594,595,596,600,601,604,605,607,608,610],{},"Reproducibility requires saving the ",[597,598,599],"em",{},"exact"," config before a run begins: all ",[231,602,603],{},"_target_"," strings, hyperparameter values, and group selections. laco provides ",[231,606,266],{}," and ",[231,609,270],{}," for this purpose.",[216,612,613,616,617,619,620,623],{},[231,614,615],{},"laco.save(cfg, path)"," serializes to YAML and returns the reloaded config (by default). The YAML is fully self-contained: it contains all ",[231,618,603],{}," paths needed to reconstruct the experiment without the original ",[231,621,622],{},".py"," config file.",[336,625,627],{"className":338,"code":626,"language":340,"meta":341,"style":341},"import pathlib\nimport tempfile\n\n# Load the MNIST training config (fast — no MNIST download).\n#\n# We load the WHOLE config file (every `__all__` export) rather than just the\n# `#train` subtree. The components in `train` interpolate hyperparameters via\n# `${hps.batch_size}` etc., and those `${hps.*}` references only resolve when the\n# `hps` node is a SIBLING in the same config tree. `laco.load(file)` bundles all\n# exports into one root tree, so `hps` travels alongside `train` and the saved\n# YAML is fully self-contained. (Saving the bare `#train` fragment would strip\n# `hps`, leaving dangling interpolations that break on reload.)\ncfg = laco.load(\"configs:\u002F\u002Fexamples\u002Fpipelines\u002Fmnist_train.py\")\n\n# Create a run directory and save the config\nrun_dir = pathlib.Path(tempfile.mkdtemp())\nsaved   = laco.save(cfg, run_dir \u002F \"config.yaml\")\nprint(f\"Config saved to: {run_dir \u002F 'config.yaml'}\")\nprint()\n\n# Peek at the saved YAML\nyaml_content = (run_dir \u002F \"config.yaml\").read_text()\nprint(\"=== Saved config.yaml (first 60 lines) ===\")\nfor line in yaml_content.splitlines()[:60]:\n    print(line)\n",[231,628,629,636,643,649,656,662,668,674,680,686,692,698,704,738,743,749,778,816,855,863,868,874,903,919,948],{"__ignoreMap":341},[345,630,631,633],{"class":347,"line":348},[345,632,352],{"class":351},[345,634,635],{"class":355}," pathlib\n",[345,637,638,640],{"class":347,"line":359},[345,639,352],{"class":351},[345,641,642],{"class":355}," tempfile\n",[345,644,645],{"class":347,"line":380},[345,646,648],{"emptyLinePlaceholder":647},true,"\n",[345,650,652],{"class":347,"line":651},4,[345,653,655],{"class":654},"sutJx","# Load the MNIST training config (fast — no MNIST download).\n",[345,657,659],{"class":347,"line":658},5,[345,660,661],{"class":654},"#\n",[345,663,665],{"class":347,"line":664},6,[345,666,667],{"class":654},"# We load the WHOLE config file (every `__all__` export) rather than just the\n",[345,669,671],{"class":347,"line":670},7,[345,672,673],{"class":654},"# `#train` subtree. The components in `train` interpolate hyperparameters via\n",[345,675,677],{"class":347,"line":676},8,[345,678,679],{"class":654},"# `${hps.batch_size}` etc., and those `${hps.*}` references only resolve when the\n",[345,681,683],{"class":347,"line":682},9,[345,684,685],{"class":654},"# `hps` node is a SIBLING in the same config tree. `laco.load(file)` bundles all\n",[345,687,689],{"class":347,"line":688},10,[345,690,691],{"class":654},"# exports into one root tree, so `hps` travels alongside `train` and the saved\n",[345,693,695],{"class":347,"line":694},11,[345,696,697],{"class":654},"# YAML is fully self-contained. (Saving the bare `#train` fragment would strip\n",[345,699,701],{"class":347,"line":700},12,[345,702,703],{"class":654},"# `hps`, leaving dangling interpolations that break on reload.)\n",[345,705,707,710,714,716,718,722,725,729,733,735],{"class":347,"line":706},13,[345,708,709],{"class":355},"cfg ",[345,711,713],{"class":712},"smGrS","=",[345,715,364],{"class":355},[345,717,368],{"class":367},[345,719,721],{"class":720},"slqww","load",[345,723,724],{"class":367},"(",[345,726,728],{"class":727},"sjJ54","\"",[345,730,732],{"class":731},"s_sjI","configs:\u002F\u002Fexamples\u002Fpipelines\u002Fmnist_train.py",[345,734,728],{"class":727},[345,736,737],{"class":367},")\n",[345,739,741],{"class":347,"line":740},14,[345,742,648],{"emptyLinePlaceholder":647},[345,744,746],{"class":347,"line":745},15,[345,747,748],{"class":654},"# Create a run directory and save the config\n",[345,750,752,755,757,760,762,765,767,770,772,775],{"class":347,"line":751},16,[345,753,754],{"class":355},"run_dir ",[345,756,713],{"class":712},[345,758,759],{"class":355}," pathlib",[345,761,368],{"class":367},[345,763,764],{"class":720},"Path",[345,766,724],{"class":367},[345,768,769],{"class":720},"tempfile",[345,771,368],{"class":367},[345,773,774],{"class":720},"mkdtemp",[345,776,777],{"class":367},"())\n",[345,779,781,784,786,788,790,793,795,798,801,804,806,809,812,814],{"class":347,"line":780},17,[345,782,783],{"class":355},"saved   ",[345,785,713],{"class":712},[345,787,364],{"class":355},[345,789,368],{"class":367},[345,791,792],{"class":720},"save",[345,794,724],{"class":367},[345,796,797],{"class":720},"cfg",[345,799,800],{"class":367},",",[345,802,803],{"class":720}," run_dir ",[345,805,182],{"class":712},[345,807,808],{"class":727}," \"",[345,810,811],{"class":731},"config.yaml",[345,813,728],{"class":727},[345,815,737],{"class":367},[345,817,819,823,825,829,832,836,838,840,843,845,848,851,853],{"class":347,"line":818},18,[345,820,822],{"class":821},"sptTA","print",[345,824,724],{"class":367},[345,826,828],{"class":827},"sbsja","f",[345,830,831],{"class":731},"\"Config saved to: ",[345,833,835],{"class":834},"srdBf","{",[345,837,754],{"class":720},[345,839,182],{"class":712},[345,841,842],{"class":727}," '",[345,844,811],{"class":731},[345,846,847],{"class":727},"'",[345,849,850],{"class":834},"}",[345,852,728],{"class":731},[345,854,737],{"class":367},[345,856,858,860],{"class":347,"line":857},19,[345,859,822],{"class":821},[345,861,862],{"class":367},"()\n",[345,864,866],{"class":347,"line":865},20,[345,867,648],{"emptyLinePlaceholder":647},[345,869,871],{"class":347,"line":870},21,[345,872,873],{"class":654},"# Peek at the saved YAML\n",[345,875,877,880,882,885,887,889,891,893,895,898,901],{"class":347,"line":876},22,[345,878,879],{"class":355},"yaml_content ",[345,881,713],{"class":712},[345,883,884],{"class":367}," (",[345,886,754],{"class":355},[345,888,182],{"class":712},[345,890,808],{"class":727},[345,892,811],{"class":731},[345,894,728],{"class":727},[345,896,897],{"class":367},").",[345,899,900],{"class":720},"read_text",[345,902,862],{"class":367},[345,904,906,908,910,912,915,917],{"class":347,"line":905},23,[345,907,822],{"class":821},[345,909,724],{"class":367},[345,911,728],{"class":727},[345,913,914],{"class":731},"=== Saved config.yaml (first 60 lines) ===",[345,916,728],{"class":727},[345,918,737],{"class":367},[345,920,922,925,928,931,934,936,939,942,945],{"class":347,"line":921},24,[345,923,924],{"class":351},"for",[345,926,927],{"class":355}," line ",[345,929,930],{"class":351},"in",[345,932,933],{"class":355}," yaml_content",[345,935,368],{"class":367},[345,937,938],{"class":720},"splitlines",[345,940,941],{"class":367},"()[:",[345,943,944],{"class":834},"60",[345,946,947],{"class":367},"]:\n",[345,949,951,954,956,958],{"class":347,"line":950},25,[345,952,953],{"class":821},"    print",[345,955,724],{"class":367},[345,957,347],{"class":720},[345,959,737],{"class":367},[961,962],"docyard-notebook-output",{"data":963,"kind":964},"Q29uZmlnIHNhdmVkIHRvOiAvdG1wL25peC1zaGVsbC54TUJYeVUvdG1weHVfOTRuMHgvY29uZmlnLnlhbWwKCj09PSBTYXZlZCBjb25maWcueWFtbCAoZmlyc3QgNjAgbGluZXMpID09PQpfbGFjb186IDEKZGF0YXNldDoKICBfY29udmVydF86IGFsbAogIF90YXJnZXRfOiB0b3JjaHZpc2lvbi5kYXRhc2V0cy5NTklTVAogIGRvd25sb2FkOiB0cnVlCiAgcm9vdDogJHtocHMuZGF0YV9yb290fQogIHRyYWluOiB0cnVlCiAgdHJhbnNmb3JtOgogICAgX2FyZ3NfOgogICAgLSBfY29udmVydF86IGFsbAogICAgICBfdGFyZ2V0XzogbGFjby5sYW5ndWFnZS5MaXN0LnRhcmdldAogICAgICBpdGVtczoKICAgICAgLSB7X2NvbnZlcnRfOiBhbGwsIF90YXJnZXRfOiB0b3JjaHZpc2lvbi50cmFuc2Zvcm1zLlRvVGVuc29yfQogICAgICAtIF9jb252ZXJ0XzogYWxsCiAgICAgICAgX3RhcmdldF86IHRvcmNodmlzaW9uLnRyYW5zZm9ybXMuTm9ybWFsaXplCiAgICAgICAgbWVhbjoKICAgICAgICAgIF9jb252ZXJ0XzogYWxsCiAgICAgICAgICBfdGFyZ2V0XzogbGFjby5sYW5ndWFnZS5MaXN0LnRhcmdldAogICAgICAgICAgaXRlbXM6IFswLjEzMDddCiAgICAgICAgc3RkOgogICAgICAgICAgX2NvbnZlcnRfOiBhbGwKICAgICAgICAgIF90YXJnZXRfOiBsYWNvLmxhbmd1YWdlLkxpc3QudGFyZ2V0CiAgICAgICAgICBpdGVtczogWzAuMzA4MV0KICAgIF9jb252ZXJ0XzogYWxsCiAgICBfdGFyZ2V0XzogdG9yY2h2aXNpb24udHJhbnNmb3Jtcy5Db21wb3NlCmhwczoge2Jhc2VfY2hhbm5lbHM6IDMyLCBiYXRjaF9zaXplOiA2NCwgZGF0YV9yb290OiAuL2RhdGEsIGluX2NoYW5uZWxzOiAxLCBsZWFybmluZ19yYXRlOiAwLjAwMSwKICBudW1fY2xhc3NlczogMTAsIG51bV9zdGFnZXM6IDMsIG51bV93b3JrZXJzOiAwfQpsb2FkZXI6CiAgX2NvbnZlcnRfOiBhbGwKICBfdGFyZ2V0XzogdG9yY2gudXRpbHMuZGF0YS5EYXRhTG9hZGVyCiAgYmF0Y2hfc2l6ZTogJHtocHMuYmF0Y2hfc2l6ZX0KICBkYXRhc2V0OgogICAgX2NvbnZlcnRfOiBhbGwKICAgIF90YXJnZXRfOiB0b3JjaHZpc2lvbi5kYXRhc2V0cy5NTklTVAogICAgZG93bmxvYWQ6IHRydWUKICAgIHJvb3Q6ICR7aHBzLmRhdGFfcm9vdH0KICAgIHRyYWluOiB0cnVlCiAgICB0cmFuc2Zvcm06CiAgICAgIF9hcmdzXzoKICAgICAgLSBfY29udmVydF86IGFsbAogICAgICAgIF90YXJnZXRfOiBsYWNvLmxhbmd1YWdlLkxpc3QudGFyZ2V0CiAgICAgICAgaXRlbXM6CiAgICAgICAgLSB7X2NvbnZlcnRfOiBhbGwsIF90YXJnZXRfOiB0b3JjaHZpc2lvbi50cmFuc2Zvcm1zLlRvVGVuc29yfQogICAgICAgIC0gX2NvbnZlcnRfOiBhbGwKICAgICAgICAgIF90YXJnZXRfOiB0b3JjaHZpc2lvbi50cmFuc2Zvcm1zLk5vcm1hbGl6ZQogICAgICAgICAgbWVhbjoKICAgICAgICAgICAgX2NvbnZlcnRfOiBhbGwKICAgICAgICAgICAgX3RhcmdldF86IGxhY28ubGFuZ3VhZ2UuTGlzdC50YXJnZXQKICAgICAgICAgICAgaXRlbXM6IFswLjEzMDddCiAgICAgICAgICBzdGQ6CiAgICAgICAgICAgIF9jb252ZXJ0XzogYWxsCiAgICAgICAgICAgIF90YXJnZXRfOiBsYWNvLmxhbmd1YWdlLkxpc3QudGFyZ2V0CiAgICAgICAgICAgIGl0ZW1zOiBbMC4zMDgxXQogICAgICBfY29udmVydF86IGFsbAogICAgICBfdGFyZ2V0XzogdG9yY2h2aXNpb24udHJhbnNmb3Jtcy5Db21wb3NlCiAgbnVtX3dvcmtlcnM6ICR7aHBzLm51bV93b3JrZXJzfQogIHNodWZmbGU6IHRydWUKbG9zczoge19jb252ZXJ0XzogYWxsLCBfdGFyZ2V0XzogdG9yY2gubm4uQ3Jvc3NFbnRyb3B5TG9zc30KbW9kZWw6CiAgX2FyZ3NfOgo=","stream",[336,966,968],{"className":338,"code":967,"language":340,"meta":341,"style":341},"# Reproduce: load from the saved YAML — no original .py file needed\ncfg_repro = laco.load(run_dir \u002F \"config.yaml\")\n\n# Verify the round-trip is perfect\nassert laco.dump(cfg) == laco.dump(cfg_repro), \"Round-trip mismatch!\"\nprint(\"Config round-trip verified.\")\nprint()\nprint(\"The saved YAML contains all _target_ strings needed to reproduce the experiment.\")\nprint(\"Share config.yaml alongside your model checkpoint for full reproducibility.\")\n\n# Cleanup\nimport shutil\nshutil.rmtree(run_dir)\n",[231,969,970,975,1002,1006,1011,1054,1069,1075,1090,1105,1109,1114,1121],{"__ignoreMap":341},[345,971,972],{"class":347,"line":348},[345,973,974],{"class":654},"# Reproduce: load from the saved YAML — no original .py file needed\n",[345,976,977,980,982,984,986,988,990,992,994,996,998,1000],{"class":347,"line":359},[345,978,979],{"class":355},"cfg_repro ",[345,981,713],{"class":712},[345,983,364],{"class":355},[345,985,368],{"class":367},[345,987,721],{"class":720},[345,989,724],{"class":367},[345,991,754],{"class":720},[345,993,182],{"class":712},[345,995,808],{"class":727},[345,997,811],{"class":731},[345,999,728],{"class":727},[345,1001,737],{"class":367},[345,1003,1004],{"class":347,"line":380},[345,1005,648],{"emptyLinePlaceholder":647},[345,1007,1008],{"class":347,"line":651},[345,1009,1010],{"class":654},"# Verify the round-trip is perfect\n",[345,1012,1013,1016,1018,1020,1023,1025,1027,1029,1032,1034,1036,1038,1040,1043,1046,1048,1051],{"class":347,"line":658},[345,1014,1015],{"class":351},"assert",[345,1017,364],{"class":355},[345,1019,368],{"class":367},[345,1021,1022],{"class":720},"dump",[345,1024,724],{"class":367},[345,1026,797],{"class":720},[345,1028,238],{"class":367},[345,1030,1031],{"class":712}," ==",[345,1033,364],{"class":355},[345,1035,368],{"class":367},[345,1037,1022],{"class":720},[345,1039,724],{"class":367},[345,1041,1042],{"class":720},"cfg_repro",[345,1044,1045],{"class":367},"),",[345,1047,808],{"class":727},[345,1049,1050],{"class":731},"Round-trip mismatch!",[345,1052,1053],{"class":727},"\"\n",[345,1055,1056,1058,1060,1062,1065,1067],{"class":347,"line":664},[345,1057,822],{"class":821},[345,1059,724],{"class":367},[345,1061,728],{"class":727},[345,1063,1064],{"class":731},"Config round-trip verified.",[345,1066,728],{"class":727},[345,1068,737],{"class":367},[345,1070,1071,1073],{"class":347,"line":670},[345,1072,822],{"class":821},[345,1074,862],{"class":367},[345,1076,1077,1079,1081,1083,1086,1088],{"class":347,"line":676},[345,1078,822],{"class":821},[345,1080,724],{"class":367},[345,1082,728],{"class":727},[345,1084,1085],{"class":731},"The saved YAML contains all _target_ strings needed to reproduce the experiment.",[345,1087,728],{"class":727},[345,1089,737],{"class":367},[345,1091,1092,1094,1096,1098,1101,1103],{"class":347,"line":682},[345,1093,822],{"class":821},[345,1095,724],{"class":367},[345,1097,728],{"class":727},[345,1099,1100],{"class":731},"Share config.yaml alongside your model checkpoint for full reproducibility.",[345,1102,728],{"class":727},[345,1104,737],{"class":367},[345,1106,1107],{"class":347,"line":688},[345,1108,648],{"emptyLinePlaceholder":647},[345,1110,1111],{"class":347,"line":694},[345,1112,1113],{"class":654},"# Cleanup\n",[345,1115,1116,1118],{"class":347,"line":700},[345,1117,352],{"class":351},[345,1119,1120],{"class":355}," shutil\n",[345,1122,1123,1126,1128,1131,1133,1136],{"class":347,"line":706},[345,1124,1125],{"class":355},"shutil",[345,1127,368],{"class":367},[345,1129,1130],{"class":720},"rmtree",[345,1132,724],{"class":367},[345,1134,1135],{"class":720},"run_dir",[345,1137,737],{"class":367},[961,1139],{"data":1140,"kind":964},"Q29uZmlnIHJvdW5kLXRyaXAgdmVyaWZpZWQuCgpUaGUgc2F2ZWQgWUFNTCBjb250YWlucyBhbGwgX3RhcmdldF8gc3RyaW5ncyBuZWVkZWQgdG8gcmVwcm9kdWNlIHRoZSBleHBlcmltZW50LgpTaGFyZSBjb25maWcueWFtbCBhbG9uZ3NpZGUgeW91ciBtb2RlbCBjaGVja3BvaW50IGZvciBmdWxsIHJlcHJvZHVjaWJpbGl0eS4K",[1142,1143,1145],"h3",{"id":1144},"best-practice-save-config-before-the-run-starts","Best practice: save config before the run starts",[336,1147,1149],{"className":338,"code":1148,"language":340,"meta":341,"style":341},"@laco.main(config_name=\"train\")\n@L.task\ndef run(model: nn.Module, optimizer, loss: nn.Module,\n        loader, num_steps: int = 10, output_dir: str = \"outputs\") -> None:\n    run_dir = pathlib.Path(output_dir)\n    run_dir.mkdir(parents=True, exist_ok=True)\n\n    # Save BEFORE any training — even a crash partway through preserves the config\n    laco.save(cfg, run_dir \u002F \"config.yaml\")  # cfg available as closure from @L.task\n\n    opt = optimizer(model.parameters())\n    # ... training ...\n",[231,1150,1151,1183,1195,1241,1294,1314,1345,1349,1354,1384,1388,1408],{"__ignoreMap":341},[345,1152,1153,1157,1161,1163,1166,1168,1172,1174,1176,1179,1181],{"class":347,"line":348},[345,1154,1156],{"class":1155},"stp6e","@",[345,1158,1160],{"class":1159},"sGLFI","laco",[345,1162,368],{"class":1155},[345,1164,1165],{"class":1159},"main",[345,1167,724],{"class":367},[345,1169,1171],{"class":1170},"s99_P","config_name",[345,1173,713],{"class":712},[345,1175,728],{"class":727},[345,1177,1178],{"class":731},"train",[345,1180,728],{"class":727},[345,1182,737],{"class":367},[345,1184,1185,1187,1190,1192],{"class":347,"line":359},[345,1186,1156],{"class":1155},[345,1188,1189],{"class":1159},"L",[345,1191,368],{"class":1155},[345,1193,1194],{"class":1159},"task\n",[345,1196,1197,1200,1203,1205,1209,1212,1215,1217,1220,1222,1225,1227,1230,1232,1234,1236,1238],{"class":347,"line":380},[345,1198,1199],{"class":827},"def",[345,1201,1202],{"class":1159}," run",[345,1204,724],{"class":367},[345,1206,1208],{"class":1207},"sFwrP","model",[345,1210,1211],{"class":367},":",[345,1213,1214],{"class":355}," nn",[345,1216,368],{"class":367},[345,1218,1219],{"class":371},"Module",[345,1221,800],{"class":367},[345,1223,1224],{"class":1207}," optimizer",[345,1226,800],{"class":367},[345,1228,1229],{"class":1207}," loss",[345,1231,1211],{"class":367},[345,1233,1214],{"class":355},[345,1235,368],{"class":367},[345,1237,1219],{"class":371},[345,1239,1240],{"class":367},",\n",[345,1242,1243,1246,1248,1251,1253,1257,1260,1263,1265,1268,1270,1273,1275,1277,1280,1282,1284,1287,1291],{"class":347,"line":651},[345,1244,1245],{"class":1207},"        loader",[345,1247,800],{"class":367},[345,1249,1250],{"class":1207}," num_steps",[345,1252,1211],{"class":367},[345,1254,1256],{"class":1255},"sZMiF"," int",[345,1258,1259],{"class":712}," =",[345,1261,1262],{"class":834}," 10",[345,1264,800],{"class":367},[345,1266,1267],{"class":1207}," output_dir",[345,1269,1211],{"class":367},[345,1271,1272],{"class":1255}," str",[345,1274,1259],{"class":712},[345,1276,808],{"class":727},[345,1278,1279],{"class":731},"outputs",[345,1281,728],{"class":727},[345,1283,238],{"class":367},[345,1285,1286],{"class":367}," ->",[345,1288,1290],{"class":1289},"s39Yj"," None",[345,1292,1293],{"class":367},":\n",[345,1295,1296,1299,1301,1303,1305,1307,1309,1312],{"class":347,"line":658},[345,1297,1298],{"class":355},"    run_dir ",[345,1300,713],{"class":712},[345,1302,759],{"class":355},[345,1304,368],{"class":367},[345,1306,764],{"class":720},[345,1308,724],{"class":367},[345,1310,1311],{"class":720},"output_dir",[345,1313,737],{"class":367},[345,1315,1316,1319,1321,1324,1326,1329,1331,1334,1336,1339,1341,1343],{"class":347,"line":664},[345,1317,1318],{"class":355},"    run_dir",[345,1320,368],{"class":367},[345,1322,1323],{"class":720},"mkdir",[345,1325,724],{"class":367},[345,1327,1328],{"class":1170},"parents",[345,1330,713],{"class":712},[345,1332,1333],{"class":1289},"True",[345,1335,800],{"class":367},[345,1337,1338],{"class":1170}," exist_ok",[345,1340,713],{"class":712},[345,1342,1333],{"class":1289},[345,1344,737],{"class":367},[345,1346,1347],{"class":347,"line":670},[345,1348,648],{"emptyLinePlaceholder":647},[345,1350,1351],{"class":347,"line":676},[345,1352,1353],{"class":654},"    # Save BEFORE any training — even a crash partway through preserves the config\n",[345,1355,1356,1359,1361,1363,1365,1367,1369,1371,1373,1375,1377,1379,1381],{"class":347,"line":682},[345,1357,1358],{"class":355},"    laco",[345,1360,368],{"class":367},[345,1362,792],{"class":720},[345,1364,724],{"class":367},[345,1366,797],{"class":720},[345,1368,800],{"class":367},[345,1370,803],{"class":720},[345,1372,182],{"class":712},[345,1374,808],{"class":727},[345,1376,811],{"class":731},[345,1378,728],{"class":727},[345,1380,238],{"class":367},[345,1382,1383],{"class":654},"  # cfg available as closure from @L.task\n",[345,1385,1386],{"class":347,"line":688},[345,1387,648],{"emptyLinePlaceholder":647},[345,1389,1390,1393,1395,1397,1399,1401,1403,1406],{"class":347,"line":694},[345,1391,1392],{"class":355},"    opt ",[345,1394,713],{"class":712},[345,1396,1224],{"class":720},[345,1398,724],{"class":367},[345,1400,1208],{"class":720},[345,1402,368],{"class":367},[345,1404,1405],{"class":720},"parameters",[345,1407,777],{"class":367},[345,1409,1410],{"class":347,"line":700},[345,1411,1412],{"class":654},"    # ... training ...\n",[216,1414,1415,1417,1418,1420,1421,1424],{},[231,1416,266],{}," returns the reloaded config (a fresh ",[231,1419,406],{}," loaded from the just-written YAML). If you use ",[231,1422,1423],{},"mode=SaveMode.NO_RELOAD",", it returns the original config object unchanged.",[397,1426,1428,1429,1431],{"id":1427},"section-3-laco_strict_nodes-catching-attribute-access-bugs","Section 3: ",[231,1430,275],{},", catching attribute-access bugs",[216,1433,1434,1435,1438,1439,1442,1443,1446,1447,1449,1450,368],{},"A lie-typed node like ",[231,1436,1437],{},"L.call(nn.Linear)(in_features=16)"," has static type ",[231,1440,1441],{},"nn.Linear"," in the IDE. This means ",[231,1444,1445],{},"cfg.in_features"," type-checks, but it's actually accessing a ",[231,1448,406],{}," key, not an attribute of a real ",[231,1451,1441],{},[216,1453,1454],{},"In most cases this is exactly what you want: you're using the config as a typed record. But occasionally you may accidentally treat a config node as a live object, for example by calling methods on it.",[216,1456,1457,1458,1461,1462,1465,1466,1469,1470,182,1473,1476],{},"Set ",[231,1459,1460],{},"LACO_STRICT_NODES=1"," to turn every ",[231,1463,1464],{},"L.call","-produced node into a strict proxy that ",[219,1467,1468],{},"only"," allows dict-key access. Any ",[231,1471,1472],{},"setattr",[231,1474,1475],{},"getattr"," that isn't a config key raises immediately.",[336,1478,1480],{"className":338,"code":1479,"language":340,"meta":341,"style":341},"import os\n\n# ---- With LACO_STRICT_NODES=1 ----\nos.environ[\"LACO_STRICT_NODES\"] = \"1\"\n\n# Re-import to pick up the env var (laco._strict checks it at module load time)\nimport importlib\nimport laco._strict\nimportlib.reload(laco._strict)\nimport laco.language as L_strict\nimportlib.reload(L_strict)\n\ncfg_strict = L_strict.call(nn.Linear)(in_features=16, out_features=8)\nprint(\"Type of cfg_strict:\", type(cfg_strict).__name__)\n\n# Key access is allowed (normal dict-key semantics):\nprint(\"in_features (key access):\", cfg_strict[\"in_features\"])\n\n# Attribute access RAISES with a clear message:\ntry:\n    _ = cfg_strict.in_features   # noqa: LACO001\nexcept AttributeError as e:\n    print(\"\\nAttributeError (LACO_STRICT_NODES):\")\n    print(str(e)[:200])\n",[231,1481,1482,1489,1493,1498,1529,1533,1538,1545,1556,1577,1592,1607,1611,1658,1689,1693,1698,1727,1731,1736,1743,1759,1774,1792],{"__ignoreMap":341},[345,1483,1484,1486],{"class":347,"line":348},[345,1485,352],{"class":351},[345,1487,1488],{"class":355}," os\n",[345,1490,1491],{"class":347,"line":359},[345,1492,648],{"emptyLinePlaceholder":647},[345,1494,1495],{"class":347,"line":380},[345,1496,1497],{"class":654},"# ---- With LACO_STRICT_NODES=1 ----\n",[345,1499,1500,1503,1505,1508,1511,1513,1515,1517,1520,1522,1524,1527],{"class":347,"line":651},[345,1501,1502],{"class":355},"os",[345,1504,368],{"class":367},[345,1506,1507],{"class":371},"environ",[345,1509,1510],{"class":367},"[",[345,1512,728],{"class":727},[345,1514,275],{"class":731},[345,1516,728],{"class":727},[345,1518,1519],{"class":367},"]",[345,1521,1259],{"class":712},[345,1523,808],{"class":727},[345,1525,1526],{"class":731},"1",[345,1528,1053],{"class":727},[345,1530,1531],{"class":347,"line":658},[345,1532,648],{"emptyLinePlaceholder":647},[345,1534,1535],{"class":347,"line":664},[345,1536,1537],{"class":654},"# Re-import to pick up the env var (laco._strict checks it at module load time)\n",[345,1539,1540,1542],{"class":347,"line":670},[345,1541,352],{"class":351},[345,1543,1544],{"class":355}," importlib\n",[345,1546,1547,1549,1551,1553],{"class":347,"line":676},[345,1548,352],{"class":351},[345,1550,364],{"class":355},[345,1552,368],{"class":367},[345,1554,1555],{"class":371},"_strict\n",[345,1557,1558,1561,1563,1566,1568,1570,1572,1575],{"class":347,"line":682},[345,1559,1560],{"class":355},"importlib",[345,1562,368],{"class":367},[345,1564,1565],{"class":720},"reload",[345,1567,724],{"class":367},[345,1569,1160],{"class":720},[345,1571,368],{"class":367},[345,1573,1574],{"class":371},"_strict",[345,1576,737],{"class":367},[345,1578,1579,1581,1583,1585,1587,1589],{"class":347,"line":688},[345,1580,352],{"class":351},[345,1582,364],{"class":355},[345,1584,368],{"class":367},[345,1586,198],{"class":371},[345,1588,374],{"class":351},[345,1590,1591],{"class":355}," L_strict\n",[345,1593,1594,1596,1598,1600,1602,1605],{"class":347,"line":694},[345,1595,1560],{"class":355},[345,1597,368],{"class":367},[345,1599,1565],{"class":720},[345,1601,724],{"class":367},[345,1603,1604],{"class":720},"L_strict",[345,1606,737],{"class":367},[345,1608,1609],{"class":347,"line":700},[345,1610,648],{"emptyLinePlaceholder":647},[345,1612,1613,1616,1618,1621,1623,1626,1628,1630,1632,1635,1638,1641,1643,1646,1648,1651,1653,1656],{"class":347,"line":706},[345,1614,1615],{"class":355},"cfg_strict ",[345,1617,713],{"class":712},[345,1619,1620],{"class":355}," L_strict",[345,1622,368],{"class":367},[345,1624,1625],{"class":720},"call",[345,1627,724],{"class":367},[345,1629,390],{"class":720},[345,1631,368],{"class":367},[345,1633,1634],{"class":371},"Linear",[345,1636,1637],{"class":367},")(",[345,1639,1640],{"class":1170},"in_features",[345,1642,713],{"class":712},[345,1644,1645],{"class":834},"16",[345,1647,800],{"class":367},[345,1649,1650],{"class":1170}," out_features",[345,1652,713],{"class":712},[345,1654,1655],{"class":834},"8",[345,1657,737],{"class":367},[345,1659,1660,1662,1664,1666,1669,1671,1673,1676,1678,1681,1683,1687],{"class":347,"line":740},[345,1661,822],{"class":821},[345,1663,724],{"class":367},[345,1665,728],{"class":727},[345,1667,1668],{"class":731},"Type of cfg_strict:",[345,1670,728],{"class":727},[345,1672,800],{"class":367},[345,1674,1675],{"class":1255}," type",[345,1677,724],{"class":367},[345,1679,1680],{"class":720},"cfg_strict",[345,1682,897],{"class":367},[345,1684,1686],{"class":1685},"s_hVV","__name__",[345,1688,737],{"class":367},[345,1690,1691],{"class":347,"line":745},[345,1692,648],{"emptyLinePlaceholder":647},[345,1694,1695],{"class":347,"line":751},[345,1696,1697],{"class":654},"# Key access is allowed (normal dict-key semantics):\n",[345,1699,1700,1702,1704,1706,1709,1711,1713,1716,1718,1720,1722,1724],{"class":347,"line":780},[345,1701,822],{"class":821},[345,1703,724],{"class":367},[345,1705,728],{"class":727},[345,1707,1708],{"class":731},"in_features (key access):",[345,1710,728],{"class":727},[345,1712,800],{"class":367},[345,1714,1715],{"class":720}," cfg_strict",[345,1717,1510],{"class":367},[345,1719,728],{"class":727},[345,1721,1640],{"class":731},[345,1723,728],{"class":727},[345,1725,1726],{"class":367},"])\n",[345,1728,1729],{"class":347,"line":818},[345,1730,648],{"emptyLinePlaceholder":647},[345,1732,1733],{"class":347,"line":857},[345,1734,1735],{"class":654},"# Attribute access RAISES with a clear message:\n",[345,1737,1738,1741],{"class":347,"line":865},[345,1739,1740],{"class":351},"try",[345,1742,1293],{"class":367},[345,1744,1745,1748,1750,1752,1754,1756],{"class":347,"line":870},[345,1746,1747],{"class":355},"    _ ",[345,1749,713],{"class":712},[345,1751,1715],{"class":355},[345,1753,368],{"class":367},[345,1755,1640],{"class":371},[345,1757,1758],{"class":654},"   # noqa: LACO001\n",[345,1760,1761,1764,1767,1769,1772],{"class":347,"line":876},[345,1762,1763],{"class":351},"except",[345,1765,1766],{"class":1255}," AttributeError",[345,1768,374],{"class":351},[345,1770,1771],{"class":355}," e",[345,1773,1293],{"class":367},[345,1775,1776,1778,1780,1782,1785,1788,1790],{"class":347,"line":905},[345,1777,953],{"class":821},[345,1779,724],{"class":367},[345,1781,728],{"class":727},[345,1783,1784],{"class":1685},"\\n",[345,1786,1787],{"class":731},"AttributeError (LACO_STRICT_NODES):",[345,1789,728],{"class":727},[345,1791,737],{"class":367},[345,1793,1794,1796,1798,1801,1803,1806,1809,1812],{"class":347,"line":921},[345,1795,953],{"class":821},[345,1797,724],{"class":367},[345,1799,1800],{"class":1255},"str",[345,1802,724],{"class":367},[345,1804,1805],{"class":720},"e",[345,1807,1808],{"class":367},")[:",[345,1810,1811],{"class":834},"200",[345,1813,1726],{"class":367},[961,1815],{"data":1816,"kind":964},"VHlwZSBvZiBjZmdfc3RyaWN0OiBEaWN0Q29uZmlnCmluX2ZlYXR1cmVzIChrZXkgYWNjZXNzKTogMTYK",[336,1818,1820],{"className":338,"code":1819,"language":340,"meta":341,"style":341},"# Disable LACO_STRICT_NODES for the rest of the notebook\nos.environ.pop(\"LACO_STRICT_NODES\", None)\nimportlib.reload(laco._strict)\nimportlib.reload(L_strict)\nprint(\"LACO_STRICT_NODES disabled — normal behaviour restored.\")\n",[231,1821,1822,1827,1854,1872,1886],{"__ignoreMap":341},[345,1823,1824],{"class":347,"line":348},[345,1825,1826],{"class":654},"# Disable LACO_STRICT_NODES for the rest of the notebook\n",[345,1828,1829,1831,1833,1835,1837,1840,1842,1844,1846,1848,1850,1852],{"class":347,"line":359},[345,1830,1502],{"class":355},[345,1832,368],{"class":367},[345,1834,1507],{"class":371},[345,1836,368],{"class":367},[345,1838,1839],{"class":720},"pop",[345,1841,724],{"class":367},[345,1843,728],{"class":727},[345,1845,275],{"class":731},[345,1847,728],{"class":727},[345,1849,800],{"class":367},[345,1851,1290],{"class":1289},[345,1853,737],{"class":367},[345,1855,1856,1858,1860,1862,1864,1866,1868,1870],{"class":347,"line":380},[345,1857,1560],{"class":355},[345,1859,368],{"class":367},[345,1861,1565],{"class":720},[345,1863,724],{"class":367},[345,1865,1160],{"class":720},[345,1867,368],{"class":367},[345,1869,1574],{"class":371},[345,1871,737],{"class":367},[345,1873,1874,1876,1878,1880,1882,1884],{"class":347,"line":651},[345,1875,1560],{"class":355},[345,1877,368],{"class":367},[345,1879,1565],{"class":720},[345,1881,724],{"class":367},[345,1883,1604],{"class":720},[345,1885,737],{"class":367},[345,1887,1888,1890,1892,1894,1897,1899],{"class":347,"line":658},[345,1889,822],{"class":821},[345,1891,724],{"class":367},[345,1893,728],{"class":727},[345,1895,1896],{"class":731},"LACO_STRICT_NODES disabled — normal behaviour restored.",[345,1898,728],{"class":727},[345,1900,737],{"class":367},[961,1902],{"data":1903,"kind":964},"TEFDT19TVFJJQ1RfTk9ERVMgZGlzYWJsZWQg4oCUIG5vcm1hbCBiZWhhdmlvdXIgcmVzdG9yZWQuCg==",[1142,1905,1907,1908],{"id":1906},"when-to-use-laco_strict_nodes","When to use ",[231,1909,275],{},[419,1911,1912,1922],{},[422,1913,1914],{},[425,1915,1916,1919],{},[428,1917,1918],{},"Phase",[428,1920,1921],{},"Recommendation",[441,1923,1924,1936,1949],{},[425,1925,1926,1931],{},[446,1927,1928],{},[219,1929,1930],{},"Development \u002F CI",[446,1932,1933,1935],{},[231,1934,1460],{},": catches accidental attribute access on config nodes",[425,1937,1938,1943],{},[446,1939,1940],{},[219,1941,1942],{},"Production",[446,1944,1945,1948],{},[231,1946,1947],{},"LACO_STRICT_NODES=0"," (default): no overhead; attribute access works normally",[425,1950,1951,1956],{},[446,1952,1953],{},[219,1954,1955],{},"Config authoring tests",[446,1957,1958,1960],{},[231,1959,1460],{},": validates that your config files don't accidentally use live-object APIs",[216,1962,1963,1965],{},[231,1964,281],{}," (Section 4) provides static analysis for the same class of bugs, without the runtime overhead.",[397,1967,1969,1970,607,1972],{"id":1968},"section-4-laco-lint-and-laco001","Section 4: ",[231,1971,281],{},[231,1973,285],{},[216,1975,1976,1978,1979,1982,1983,1985,1986,182,1988,1991,1992,1995],{},[231,1977,281],{}," is a standalone AST-based linter that checks for ",[219,1980,1981],{},"attribute access on lie-typed nodes",": the ",[231,1984,285],{}," violation. It reads Python source files, finds ",[231,1987,1464],{},[231,1989,1990],{},"L.partial"," assignments, and flags any subsequent ",[231,1993,1994],{},"cfg.attribute_name"," access on those names.",[216,1997,1998,1999,2002],{},"The check can be suppressed per-line with ",[231,2000,2001],{},"# noqa: LACO001"," (you'll have seen this comment throughout the tutorial notebooks).",[336,2004,2006],{"className":338,"code":2005,"language":340,"meta":341,"style":341},"# What LACO001 catches:\n\nexample_bad = '''\nimport laco.language as L\nimport torch.nn as nn\n\ncfg = L.call(nn.Linear)(in_features=16, out_features=8)\n# BAD: cfg is a DictConfig, but the IDE (and this code) treats it as nn.Linear\nprint(cfg.in_features)  # LACO001: attribute access on a lie-typed node\n'''\n\nexample_good = '''\nimport laco.language as L\nimport torch.nn as nn\n\ncfg = L.call(nn.Linear)(in_features=16, out_features=8)\n# GOOD 1: suppressed with noqa comment (intentional config key access)\nprint(cfg.in_features)  # noqa: LACO001 -- intentional: exercising real key access\n\n# GOOD 2: use dict-key syntax (always safe, no suppression needed)\nprint(cfg[\"in_features\"])  # plain dict key — no LACO001\n'''\n\nprint(\"=== Bad pattern (triggers LACO001) ===\")\nprint(example_bad)\nprint(\"=== Good patterns ===\")\nprint(example_good)\n",[231,2007,2008,2013,2017,2027,2032,2037,2041,2046,2051,2056,2061,2065,2074,2078,2082,2086,2090,2095,2100,2104,2109,2114,2118,2122,2137,2148,2164],{"__ignoreMap":341},[345,2009,2010],{"class":347,"line":348},[345,2011,2012],{"class":654},"# What LACO001 catches:\n",[345,2014,2015],{"class":347,"line":359},[345,2016,648],{"emptyLinePlaceholder":647},[345,2018,2019,2022,2024],{"class":347,"line":380},[345,2020,2021],{"class":355},"example_bad ",[345,2023,713],{"class":712},[345,2025,2026],{"class":727}," '''\n",[345,2028,2029],{"class":347,"line":651},[345,2030,2031],{"class":731},"import laco.language as L\n",[345,2033,2034],{"class":347,"line":658},[345,2035,2036],{"class":731},"import torch.nn as nn\n",[345,2038,2039],{"class":347,"line":664},[345,2040,648],{"emptyLinePlaceholder":647},[345,2042,2043],{"class":347,"line":670},[345,2044,2045],{"class":731},"cfg = L.call(nn.Linear)(in_features=16, out_features=8)\n",[345,2047,2048],{"class":347,"line":676},[345,2049,2050],{"class":731},"# BAD: cfg is a DictConfig, but the IDE (and this code) treats it as nn.Linear\n",[345,2052,2053],{"class":347,"line":682},[345,2054,2055],{"class":731},"print(cfg.in_features)  # LACO001: attribute access on a lie-typed node\n",[345,2057,2058],{"class":347,"line":688},[345,2059,2060],{"class":727},"'''\n",[345,2062,2063],{"class":347,"line":694},[345,2064,648],{"emptyLinePlaceholder":647},[345,2066,2067,2070,2072],{"class":347,"line":700},[345,2068,2069],{"class":355},"example_good ",[345,2071,713],{"class":712},[345,2073,2026],{"class":727},[345,2075,2076],{"class":347,"line":706},[345,2077,2031],{"class":731},[345,2079,2080],{"class":347,"line":740},[345,2081,2036],{"class":731},[345,2083,2084],{"class":347,"line":745},[345,2085,648],{"emptyLinePlaceholder":647},[345,2087,2088],{"class":347,"line":751},[345,2089,2045],{"class":731},[345,2091,2092],{"class":347,"line":780},[345,2093,2094],{"class":731},"# GOOD 1: suppressed with noqa comment (intentional config key access)\n",[345,2096,2097],{"class":347,"line":818},[345,2098,2099],{"class":731},"print(cfg.in_features)  # noqa: LACO001 -- intentional: exercising real key access\n",[345,2101,2102],{"class":347,"line":857},[345,2103,648],{"emptyLinePlaceholder":647},[345,2105,2106],{"class":347,"line":865},[345,2107,2108],{"class":731},"# GOOD 2: use dict-key syntax (always safe, no suppression needed)\n",[345,2110,2111],{"class":347,"line":870},[345,2112,2113],{"class":731},"print(cfg[\"in_features\"])  # plain dict key — no LACO001\n",[345,2115,2116],{"class":347,"line":876},[345,2117,2060],{"class":727},[345,2119,2120],{"class":347,"line":905},[345,2121,648],{"emptyLinePlaceholder":647},[345,2123,2124,2126,2128,2130,2133,2135],{"class":347,"line":921},[345,2125,822],{"class":821},[345,2127,724],{"class":367},[345,2129,728],{"class":727},[345,2131,2132],{"class":731},"=== Bad pattern (triggers LACO001) ===",[345,2134,728],{"class":727},[345,2136,737],{"class":367},[345,2138,2139,2141,2143,2146],{"class":347,"line":950},[345,2140,822],{"class":821},[345,2142,724],{"class":367},[345,2144,2145],{"class":720},"example_bad",[345,2147,737],{"class":367},[345,2149,2151,2153,2155,2157,2160,2162],{"class":347,"line":2150},26,[345,2152,822],{"class":821},[345,2154,724],{"class":367},[345,2156,728],{"class":727},[345,2158,2159],{"class":731},"=== Good patterns ===",[345,2161,728],{"class":727},[345,2163,737],{"class":367},[345,2165,2167,2169,2171,2174],{"class":347,"line":2166},27,[345,2168,822],{"class":821},[345,2170,724],{"class":367},[345,2172,2173],{"class":720},"example_good",[345,2175,737],{"class":367},[961,2177],{"data":2178,"kind":964},"PT09IEJhZCBwYXR0ZXJuICh0cmlnZ2VycyBMQUNPMDAxKSA9PT0KCmltcG9ydCBsYWNvLmxhbmd1YWdlIGFzIEwKaW1wb3J0IHRvcmNoLm5uIGFzIG5uCgpjZmcgPSBMLmNhbGwobm4uTGluZWFyKShpbl9mZWF0dXJlcz0xNiwgb3V0X2ZlYXR1cmVzPTgpCiMgQkFEOiBjZmcgaXMgYSBEaWN0Q29uZmlnLCBidXQgdGhlIElERSAoYW5kIHRoaXMgY29kZSkgdHJlYXRzIGl0IGFzIG5uLkxpbmVhcgpwcmludChjZmcuaW5fZmVhdHVyZXMpICAjIExBQ08wMDE6IGF0dHJpYnV0ZSBhY2Nlc3Mgb24gYSBsaWUtdHlwZWQgbm9kZQoKPT09IEdvb2QgcGF0dGVybnMgPT09CgppbXBvcnQgbGFjby5sYW5ndWFnZSBhcyBMCmltcG9ydCB0b3JjaC5ubiBhcyBubgoKY2ZnID0gTC5jYWxsKG5uLkxpbmVhcikoaW5fZmVhdHVyZXM9MTYsIG91dF9mZWF0dXJlcz04KQojIEdPT0QgMTogc3VwcHJlc3NlZCB3aXRoIG5vcWEgY29tbWVudCAoaW50ZW50aW9uYWwgY29uZmlnIGtleSBhY2Nlc3MpCnByaW50KGNmZy5pbl9mZWF0dXJlcykgICMgbm9xYTogTEFDTzAwMSAtLSBpbnRlbnRpb25hbDogZXhlcmNpc2luZyByZWFsIGtleSBhY2Nlc3MKCiMgR09PRCAyOiB1c2UgZGljdC1rZXkgc3ludGF4IChhbHdheXMgc2FmZSwgbm8gc3VwcHJlc3Npb24gbmVlZGVkKQpwcmludChjZmdbImluX2ZlYXR1cmVzIl0pICAjIHBsYWluIGRpY3Qga2V5IOKAlCBubyBMQUNPMDAxCgo=",[336,2180,2182],{"className":338,"code":2181,"language":340,"meta":341,"style":341},"import subprocess\n\n# Run laco-lint on the examples directory\nresult = subprocess.run(\n    [\"laco-lint\", \"sources\u002Flaco\u002Fexamples\u002F\"],\n    capture_output=True, text=True,\n    cwd=\"\u002Fhome\u002Fkhwstolle\u002FProjects\u002Fresearch\u002Flaco\",\n    timeout=30,\n)\nprint(\"laco-lint stdout:\")\nprint(result.stdout or \"(no violations found)\")\nif result.stderr:\n    print(\"laco-lint stderr:\")\n    print(result.stderr[:300])\nprint(\"Return code:\", result.returncode, \"(0 = clean, nonzero = violations found)\")\n",[231,2183,2184,2191,2195,2200,2218,2241,2261,2277,2289,2293,2308,2334,2349,2364,2384],{"__ignoreMap":341},[345,2185,2186,2188],{"class":347,"line":348},[345,2187,352],{"class":351},[345,2189,2190],{"class":355}," subprocess\n",[345,2192,2193],{"class":347,"line":359},[345,2194,648],{"emptyLinePlaceholder":647},[345,2196,2197],{"class":347,"line":380},[345,2198,2199],{"class":654},"# Run laco-lint on the examples directory\n",[345,2201,2202,2205,2207,2210,2212,2215],{"class":347,"line":651},[345,2203,2204],{"class":355},"result ",[345,2206,713],{"class":712},[345,2208,2209],{"class":355}," subprocess",[345,2211,368],{"class":367},[345,2213,2214],{"class":720},"run",[345,2216,2217],{"class":367},"(\n",[345,2219,2220,2223,2225,2227,2229,2231,2233,2236,2238],{"class":347,"line":658},[345,2221,2222],{"class":367},"    [",[345,2224,728],{"class":727},[345,2226,281],{"class":731},[345,2228,728],{"class":727},[345,2230,800],{"class":367},[345,2232,808],{"class":727},[345,2234,2235],{"class":731},"sources\u002Flaco\u002Fexamples\u002F",[345,2237,728],{"class":727},[345,2239,2240],{"class":367},"],\n",[345,2242,2243,2246,2248,2250,2252,2255,2257,2259],{"class":347,"line":664},[345,2244,2245],{"class":1170},"    capture_output",[345,2247,713],{"class":712},[345,2249,1333],{"class":1289},[345,2251,800],{"class":367},[345,2253,2254],{"class":1170}," text",[345,2256,713],{"class":712},[345,2258,1333],{"class":1289},[345,2260,1240],{"class":367},[345,2262,2263,2266,2268,2270,2273,2275],{"class":347,"line":670},[345,2264,2265],{"class":1170},"    cwd",[345,2267,713],{"class":712},[345,2269,728],{"class":727},[345,2271,2272],{"class":731},"\u002Fhome\u002Fkhwstolle\u002FProjects\u002Fresearch\u002Flaco",[345,2274,728],{"class":727},[345,2276,1240],{"class":367},[345,2278,2279,2282,2284,2287],{"class":347,"line":676},[345,2280,2281],{"class":1170},"    timeout",[345,2283,713],{"class":712},[345,2285,2286],{"class":834},"30",[345,2288,1240],{"class":367},[345,2290,2291],{"class":347,"line":682},[345,2292,737],{"class":367},[345,2294,2295,2297,2299,2301,2304,2306],{"class":347,"line":688},[345,2296,822],{"class":821},[345,2298,724],{"class":367},[345,2300,728],{"class":727},[345,2302,2303],{"class":731},"laco-lint stdout:",[345,2305,728],{"class":727},[345,2307,737],{"class":367},[345,2309,2310,2312,2314,2317,2319,2322,2325,2327,2330,2332],{"class":347,"line":694},[345,2311,822],{"class":821},[345,2313,724],{"class":367},[345,2315,2316],{"class":720},"result",[345,2318,368],{"class":367},[345,2320,2321],{"class":371},"stdout",[345,2323,2324],{"class":351}," or",[345,2326,808],{"class":727},[345,2328,2329],{"class":731},"(no violations found)",[345,2331,728],{"class":727},[345,2333,737],{"class":367},[345,2335,2336,2339,2342,2344,2347],{"class":347,"line":700},[345,2337,2338],{"class":351},"if",[345,2340,2341],{"class":355}," result",[345,2343,368],{"class":367},[345,2345,2346],{"class":371},"stderr",[345,2348,1293],{"class":367},[345,2350,2351,2353,2355,2357,2360,2362],{"class":347,"line":706},[345,2352,953],{"class":821},[345,2354,724],{"class":367},[345,2356,728],{"class":727},[345,2358,2359],{"class":731},"laco-lint stderr:",[345,2361,728],{"class":727},[345,2363,737],{"class":367},[345,2365,2366,2368,2370,2372,2374,2376,2379,2382],{"class":347,"line":740},[345,2367,953],{"class":821},[345,2369,724],{"class":367},[345,2371,2316],{"class":720},[345,2373,368],{"class":367},[345,2375,2346],{"class":371},[345,2377,2378],{"class":367},"[:",[345,2380,2381],{"class":834},"300",[345,2383,1726],{"class":367},[345,2385,2386,2388,2390,2392,2395,2397,2399,2401,2403,2406,2408,2410,2413,2415],{"class":347,"line":745},[345,2387,822],{"class":821},[345,2389,724],{"class":367},[345,2391,728],{"class":727},[345,2393,2394],{"class":731},"Return code:",[345,2396,728],{"class":727},[345,2398,800],{"class":367},[345,2400,2341],{"class":720},[345,2402,368],{"class":367},[345,2404,2405],{"class":371},"returncode",[345,2407,800],{"class":367},[345,2409,808],{"class":727},[345,2411,2412],{"class":731},"(0 = clean, nonzero = violations found)",[345,2414,728],{"class":727},[345,2416,737],{"class":367},[961,2418],{"data":2419,"kind":964},"bGFjby1saW50IHN0ZG91dDoKKG5vIHZpb2xhdGlvbnMgZm91bmQpClJldHVybiBjb2RlOiAwICgwID0gY2xlYW4sIG5vbnplcm8gPSB2aW9sYXRpb25zIGZvdW5kKQo=",[1142,2421,2423,2424,2426],{"id":2422},"integrating-laco-lint-into-ci","Integrating ",[231,2425,281],{}," into CI",[336,2428,2432],{"className":2429,"code":2430,"language":2431,"meta":341,"style":341},"language-yaml shiki shiki-themes material-theme-lighter github-light github-dark","# .github\u002Fworkflows\u002Flint.yml\n- name: laco-lint\n  run: laco-lint sources\u002F tests\u002F\n","yaml",[231,2433,2434,2439,2453],{"__ignoreMap":341},[345,2435,2436],{"class":347,"line":348},[345,2437,2438],{"class":654},"# .github\u002Fworkflows\u002Flint.yml\n",[345,2440,2441,2444,2448,2450],{"class":347,"line":359},[345,2442,2443],{"class":367},"-",[345,2445,2447],{"class":2446},"sQzsp"," name",[345,2449,1211],{"class":367},[345,2451,2452],{"class":731}," laco-lint\n",[345,2454,2455,2458,2460],{"class":347,"line":380},[345,2456,2457],{"class":2446},"  run",[345,2459,1211],{"class":367},[345,2461,2462],{"class":731}," laco-lint sources\u002F tests\u002F\n",[216,2464,2465,2466,267,2469,2472,2473,2475],{},"Or add it to your ",[231,2467,2468],{},"Makefile",[231,2470,2471],{},"pre-commit"," hooks. ",[231,2474,281],{}," returns exit code 0 when clean, non-zero when violations are found, so it integrates naturally with standard CI gate logic.",[216,2477,289,2478,2480,2481,2484,2485,2487],{},[231,2479,285],{}," code is registered as an external code in laco's ",[231,2482,2483],{},"ruff"," configuration so ruff won't flag your ",[231,2486,2001],{}," comments as unknown.",[397,2489,2491,2492,2494],{"id":2490},"section-5-the-migrate_target-hook","Section 5: The ",[231,2493,292],{}," hook",[216,2496,2497,2498,2501,2502,2505,2506,2508,2509,368],{},"When you rename a class across library versions (e.g., ",[231,2499,2500],{},"mypackage.models.OldNet"," → ",[231,2503,2504],{},"mypackage.models.NewNet","), saved YAML configs from before the rename will still reference the old path. Without intervention, ",[231,2507,588],{}," will raise ",[231,2510,2511],{},"ImportError",[216,2513,289,2514,2516,2517,2519,2520,368],{},[231,2515,292],{}," hook lets you remap old ",[231,2518,603],{}," strings to new ones at instantiation time, allowing old configs to keep working while emitting a ",[231,2521,2522],{},"DeprecationWarning",[336,2524,2526],{"className":338,"code":2525,"language":340,"meta":341,"style":341},"import laco._lazy\nimport warnings\n\n# Save the original (identity) hook so we can restore it later\noriginal_migrate = laco._lazy._DEFAULT_MIGRATE_TARGET\n\n# Define a migration table for a hypothetical 1.0 → 2.0 rename:\nMIGRATIONS = {\n    \"mypackage.old.ResNet\": \"mypackage.models.ResNet\",\n    \"mypackage.utils.OldNorm\": \"mypackage.layers.LayerNorm\",\n}\n\ndef my_migration_hook(target):\n    if target in MIGRATIONS:\n        new_target = MIGRATIONS[target]\n        warnings.warn(\n            f\"'{target}' is deprecated; automatically remapped to '{new_target}'. \"\n            f\"Update your YAML configs to use the new path.\",\n            DeprecationWarning,\n            stacklevel=4,\n        )\n        return new_target\n    return target\n\n# Install the hook:\nlaco._lazy.migrate_target = my_migration_hook\n\n# Test the hook:\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter(\"always\")\n    result = laco._lazy.migrate_target(\"mypackage.old.ResNet\")\n    unchanged = laco._lazy.migrate_target(\"mypackage.models.NewNet\")\n\nprint(f\"Old path remapped to: {result}\")\nprint(f\"Unknown path unchanged: {unchanged}\")\nif w:\n    print(f\"Warning: {w[0].message}\")\n",[231,2527,2528,2539,2546,2550,2555,2575,2579,2584,2594,2615,2635,2640,2644,2659,2674,2690,2702,2729,2738,2745,2757,2762,2770,2778,2782,2787,2804,2808,2814,2846,2868,2896,2924,2929,2951,2974,2983],{"__ignoreMap":341},[345,2529,2530,2532,2534,2536],{"class":347,"line":348},[345,2531,352],{"class":351},[345,2533,364],{"class":355},[345,2535,368],{"class":367},[345,2537,2538],{"class":371},"_lazy\n",[345,2540,2541,2543],{"class":347,"line":359},[345,2542,352],{"class":351},[345,2544,2545],{"class":355}," warnings\n",[345,2547,2548],{"class":347,"line":380},[345,2549,648],{"emptyLinePlaceholder":647},[345,2551,2552],{"class":347,"line":651},[345,2553,2554],{"class":654},"# Save the original (identity) hook so we can restore it later\n",[345,2556,2557,2560,2562,2564,2566,2569,2571],{"class":347,"line":658},[345,2558,2559],{"class":355},"original_migrate ",[345,2561,713],{"class":712},[345,2563,364],{"class":355},[345,2565,368],{"class":367},[345,2567,2568],{"class":371},"_lazy",[345,2570,368],{"class":367},[345,2572,2574],{"class":2573},"swQdS","_DEFAULT_MIGRATE_TARGET\n",[345,2576,2577],{"class":347,"line":664},[345,2578,648],{"emptyLinePlaceholder":647},[345,2580,2581],{"class":347,"line":670},[345,2582,2583],{"class":654},"# Define a migration table for a hypothetical 1.0 → 2.0 rename:\n",[345,2585,2586,2589,2591],{"class":347,"line":676},[345,2587,2588],{"class":1685},"MIGRATIONS",[345,2590,1259],{"class":712},[345,2592,2593],{"class":367}," {\n",[345,2595,2596,2599,2602,2604,2606,2608,2611,2613],{"class":347,"line":682},[345,2597,2598],{"class":727},"    \"",[345,2600,2601],{"class":731},"mypackage.old.ResNet",[345,2603,728],{"class":727},[345,2605,1211],{"class":367},[345,2607,808],{"class":727},[345,2609,2610],{"class":731},"mypackage.models.ResNet",[345,2612,728],{"class":727},[345,2614,1240],{"class":367},[345,2616,2617,2619,2622,2624,2626,2628,2631,2633],{"class":347,"line":688},[345,2618,2598],{"class":727},[345,2620,2621],{"class":731},"mypackage.utils.OldNorm",[345,2623,728],{"class":727},[345,2625,1211],{"class":367},[345,2627,808],{"class":727},[345,2629,2630],{"class":731},"mypackage.layers.LayerNorm",[345,2632,728],{"class":727},[345,2634,1240],{"class":367},[345,2636,2637],{"class":347,"line":694},[345,2638,2639],{"class":367},"}\n",[345,2641,2642],{"class":347,"line":700},[345,2643,648],{"emptyLinePlaceholder":647},[345,2645,2646,2648,2651,2653,2656],{"class":347,"line":706},[345,2647,1199],{"class":827},[345,2649,2650],{"class":1159}," my_migration_hook",[345,2652,724],{"class":367},[345,2654,2655],{"class":1207},"target",[345,2657,2658],{"class":367},"):\n",[345,2660,2661,2664,2667,2669,2672],{"class":347,"line":740},[345,2662,2663],{"class":351},"    if",[345,2665,2666],{"class":355}," target ",[345,2668,930],{"class":712},[345,2670,2671],{"class":1685}," MIGRATIONS",[345,2673,1293],{"class":367},[345,2675,2676,2679,2681,2683,2685,2687],{"class":347,"line":745},[345,2677,2678],{"class":355},"        new_target ",[345,2680,713],{"class":712},[345,2682,2671],{"class":1685},[345,2684,1510],{"class":367},[345,2686,2655],{"class":355},[345,2688,2689],{"class":367},"]\n",[345,2691,2692,2695,2697,2700],{"class":347,"line":751},[345,2693,2694],{"class":355},"        warnings",[345,2696,368],{"class":367},[345,2698,2699],{"class":720},"warn",[345,2701,2217],{"class":367},[345,2703,2704,2707,2710,2712,2714,2716,2719,2721,2724,2726],{"class":347,"line":780},[345,2705,2706],{"class":827},"            f",[345,2708,2709],{"class":731},"\"'",[345,2711,835],{"class":834},[345,2713,2655],{"class":720},[345,2715,850],{"class":834},[345,2717,2718],{"class":731},"' is deprecated; automatically remapped to '",[345,2720,835],{"class":834},[345,2722,2723],{"class":720},"new_target",[345,2725,850],{"class":834},[345,2727,2728],{"class":731},"'. \"\n",[345,2730,2731,2733,2736],{"class":347,"line":818},[345,2732,2706],{"class":827},[345,2734,2735],{"class":731},"\"Update your YAML configs to use the new path.\"",[345,2737,1240],{"class":367},[345,2739,2740,2743],{"class":347,"line":857},[345,2741,2742],{"class":1255},"            DeprecationWarning",[345,2744,1240],{"class":367},[345,2746,2747,2750,2752,2755],{"class":347,"line":865},[345,2748,2749],{"class":1170},"            stacklevel",[345,2751,713],{"class":712},[345,2753,2754],{"class":834},"4",[345,2756,1240],{"class":367},[345,2758,2759],{"class":347,"line":870},[345,2760,2761],{"class":367},"        )\n",[345,2763,2764,2767],{"class":347,"line":876},[345,2765,2766],{"class":351},"        return",[345,2768,2769],{"class":355}," new_target\n",[345,2771,2772,2775],{"class":347,"line":905},[345,2773,2774],{"class":351},"    return",[345,2776,2777],{"class":355}," target\n",[345,2779,2780],{"class":347,"line":921},[345,2781,648],{"emptyLinePlaceholder":647},[345,2783,2784],{"class":347,"line":950},[345,2785,2786],{"class":654},"# Install the hook:\n",[345,2788,2789,2791,2793,2795,2797,2799,2801],{"class":347,"line":2150},[345,2790,1160],{"class":355},[345,2792,368],{"class":367},[345,2794,2568],{"class":371},[345,2796,368],{"class":367},[345,2798,292],{"class":371},[345,2800,1259],{"class":712},[345,2802,2803],{"class":355}," my_migration_hook\n",[345,2805,2806],{"class":347,"line":2166},[345,2807,648],{"emptyLinePlaceholder":647},[345,2809,2811],{"class":347,"line":2810},28,[345,2812,2813],{"class":654},"# Test the hook:\n",[345,2815,2817,2820,2823,2825,2828,2830,2833,2835,2837,2839,2841,2844],{"class":347,"line":2816},29,[345,2818,2819],{"class":351},"with",[345,2821,2822],{"class":355}," warnings",[345,2824,368],{"class":367},[345,2826,2827],{"class":720},"catch_warnings",[345,2829,724],{"class":367},[345,2831,2832],{"class":1170},"record",[345,2834,713],{"class":712},[345,2836,1333],{"class":1289},[345,2838,238],{"class":367},[345,2840,374],{"class":351},[345,2842,2843],{"class":355}," w",[345,2845,1293],{"class":367},[345,2847,2849,2852,2854,2857,2859,2861,2864,2866],{"class":347,"line":2848},30,[345,2850,2851],{"class":355},"    warnings",[345,2853,368],{"class":367},[345,2855,2856],{"class":720},"simplefilter",[345,2858,724],{"class":367},[345,2860,728],{"class":727},[345,2862,2863],{"class":731},"always",[345,2865,728],{"class":727},[345,2867,737],{"class":367},[345,2869,2871,2874,2876,2878,2880,2882,2884,2886,2888,2890,2892,2894],{"class":347,"line":2870},31,[345,2872,2873],{"class":355},"    result ",[345,2875,713],{"class":712},[345,2877,364],{"class":355},[345,2879,368],{"class":367},[345,2881,2568],{"class":371},[345,2883,368],{"class":367},[345,2885,292],{"class":720},[345,2887,724],{"class":367},[345,2889,728],{"class":727},[345,2891,2601],{"class":731},[345,2893,728],{"class":727},[345,2895,737],{"class":367},[345,2897,2899,2902,2904,2906,2908,2910,2912,2914,2916,2918,2920,2922],{"class":347,"line":2898},32,[345,2900,2901],{"class":355},"    unchanged ",[345,2903,713],{"class":712},[345,2905,364],{"class":355},[345,2907,368],{"class":367},[345,2909,2568],{"class":371},[345,2911,368],{"class":367},[345,2913,292],{"class":720},[345,2915,724],{"class":367},[345,2917,728],{"class":727},[345,2919,2504],{"class":731},[345,2921,728],{"class":727},[345,2923,737],{"class":367},[345,2925,2927],{"class":347,"line":2926},33,[345,2928,648],{"emptyLinePlaceholder":647},[345,2930,2932,2934,2936,2938,2941,2943,2945,2947,2949],{"class":347,"line":2931},34,[345,2933,822],{"class":821},[345,2935,724],{"class":367},[345,2937,828],{"class":827},[345,2939,2940],{"class":731},"\"Old path remapped to: ",[345,2942,835],{"class":834},[345,2944,2316],{"class":720},[345,2946,850],{"class":834},[345,2948,728],{"class":731},[345,2950,737],{"class":367},[345,2952,2954,2956,2958,2960,2963,2965,2968,2970,2972],{"class":347,"line":2953},35,[345,2955,822],{"class":821},[345,2957,724],{"class":367},[345,2959,828],{"class":827},[345,2961,2962],{"class":731},"\"Unknown path unchanged: ",[345,2964,835],{"class":834},[345,2966,2967],{"class":720},"unchanged",[345,2969,850],{"class":834},[345,2971,728],{"class":731},[345,2973,737],{"class":367},[345,2975,2977,2979,2981],{"class":347,"line":2976},36,[345,2978,2338],{"class":351},[345,2980,2843],{"class":355},[345,2982,1293],{"class":367},[345,2984,2986,2988,2990,2992,2995,2997,3000,3002,3005,3008,3011,3013,3015],{"class":347,"line":2985},37,[345,2987,953],{"class":821},[345,2989,724],{"class":367},[345,2991,828],{"class":827},[345,2993,2994],{"class":731},"\"Warning: ",[345,2996,835],{"class":834},[345,2998,2999],{"class":720},"w",[345,3001,1510],{"class":367},[345,3003,3004],{"class":834},"0",[345,3006,3007],{"class":367},"].",[345,3009,3010],{"class":371},"message",[345,3012,850],{"class":834},[345,3014,728],{"class":731},[345,3016,737],{"class":367},[961,3018],{"data":3019,"kind":964},"T2xkIHBhdGggcmVtYXBwZWQgdG86IG15cGFja2FnZS5tb2RlbHMuUmVzTmV0ClVua25vd24gcGF0aCB1bmNoYW5nZWQ6IG15cGFja2FnZS5tb2RlbHMuTmV3TmV0Cldhcm5pbmc6ICdteXBhY2thZ2Uub2xkLlJlc05ldCcgaXMgZGVwcmVjYXRlZDsgYXV0b21hdGljYWxseSByZW1hcHBlZCB0byAnbXlwYWNrYWdlLm1vZGVscy5SZXNOZXQnLiBVcGRhdGUgeW91ciBZQU1MIGNvbmZpZ3MgdG8gdXNlIHRoZSBuZXcgcGF0aC4K",[336,3021,3023],{"className":338,"code":3022,"language":340,"meta":341,"style":341},"# Restore the identity hook:\nlaco._lazy.migrate_target = original_migrate\nprint(\"migrate_target restored to identity hook.\")\n",[231,3024,3025,3030,3047],{"__ignoreMap":341},[345,3026,3027],{"class":347,"line":348},[345,3028,3029],{"class":654},"# Restore the identity hook:\n",[345,3031,3032,3034,3036,3038,3040,3042,3044],{"class":347,"line":359},[345,3033,1160],{"class":355},[345,3035,368],{"class":367},[345,3037,2568],{"class":371},[345,3039,368],{"class":367},[345,3041,292],{"class":371},[345,3043,1259],{"class":712},[345,3045,3046],{"class":355}," original_migrate\n",[345,3048,3049,3051,3053,3055,3058,3060],{"class":347,"line":380},[345,3050,822],{"class":821},[345,3052,724],{"class":367},[345,3054,728],{"class":727},[345,3056,3057],{"class":731},"migrate_target restored to identity hook.",[345,3059,728],{"class":727},[345,3061,737],{"class":367},[961,3063],{"data":3064,"kind":964},"bWlncmF0ZV90YXJnZXQgcmVzdG9yZWQgdG8gaWRlbnRpdHkgaG9vay4K",[1142,3066,3068,3069,3071],{"id":3067},"how-migrate_target-is-called","How ",[231,3070,292],{}," is called",[216,3073,3074,3075,3077,3078,3081,3082,3084,3085,3087,3088,3091,3092,3094],{},"Inside ",[231,3076,588],{}," (via ",[231,3079,3080],{},"laco._lazy","), when a ",[231,3083,406],{}," node has a ",[231,3086,603],{}," key, laco calls ",[231,3089,3090],{},"migrate_target(target_string)"," before attempting the import. If the hook returns a different string, the new string is used for the import. The original ",[231,3093,406],{}," is not mutated.",[216,3096,3097,3100,3101,3104,3105,3108],{},[219,3098,3099],{},"Important:"," only install the hook once near the start of your application (e.g., in your ",[231,3102,3103],{},"__init__.py"," or ",[231,3106,3107],{},"conftest.py","). Installing it multiple times or mid-session can lead to unexpected behavior.",[397,3110,3112,3113,3115],{"id":3111},"section-6-lacocompat-auto-install-backward-compat-shims","Section 6: ",[231,3114,298],{},", auto-install backward-compat shims",[216,3117,3118,3120,3121,3124,3125,3128],{},[231,3119,298],{}," handles a specific backward-compatibility case: 0.x laco configs that used ",[231,3122,3123],{},"_target_: laco.ops.partial"," instead of the Hydra-native ",[231,3126,3127],{},"_partial_: true"," representation.",[216,3130,3131,3132,3134,3135,3137],{},"Importing ",[231,3133,298],{}," is sufficient: it installs the ",[231,3136,292],{}," hook automatically.",[336,3139,3141],{"className":338,"code":3140,"language":340,"meta":341,"style":341},"import laco.compat\nimport warnings\n\n# The hook is installed on import.\n# It does NOT raise an error for the old format — it just warns:\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter(\"always\")\n    result = laco._lazy.migrate_target(\"laco.ops.partial\")\n\nprint(f\"Target after compat hook: {result!r}\")  # 'laco.ops.partial' — returned unchanged\nif w:\n    print(f\"Warning category: {w[0].category.__name__}\")\n    print(f\"Warning message: {w[0].message}\")\n",[231,3142,3143,3154,3160,3164,3169,3174,3200,3218,3245,3249,3276,3284,3318],{"__ignoreMap":341},[345,3144,3145,3147,3149,3151],{"class":347,"line":348},[345,3146,352],{"class":351},[345,3148,364],{"class":355},[345,3150,368],{"class":367},[345,3152,3153],{"class":371},"compat\n",[345,3155,3156,3158],{"class":347,"line":359},[345,3157,352],{"class":351},[345,3159,2545],{"class":355},[345,3161,3162],{"class":347,"line":380},[345,3163,648],{"emptyLinePlaceholder":647},[345,3165,3166],{"class":347,"line":651},[345,3167,3168],{"class":654},"# The hook is installed on import.\n",[345,3170,3171],{"class":347,"line":658},[345,3172,3173],{"class":654},"# It does NOT raise an error for the old format — it just warns:\n",[345,3175,3176,3178,3180,3182,3184,3186,3188,3190,3192,3194,3196,3198],{"class":347,"line":664},[345,3177,2819],{"class":351},[345,3179,2822],{"class":355},[345,3181,368],{"class":367},[345,3183,2827],{"class":720},[345,3185,724],{"class":367},[345,3187,2832],{"class":1170},[345,3189,713],{"class":712},[345,3191,1333],{"class":1289},[345,3193,238],{"class":367},[345,3195,374],{"class":351},[345,3197,2843],{"class":355},[345,3199,1293],{"class":367},[345,3201,3202,3204,3206,3208,3210,3212,3214,3216],{"class":347,"line":670},[345,3203,2851],{"class":355},[345,3205,368],{"class":367},[345,3207,2856],{"class":720},[345,3209,724],{"class":367},[345,3211,728],{"class":727},[345,3213,2863],{"class":731},[345,3215,728],{"class":727},[345,3217,737],{"class":367},[345,3219,3220,3222,3224,3226,3228,3230,3232,3234,3236,3238,3241,3243],{"class":347,"line":676},[345,3221,2873],{"class":355},[345,3223,713],{"class":712},[345,3225,364],{"class":355},[345,3227,368],{"class":367},[345,3229,2568],{"class":371},[345,3231,368],{"class":367},[345,3233,292],{"class":720},[345,3235,724],{"class":367},[345,3237,728],{"class":727},[345,3239,3240],{"class":731},"laco.ops.partial",[345,3242,728],{"class":727},[345,3244,737],{"class":367},[345,3246,3247],{"class":347,"line":682},[345,3248,648],{"emptyLinePlaceholder":647},[345,3250,3251,3253,3255,3257,3260,3262,3264,3267,3269,3271,3273],{"class":347,"line":688},[345,3252,822],{"class":821},[345,3254,724],{"class":367},[345,3256,828],{"class":827},[345,3258,3259],{"class":731},"\"Target after compat hook: ",[345,3261,835],{"class":834},[345,3263,2316],{"class":720},[345,3265,3266],{"class":827},"!r",[345,3268,850],{"class":834},[345,3270,728],{"class":731},[345,3272,238],{"class":367},[345,3274,3275],{"class":654},"  # 'laco.ops.partial' — returned unchanged\n",[345,3277,3278,3280,3282],{"class":347,"line":694},[345,3279,2338],{"class":351},[345,3281,2843],{"class":355},[345,3283,1293],{"class":367},[345,3285,3286,3288,3290,3292,3295,3297,3299,3301,3303,3305,3308,3310,3312,3314,3316],{"class":347,"line":700},[345,3287,953],{"class":821},[345,3289,724],{"class":367},[345,3291,828],{"class":827},[345,3293,3294],{"class":731},"\"Warning category: ",[345,3296,835],{"class":834},[345,3298,2999],{"class":720},[345,3300,1510],{"class":367},[345,3302,3004],{"class":834},[345,3304,3007],{"class":367},[345,3306,3307],{"class":371},"category",[345,3309,368],{"class":367},[345,3311,1686],{"class":1685},[345,3313,850],{"class":834},[345,3315,728],{"class":731},[345,3317,737],{"class":367},[345,3319,3320,3322,3324,3326,3329,3331,3333,3335,3337,3339,3341,3343,3345],{"class":347,"line":706},[345,3321,953],{"class":821},[345,3323,724],{"class":367},[345,3325,828],{"class":827},[345,3327,3328],{"class":731},"\"Warning message: ",[345,3330,835],{"class":834},[345,3332,2999],{"class":720},[345,3334,1510],{"class":367},[345,3336,3004],{"class":834},[345,3338,3007],{"class":367},[345,3340,3010],{"class":371},[345,3342,850],{"class":834},[345,3344,728],{"class":731},[345,3346,737],{"class":367},[961,3348],{"data":3349,"kind":964},"VGFyZ2V0IGFmdGVyIGNvbXBhdCBob29rOiAnbGFjby5vcHMucGFydGlhbCcKV2FybmluZyBjYXRlZ29yeTogRGVwcmVjYXRpb25XYXJuaW5nCldhcm5pbmcgbWVzc2FnZTogJ190YXJnZXRfOiBsYWNvLm9wcy5wYXJ0aWFsJyBpcyBkZXByZWNhdGVkLiBVc2UgJ19wYXJ0aWFsXzogdHJ1ZScgaW5zdGVhZCAoSHlkcmEtbmF0aXZlIHBhcnRpYWwpLiBSdW4gJ2xhY28gZml4JyB0byB1cGRhdGUgY29uZmlncyBhdXRvbWF0aWNhbGx5Lgo=",[336,3351,3353],{"className":338,"code":3352,"language":340,"meta":341,"style":341},"# Uninstall when done (restores identity hook):\nlaco.compat.uninstall()\nprint(\"compat hook uninstalled.\")\nprint(\"migrate_target is now identity:\",\n      laco._lazy.migrate_target is laco._lazy._DEFAULT_MIGRATE_TARGET)\n",[231,3354,3355,3360,3375,3390,3405],{"__ignoreMap":341},[345,3356,3357],{"class":347,"line":348},[345,3358,3359],{"class":654},"# Uninstall when done (restores identity hook):\n",[345,3361,3362,3364,3366,3368,3370,3373],{"class":347,"line":359},[345,3363,1160],{"class":355},[345,3365,368],{"class":367},[345,3367,189],{"class":371},[345,3369,368],{"class":367},[345,3371,3372],{"class":720},"uninstall",[345,3374,862],{"class":367},[345,3376,3377,3379,3381,3383,3386,3388],{"class":347,"line":380},[345,3378,822],{"class":821},[345,3380,724],{"class":367},[345,3382,728],{"class":727},[345,3384,3385],{"class":731},"compat hook uninstalled.",[345,3387,728],{"class":727},[345,3389,737],{"class":367},[345,3391,3392,3394,3396,3398,3401,3403],{"class":347,"line":651},[345,3393,822],{"class":821},[345,3395,724],{"class":367},[345,3397,728],{"class":727},[345,3399,3400],{"class":731},"migrate_target is now identity:",[345,3402,728],{"class":727},[345,3404,1240],{"class":367},[345,3406,3407,3410,3412,3414,3416,3418,3421,3423,3425,3427,3429,3432],{"class":347,"line":658},[345,3408,3409],{"class":720},"      laco",[345,3411,368],{"class":367},[345,3413,2568],{"class":371},[345,3415,368],{"class":367},[345,3417,292],{"class":371},[345,3419,3420],{"class":351}," is",[345,3422,364],{"class":720},[345,3424,368],{"class":367},[345,3426,2568],{"class":371},[345,3428,368],{"class":367},[345,3430,3431],{"class":2573},"_DEFAULT_MIGRATE_TARGET",[345,3433,737],{"class":367},[961,3435],{"data":3436,"kind":964},"Y29tcGF0IGhvb2sgdW5pbnN0YWxsZWQuCm1pZ3JhdGVfdGFyZ2V0IGlzIG5vdyBpZGVudGl0eTogVHJ1ZQo=",[1142,3438,3440],{"id":3439},"workflow-for-0x-1x-migration","Workflow for 0.x → 1.x migration",[216,3442,3443,3446,3447,3450],{},[219,3444,3445],{},"Short-term (during transition):"," Add ",[231,3448,3449],{},"import laco.compat"," near the start of your entry point. Old YAML files work with a deprecation warning.",[216,3452,3453,3456,3457,3460,3461,3463,3464,3466,3467,3469],{},[219,3454,3455],{},"Long-term (cleanup):"," Run ",[231,3458,3459],{},"laco fix \u003Cconfig_dir>"," to update all YAML files in-place, replacing ",[231,3462,3123],{}," with ",[231,3465,3127],{},". Once all configs are updated, remove the ",[231,3468,3449],{}," line.",[397,3471,3473,3474,3476],{"id":3472},"section-7-advanced-lgroup-patterns","Section 7: Advanced ",[231,3475,305],{}," patterns",[1142,3478,3480,3483,3484,3486],{"id":3479},"lbind_strict-luse-statically-checked-bindings",[231,3481,3482],{},"L.bind_strict"," + ",[231,3485,313],{},": statically-checked bindings",[216,3488,3489,3490,3493,3494,3497,3498,3501,3502,3505],{},"Regular ",[231,3491,3492],{},"L.bind(slot, entry)"," provides a runtime mismatch check (raises ",[231,3495,3496],{},"TypeError"," if the groups don't match). ",[231,3499,3500],{},"L.bind_strict(slot, L.use(entry))"," adds ",[219,3503,3504],{},"static checking",": pyright will flag a type mismatch at edit time.",[336,3507,3509],{"className":338,"code":3508,"language":340,"meta":341,"style":341},"# Illustrate the bind_strict + use API:\nfrom laco.language import bind_strict, use, bind, Defaults, self_, slot\n\n# Define two groups with the same element type:\nclass ActivationGroup(L.Group[nn.Module]):\n    relu    = L.call(nn.ReLU)()\n    gelu    = L.call(nn.GELU)()\n    silu    = L.call(nn.SiLU)()\n\nclass NormGroup(L.Group[nn.Module]):\n    layer   = L.call(nn.LayerNorm)(normalized_shape=256)\n\n@L.config\nclass BackboneSchema:\n    hidden:     int       = 256\n    activation: nn.Module = slot(ActivationGroup)\n\n# L.bind — runtime check only:\nbinding_ok   = bind(BackboneSchema.activation, ActivationGroup.gelu)\nprint(\"bind OK  :\", binding_ok)\n\n# L.bind with mismatched groups raises at config-build time:\ntry:\n    bind(BackboneSchema.activation, NormGroup.layer)  # wrong group!\nexcept TypeError as e:\n    print(\"bind mismatch TypeError:\", str(e)[:120])\n",[231,3510,3511,3516,3558,3562,3567,3596,3622,3646,3670,3674,3699,3733,3737,3748,3757,3773,3798,3802,3807,3837,3857,3861,3866,3872,3899,3912],{"__ignoreMap":341},[345,3512,3513],{"class":347,"line":348},[345,3514,3515],{"class":654},"# Illustrate the bind_strict + use API:\n",[345,3517,3518,3521,3523,3525,3528,3530,3533,3535,3538,3540,3543,3545,3548,3550,3553,3555],{"class":347,"line":359},[345,3519,3520],{"class":351},"from",[345,3522,364],{"class":355},[345,3524,368],{"class":367},[345,3526,3527],{"class":355},"language ",[345,3529,352],{"class":351},[345,3531,3532],{"class":355}," bind_strict",[345,3534,800],{"class":367},[345,3536,3537],{"class":355}," use",[345,3539,800],{"class":367},[345,3541,3542],{"class":355}," bind",[345,3544,800],{"class":367},[345,3546,3547],{"class":355}," Defaults",[345,3549,800],{"class":367},[345,3551,3552],{"class":355}," self_",[345,3554,800],{"class":367},[345,3556,3557],{"class":355}," slot\n",[345,3559,3560],{"class":347,"line":380},[345,3561,648],{"emptyLinePlaceholder":647},[345,3563,3564],{"class":347,"line":651},[345,3565,3566],{"class":654},"# Define two groups with the same element type:\n",[345,3568,3569,3572,3576,3578,3580,3582,3585,3587,3589,3591,3593],{"class":347,"line":658},[345,3570,3571],{"class":827},"class",[345,3573,3575],{"class":3574},"sbgvK"," ActivationGroup",[345,3577,724],{"class":367},[345,3579,1189],{"class":3574},[345,3581,368],{"class":367},[345,3583,3584],{"class":371},"Group",[345,3586,1510],{"class":367},[345,3588,390],{"class":371},[345,3590,368],{"class":367},[345,3592,1219],{"class":371},[345,3594,3595],{"class":367},"]):\n",[345,3597,3598,3601,3603,3606,3608,3610,3612,3614,3616,3619],{"class":347,"line":664},[345,3599,3600],{"class":355},"    relu    ",[345,3602,713],{"class":712},[345,3604,3605],{"class":355}," L",[345,3607,368],{"class":367},[345,3609,1625],{"class":720},[345,3611,724],{"class":367},[345,3613,390],{"class":720},[345,3615,368],{"class":367},[345,3617,3618],{"class":371},"ReLU",[345,3620,3621],{"class":367},")()\n",[345,3623,3624,3627,3629,3631,3633,3635,3637,3639,3641,3644],{"class":347,"line":670},[345,3625,3626],{"class":355},"    gelu    ",[345,3628,713],{"class":712},[345,3630,3605],{"class":355},[345,3632,368],{"class":367},[345,3634,1625],{"class":720},[345,3636,724],{"class":367},[345,3638,390],{"class":720},[345,3640,368],{"class":367},[345,3642,3643],{"class":2573},"GELU",[345,3645,3621],{"class":367},[345,3647,3648,3651,3653,3655,3657,3659,3661,3663,3665,3668],{"class":347,"line":676},[345,3649,3650],{"class":355},"    silu    ",[345,3652,713],{"class":712},[345,3654,3605],{"class":355},[345,3656,368],{"class":367},[345,3658,1625],{"class":720},[345,3660,724],{"class":367},[345,3662,390],{"class":720},[345,3664,368],{"class":367},[345,3666,3667],{"class":371},"SiLU",[345,3669,3621],{"class":367},[345,3671,3672],{"class":347,"line":682},[345,3673,648],{"emptyLinePlaceholder":647},[345,3675,3676,3678,3681,3683,3685,3687,3689,3691,3693,3695,3697],{"class":347,"line":688},[345,3677,3571],{"class":827},[345,3679,3680],{"class":3574}," NormGroup",[345,3682,724],{"class":367},[345,3684,1189],{"class":3574},[345,3686,368],{"class":367},[345,3688,3584],{"class":371},[345,3690,1510],{"class":367},[345,3692,390],{"class":371},[345,3694,368],{"class":367},[345,3696,1219],{"class":371},[345,3698,3595],{"class":367},[345,3700,3701,3704,3706,3708,3710,3712,3714,3716,3718,3721,3723,3726,3728,3731],{"class":347,"line":694},[345,3702,3703],{"class":355},"    layer   ",[345,3705,713],{"class":712},[345,3707,3605],{"class":355},[345,3709,368],{"class":367},[345,3711,1625],{"class":720},[345,3713,724],{"class":367},[345,3715,390],{"class":720},[345,3717,368],{"class":367},[345,3719,3720],{"class":371},"LayerNorm",[345,3722,1637],{"class":367},[345,3724,3725],{"class":1170},"normalized_shape",[345,3727,713],{"class":712},[345,3729,3730],{"class":834},"256",[345,3732,737],{"class":367},[345,3734,3735],{"class":347,"line":700},[345,3736,648],{"emptyLinePlaceholder":647},[345,3738,3739,3741,3743,3745],{"class":347,"line":706},[345,3740,1156],{"class":1155},[345,3742,1189],{"class":1159},[345,3744,368],{"class":1155},[345,3746,3747],{"class":1159},"config\n",[345,3749,3750,3752,3755],{"class":347,"line":740},[345,3751,3571],{"class":827},[345,3753,3754],{"class":3574}," BackboneSchema",[345,3756,1293],{"class":367},[345,3758,3759,3762,3764,3767,3770],{"class":347,"line":745},[345,3760,3761],{"class":355},"    hidden",[345,3763,1211],{"class":367},[345,3765,3766],{"class":1255},"     int",[345,3768,3769],{"class":712},"       =",[345,3771,3772],{"class":834}," 256\n",[345,3774,3775,3778,3780,3782,3784,3786,3788,3791,3793,3796],{"class":347,"line":751},[345,3776,3777],{"class":355},"    activation",[345,3779,1211],{"class":367},[345,3781,1214],{"class":355},[345,3783,368],{"class":367},[345,3785,1219],{"class":371},[345,3787,1259],{"class":712},[345,3789,3790],{"class":720}," slot",[345,3792,724],{"class":367},[345,3794,3795],{"class":720},"ActivationGroup",[345,3797,737],{"class":367},[345,3799,3800],{"class":347,"line":780},[345,3801,648],{"emptyLinePlaceholder":647},[345,3803,3804],{"class":347,"line":818},[345,3805,3806],{"class":654},"# L.bind — runtime check only:\n",[345,3808,3809,3812,3814,3816,3818,3821,3823,3826,3828,3830,3832,3835],{"class":347,"line":857},[345,3810,3811],{"class":355},"binding_ok   ",[345,3813,713],{"class":712},[345,3815,3542],{"class":720},[345,3817,724],{"class":367},[345,3819,3820],{"class":720},"BackboneSchema",[345,3822,368],{"class":367},[345,3824,3825],{"class":371},"activation",[345,3827,800],{"class":367},[345,3829,3575],{"class":720},[345,3831,368],{"class":367},[345,3833,3834],{"class":371},"gelu",[345,3836,737],{"class":367},[345,3838,3839,3841,3843,3845,3848,3850,3852,3855],{"class":347,"line":865},[345,3840,822],{"class":821},[345,3842,724],{"class":367},[345,3844,728],{"class":727},[345,3846,3847],{"class":731},"bind OK  :",[345,3849,728],{"class":727},[345,3851,800],{"class":367},[345,3853,3854],{"class":720}," binding_ok",[345,3856,737],{"class":367},[345,3858,3859],{"class":347,"line":870},[345,3860,648],{"emptyLinePlaceholder":647},[345,3862,3863],{"class":347,"line":876},[345,3864,3865],{"class":654},"# L.bind with mismatched groups raises at config-build time:\n",[345,3867,3868,3870],{"class":347,"line":905},[345,3869,1740],{"class":351},[345,3871,1293],{"class":367},[345,3873,3874,3877,3879,3881,3883,3885,3887,3889,3891,3894,3896],{"class":347,"line":921},[345,3875,3876],{"class":720},"    bind",[345,3878,724],{"class":367},[345,3880,3820],{"class":720},[345,3882,368],{"class":367},[345,3884,3825],{"class":371},[345,3886,800],{"class":367},[345,3888,3680],{"class":720},[345,3890,368],{"class":367},[345,3892,3893],{"class":371},"layer",[345,3895,238],{"class":367},[345,3897,3898],{"class":654},"  # wrong group!\n",[345,3900,3901,3903,3906,3908,3910],{"class":347,"line":950},[345,3902,1763],{"class":351},[345,3904,3905],{"class":1255}," TypeError",[345,3907,374],{"class":351},[345,3909,1771],{"class":355},[345,3911,1293],{"class":367},[345,3913,3914,3916,3918,3920,3923,3925,3927,3929,3931,3933,3935,3938],{"class":347,"line":2150},[345,3915,953],{"class":821},[345,3917,724],{"class":367},[345,3919,728],{"class":727},[345,3921,3922],{"class":731},"bind mismatch TypeError:",[345,3924,728],{"class":727},[345,3926,800],{"class":367},[345,3928,1272],{"class":1255},[345,3930,724],{"class":367},[345,3932,1805],{"class":720},[345,3934,1808],{"class":367},[345,3936,3937],{"class":834},"120",[345,3939,1726],{"class":367},[961,3941],{"data":3942,"kind":964},"YmluZCBPSyAgOiBEZWZhdWx0c0JpbmRpbmcoZ3JvdXA9J2FjdGl2YXRpb25ncm91cCcsIG5hbWU9J2dlbHUnLCBwYWNrYWdlPSdhY3RpdmF0aW9uJykKYmluZCBtaXNtYXRjaCBUeXBlRXJyb3I6IGJpbmQoKSB0eXBlIG1pc21hdGNoOiBzbG90IGlzIGJvdW5kIHRvIGdyb3VwICdhY3RpdmF0aW9uZ3JvdXAnIGJ1dCBlbnRyeSAnbGF5ZXInIGJlbG9uZ3MgdG8gZ3JvdXAgJ25vcm1ncm91cCcuCg==",[336,3944,3946],{"className":338,"code":3945,"language":340,"meta":341,"style":341},"# L.bind_strict — also requires L.use() wrapper on the entry:\nbinding_strict = bind_strict(BackboneSchema.activation, use(ActivationGroup.relu))\nprint(\"bind_strict OK:\", binding_strict)\n\n# At STATIC analysis time (pyright), this would also be caught:\n# bind_strict(BackboneSchema.activation, use(NormGroup.layer))  # \u003C-- pyright error\n# The invariant EntryRef[T] parameter forces the type mismatch to surface.\nprint()\nprint(\"L.use() at runtime is identity (returns the entry unchanged):\")\nimport laco._groups\nentry = ActivationGroup.relu\nwrapped = use(entry)\nprint(f\"  entry is use(entry): {entry is wrapped}\")\n",[231,3947,3948,3953,3986,4006,4010,4015,4020,4025,4031,4046,4057,4071,4087],{"__ignoreMap":341},[345,3949,3950],{"class":347,"line":348},[345,3951,3952],{"class":654},"# L.bind_strict — also requires L.use() wrapper on the entry:\n",[345,3954,3955,3958,3960,3962,3964,3966,3968,3970,3972,3974,3976,3978,3980,3983],{"class":347,"line":359},[345,3956,3957],{"class":355},"binding_strict ",[345,3959,713],{"class":712},[345,3961,3532],{"class":720},[345,3963,724],{"class":367},[345,3965,3820],{"class":720},[345,3967,368],{"class":367},[345,3969,3825],{"class":371},[345,3971,800],{"class":367},[345,3973,3537],{"class":720},[345,3975,724],{"class":367},[345,3977,3795],{"class":720},[345,3979,368],{"class":367},[345,3981,3982],{"class":371},"relu",[345,3984,3985],{"class":367},"))\n",[345,3987,3988,3990,3992,3994,3997,3999,4001,4004],{"class":347,"line":380},[345,3989,822],{"class":821},[345,3991,724],{"class":367},[345,3993,728],{"class":727},[345,3995,3996],{"class":731},"bind_strict OK:",[345,3998,728],{"class":727},[345,4000,800],{"class":367},[345,4002,4003],{"class":720}," binding_strict",[345,4005,737],{"class":367},[345,4007,4008],{"class":347,"line":651},[345,4009,648],{"emptyLinePlaceholder":647},[345,4011,4012],{"class":347,"line":658},[345,4013,4014],{"class":654},"# At STATIC analysis time (pyright), this would also be caught:\n",[345,4016,4017],{"class":347,"line":664},[345,4018,4019],{"class":654},"# bind_strict(BackboneSchema.activation, use(NormGroup.layer))  # \u003C-- pyright error\n",[345,4021,4022],{"class":347,"line":670},[345,4023,4024],{"class":654},"# The invariant EntryRef[T] parameter forces the type mismatch to surface.\n",[345,4026,4027,4029],{"class":347,"line":676},[345,4028,822],{"class":821},[345,4030,862],{"class":367},[345,4032,4033,4035,4037,4039,4042,4044],{"class":347,"line":682},[345,4034,822],{"class":821},[345,4036,724],{"class":367},[345,4038,728],{"class":727},[345,4040,4041],{"class":731},"L.use() at runtime is identity (returns the entry unchanged):",[345,4043,728],{"class":727},[345,4045,737],{"class":367},[345,4047,4048,4050,4052,4054],{"class":347,"line":688},[345,4049,352],{"class":351},[345,4051,364],{"class":355},[345,4053,368],{"class":367},[345,4055,4056],{"class":371},"_groups\n",[345,4058,4059,4062,4064,4066,4068],{"class":347,"line":694},[345,4060,4061],{"class":355},"entry ",[345,4063,713],{"class":712},[345,4065,3575],{"class":355},[345,4067,368],{"class":367},[345,4069,4070],{"class":371},"relu\n",[345,4072,4073,4076,4078,4080,4082,4085],{"class":347,"line":700},[345,4074,4075],{"class":355},"wrapped ",[345,4077,713],{"class":712},[345,4079,3537],{"class":720},[345,4081,724],{"class":367},[345,4083,4084],{"class":720},"entry",[345,4086,737],{"class":367},[345,4088,4089,4091,4093,4095,4098,4100,4102,4105,4108,4110,4112],{"class":347,"line":706},[345,4090,822],{"class":821},[345,4092,724],{"class":367},[345,4094,828],{"class":827},[345,4096,4097],{"class":731},"\"  entry is use(entry): ",[345,4099,835],{"class":834},[345,4101,4061],{"class":720},[345,4103,4104],{"class":712},"is",[345,4106,4107],{"class":720}," wrapped",[345,4109,850],{"class":834},[345,4111,728],{"class":731},[345,4113,737],{"class":367},[961,4115],{"data":4116,"kind":964},"YmluZF9zdHJpY3QgT0s6IERlZmF1bHRzQmluZGluZyhncm91cD0nYWN0aXZhdGlvbmdyb3VwJywgbmFtZT0ncmVsdScsIHBhY2thZ2U9J2FjdGl2YXRpb24nKQoKTC51c2UoKSBhdCBydW50aW1lIGlzIGlkZW50aXR5IChyZXR1cm5zIHRoZSBlbnRyeSB1bmNoYW5nZWQpOgogIGVudHJ5IGlzIHVzZShlbnRyeSk6IFRydWUK",[1142,4118,4120,4122],{"id":4119},"modeextend-adding-entries-to-an-existing-group",[231,4121,316],{},": adding entries to an existing group",[216,4124,4125,4126,3463,4128,4130],{},"A subclass of ",[231,4127,305],{},[231,4129,316],{}," inherits the parent group's name and entries, then adds more. This is useful for plugin-style architectures where downstream packages extend a core group.",[336,4132,4134],{"className":338,"code":4133,"language":340,"meta":341,"style":341},"# Base group (defined in core library):\nclass LossGroup(L.Group[nn.Module]):\n    cross_entropy  = L.call(nn.CrossEntropyLoss)()\n    mse            = L.call(nn.MSELoss)()\n\n# Extension group (defined in a downstream package or plugin):\nclass MoreLosses(LossGroup, mode=\"extend\"):\n    huber          = L.call(nn.HuberLoss)()\n    bce_logits     = L.call(nn.BCEWithLogitsLoss)()\n\n# All entries are accessible from the extension:\nprint(\"LossGroup entries    :\", [k for k in vars(LossGroup) if not k.startswith('_')])\nprint(\"MoreLosses entries   :\", [k for k in vars(MoreLosses) if not k.startswith('_')])\nprint()\n# Can build a node for the new entries:\nprint(laco.dump(MoreLosses.huber))\n",[231,4135,4136,4141,4166,4190,4214,4218,4223,4251,4275,4299,4303,4308,4371,4425,4431,4436],{"__ignoreMap":341},[345,4137,4138],{"class":347,"line":348},[345,4139,4140],{"class":654},"# Base group (defined in core library):\n",[345,4142,4143,4145,4148,4150,4152,4154,4156,4158,4160,4162,4164],{"class":347,"line":359},[345,4144,3571],{"class":827},[345,4146,4147],{"class":3574}," LossGroup",[345,4149,724],{"class":367},[345,4151,1189],{"class":3574},[345,4153,368],{"class":367},[345,4155,3584],{"class":371},[345,4157,1510],{"class":367},[345,4159,390],{"class":371},[345,4161,368],{"class":367},[345,4163,1219],{"class":371},[345,4165,3595],{"class":367},[345,4167,4168,4171,4173,4175,4177,4179,4181,4183,4185,4188],{"class":347,"line":380},[345,4169,4170],{"class":355},"    cross_entropy  ",[345,4172,713],{"class":712},[345,4174,3605],{"class":355},[345,4176,368],{"class":367},[345,4178,1625],{"class":720},[345,4180,724],{"class":367},[345,4182,390],{"class":720},[345,4184,368],{"class":367},[345,4186,4187],{"class":371},"CrossEntropyLoss",[345,4189,3621],{"class":367},[345,4191,4192,4195,4197,4199,4201,4203,4205,4207,4209,4212],{"class":347,"line":651},[345,4193,4194],{"class":355},"    mse            ",[345,4196,713],{"class":712},[345,4198,3605],{"class":355},[345,4200,368],{"class":367},[345,4202,1625],{"class":720},[345,4204,724],{"class":367},[345,4206,390],{"class":720},[345,4208,368],{"class":367},[345,4210,4211],{"class":371},"MSELoss",[345,4213,3621],{"class":367},[345,4215,4216],{"class":347,"line":658},[345,4217,648],{"emptyLinePlaceholder":647},[345,4219,4220],{"class":347,"line":664},[345,4221,4222],{"class":654},"# Extension group (defined in a downstream package or plugin):\n",[345,4224,4225,4227,4230,4232,4235,4237,4240,4242,4244,4247,4249],{"class":347,"line":670},[345,4226,3571],{"class":827},[345,4228,4229],{"class":3574}," MoreLosses",[345,4231,724],{"class":367},[345,4233,4234],{"class":3574},"LossGroup",[345,4236,800],{"class":367},[345,4238,4239],{"class":1170}," mode",[345,4241,713],{"class":712},[345,4243,728],{"class":727},[345,4245,4246],{"class":731},"extend",[345,4248,728],{"class":727},[345,4250,2658],{"class":367},[345,4252,4253,4256,4258,4260,4262,4264,4266,4268,4270,4273],{"class":347,"line":676},[345,4254,4255],{"class":355},"    huber          ",[345,4257,713],{"class":712},[345,4259,3605],{"class":355},[345,4261,368],{"class":367},[345,4263,1625],{"class":720},[345,4265,724],{"class":367},[345,4267,390],{"class":720},[345,4269,368],{"class":367},[345,4271,4272],{"class":371},"HuberLoss",[345,4274,3621],{"class":367},[345,4276,4277,4280,4282,4284,4286,4288,4290,4292,4294,4297],{"class":347,"line":682},[345,4278,4279],{"class":355},"    bce_logits     ",[345,4281,713],{"class":712},[345,4283,3605],{"class":355},[345,4285,368],{"class":367},[345,4287,1625],{"class":720},[345,4289,724],{"class":367},[345,4291,390],{"class":720},[345,4293,368],{"class":367},[345,4295,4296],{"class":371},"BCEWithLogitsLoss",[345,4298,3621],{"class":367},[345,4300,4301],{"class":347,"line":688},[345,4302,648],{"emptyLinePlaceholder":647},[345,4304,4305],{"class":347,"line":694},[345,4306,4307],{"class":654},"# All entries are accessible from the extension:\n",[345,4309,4310,4312,4314,4316,4319,4321,4323,4326,4329,4331,4334,4336,4339,4341,4343,4345,4348,4351,4354,4356,4359,4361,4363,4366,4368],{"class":347,"line":700},[345,4311,822],{"class":821},[345,4313,724],{"class":367},[345,4315,728],{"class":727},[345,4317,4318],{"class":731},"LossGroup entries    :",[345,4320,728],{"class":727},[345,4322,800],{"class":367},[345,4324,4325],{"class":367}," [",[345,4327,4328],{"class":720},"k ",[345,4330,924],{"class":351},[345,4332,4333],{"class":720}," k ",[345,4335,930],{"class":351},[345,4337,4338],{"class":821}," vars",[345,4340,724],{"class":367},[345,4342,4234],{"class":720},[345,4344,238],{"class":367},[345,4346,4347],{"class":351}," if",[345,4349,4350],{"class":712}," not",[345,4352,4353],{"class":720}," k",[345,4355,368],{"class":367},[345,4357,4358],{"class":720},"startswith",[345,4360,724],{"class":367},[345,4362,847],{"class":727},[345,4364,4365],{"class":731},"_",[345,4367,847],{"class":727},[345,4369,4370],{"class":367},")])\n",[345,4372,4373,4375,4377,4379,4382,4384,4386,4388,4390,4392,4394,4396,4398,4400,4403,4405,4407,4409,4411,4413,4415,4417,4419,4421,4423],{"class":347,"line":706},[345,4374,822],{"class":821},[345,4376,724],{"class":367},[345,4378,728],{"class":727},[345,4380,4381],{"class":731},"MoreLosses entries   :",[345,4383,728],{"class":727},[345,4385,800],{"class":367},[345,4387,4325],{"class":367},[345,4389,4328],{"class":720},[345,4391,924],{"class":351},[345,4393,4333],{"class":720},[345,4395,930],{"class":351},[345,4397,4338],{"class":821},[345,4399,724],{"class":367},[345,4401,4402],{"class":720},"MoreLosses",[345,4404,238],{"class":367},[345,4406,4347],{"class":351},[345,4408,4350],{"class":712},[345,4410,4353],{"class":720},[345,4412,368],{"class":367},[345,4414,4358],{"class":720},[345,4416,724],{"class":367},[345,4418,847],{"class":727},[345,4420,4365],{"class":731},[345,4422,847],{"class":727},[345,4424,4370],{"class":367},[345,4426,4427,4429],{"class":347,"line":740},[345,4428,822],{"class":821},[345,4430,862],{"class":367},[345,4432,4433],{"class":347,"line":745},[345,4434,4435],{"class":654},"# Can build a node for the new entries:\n",[345,4437,4438,4440,4442,4444,4446,4448,4450,4452,4454,4457],{"class":347,"line":751},[345,4439,822],{"class":821},[345,4441,724],{"class":367},[345,4443,1160],{"class":720},[345,4445,368],{"class":367},[345,4447,1022],{"class":720},[345,4449,724],{"class":367},[345,4451,4402],{"class":720},[345,4453,368],{"class":367},[345,4455,4456],{"class":371},"huber",[345,4458,3985],{"class":367},[961,4460],{"data":4461,"kind":964},"TG9zc0dyb3VwIGVudHJpZXMgICAgOiBbJ2Nyb3NzX2VudHJvcHknLCAnbXNlJ10KTW9yZUxvc3NlcyBlbnRyaWVzICAgOiBbJ2h1YmVyJywgJ2JjZV9sb2dpdHMnXQoKe19jb252ZXJ0XzogYWxsLCBfbGFjb186IDEsIF90YXJnZXRfOiB0b3JjaC5ubi5IdWJlckxvc3N9Cgo=",[1142,4463,4465,4467],{"id":4464},"ldelete-removing-entries-from-the-defaults-list",[231,4466,319],{},": removing entries from the defaults list",[216,4469,4470,4473,4474,4477],{},[231,4471,4472],{},"L.delete(group_name)"," produces a Hydra ",[231,4475,4476],{},"~group_name"," defaults-list entry, which removes a previously-composed config group from the merge. Useful when inheriting a defaults list and needing to exclude an entry.",[336,4479,4481],{"className":338,"code":4480,"language":340,"meta":341,"style":341},"from laco.language import delete, Defaults, self_\n\n# L.delete produces the Hydra ~group removal entry:\ndel_entry = delete(\"logger\")\nprint(\"L.delete('logger'):\", del_entry)\nprint(\"Type:\", type(del_entry).__name__)\n\n# Using it in a Defaults list:\n# defaults = Defaults(self_, delete(\"logger\"), bind(Schema.optimizer, OptimizerGroup.adam))\n# This would:\n#   1. position self_ (the schema config) in the merge order\n#   2. remove the 'logger' group from the composed config\n#   3. select 'adam' from OptimizerGroup\nprint()\nprint(\"Typical Defaults usage:\")\nprint(\"  Defaults(self_,\")\nprint(\"          delete('logger'),\")\nprint(\"          bind(Schema.optimizer, OptimizerGroup.adam))\")\n",[231,4482,4483,4507,4511,4516,4536,4556,4584,4588,4593,4598,4603,4608,4613,4618,4624,4639,4654,4669],{"__ignoreMap":341},[345,4484,4485,4487,4489,4491,4493,4495,4498,4500,4502,4504],{"class":347,"line":348},[345,4486,3520],{"class":351},[345,4488,364],{"class":355},[345,4490,368],{"class":367},[345,4492,3527],{"class":355},[345,4494,352],{"class":351},[345,4496,4497],{"class":355}," delete",[345,4499,800],{"class":367},[345,4501,3547],{"class":355},[345,4503,800],{"class":367},[345,4505,4506],{"class":355}," self_\n",[345,4508,4509],{"class":347,"line":359},[345,4510,648],{"emptyLinePlaceholder":647},[345,4512,4513],{"class":347,"line":380},[345,4514,4515],{"class":654},"# L.delete produces the Hydra ~group removal entry:\n",[345,4517,4518,4521,4523,4525,4527,4529,4532,4534],{"class":347,"line":651},[345,4519,4520],{"class":355},"del_entry ",[345,4522,713],{"class":712},[345,4524,4497],{"class":720},[345,4526,724],{"class":367},[345,4528,728],{"class":727},[345,4530,4531],{"class":731},"logger",[345,4533,728],{"class":727},[345,4535,737],{"class":367},[345,4537,4538,4540,4542,4544,4547,4549,4551,4554],{"class":347,"line":658},[345,4539,822],{"class":821},[345,4541,724],{"class":367},[345,4543,728],{"class":727},[345,4545,4546],{"class":731},"L.delete('logger'):",[345,4548,728],{"class":727},[345,4550,800],{"class":367},[345,4552,4553],{"class":720}," del_entry",[345,4555,737],{"class":367},[345,4557,4558,4560,4562,4564,4567,4569,4571,4573,4575,4578,4580,4582],{"class":347,"line":664},[345,4559,822],{"class":821},[345,4561,724],{"class":367},[345,4563,728],{"class":727},[345,4565,4566],{"class":731},"Type:",[345,4568,728],{"class":727},[345,4570,800],{"class":367},[345,4572,1675],{"class":1255},[345,4574,724],{"class":367},[345,4576,4577],{"class":720},"del_entry",[345,4579,897],{"class":367},[345,4581,1686],{"class":1685},[345,4583,737],{"class":367},[345,4585,4586],{"class":347,"line":670},[345,4587,648],{"emptyLinePlaceholder":647},[345,4589,4590],{"class":347,"line":676},[345,4591,4592],{"class":654},"# Using it in a Defaults list:\n",[345,4594,4595],{"class":347,"line":682},[345,4596,4597],{"class":654},"# defaults = Defaults(self_, delete(\"logger\"), bind(Schema.optimizer, OptimizerGroup.adam))\n",[345,4599,4600],{"class":347,"line":688},[345,4601,4602],{"class":654},"# This would:\n",[345,4604,4605],{"class":347,"line":694},[345,4606,4607],{"class":654},"#   1. position self_ (the schema config) in the merge order\n",[345,4609,4610],{"class":347,"line":700},[345,4611,4612],{"class":654},"#   2. remove the 'logger' group from the composed config\n",[345,4614,4615],{"class":347,"line":706},[345,4616,4617],{"class":654},"#   3. select 'adam' from OptimizerGroup\n",[345,4619,4620,4622],{"class":347,"line":740},[345,4621,822],{"class":821},[345,4623,862],{"class":367},[345,4625,4626,4628,4630,4632,4635,4637],{"class":347,"line":745},[345,4627,822],{"class":821},[345,4629,724],{"class":367},[345,4631,728],{"class":727},[345,4633,4634],{"class":731},"Typical Defaults usage:",[345,4636,728],{"class":727},[345,4638,737],{"class":367},[345,4640,4641,4643,4645,4647,4650,4652],{"class":347,"line":751},[345,4642,822],{"class":821},[345,4644,724],{"class":367},[345,4646,728],{"class":727},[345,4648,4649],{"class":731},"  Defaults(self_,",[345,4651,728],{"class":727},[345,4653,737],{"class":367},[345,4655,4656,4658,4660,4662,4665,4667],{"class":347,"line":780},[345,4657,822],{"class":821},[345,4659,724],{"class":367},[345,4661,728],{"class":727},[345,4663,4664],{"class":731},"          delete('logger'),",[345,4666,728],{"class":727},[345,4668,737],{"class":367},[345,4670,4671,4673,4675,4677,4680,4682],{"class":347,"line":818},[345,4672,822],{"class":821},[345,4674,724],{"class":367},[345,4676,728],{"class":727},[345,4678,4679],{"class":731},"          bind(Schema.optimizer, OptimizerGroup.adam))",[345,4681,728],{"class":727},[345,4683,737],{"class":367},[961,4685],{"data":4686,"kind":964},"TC5kZWxldGUoJ2xvZ2dlcicpOiB+bG9nZ2VyClR5cGU6IHN0cgoKVHlwaWNhbCBEZWZhdWx0cyB1c2FnZToKICBEZWZhdWx0cyhzZWxmXywKICAgICAgICAgIGRlbGV0ZSgnbG9nZ2VyJyksCiAgICAgICAgICBiaW5kKFNjaGVtYS5vcHRpbWl6ZXIsIE9wdGltaXplckdyb3VwLmFkYW0pKQo=",[397,4688,4690],{"id":4689},"section-8-a-full-production-config-pattern","Section 8: A full production config pattern",[216,4692,4693,4694,4696,4697,4700,4701,4704],{},"Here is a complete, self-contained example bringing together typed groups (",[231,4695,305],{},"), a typed schema (",[231,4698,4699],{},"@L.config","), a task function (",[231,4702,4703],{},"@L.task","), and the reproducibility workflow. No external files needed.",[336,4706,4708],{"className":338,"code":4707,"language":340,"meta":341,"style":341},"import torch.nn as nn\nimport torch.optim as optim\nimport laco\nimport laco.language as L\nfrom laco.language import bind, Defaults, self_, slot\n\n# ================================================================\n# 1. Config groups: swappable components\n# ================================================================\n\nclass OptimizerGroup(L.Group[object]):  # object base since partial is not nn.Module\n    adam = L.partial(optim.Adam)(lr=1e-3, weight_decay=1e-5)\n    sgd  = L.partial(optim.SGD)(lr=1e-2, momentum=0.9)\n\nclass ModelGroup(L.Group[nn.Module]):\n    small  = L.call(nn.Linear)(in_features=64,  out_features=10)\n    medium = L.call(nn.Linear)(in_features=256, out_features=10)\n\n# ================================================================\n# 2. Typed schema: validates fields at compose time\n# ================================================================\n\n@L.config\nclass TrainSchema:\n    epochs:     int    = 10\n    batch_size: int    = 32\n    optimizer:  object = slot(OptimizerGroup)\n    model:      nn.Module = slot(ModelGroup)\n\n# ================================================================\n# 3. Defaults list: select concrete entries\n# ================================================================\n\ndefaults = Defaults(\n    self_,\n    bind(TrainSchema.optimizer, OptimizerGroup.adam),\n    bind(TrainSchema.model,     ModelGroup.small),\n)\n\nprint(\"Schema:\", TrainSchema)\nprint(\"Defaults:\", defaults)\n",[231,4709,4710,4724,4740,4746,4760,4786,4790,4795,4800,4804,4808,4834,4879,4922,4926,4951,4993,5032,5036,5040,5045,5049,5053,5063,5072,5087,5101,5122,5147,5151,5155,5160,5164,5168,5179,5186,5212,5236,5241,5246,5266],{"__ignoreMap":341},[345,4711,4712,4714,4716,4718,4720,4722],{"class":347,"line":348},[345,4713,352],{"class":351},[345,4715,385],{"class":355},[345,4717,368],{"class":367},[345,4719,390],{"class":371},[345,4721,374],{"class":351},[345,4723,395],{"class":355},[345,4725,4726,4728,4730,4732,4735,4737],{"class":347,"line":359},[345,4727,352],{"class":351},[345,4729,385],{"class":355},[345,4731,368],{"class":367},[345,4733,4734],{"class":371},"optim",[345,4736,374],{"class":351},[345,4738,4739],{"class":355}," optim\n",[345,4741,4742,4744],{"class":347,"line":380},[345,4743,352],{"class":351},[345,4745,356],{"class":355},[345,4747,4748,4750,4752,4754,4756,4758],{"class":347,"line":651},[345,4749,352],{"class":351},[345,4751,364],{"class":355},[345,4753,368],{"class":367},[345,4755,198],{"class":371},[345,4757,374],{"class":351},[345,4759,377],{"class":355},[345,4761,4762,4764,4766,4768,4770,4772,4774,4776,4778,4780,4782,4784],{"class":347,"line":658},[345,4763,3520],{"class":351},[345,4765,364],{"class":355},[345,4767,368],{"class":367},[345,4769,3527],{"class":355},[345,4771,352],{"class":351},[345,4773,3542],{"class":355},[345,4775,800],{"class":367},[345,4777,3547],{"class":355},[345,4779,800],{"class":367},[345,4781,3552],{"class":355},[345,4783,800],{"class":367},[345,4785,3557],{"class":355},[345,4787,4788],{"class":347,"line":664},[345,4789,648],{"emptyLinePlaceholder":647},[345,4791,4792],{"class":347,"line":670},[345,4793,4794],{"class":654},"# ================================================================\n",[345,4796,4797],{"class":347,"line":676},[345,4798,4799],{"class":654},"# 1. Config groups: swappable components\n",[345,4801,4802],{"class":347,"line":682},[345,4803,4794],{"class":654},[345,4805,4806],{"class":347,"line":688},[345,4807,648],{"emptyLinePlaceholder":647},[345,4809,4810,4812,4815,4817,4819,4821,4823,4825,4828,4831],{"class":347,"line":694},[345,4811,3571],{"class":827},[345,4813,4814],{"class":3574}," OptimizerGroup",[345,4816,724],{"class":367},[345,4818,1189],{"class":3574},[345,4820,368],{"class":367},[345,4822,3584],{"class":371},[345,4824,1510],{"class":367},[345,4826,4827],{"class":1255},"object",[345,4829,4830],{"class":367},"]):",[345,4832,4833],{"class":654},"  # object base since partial is not nn.Module\n",[345,4835,4836,4839,4841,4843,4845,4848,4850,4852,4854,4857,4859,4862,4864,4867,4869,4872,4874,4877],{"class":347,"line":700},[345,4837,4838],{"class":355},"    adam ",[345,4840,713],{"class":712},[345,4842,3605],{"class":355},[345,4844,368],{"class":367},[345,4846,4847],{"class":720},"partial",[345,4849,724],{"class":367},[345,4851,4734],{"class":720},[345,4853,368],{"class":367},[345,4855,4856],{"class":371},"Adam",[345,4858,1637],{"class":367},[345,4860,4861],{"class":1170},"lr",[345,4863,713],{"class":712},[345,4865,4866],{"class":834},"1e-3",[345,4868,800],{"class":367},[345,4870,4871],{"class":1170}," weight_decay",[345,4873,713],{"class":712},[345,4875,4876],{"class":834},"1e-5",[345,4878,737],{"class":367},[345,4880,4881,4884,4886,4888,4890,4892,4894,4896,4898,4901,4903,4905,4907,4910,4912,4915,4917,4920],{"class":347,"line":706},[345,4882,4883],{"class":355},"    sgd  ",[345,4885,713],{"class":712},[345,4887,3605],{"class":355},[345,4889,368],{"class":367},[345,4891,4847],{"class":720},[345,4893,724],{"class":367},[345,4895,4734],{"class":720},[345,4897,368],{"class":367},[345,4899,4900],{"class":2573},"SGD",[345,4902,1637],{"class":367},[345,4904,4861],{"class":1170},[345,4906,713],{"class":712},[345,4908,4909],{"class":834},"1e-2",[345,4911,800],{"class":367},[345,4913,4914],{"class":1170}," momentum",[345,4916,713],{"class":712},[345,4918,4919],{"class":834},"0.9",[345,4921,737],{"class":367},[345,4923,4924],{"class":347,"line":740},[345,4925,648],{"emptyLinePlaceholder":647},[345,4927,4928,4930,4933,4935,4937,4939,4941,4943,4945,4947,4949],{"class":347,"line":745},[345,4929,3571],{"class":827},[345,4931,4932],{"class":3574}," ModelGroup",[345,4934,724],{"class":367},[345,4936,1189],{"class":3574},[345,4938,368],{"class":367},[345,4940,3584],{"class":371},[345,4942,1510],{"class":367},[345,4944,390],{"class":371},[345,4946,368],{"class":367},[345,4948,1219],{"class":371},[345,4950,3595],{"class":367},[345,4952,4953,4956,4958,4960,4962,4964,4966,4968,4970,4972,4974,4976,4978,4981,4983,4986,4988,4991],{"class":347,"line":751},[345,4954,4955],{"class":355},"    small  ",[345,4957,713],{"class":712},[345,4959,3605],{"class":355},[345,4961,368],{"class":367},[345,4963,1625],{"class":720},[345,4965,724],{"class":367},[345,4967,390],{"class":720},[345,4969,368],{"class":367},[345,4971,1634],{"class":371},[345,4973,1637],{"class":367},[345,4975,1640],{"class":1170},[345,4977,713],{"class":712},[345,4979,4980],{"class":834},"64",[345,4982,800],{"class":367},[345,4984,4985],{"class":1170},"  out_features",[345,4987,713],{"class":712},[345,4989,4990],{"class":834},"10",[345,4992,737],{"class":367},[345,4994,4995,4998,5000,5002,5004,5006,5008,5010,5012,5014,5016,5018,5020,5022,5024,5026,5028,5030],{"class":347,"line":780},[345,4996,4997],{"class":355},"    medium ",[345,4999,713],{"class":712},[345,5001,3605],{"class":355},[345,5003,368],{"class":367},[345,5005,1625],{"class":720},[345,5007,724],{"class":367},[345,5009,390],{"class":720},[345,5011,368],{"class":367},[345,5013,1634],{"class":371},[345,5015,1637],{"class":367},[345,5017,1640],{"class":1170},[345,5019,713],{"class":712},[345,5021,3730],{"class":834},[345,5023,800],{"class":367},[345,5025,1650],{"class":1170},[345,5027,713],{"class":712},[345,5029,4990],{"class":834},[345,5031,737],{"class":367},[345,5033,5034],{"class":347,"line":818},[345,5035,648],{"emptyLinePlaceholder":647},[345,5037,5038],{"class":347,"line":857},[345,5039,4794],{"class":654},[345,5041,5042],{"class":347,"line":865},[345,5043,5044],{"class":654},"# 2. Typed schema: validates fields at compose time\n",[345,5046,5047],{"class":347,"line":870},[345,5048,4794],{"class":654},[345,5050,5051],{"class":347,"line":876},[345,5052,648],{"emptyLinePlaceholder":647},[345,5054,5055,5057,5059,5061],{"class":347,"line":905},[345,5056,1156],{"class":1155},[345,5058,1189],{"class":1159},[345,5060,368],{"class":1155},[345,5062,3747],{"class":1159},[345,5064,5065,5067,5070],{"class":347,"line":921},[345,5066,3571],{"class":827},[345,5068,5069],{"class":3574}," TrainSchema",[345,5071,1293],{"class":367},[345,5073,5074,5077,5079,5081,5084],{"class":347,"line":950},[345,5075,5076],{"class":355},"    epochs",[345,5078,1211],{"class":367},[345,5080,3766],{"class":1255},[345,5082,5083],{"class":712},"    =",[345,5085,5086],{"class":834}," 10\n",[345,5088,5089,5092,5094,5096,5098],{"class":347,"line":2150},[345,5090,5091],{"class":355},"    batch_size",[345,5093,1211],{"class":367},[345,5095,1256],{"class":1255},[345,5097,5083],{"class":712},[345,5099,5100],{"class":834}," 32\n",[345,5102,5103,5106,5108,5111,5113,5115,5117,5120],{"class":347,"line":2166},[345,5104,5105],{"class":355},"    optimizer",[345,5107,1211],{"class":367},[345,5109,5110],{"class":1255},"  object",[345,5112,1259],{"class":712},[345,5114,3790],{"class":720},[345,5116,724],{"class":367},[345,5118,5119],{"class":720},"OptimizerGroup",[345,5121,737],{"class":367},[345,5123,5124,5127,5129,5132,5134,5136,5138,5140,5142,5145],{"class":347,"line":2810},[345,5125,5126],{"class":355},"    model",[345,5128,1211],{"class":367},[345,5130,5131],{"class":355},"      nn",[345,5133,368],{"class":367},[345,5135,1219],{"class":371},[345,5137,1259],{"class":712},[345,5139,3790],{"class":720},[345,5141,724],{"class":367},[345,5143,5144],{"class":720},"ModelGroup",[345,5146,737],{"class":367},[345,5148,5149],{"class":347,"line":2816},[345,5150,648],{"emptyLinePlaceholder":647},[345,5152,5153],{"class":347,"line":2848},[345,5154,4794],{"class":654},[345,5156,5157],{"class":347,"line":2870},[345,5158,5159],{"class":654},"# 3. Defaults list: select concrete entries\n",[345,5161,5162],{"class":347,"line":2898},[345,5163,4794],{"class":654},[345,5165,5166],{"class":347,"line":2926},[345,5167,648],{"emptyLinePlaceholder":647},[345,5169,5170,5173,5175,5177],{"class":347,"line":2931},[345,5171,5172],{"class":355},"defaults ",[345,5174,713],{"class":712},[345,5176,3547],{"class":720},[345,5178,2217],{"class":367},[345,5180,5181,5184],{"class":347,"line":2953},[345,5182,5183],{"class":720},"    self_",[345,5185,1240],{"class":367},[345,5187,5188,5190,5192,5195,5197,5200,5202,5204,5206,5209],{"class":347,"line":2976},[345,5189,3876],{"class":720},[345,5191,724],{"class":367},[345,5193,5194],{"class":720},"TrainSchema",[345,5196,368],{"class":367},[345,5198,5199],{"class":371},"optimizer",[345,5201,800],{"class":367},[345,5203,4814],{"class":720},[345,5205,368],{"class":367},[345,5207,5208],{"class":371},"adam",[345,5210,5211],{"class":367},"),\n",[345,5213,5214,5216,5218,5220,5222,5224,5226,5229,5231,5234],{"class":347,"line":2985},[345,5215,3876],{"class":720},[345,5217,724],{"class":367},[345,5219,5194],{"class":720},[345,5221,368],{"class":367},[345,5223,1208],{"class":371},[345,5225,800],{"class":367},[345,5227,5228],{"class":720},"     ModelGroup",[345,5230,368],{"class":367},[345,5232,5233],{"class":371},"small",[345,5235,5211],{"class":367},[345,5237,5239],{"class":347,"line":5238},38,[345,5240,737],{"class":367},[345,5242,5244],{"class":347,"line":5243},39,[345,5245,648],{"emptyLinePlaceholder":647},[345,5247,5249,5251,5253,5255,5258,5260,5262,5264],{"class":347,"line":5248},40,[345,5250,822],{"class":821},[345,5252,724],{"class":367},[345,5254,728],{"class":727},[345,5256,5257],{"class":731},"Schema:",[345,5259,728],{"class":727},[345,5261,800],{"class":367},[345,5263,5069],{"class":720},[345,5265,737],{"class":367},[345,5267,5269,5271,5273,5275,5278,5280,5282,5285],{"class":347,"line":5268},41,[345,5270,822],{"class":821},[345,5272,724],{"class":367},[345,5274,728],{"class":727},[345,5276,5277],{"class":731},"Defaults:",[345,5279,728],{"class":727},[345,5281,800],{"class":367},[345,5283,5284],{"class":720}," defaults",[345,5286,737],{"class":367},[961,5288],{"data":5289,"kind":964},"U2NoZW1hOiA8Y2xhc3MgJ19fbWFpbl9fLlRyYWluU2NoZW1hJz4KRGVmYXVsdHM6IFsnX3NlbGZfJywgeydvcHRpbWl6ZXJncm91cEBvcHRpbWl6ZXInOiAnYWRhbSd9LCB7J21vZGVsZ3JvdXBAbW9kZWwnOiAnc21hbGwnfV0K",[336,5291,5293],{"className":338,"code":5292,"language":340,"meta":341,"style":341},"# ================================================================\n# 4. Task function: receives instantiated objects\n# ================================================================\n\n@L.task\ndef run(model: nn.Module, optimizer, epochs: int = 10, batch_size: int = 32):\n    \"\"\"Training task — parameters automatically instantiated by @L.task.\"\"\"\n    opt = optimizer(model.parameters())\n    print(f\"  model     : {model}\")\n    print(f\"  optimizer : {type(opt).__name__}  lr={opt.param_groups[0]['lr']}\")\n    print(f\"  epochs    : {epochs}\")\n    print(f\"  batch_size: {batch_size}\")\n    # ... actual training loop here ...\n\n# ================================================================\n# 5. Build and run\n# ================================================================\n\n# Build a DictConfig manually for demonstration (in production: @laco.main does this)\nfrom omegaconf import OmegaConf\ncfg_run = OmegaConf.create({\n    \"model\":      OmegaConf.to_container(ModelGroup.small,     resolve=False),\n    \"optimizer\":  OmegaConf.to_container(OptimizerGroup.adam,  resolve=False),\n    \"epochs\":     5,\n    \"batch_size\": 64,\n})\n\nprint(\"=== Running task ===\")\nrun(cfg_run)\n",[231,5294,5295,5299,5304,5308,5312,5322,5373,5386,5404,5425,5485,5507,5529,5534,5538,5542,5547,5551,5555,5560,5572,5590,5628,5664,5679,5694,5699,5703,5718],{"__ignoreMap":341},[345,5296,5297],{"class":347,"line":348},[345,5298,4794],{"class":654},[345,5300,5301],{"class":347,"line":359},[345,5302,5303],{"class":654},"# 4. Task function: receives instantiated objects\n",[345,5305,5306],{"class":347,"line":380},[345,5307,4794],{"class":654},[345,5309,5310],{"class":347,"line":651},[345,5311,648],{"emptyLinePlaceholder":647},[345,5313,5314,5316,5318,5320],{"class":347,"line":658},[345,5315,1156],{"class":1155},[345,5317,1189],{"class":1159},[345,5319,368],{"class":1155},[345,5321,1194],{"class":1159},[345,5323,5324,5326,5328,5330,5332,5334,5336,5338,5340,5342,5344,5346,5349,5351,5353,5355,5357,5359,5362,5364,5366,5368,5371],{"class":347,"line":664},[345,5325,1199],{"class":827},[345,5327,1202],{"class":1159},[345,5329,724],{"class":367},[345,5331,1208],{"class":1207},[345,5333,1211],{"class":367},[345,5335,1214],{"class":355},[345,5337,368],{"class":367},[345,5339,1219],{"class":371},[345,5341,800],{"class":367},[345,5343,1224],{"class":1207},[345,5345,800],{"class":367},[345,5347,5348],{"class":1207}," epochs",[345,5350,1211],{"class":367},[345,5352,1256],{"class":1255},[345,5354,1259],{"class":712},[345,5356,1262],{"class":834},[345,5358,800],{"class":367},[345,5360,5361],{"class":1207}," batch_size",[345,5363,1211],{"class":367},[345,5365,1256],{"class":1255},[345,5367,1259],{"class":712},[345,5369,5370],{"class":834}," 32",[345,5372,2658],{"class":367},[345,5374,5375,5379,5383],{"class":347,"line":670},[345,5376,5378],{"class":5377},"s2W-s","    \"\"\"",[345,5380,5382],{"class":5381},"sithA","Training task — parameters automatically instantiated by @L.task.",[345,5384,5385],{"class":5377},"\"\"\"\n",[345,5387,5388,5390,5392,5394,5396,5398,5400,5402],{"class":347,"line":676},[345,5389,1392],{"class":355},[345,5391,713],{"class":712},[345,5393,1224],{"class":720},[345,5395,724],{"class":367},[345,5397,1208],{"class":720},[345,5399,368],{"class":367},[345,5401,1405],{"class":720},[345,5403,777],{"class":367},[345,5405,5406,5408,5410,5412,5415,5417,5419,5421,5423],{"class":347,"line":682},[345,5407,953],{"class":821},[345,5409,724],{"class":367},[345,5411,828],{"class":827},[345,5413,5414],{"class":731},"\"  model     : ",[345,5416,835],{"class":834},[345,5418,1208],{"class":720},[345,5420,850],{"class":834},[345,5422,728],{"class":731},[345,5424,737],{"class":367},[345,5426,5427,5429,5431,5433,5436,5438,5441,5443,5446,5448,5450,5452,5455,5457,5459,5461,5464,5466,5468,5471,5473,5475,5477,5479,5481,5483],{"class":347,"line":688},[345,5428,953],{"class":821},[345,5430,724],{"class":367},[345,5432,828],{"class":827},[345,5434,5435],{"class":731},"\"  optimizer : ",[345,5437,835],{"class":834},[345,5439,5440],{"class":1255},"type",[345,5442,724],{"class":367},[345,5444,5445],{"class":720},"opt",[345,5447,897],{"class":367},[345,5449,1686],{"class":1685},[345,5451,850],{"class":834},[345,5453,5454],{"class":731},"  lr=",[345,5456,835],{"class":834},[345,5458,5445],{"class":720},[345,5460,368],{"class":367},[345,5462,5463],{"class":371},"param_groups",[345,5465,1510],{"class":367},[345,5467,3004],{"class":834},[345,5469,5470],{"class":367},"][",[345,5472,847],{"class":727},[345,5474,4861],{"class":731},[345,5476,847],{"class":727},[345,5478,1519],{"class":367},[345,5480,850],{"class":834},[345,5482,728],{"class":731},[345,5484,737],{"class":367},[345,5486,5487,5489,5491,5493,5496,5498,5501,5503,5505],{"class":347,"line":694},[345,5488,953],{"class":821},[345,5490,724],{"class":367},[345,5492,828],{"class":827},[345,5494,5495],{"class":731},"\"  epochs    : ",[345,5497,835],{"class":834},[345,5499,5500],{"class":720},"epochs",[345,5502,850],{"class":834},[345,5504,728],{"class":731},[345,5506,737],{"class":367},[345,5508,5509,5511,5513,5515,5518,5520,5523,5525,5527],{"class":347,"line":700},[345,5510,953],{"class":821},[345,5512,724],{"class":367},[345,5514,828],{"class":827},[345,5516,5517],{"class":731},"\"  batch_size: ",[345,5519,835],{"class":834},[345,5521,5522],{"class":720},"batch_size",[345,5524,850],{"class":834},[345,5526,728],{"class":731},[345,5528,737],{"class":367},[345,5530,5531],{"class":347,"line":706},[345,5532,5533],{"class":654},"    # ... actual training loop here ...\n",[345,5535,5536],{"class":347,"line":740},[345,5537,648],{"emptyLinePlaceholder":647},[345,5539,5540],{"class":347,"line":745},[345,5541,4794],{"class":654},[345,5543,5544],{"class":347,"line":751},[345,5545,5546],{"class":654},"# 5. Build and run\n",[345,5548,5549],{"class":347,"line":780},[345,5550,4794],{"class":654},[345,5552,5553],{"class":347,"line":818},[345,5554,648],{"emptyLinePlaceholder":647},[345,5556,5557],{"class":347,"line":857},[345,5558,5559],{"class":654},"# Build a DictConfig manually for demonstration (in production: @laco.main does this)\n",[345,5561,5562,5564,5567,5569],{"class":347,"line":865},[345,5563,3520],{"class":351},[345,5565,5566],{"class":355}," omegaconf ",[345,5568,352],{"class":351},[345,5570,5571],{"class":355}," OmegaConf\n",[345,5573,5574,5577,5579,5582,5584,5587],{"class":347,"line":870},[345,5575,5576],{"class":355},"cfg_run ",[345,5578,713],{"class":712},[345,5580,5581],{"class":355}," OmegaConf",[345,5583,368],{"class":367},[345,5585,5586],{"class":720},"create",[345,5588,5589],{"class":367},"({\n",[345,5591,5592,5594,5596,5598,5600,5603,5605,5608,5610,5612,5614,5616,5618,5621,5623,5626],{"class":347,"line":876},[345,5593,2598],{"class":727},[345,5595,1208],{"class":731},[345,5597,728],{"class":727},[345,5599,1211],{"class":367},[345,5601,5602],{"class":720},"      OmegaConf",[345,5604,368],{"class":367},[345,5606,5607],{"class":720},"to_container",[345,5609,724],{"class":367},[345,5611,5144],{"class":720},[345,5613,368],{"class":367},[345,5615,5233],{"class":371},[345,5617,800],{"class":367},[345,5619,5620],{"class":1170},"     resolve",[345,5622,713],{"class":712},[345,5624,5625],{"class":1289},"False",[345,5627,5211],{"class":367},[345,5629,5630,5632,5634,5636,5638,5641,5643,5645,5647,5649,5651,5653,5655,5658,5660,5662],{"class":347,"line":905},[345,5631,2598],{"class":727},[345,5633,5199],{"class":731},[345,5635,728],{"class":727},[345,5637,1211],{"class":367},[345,5639,5640],{"class":720},"  OmegaConf",[345,5642,368],{"class":367},[345,5644,5607],{"class":720},[345,5646,724],{"class":367},[345,5648,5119],{"class":720},[345,5650,368],{"class":367},[345,5652,5208],{"class":371},[345,5654,800],{"class":367},[345,5656,5657],{"class":1170},"  resolve",[345,5659,713],{"class":712},[345,5661,5625],{"class":1289},[345,5663,5211],{"class":367},[345,5665,5666,5668,5670,5672,5674,5677],{"class":347,"line":921},[345,5667,2598],{"class":727},[345,5669,5500],{"class":731},[345,5671,728],{"class":727},[345,5673,1211],{"class":367},[345,5675,5676],{"class":834},"     5",[345,5678,1240],{"class":367},[345,5680,5681,5683,5685,5687,5689,5692],{"class":347,"line":950},[345,5682,2598],{"class":727},[345,5684,5522],{"class":731},[345,5686,728],{"class":727},[345,5688,1211],{"class":367},[345,5690,5691],{"class":834}," 64",[345,5693,1240],{"class":367},[345,5695,5696],{"class":347,"line":2150},[345,5697,5698],{"class":367},"})\n",[345,5700,5701],{"class":347,"line":2166},[345,5702,648],{"emptyLinePlaceholder":647},[345,5704,5705,5707,5709,5711,5714,5716],{"class":347,"line":2810},[345,5706,822],{"class":821},[345,5708,724],{"class":367},[345,5710,728],{"class":727},[345,5712,5713],{"class":731},"=== Running task ===",[345,5715,728],{"class":727},[345,5717,737],{"class":367},[345,5719,5720,5722,5724,5727],{"class":347,"line":2816},[345,5721,2214],{"class":720},[345,5723,724],{"class":367},[345,5725,5726],{"class":720},"cfg_run",[345,5728,737],{"class":367},[961,5730],{"data":5731,"kind":964},"PT09IFJ1bm5pbmcgdGFzayA9PT0KICBtb2RlbCAgICAgOiBMaW5lYXIoaW5fZmVhdHVyZXM9NjQsIG91dF9mZWF0dXJlcz0xMCwgYmlhcz1UcnVlKQogIG9wdGltaXplciA6IEFkYW0gIGxyPTAuMDAxCiAgZXBvY2hzICAgIDogNQogIGJhdGNoX3NpemU6IDY0Cg==",[336,5733,5735],{"className":338,"code":5734,"language":340,"meta":341,"style":341},"# ================================================================\n# 6. Save for reproducibility\n# ================================================================\n\nimport pathlib, tempfile\n\nrun_dir = pathlib.Path(tempfile.mkdtemp())\nlaco.save(cfg_run, run_dir \u002F \"config.yaml\")\n\nprint(\"Saved config:\")\nprint((run_dir \u002F \"config.yaml\").read_text())\n\n# Later: reload and run again\ncfg_repro = laco.load(run_dir \u002F \"config.yaml\")\nprint(\"=== Reproduced run ===\")\nrun(cfg_repro)\n\nimport shutil\nshutil.rmtree(run_dir)\n",[231,5736,5737,5741,5746,5750,5754,5764,5768,5790,5816,5820,5835,5858,5862,5867,5893,5908,5918,5922,5928],{"__ignoreMap":341},[345,5738,5739],{"class":347,"line":348},[345,5740,4794],{"class":654},[345,5742,5743],{"class":347,"line":359},[345,5744,5745],{"class":654},"# 6. Save for reproducibility\n",[345,5747,5748],{"class":347,"line":380},[345,5749,4794],{"class":654},[345,5751,5752],{"class":347,"line":651},[345,5753,648],{"emptyLinePlaceholder":647},[345,5755,5756,5758,5760,5762],{"class":347,"line":658},[345,5757,352],{"class":351},[345,5759,759],{"class":355},[345,5761,800],{"class":367},[345,5763,642],{"class":355},[345,5765,5766],{"class":347,"line":664},[345,5767,648],{"emptyLinePlaceholder":647},[345,5769,5770,5772,5774,5776,5778,5780,5782,5784,5786,5788],{"class":347,"line":670},[345,5771,754],{"class":355},[345,5773,713],{"class":712},[345,5775,759],{"class":355},[345,5777,368],{"class":367},[345,5779,764],{"class":720},[345,5781,724],{"class":367},[345,5783,769],{"class":720},[345,5785,368],{"class":367},[345,5787,774],{"class":720},[345,5789,777],{"class":367},[345,5791,5792,5794,5796,5798,5800,5802,5804,5806,5808,5810,5812,5814],{"class":347,"line":676},[345,5793,1160],{"class":355},[345,5795,368],{"class":367},[345,5797,792],{"class":720},[345,5799,724],{"class":367},[345,5801,5726],{"class":720},[345,5803,800],{"class":367},[345,5805,803],{"class":720},[345,5807,182],{"class":712},[345,5809,808],{"class":727},[345,5811,811],{"class":731},[345,5813,728],{"class":727},[345,5815,737],{"class":367},[345,5817,5818],{"class":347,"line":682},[345,5819,648],{"emptyLinePlaceholder":647},[345,5821,5822,5824,5826,5828,5831,5833],{"class":347,"line":688},[345,5823,822],{"class":821},[345,5825,724],{"class":367},[345,5827,728],{"class":727},[345,5829,5830],{"class":731},"Saved config:",[345,5832,728],{"class":727},[345,5834,737],{"class":367},[345,5836,5837,5839,5842,5844,5846,5848,5850,5852,5854,5856],{"class":347,"line":694},[345,5838,822],{"class":821},[345,5840,5841],{"class":367},"((",[345,5843,754],{"class":720},[345,5845,182],{"class":712},[345,5847,808],{"class":727},[345,5849,811],{"class":731},[345,5851,728],{"class":727},[345,5853,897],{"class":367},[345,5855,900],{"class":720},[345,5857,777],{"class":367},[345,5859,5860],{"class":347,"line":700},[345,5861,648],{"emptyLinePlaceholder":647},[345,5863,5864],{"class":347,"line":706},[345,5865,5866],{"class":654},"# Later: reload and run again\n",[345,5868,5869,5871,5873,5875,5877,5879,5881,5883,5885,5887,5889,5891],{"class":347,"line":740},[345,5870,979],{"class":355},[345,5872,713],{"class":712},[345,5874,364],{"class":355},[345,5876,368],{"class":367},[345,5878,721],{"class":720},[345,5880,724],{"class":367},[345,5882,754],{"class":720},[345,5884,182],{"class":712},[345,5886,808],{"class":727},[345,5888,811],{"class":731},[345,5890,728],{"class":727},[345,5892,737],{"class":367},[345,5894,5895,5897,5899,5901,5904,5906],{"class":347,"line":745},[345,5896,822],{"class":821},[345,5898,724],{"class":367},[345,5900,728],{"class":727},[345,5902,5903],{"class":731},"=== Reproduced run ===",[345,5905,728],{"class":727},[345,5907,737],{"class":367},[345,5909,5910,5912,5914,5916],{"class":347,"line":751},[345,5911,2214],{"class":720},[345,5913,724],{"class":367},[345,5915,1042],{"class":720},[345,5917,737],{"class":367},[345,5919,5920],{"class":347,"line":780},[345,5921,648],{"emptyLinePlaceholder":647},[345,5923,5924,5926],{"class":347,"line":818},[345,5925,352],{"class":351},[345,5927,1120],{"class":355},[345,5929,5930,5932,5934,5936,5938,5940],{"class":347,"line":857},[345,5931,1125],{"class":355},[345,5933,368],{"class":367},[345,5935,1130],{"class":720},[345,5937,724],{"class":367},[345,5939,1135],{"class":720},[345,5941,737],{"class":367},[961,5943],{"data":5944,"kind":964},"U2F2ZWQgY29uZmlnOgpfbGFjb186IDEKYmF0Y2hfc2l6ZTogNjQKZXBvY2hzOiA1Cm1vZGVsOiB7X2NvbnZlcnRfOiBhbGwsIF90YXJnZXRfOiB0b3JjaC5ubi5MaW5lYXIsIGluX2ZlYXR1cmVzOiA2NCwgb3V0X2ZlYXR1cmVzOiAxMH0Kb3B0aW1pemVyOiB7X2NvbnZlcnRfOiBhbGwsIF9wYXJ0aWFsXzogdHJ1ZSwgX3RhcmdldF86IHRvcmNoLm9wdGltLkFkYW0sIGxyOiAwLjAwMSwKICB3ZWlnaHRfZGVjYXk6IDEuMGUtMDV9Cgo9PT0gUmVwcm9kdWNlZCBydW4gPT09CiAgbW9kZWwgICAgIDogTGluZWFyKGluX2ZlYXR1cmVzPTY0LCBvdXRfZmVhdHVyZXM9MTAsIGJpYXM9VHJ1ZSkKICBvcHRpbWl6ZXIgOiBBZGFtICBscj0wLjAwMQogIGVwb2NocyAgICA6IDUKICBiYXRjaF9zaXplOiA2NAo=",[397,5946,5948],{"id":5947},"section-9-what-to-read-next","Section 9: What to read next",[216,5950,5951],{},"You've completed the laco tutorial series. Here are the recommended next resources:",[1142,5953,5955],{"id":5954},"real-world-config-examples","Real-world config examples",[5957,5958,5959,5969,5975],"ul",{},[258,5960,5961,5964,5965,5968],{},[231,5962,5963],{},"sources\u002Flaco\u002Fexamples\u002Fmodels\u002F",": ResNet, ViT, DINOv3, Gemma3, Qwen3 config files showing ",[231,5966,5967],{},"@L.params",", nested groups, and multi-stage pipelines",[258,5970,5971,5974],{},[231,5972,5973],{},"sources\u002Flaco\u002Fexamples\u002Fintegrations\u002F",": Lightning, Transformers, TensorDict integration configs",[258,5976,5977,5980],{},[231,5978,5979],{},"sources\u002Flaco\u002Fexamples\u002Fpipelines\u002F",": MNIST and CLM fine-tuning end-to-end pipelines",[1142,5982,5984],{"id":5983},"migration-and-compatibility","Migration and compatibility",[5957,5986,5987,5993],{},[258,5988,5989,5992],{},[231,5990,5991],{},"docs\u002Fmigration-0.x-to-1.0.md",": complete guide for migrating 0.x configs and code to 1.0",[258,5994,5995,5997],{},[231,5996,3459],{},": CLI command to auto-update 0.x YAML files in-place",[1142,5999,6001],{"id":6000},"hydra-ecosystem","Hydra ecosystem",[5957,6003,6004,6014,6022],{},[258,6005,6006,6013],{},[6007,6008,6012],"a",{"href":6009,"rel":6010},"https:\u002F\u002Fhydra.cc\u002Fdocs\u002Fintro\u002F",[6011],"nofollow","Hydra documentation",": config composition, defaults lists, overrides",[258,6015,6016,6021],{},[6007,6017,6020],{"href":6018,"rel":6019},"https:\u002F\u002Fhydra.cc\u002Fdocs\u002Ftutorials\u002Fbasic\u002Frunning_your_app\u002Fmulti-run\u002F",[6011],"Hydra multirun \u002F sweepers",": Optuna, Nevergrad, Ax sweepers",[258,6023,6024,6029],{},[6007,6025,6028],{"href":6026,"rel":6027},"https:\u002F\u002Fhydra.cc\u002Fdocs\u002Fplugins\u002Fsubmitit_launcher\u002F",[6011],"Hydra launchers",": SLURM, Joblib, RQ cluster launchers",[1142,6031,6033],{"id":6032},"laco-source-modules-worth-reading-directly","laco source modules worth reading directly",[5957,6035,6036,6042,6063,6074],{},[258,6037,6038,6041],{},[231,6039,6040],{},"sources\u002Flaco\u002Flanguage.py",": the full DSL with the \"five fictions\" module docstring",[258,6043,6044,6047,6048,310,6050,310,6053,310,6056,310,6059,6062],{},[231,6045,6046],{},"sources\u002Flaco\u002F_groups.py",": ",[231,6049,3584],{},[231,6051,6052],{},"config",[231,6054,6055],{},"slot",[231,6057,6058],{},"bind",[231,6060,6061],{},"Defaults"," implementation",[258,6064,6065,6047,6068,607,6071,6073],{},[231,6066,6067],{},"sources\u002Flaco\u002F_lazy.py",[231,6069,6070],{},"instantiate",[231,6072,292],{}," internals",[258,6075,6076,6047,6079,6081],{},[231,6077,6078],{},"sources\u002Flaco\u002F_lint\u002Flie_typing.py",[231,6080,281],{}," AST walker",[397,6083,6085],{"id":6084},"section-10-series-summary-the-learning-path","Section 10: Series summary, the learning path",[419,6087,6088,6102],{},[422,6089,6090],{},[425,6091,6092,6095,6098,6100],{},[428,6093,6094],{},"#",[428,6096,6097],{},"Notebook",[428,6099,67],{},[428,6101,1918],{},[441,6103,6104,6118,6135,6158,6179,6195,6210,6232,6245,6263,6281],{},[425,6105,6106,6109,6112,6115],{},[446,6107,6108],{},"00",[446,6110,6111],{},"Why laco?",[446,6113,6114],{},"Motivation: call vs. config",[446,6116,6117],{},"Foundations",[425,6119,6120,6123,6126,6133],{},[446,6121,6122],{},"01",[446,6124,6125],{},"Config basics",[446,6127,6128,310,6130,6132],{},[231,6129,270],{},[231,6131,1022],{},", OmegaConf",[446,6134,6117],{},[425,6136,6137,6140,6143,6155],{},[446,6138,6139],{},"02",[446,6141,6142],{},"Lazy call & partial",[446,6144,6145,310,6147,310,6149,310,6152],{},[231,6146,1464],{},[231,6148,1990],{},[231,6150,6151],{},"L.just",[231,6153,6154],{},"L.required",[446,6156,6157],{},"DSL core",[425,6159,6160,6163,6166,6177],{},[446,6161,6162],{},"03",[446,6164,6165],{},"Params & interpolation",[446,6167,6168,310,6170,310,6173,6176],{},[231,6169,5967],{},[231,6171,6172],{},"L.ref",[231,6174,6175],{},"L.r",", sweeps",[446,6178,6157],{},[425,6180,6181,6184,6187,6192],{},[446,6182,6183],{},"04",[446,6185,6186],{},"Instantiate",[446,6188,6189,6191],{},[231,6190,588],{},", cycles, YAML",[446,6193,6194],{},"Instantiation",[425,6196,6197,6200,6203,6208],{},[446,6198,6199],{},"05",[446,6201,6202],{},"Structured configs",[446,6204,6205,6207],{},[231,6206,4699],{},", dataclass fields",[446,6209,6194],{},[425,6211,6212,6215,6218,6229],{},[446,6213,6214],{},"06",[446,6216,6217],{},"Config groups",[446,6219,6220,310,6222,310,6225,6228],{},[231,6221,305],{},[231,6223,6224],{},"L.slot",[231,6226,6227],{},"L.bind",", Defaults",[446,6230,6231],{},"Groups",[425,6233,6234,6237,6240,6243],{},[446,6235,6236],{},"07",[446,6238,6239],{},"Overrides & CLI",[446,6241,6242],{},"CLI overrides, app patterns",[446,6244,6231],{},[425,6246,6247,6250,6253,6260],{},[446,6248,6249],{},"08",[446,6251,6252],{},"Tasks & app loop",[446,6254,6255,310,6257],{},[231,6256,4703],{},[231,6258,6259],{},"@laco.main",[446,6261,6262],{},"Execution",[425,6264,6265,6268,6270,6279],{},[446,6266,6267],{},"09",[446,6269,59],{},[446,6271,6272,310,6274,310,6276],{},[231,6273,554],{},[231,6275,558],{},[231,6277,6278],{},"_TRACING",[446,6280,6262],{},[425,6282,6283,6285,6288,6291],{},[446,6284,4990],{},[446,6286,6287],{},"Production patterns",[446,6289,6290],{},"save\u002Fload, lint, migrate, compat",[446,6292,1942],{},[397,6294,6296],{"id":6295},"recap-production-checklist","Recap: Production Checklist",[216,6298,6299],{},"Use this checklist when shipping a laco-powered project:",[419,6301,6302,6315],{},[422,6303,6304],{},[425,6305,6306,6309,6312],{},[428,6307,6308],{},"Step",[428,6310,6311],{},"Tool",[428,6313,6314],{},"Notes",[441,6316,6317,6330,6343,6356,6369,6382,6394,6407],{},[425,6318,6319,6322,6327],{},[446,6320,6321],{},"Validate config files",[446,6323,6324],{},[231,6325,6326],{},"python -c 'import laco; laco.load(\"configs:\u002F\u002F...\")",[446,6328,6329],{},"Fast, no instantiation",[425,6331,6332,6335,6340],{},[446,6333,6334],{},"Catch attribute-access bugs",[446,6336,6337],{},[231,6338,6339],{},"LACO_STRICT_NODES=1 pytest",[446,6341,6342],{},"Enable in CI",[425,6344,6345,6348,6353],{},[446,6346,6347],{},"Static node-access lint",[446,6349,6350],{},[231,6351,6352],{},"laco-lint sources\u002F tests\u002F",[446,6354,6355],{},"Add to pre-commit \u002F CI",[425,6357,6358,6361,6366],{},[446,6359,6360],{},"Save run config",[446,6362,6363],{},[231,6364,6365],{},"laco.save(cfg, run_dir \u002F 'config.yaml')",[446,6367,6368],{},"Before training starts",[425,6370,6371,6374,6379],{},[446,6372,6373],{},"Handle renamed classes",[446,6375,6376],{},[231,6377,6378],{},"laco._lazy.migrate_target = my_hook",[446,6380,6381],{},"One-time near startup",[425,6383,6384,6387,6391],{},[446,6385,6386],{},"Migrate 0.x YAML files",[446,6388,6389],{},[231,6390,3459],{},[446,6392,6393],{},"Run once per repo",[425,6395,6396,6399,6404],{},[446,6397,6398],{},"Verify round-trip",[446,6400,6401],{},[231,6402,6403],{},"assert laco.dump(cfg) == laco.dump(laco.load(path))",[446,6405,6406],{},"In tests",[425,6408,6409,6412,6417],{},[446,6410,6411],{},"Sweep hyperparameters",[446,6413,6414],{},[231,6415,6416],{},"python train.py -m optimizer=sgd,adam",[446,6418,6419],{},"Hydra multirun",[249,6421],{},[216,6423,6424,6427],{},[219,6425,6426],{},"Congratulations. You've completed the laco tutorial series."," You now understand the full stack: from the lie-typing contract and lazy construction, through config groups and typed schemas, all the way to task functions, tracing, and production operations.",[6429,6430,6431],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .slqww, html code.shiki .slqww{--shiki-light:#6182B8;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .stp6e, html code.shiki .stp6e{--shiki-light:#39ADB5;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sFwrP, html code.shiki .sFwrP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#24292E;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sQzsp, html code.shiki .sQzsp{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .swQdS, html code.shiki .swQdS{--shiki-light:#E53935;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s2W-s, html code.shiki .s2W-s{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#032F62;--shiki-default-font-style:inherit;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit}html pre.shiki code .sithA, html code.shiki .sithA{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#032F62;--shiki-default-font-style:inherit;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit}",{"title":341,"searchDepth":380,"depth":380,"links":6433},[6434,6435,6438,6443,6448,6453,6457,6466,6467,6473,6474],{"id":399,"depth":359,"text":400},{"id":591,"depth":359,"text":592,"children":6436},[6437],{"id":1144,"depth":380,"text":1145},{"id":1427,"depth":359,"text":6439,"children":6440},"Section 3: LACO_STRICT_NODES, catching attribute-access bugs",[6441],{"id":1906,"depth":380,"text":6442},"When to use LACO_STRICT_NODES",{"id":1968,"depth":359,"text":6444,"children":6445},"Section 4: laco-lint and LACO001",[6446],{"id":2422,"depth":380,"text":6447},"Integrating laco-lint into CI",{"id":2490,"depth":359,"text":6449,"children":6450},"Section 5: The migrate_target hook",[6451],{"id":3067,"depth":380,"text":6452},"How migrate_target is called",{"id":3111,"depth":359,"text":6454,"children":6455},"Section 6: laco.compat, auto-install backward-compat shims",[6456],{"id":3439,"depth":380,"text":3440},{"id":3472,"depth":359,"text":6458,"children":6459},"Section 7: Advanced L.Group patterns",[6460,6462,6464],{"id":3479,"depth":380,"text":6461},"L.bind_strict + L.use: statically-checked bindings",{"id":4119,"depth":380,"text":6463},"mode=\"extend\": adding entries to an existing group",{"id":4464,"depth":380,"text":6465},"L.delete: removing entries from the defaults list",{"id":4689,"depth":359,"text":4690},{"id":5947,"depth":359,"text":5948,"children":6468},[6469,6470,6471,6472],{"id":5954,"depth":380,"text":5955},{"id":5983,"depth":380,"text":5984},{"id":6000,"depth":380,"text":6001},{"id":6032,"depth":380,"text":6033},{"id":6084,"depth":359,"text":6085},{"id":6295,"depth":359,"text":6296},"Series: laco tutorial notebooksPrerequisites: All prior notebooks (01.why-laco.ipynb through 10.tracing.ipynb)Dependencies: torch","md",{"notebook":647},{"icon":25},{"title":63,"description":6475},"76OZtSqdSjNM7z1Ti1eBzWBEuAGpB_nv5jZtQ4hGwiA",{},1785687300948]