--- name: graph description: Use ProgramGraph commands as the primary agent authoring and inspection surface. --- # Zero Graph Authoring Use this when creating, inspecting, patching, importing, or exporting Zero programs through the graph interface, the primary agent authoring surface. `zero.graph` is the repository graph store for packages, `.0` files are the human-readable source projection, and `.program-graph` files are derived debug/interchange artifacts. ## Source Boundary - Normal `zero check`, `zero run`, `zero test`, `zero build`, `zero size`, and `zero mem` compile packages from `zero.graph` (`zero.toml` takes precedence over `zero.json`). When the `.0` projection was edited, those commands refresh the stale store from source first and note it on stderr; `ZERO_STALE=fail` turns that refresh into an RGP008 error instead. - `zero import` refreshes `zero.graph` from edited source explicitly. It accepts the package root, manifest, or any source path inside the package, updates an existing store in place, and preserves node handles where the edit is unambiguous. When several edited nodes could claim one handle, import picks the structurally closest match and notes it on stderr. A whole-file rewrite that keeps the file's function set (names and signatures) is accepted in one pass with regenerated node identities for that file, noted on stderr; only ties that span files or change the function set fail (RGP007) with a split-the-edit strategy. Never delete the store to force a reimport, and omit `--out` for package imports. - `zero export [package]` materializes `.0` projections for human review; do not export just to silence stale-projection notes or after every patch. Compiler commands report projection state but never rewrite `.0` files. `zero verify-projection [package]` fails on drift without writing anything. - `zero.graph` is binary by default. Reads auto-detect text and binary stores, writes preserve the existing encoding, and `zero status` reports `store format: text|binary`. Use `--format text` only for a deliberately readable debug store. Stdlib `std/*.graph` stores are binary; sibling `std/*.0` files are projections, not the stdlib compile source. ## Create ```sh zero init zero patch --op 'addMain' ``` `zero init` defaults to the current directory and that folder's name. Use `zero init app` for a new subdirectory, `--manifest json` only for explicit compatibility, and `--template cli|lib|package` only when the user asks for starter files. ## Inspect ```sh zero query userTotals # bare name that is not a path = --find in the current package zero query --fn main # one function's signature and call summary zero query --fn main --handles # adds stmt/param patch handles; use before patching zero query --calls std # resolved call targets zero query --refs add # semantic references zero query --node '#expr_2cad38f9' --depth 2 # node-scoped: span, parents, children zero view --fn main # one function's canonical source zero view --fn main --handles # the same source with a trailing // #handle per statement zero view --fn main --around minLength # only the enclosing block containing the text zero view --outline src/main.0 # signatures plus one-line docs, no bodies zero status # store format and projection state ``` `--node` defaults to depth 1; add `--full` for the whole-module report. Use handles from `zero view --fn --handles`, `--find`, or `--fn --handles` for checked edits (`set`, `insert`, `insertEdge`, `replace`, `replaceExpr`, `rename`, `delete`); delete compacts ordered graph groups so valid sibling order is preserved. Handles accept short forms: the id segment (`#55ae541c`), any unique prefix (`#55ae`), or `#head..tail` for ids with long shared prefixes; `--handles` views print the shortest form that resolves, and a missing handle fails with the nearest existing one. Reserve unfiltered `zero query` dumps for tools that need every node and edge. ## Patches Edit through the graph: `zero patch` covers everything from one-line changes (`addCheckWrite`, `rename`, `set`) to whole function bodies (`--replace-fn --body-file -` with a heredoc). Direct `.0` text edits are a last resort for changes no patch op expresses; the compiler will refresh the graph from edited source, but patch keeps the loop faster (0.2s validation, no reconcile pass) and preserves node identity for queries. A successful patch loads, applies, validates, and saves `zero.graph`, and prints the saved path, new graph hash, functions, and tests. Do not run `zero check`, `zero view`, `zero query`, or `zero export` just to confirm that the patch applied. Use those only when you need current text/handles, projection review, or a diagnostic loop. ```sh zero patch \ --op 'addFunction name="add" ret="i32"' \ --op 'addParam fn="add" name="left" type="i32"' \ --op 'addParam fn="add" name="right" type="i32"' \ --op 'addReturnBinary fn="add" name="+" left="left" right="right" type="i32"' \ --op 'addTest name="addition works" call="add" arg0="40" arg1="2" expect="42" type="i32"' ``` Use `addTest` for one pure helper call; reserve `addTestBody` for custom body rows. Test labels are display names, not `__zero_test_*` function names. If a custom test fails as an unknown function label, delete it and recreate simple coverage with `addTest` instead of renaming the label. For declaration-level edits, stay in patch ops instead of rewriting files. `setConst name="limit" value="64"` replaces a top-level const's initializer by package-scoped name. `addParamTo fn="scan" name="bias" type="i32" default="0"` appends a parameter to an existing function and updates every call site in the package (nested calls included) to pass the default explicitly, reporting `updated N call sites`; without `default` it fails with the call-site count. `setReturnType fn="scan" type="i64"` changes a declared return type. All three revalidate and batch like any other op. For a new or replacement multi-statement helper, use complete source through `upsertFunction` instead of editing `.0` and importing: ```text zero-program-graph-patch v1 upsertFunction handle fn handle(request: Span, response: MutSpan) -> Maybe> { return null } end ``` For runnable CLI programs, keep `World` on `pub fn main`; value-based helpers build and run more reliably. HTTP server helpers use `handle(request, response)`. `upsertFunction` parses exactly one complete function declaration, inserts it if missing, and replaces the prior declaration and body if it already exists. For smaller append-only work, `appendStmt fn="main" stmt="check std.http.listen(world, 3000_u16)"` appends one canonical statement, and `addReturnExpr fn="maybe" expr="null"` appends a return statement for any expression. `addReturnValue` is only for identifier returns. For sub-line edits, think in graph: take a handle from `zero view --fn --handles` and change exactly one thing. `set` edits one field (a literal `value`, a declared `type`, a `name`/operator); `replaceExpr` swaps any expression subtree, and aimed at a statement handle it replaces that statement's expression (initializer, condition, return value). Repeat `--op` to batch several micro-ops into one patch with a single revalidation: ```sh zero patch . \ --op 'set node="#a647" field="value" expect="1" value="8"' \ --op 'replaceExpr node="#5f15" with="i < k + 1"' ``` To express one cross-cutting transformation instead of editing N sites, use structural rewrite by example. `--rewrite '' --to '