Skip to content

System Design ​

Every row below points at a file that exists

The Python package is in nano/. This page was written before the code and has been corrected against it: each module link resolves, and the boundaries described here are the ones tests/ enforces — including a leakage test that flips hidden reality at every unmeasured die and requires the agent's trajectory to come out identical.

Data flow ​

Reality reaches the agent only through the observation tool. The biased prior and the observed values feed the reality model, which emits prediction and uncertainty; the acquisition policy reads those and asks the observation tool for one more die. Reality also flows directly to the evaluation harness, which the agent never reads.

The single most important property of this graph: reality reaches the agent only through the observation tool. The direct edge from reality to the evaluation harness carries ground truth that the agent never sees. Any shortcut across that boundary invalidates every number on the benchmark page.

Modules ​

ModuleResponsibilityInputOutput
nano/data.pyLoad WM-811K, filter and index the evaluation subset, expose the in-wafer die maskDataset path, seedWafer records: reality field, die mask, pattern label
nano/prior.pyGenerate the deliberately biased simulation prior from a reality fieldReality field, bias parametersPrior field defined on every in-wafer die
nano/tools/observe.pyThe only channel to reality. Reveals one die's value and spends one unit of budgetDie indexMeasured value, updated observation state
nano/model.pyReconcile prior with observations; produce prediction, uncertainty, reality-gap and expected-disagreement mapsPrior, observed mask, observed valuesprediction, uncertainty, reality_gap, expected_disagreement
nano/policy.pyScore unmeasured dies and select the next measurementModel outputs, observed masknext_index, next_score, per-term breakdown
nano/agent.pyRun the Observe → Estimate → Select → Measure loop until the budget is exhaustedWafer record, budget, seedDecision trace, per-step maps
nano/baselines.pyRandom and Grid selection rules behind the same policy interfaceModel outputs, observed masknext_index
nano/evaluate.pyScore predictions against hidden ground truth and aggregate over wafers and seedsPredictions, reality fieldsresults/benchmark_summary.json
nano/figures.pyDraw every published figure from a run, never from an illustrationSummary or episoderesults/*.svg, results/*.webp, results/demo.gif
nano/cli.pyShared argument parsing; re-run one episode exactly as the benchmark ran itCommand-line argumentsWafer records, episode bundle

Entry points: python -m nano.benchmark (all arms, writes the results file), python -m nano.demo (one narrated episode plus its figures) and python -m nano.subset (derive the versioned evaluation index from a local WM-811K).

Boundaries that matter ​

One tool, one budget. Every measurement goes through nano.tools.observe. Budget accounting lives inside the tool, not in the caller, so no strategy can quietly take an extra look.

Baselines share the policy interface. Random and Grid implement the same signature as the NANO policy and are driven by the same loop. Swapping the selection rule is the only change between arms — which is what makes the comparison mean anything.

Evaluation is downstream of everything. nano.evaluate is the only module that touches full reality fields, and it never returns anything to the agent.

One results file. nano/evaluate.py writes results/benchmark_summary.json; the site reads it. Charts, tables and headline numbers on this site all derive from that file, so a number cannot be updated in one place and stale in another. Schema is documented on the benchmark page.

Documentation site ​

The site is deliberately boring: a static VitePress build with no backend, no runtime data fetching and no analytics.

PiecePathRole
Configdocs/.vitepress/config.mtsNav, sidebar, SEO, Mermaid, base-path handling for project and user Pages
Results loaderdocs/.vitepress/data/benchmark.data.mtsReads and validates results/benchmark_summary.json at build time
Asset loaderdocs/.vitepress/data/assets.data.mtsLists docs/public/results/ so missing figures degrade to a pending state
Componentsdocs/.vitepress/theme/components/AgentLoop, WaferComparison, BenchmarkChart, BenchmarkTable, EvidenceStrip, MetricCard, ResultAsset
Asset syncscripts/sync-doc-assets.mjsCopies published figures from results/ into docs/public/results/
Figure scriptsscripts/plot_*.py, scripts/record_demo.pyRegenerate one published figure at a time from a run
Playground sourceplayground/template.htmlThe page, minus its wafers: markup, styles, and a JavaScript port of the loop
Playground buildnano/playground.pyEmbeds the evaluation wafers and the published configuration, writing docs/public/playground.html
Playground checkscripts/check-playground-parity.mjsReplays Python's decisions through the engine that page ships, and stamps the count into it
Deployment.github/workflows/deploy-docs.ymlBuilds on push to main and publishes to GitHub Pages

Components render at build time, so the pages carry their content as static HTML. With JavaScript disabled the prose, the tables, the wafer schematic and the result figures all still read; only Mermaid diagrams and the search box need the client runtime.

The one exception is the playground, which re-runs the loop in the browser and is therefore nothing without JavaScript. It is still a file, not a service: the twelve evaluation wafers and their priors are embedded in the page, so it fetches nothing at runtime either.

Next: run it yourself →

Built for the AI Development Lifecycle Hackathon. Content is research prototype material, not production guidance.