chore: import upstream snapshot with attribution
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
---
|
||||
name: agent
|
||||
description: Graph-first agent workflow for making focused Zero changes with CLI feedback.
|
||||
---
|
||||
|
||||
# Zero Agent Workflow
|
||||
|
||||
Use this when editing Zero code. `zero.graph` is compiler input; `.0` is the human projection. Use JSON only when another tool must parse stable fields.
|
||||
|
||||
## Edit Through Patch
|
||||
|
||||
Anchored edits win. Do not retype a function for one line or rewrite `.0` for one declaration.
|
||||
|
||||
1. `--replace-in-fn`: edit one function's canonical body text.
|
||||
|
||||
```sh
|
||||
zero patch . --replace-in-fn handleLine --old 'limit + 1' --new 'limit + 2'
|
||||
```
|
||||
|
||||
`--old` must match `zero view --fn <name>` output exactly once.
|
||||
|
||||
2. `--replace-fn` for one whole body:
|
||||
|
||||
```sh
|
||||
zero patch . --replace-fn greet --body-file - <<'EOF'
|
||||
check world.out.write("hello agent\n")
|
||||
EOF
|
||||
```
|
||||
|
||||
3. Declaration work stays in ops; call sites update:
|
||||
|
||||
```sh
|
||||
zero patch . --op 'setConst name="limit" value="64"'
|
||||
zero patch . --op 'addParamTo fn="scan" name="bias" type="i32" default="0"' # updates every call site
|
||||
zero patch . --op 'setReturnType fn="scan" type="i64"'
|
||||
```
|
||||
|
||||
4. New helpers stay graph-native:
|
||||
|
||||
```text
|
||||
zero-program-graph-patch v1
|
||||
upsertFunction handle
|
||||
fn handle(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return null
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
Pass a patch file, or stream full `zero-program-graph-patch v1` text with `zero patch . --patch-text -`.
|
||||
|
||||
Use `addReturnExpr fn="maybe" expr="null"` for non-id returns and `appendStmt fn="main" stmt="check std.http.listen(world, 3000_u16)"` for one stmt. For pure helper tests, use `addTest name="addition works" call="add" arg0="2" arg1="3" expect="5" type="i32"`; reserve `addTestBody name="api add" ... end` for custom bodies and remove bad ones with `deleteTest name="api add"`. Labels are display names, not `__zero_test_*`.
|
||||
|
||||
Runnable CLIs keep `World` on `pub fn main`; helpers are value-based. HTTP uses `handle(request, response)`.
|
||||
|
||||
After `validated: check-equivalent`, the graph is saved and checked. Do not run `zero check`, `zero view`, or `zero export` just to confirm. `zero run . -- <args>` / `zero test` prove behavior or debug. Export only for requested `.0` review. Repeat `--op` to batch edits. For rewrites/handles: `zero skills get graph`.
|
||||
|
||||
Read only for current code or handles:
|
||||
|
||||
- `zero view --fn <name>`: one function source.
|
||||
- `zero view --fn <name> --around <text>`: enclosing block only.
|
||||
- `zero view --outline <module-or-file>`: signatures plus one-line docs.
|
||||
|
||||
For a new package: `zero init`, then `zero patch --op 'addMain'`.
|
||||
|
||||
## zero query
|
||||
|
||||
```text
|
||||
zero query [--json] [--fn <name>] [--find <text>] [--refs <name>] [--calls <name>]
|
||||
[--node <id>] [--depth <n>] [--full] [--handles] [--no-help] [graph-input|name]
|
||||
```
|
||||
|
||||
- bare name that is not an existing path: runs `--find` against the current package
|
||||
- `zero query --fn <name> --handles`: patch handles for one function
|
||||
- add `--no-help` when you need handles without the patch-operation footer
|
||||
- `--find <text>`: search names, ids, types, values, and node kinds; prints matches with spans
|
||||
- `--calls <name>` / `--refs <name>`: resolved calls and semantic references
|
||||
- `--node <id>`: one node's span, parents, and children; short handles resolve here too
|
||||
|
||||
Import/export, identity recovery, structural edits, and merge live in `graph`. Direct `.0` edits are a last resort; never delete `zero.graph`.
|
||||
|
||||
## Verify Before Done
|
||||
|
||||
After a fix works, exercise typical and boundary inputs.
|
||||
|
||||
```sh
|
||||
zero run . -- <typical input>
|
||||
zero run . -- <empty or boundary input>
|
||||
zero test
|
||||
```
|
||||
|
||||
If behavior changed, add or update a `test` block. On a diagnostic, run `zero explain <code>`.
|
||||
|
||||
## Rules
|
||||
|
||||
- Treat effects as capabilities, not ambient globals: `World`, `std.fs`, `std.args`, `std.env`.
|
||||
- Use `Maybe<T>`, explicit `raises` / `raises [...]`, and `check` / `rescue` instead of hidden failure.
|
||||
- Do not invent syntax or CLI fields; load `language` when unsure.
|
||||
- Check `stdlib` before hand-writing parsing or validation; it ships validators such as `std.time`, `std.inet`, `std.regex`, and `std.unicode`. Fetch one module with `zero skills get stdlib --topic std.time`.
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
name: builds
|
||||
description: Build, run, target, and profile Zero programs.
|
||||
---
|
||||
|
||||
# Zero Builds
|
||||
|
||||
Use this when an agent needs to run, build, cross-build, inspect artifacts, or explain target support for a Zero program.
|
||||
|
||||
## Inputs
|
||||
|
||||
Most build commands accept one of these graph-backed inputs:
|
||||
|
||||
- a direct `.graph` or `.program-graph` artifact
|
||||
- a package directory containing `zero.toml` or `zero.json`
|
||||
- a direct path to `zero.toml` or `zero.json`
|
||||
|
||||
When both manifests are present in the same package root, Zero uses
|
||||
`zero.toml`. Prefer one checked-in manifest unless testing precedence.
|
||||
|
||||
For packages, normal check, build, run, test, size, and mem commands compile from the checked-in `zero.graph` store. When the `.0` source projection was edited, those commands refresh the stale store from source first and note it on stderr; set `ZERO_STALE=fail` to make staleness an error (RGP008) instead. They never rewrite `.0` files. Use `zero verify-projection` when CI or review needs projection drift to fail, and `zero export` only when a human-readable projection needs regeneration. When already inside a package, omit the input and commands default to the current directory.
|
||||
|
||||
## Run
|
||||
|
||||
Use `zero run` for the host development loop:
|
||||
|
||||
```sh
|
||||
zero run
|
||||
zero run -- input.txt
|
||||
zero run examples/hello.graph
|
||||
zero run examples/cli-file.graph -- input.txt
|
||||
```
|
||||
|
||||
Arguments after `--` are passed to the Zero program.
|
||||
|
||||
## Build
|
||||
|
||||
Use `zero build` when the user asks for an artifact. It is the normal command
|
||||
for executables, object files, LLVM IR, cross-target artifacts, and CI outputs.
|
||||
Use direct emitters. The removed generated-C backend is not a fallback path.
|
||||
|
||||
```sh
|
||||
zero build --emit exe --out .zero/out/app
|
||||
zero build --emit obj --out .zero/out/app.o
|
||||
zero build --emit exe examples/hello.graph --out .zero/out/hello
|
||||
zero build --emit obj examples/hello.graph --out .zero/out/hello.o
|
||||
```
|
||||
|
||||
Use LLVM only when the request is explicit. LLVM is experimental: it is not the
|
||||
default backend and not release eligible. Textual IR is inspectable with
|
||||
`--emit llvm-ir`; host executable builds require a ready clang toolchain. LLVM
|
||||
currently lowers scalar code, direct calls, branches, loops, primitive fixed
|
||||
arrays, byte views, readonly strings, and primitive `std.mem` helpers:
|
||||
|
||||
```sh
|
||||
zero build --backend llvm --emit llvm-ir examples/hello.graph --out .zero/out/hello.ll
|
||||
zero build --backend llvm --emit exe examples/hello.graph --out .zero/out/hello-llvm
|
||||
zero run --backend llvm examples/hello.graph
|
||||
```
|
||||
|
||||
Use `--json` when a tool will read exact build fields:
|
||||
|
||||
```sh
|
||||
zero build --json --target linux-musl-x64 examples/memory-package
|
||||
```
|
||||
|
||||
Useful JSON fields include `artifact`, `sizeBytes`, `toolchain`, `releaseTargetContract`, selected target facts, linker flavor, and sysroot status.
|
||||
|
||||
## Graph Inputs
|
||||
|
||||
When an agent is authoring a repository graph package, patch the package graph
|
||||
and use normal build/run commands. They compile from `zero.graph` and do not
|
||||
require `.0` projections to exist:
|
||||
|
||||
```sh
|
||||
zero patch --op 'addMain'
|
||||
zero run
|
||||
zero build --out .zero/out/app
|
||||
```
|
||||
|
||||
Use `zero export` when humans need checked-in `.0` projections. After a human edits a projection, the next graph-store compile refreshes the store automatically, or run `zero import` to refresh it explicitly. `zero status` reports the active store format.
|
||||
|
||||
Build, run, test, size, and mem commands maintain a derived final-MIR cache in the native cache, keyed by graph hash, compiler version, target, emit kind, and backend request. Agents should not patch `.zmir` files; JSON outputs report cache reuse in a `mappedFinalMir` row.
|
||||
|
||||
If another tool hands you a standalone `.program-graph`, normal `zero build`
|
||||
and `zero run` can validate it as an interchange artifact. Do not create a
|
||||
standalone graph artifact for the ordinary package loop; use the package path so
|
||||
the compiler reads `zero.graph` directly.
|
||||
|
||||
## Targets
|
||||
|
||||
Inspect target names and capability facts before cross-building:
|
||||
|
||||
```sh
|
||||
zero targets
|
||||
zero check --target linux-musl-x64 examples/memory-package
|
||||
zero inspect --target linux-musl-x64 examples/memory-package
|
||||
```
|
||||
|
||||
Hosted APIs such as process args, environment, filesystem, net, and proc are target-gated. A non-host target may reject code that checks on the host.
|
||||
|
||||
## Profiles
|
||||
|
||||
Common profile names are `debug`, `dev`, `release-fast`, `release-small`, `tiny`, and `audit`.
|
||||
|
||||
```sh
|
||||
zero build --profile release-small examples/hello.graph
|
||||
zero size --profile tiny examples/hello.graph
|
||||
```
|
||||
|
||||
Use `zero size` to explain retained functions, sections, literals, runtime shims, imports, debug metadata, and optimization hints. Add `--json` when a tool needs exact fields.
|
||||
Use `zero size --backend llvm` when the question is specifically about the explicit LLVM backend; the report includes LLVM target triple, optimization level, retained runtime/helper facts, toolchain readiness, and direct-vs-LLVM comparison rows.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- `zero doctor` checks host and target readiness.
|
||||
- `zero doctor --json` reports `llvmToolchain` readiness for explicit LLVM host builds.
|
||||
- LLVM JSON facts include `backendLifecycle` so tools can distinguish explicit experimental readiness from release support.
|
||||
- `BLD003` means an old backend flag was requested; remove it.
|
||||
- `BLD004` with `backendBlocker.backend: "llvm"` means the selected LLVM artifact, target, command, MIR subset, or clang toolchain is not ready.
|
||||
- Missing sysroot facts identify the required `ZERO_SYSROOT_*` variable.
|
||||
- Unsupported targets fail explicitly instead of silently choosing another backend.
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
name: diagnostics
|
||||
description: Read Zero diagnostics, explanations, and typed fix plans.
|
||||
---
|
||||
|
||||
# Zero Diagnostics
|
||||
|
||||
Use this when Zero code fails to parse, typecheck, build, test, or target-check.
|
||||
Zero diagnostics are intended for agents: start with the readable command
|
||||
output. Use JSON only when an automation tool needs stable fields or a debugging
|
||||
session needs exact spans, repair metadata, or machine-readable diagnostics.
|
||||
|
||||
## Commands
|
||||
|
||||
```sh
|
||||
zero check
|
||||
zero explain <diagnostic-code>
|
||||
```
|
||||
|
||||
Use machine-readable output when a tool needs exact fields:
|
||||
|
||||
```sh
|
||||
zero check --json
|
||||
zero explain --json <diagnostic-code>
|
||||
zero fix --plan --json
|
||||
```
|
||||
|
||||
`zero fix` reads graph-backed inputs. It reports candidate repairs for graph diagnostics; projection-only source must be imported before repair planning.
|
||||
|
||||
## Diagnostic Shape
|
||||
|
||||
Important fields from `zero check --json`:
|
||||
|
||||
- `code`: stable diagnostic code such as `NAM003` or `TAR002`
|
||||
- `message`: short human summary
|
||||
- `path`, `line`, `column`, `length`: source span
|
||||
- `expected` and `actual`: structured mismatch facts when available
|
||||
- `help`: concise next action
|
||||
- `fixSafety`: safety label for an agent repair
|
||||
- `repair`: optional repair id and summary
|
||||
- `related`: extra spans or facts
|
||||
|
||||
Do not scrape terminal prose for automation. Use JSON when a script or tool needs stable fields.
|
||||
|
||||
## Fix Safety
|
||||
|
||||
`zero fix --plan --json` reports `safetyLevels` and per-fix `safety`:
|
||||
|
||||
- `format-only`: formatting or trivia only
|
||||
- `behavior-preserving`: intended not to change runtime behavior
|
||||
- `api-changing`: signatures, exports, or call sites may change
|
||||
- `target-changing`: target support or capability use may change
|
||||
- `requires-human-review`: the compiler cannot prove the edit is safe
|
||||
|
||||
Apply only the edit you can justify from the source and fix plan. Treat `requires-human-review` as a planning hint, not an automatic patch.
|
||||
|
||||
## Common Codes
|
||||
|
||||
- `NAM003`: unknown name; declare it, import it, or fix spelling.
|
||||
- `IMP001`: unknown package-local import.
|
||||
- `IMP002`: package-local import cycle.
|
||||
- `PKG001`: local dependency path lacks `zero.toml` or a compatibility
|
||||
`zero.json`.
|
||||
- `PKG002`: package dependency cycle.
|
||||
- `PKG003`: one package name resolves to conflicting versions.
|
||||
- `PKG004`: selected target is not supported by a dependency.
|
||||
- `TAR001`: unknown target; inspect `zero targets`.
|
||||
- `TAR002`: capability unavailable for selected target.
|
||||
- `BLD003`: removed backend flag; use direct emitters.
|
||||
- `STD002`: unknown standard-library helper; use a documented `std.<module>.<helper>` name.
|
||||
- `STD003`: standard-library capability or contract mismatch; inspect the helper signature and required capability.
|
||||
- `TYP009`: immutable value used where a mutable destination is required; make the binding `var` or pass mutable storage.
|
||||
- `MEM003`: one function's fixed locals exceed the 128 KiB frame limit; split the buffer into smaller buffers in helper functions, or process the data in fixed-size chunks.
|
||||
- `RGP007`: ambiguous source identity during import; split the text edit into smaller passes or make the change with `zero patch`.
|
||||
- `RGP008`: stale package projection while `ZERO_STALE=fail` is set; run `zero import`, or unset the variable to let the command refresh automatically.
|
||||
- `RGP009`: binary `zero.graph` store unreadable by this compiler, usually written by a different zero build; rebuild it with this binary via `zero import .` or install the matching compiler (compare `zero --version` build hashes).
|
||||
|
||||
## Agent Triage
|
||||
|
||||
1. Run the failing command normally first.
|
||||
2. If a debugging session needs exact machine fields, rerun with `--json` and use the span to inspect only the relevant source.
|
||||
3. Run `zero explain <code>` before broad refactors.
|
||||
4. If multiple diagnostics share a root cause, fix the earliest source issue.
|
||||
5. Re-run the same command after the patch.
|
||||
@@ -0,0 +1,237 @@
|
||||
---
|
||||
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 <name> --handles`, `--find`, or `--fn <name> --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 <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<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
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 <name> --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 '<pattern>' --to '<template>'` matches canonical projection expressions structurally; `$A`, `$B` bind arbitrary subtrees and the same metavariable twice must match equal subtrees. The default is a dry run that lists every site as `path fn:handle` with rendered before/after; `--apply` rewrites all sites in one batch with one revalidation, and `--fn <name>` scopes matching to one function. Patterns are expression-level only; unsupported subtree kinds are skipped and counted.
|
||||
|
||||
```sh
|
||||
zero patch . --rewrite 'bnCmp($A, $B) == 0' --to 'bnEq($A, $B)' # dry run
|
||||
zero patch . --rewrite 'bnCmp($A, $B) == 0' --to 'bnEq($A, $B)' --apply # rewrite every site
|
||||
```
|
||||
|
||||
For multi-statement bodies, use `replaceFunctionBody` for a whole function or `replaceBlockBody` for one selected `Block` node. Body rows accept canonical projection syntax, the same text `zero view` prints:
|
||||
|
||||
```text
|
||||
zero-program-graph-patch v1
|
||||
expect graphHash "graph:a7f7e6899a73f3b4"
|
||||
replaceFunctionBody main
|
||||
let name: Maybe<String> = std.args.get(1)
|
||||
if name.has {
|
||||
check world.out.write("hello ")
|
||||
check world.out.write(name.value)
|
||||
check world.out.write("\n")
|
||||
} else {
|
||||
check world.out.write("hello anonymous\n")
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
To replace one function body without patch syntax or shell quoting, use `--replace-fn` with `--body-file`. `--body-file -` reads the body rows from stdin, so a heredoc does the whole edit in one call:
|
||||
|
||||
```sh
|
||||
zero patch --replace-fn main --body-file - <<'EOF'
|
||||
let name: Maybe<String> = std.args.get(1)
|
||||
if name.has {
|
||||
check world.out.write("hello ")
|
||||
check world.out.write(name.value)
|
||||
check world.out.write("\n")
|
||||
} else {
|
||||
check world.out.write("hello anonymous\n")
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
The body holds only the new rows, exactly what `zero view --fn <name>` prints between the signature braces (no header, no `end`). Quotes, `$variables`, and backslashes pass through a quoted heredoc untouched. The alternative is a file path: `zero patch --replace-fn <name> --body-file /tmp/main.body`.
|
||||
|
||||
To change a few characters inside a large function, do not retype the body: `--replace-in-fn` replaces one unique literal occurrence of `--old` in the function's canonical body text with `--new` (Edit semantics), then revalidates exactly like `--replace-fn`:
|
||||
|
||||
```sh
|
||||
zero patch --replace-in-fn handleLine --old 'limit + 1' --new 'limit + 2'
|
||||
```
|
||||
|
||||
A missing or non-unique `--old` fails with the occurrence count; extend `--old` with surrounding lines from `zero view --fn <name>` until it matches once. Inline `--old`/`--new` accept `\n` escapes; `--old-file`/`--new-file <file|->` read multi-line text from a file or stdin.
|
||||
|
||||
To patch one branch instead of rewriting the whole function, find the block handle first:
|
||||
|
||||
```sh
|
||||
zero query --find Block
|
||||
```
|
||||
|
||||
```text
|
||||
zero-program-graph-patch v1
|
||||
replaceBlockBody #block_32cefdd9
|
||||
check world.out.write("updated\n")
|
||||
end
|
||||
```
|
||||
|
||||
Preview without writing, and list operation shapes without loading a graph:
|
||||
|
||||
```sh
|
||||
zero patch --check-only /tmp/body.patch
|
||||
zero patch --dry-run --json /tmp/body.patch
|
||||
zero patch --op help
|
||||
```
|
||||
|
||||
Supported graph patch operations (authoring ops first; node-handle ops are the advanced surface):
|
||||
|
||||
```text
|
||||
addMain
|
||||
addCheckWrite fn="main" text="hello\n"
|
||||
addFunction name="add" ret="i32"
|
||||
addParam fn="add" name="left" type="i32"
|
||||
addParamTo fn="add" name="bias" type="i32" default="0"
|
||||
setConst name="limit" value="64"
|
||||
setReturnType fn="add" type="i64"
|
||||
addReturnBinary fn="add" name="+" left="left" right="right" type="i32"
|
||||
addLetLiteral fn="main" name="count" type="u32" value="0"
|
||||
addLetBinary fn="add" name="sum" type="i32" operator="+" left="left" right="right"
|
||||
addReturnValue fn="identity" value="input" type="i32"
|
||||
addReturnExpr fn="maybe" expr="null"
|
||||
appendStmt fn="main" stmt="check std.http.listen(world, 3000_u16)"
|
||||
addCheckWriteValue fn="main" value="message" type="String"
|
||||
addTest name="addition works" call="add" arg0="40" arg1="2" expect="42" type="i32"
|
||||
addTestBody name="api add"
|
||||
expect apiAddOk()
|
||||
end
|
||||
renameTest name="api add" value="api add route"
|
||||
deleteTest name="api add"
|
||||
upsertFunction handle
|
||||
fn handle(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return null
|
||||
}
|
||||
end
|
||||
replaceFunctionBody main
|
||||
let name Maybe<String> = std.args.get 1
|
||||
if name.has
|
||||
check world.out.write "hello "
|
||||
check world.out.write name.value
|
||||
check world.out.write "\n"
|
||||
else
|
||||
check world.out.write "hello anonymous\n"
|
||||
end
|
||||
replaceBlockBody #block_id
|
||||
check world.out.write "updated\n"
|
||||
end
|
||||
expect graphHash "graph:a7f7e6899a73f3b4"
|
||||
set node="#id" field="value" expect="old" value="new"
|
||||
insert node="#id" kind="Literal" parent="#parent" edge="arg" order="0" type="String" value="text"
|
||||
insertEdge from="#from" to="#to" edge="arg" target="node" order="0"
|
||||
replace node="#id" expect="nodehash:abc123" kind="Literal" type="String" value="text"
|
||||
replaceExpr node="#id" with="left + 1"
|
||||
delete node="#id" expect="nodehash:abc123"
|
||||
delete node="#id"
|
||||
rename node="#id" expect="old" value="new"
|
||||
```
|
||||
|
||||
`insert` and `insertEdge` default `order` to `0`, which fits singular edges like `expr`, `left`, and `declaredType`. For precise existing-node edits, pin the graph hash and node facts:
|
||||
|
||||
```sh
|
||||
zero patch \
|
||||
--expect-graph-hash graph:a7f7e6899a73f3b4 \
|
||||
--op 'set node="#expr_653eeb6e" field="value" expect="hello from zero\n" value="hello agent\n"'
|
||||
```
|
||||
|
||||
For larger edits, write a patch file under `/tmp` or pass `--patch-text`; `--patch-text -` reads a complete `zero-program-graph-patch v1` patch from stdin. Always include `expect graphHash` when a patch is carried across tool calls.
|
||||
|
||||
## Artifacts, Reconcile, And Diff
|
||||
|
||||
Create a derived artifact only to carry a graph between tools, and validate it before applying accepted changes back to a package store:
|
||||
|
||||
```sh
|
||||
zero dump --out .zero/agent/app.program-graph
|
||||
zero validate .zero/agent/app.program-graph
|
||||
zero view .zero/agent/app.program-graph
|
||||
```
|
||||
|
||||
Do not commit `.program-graph` files unless the user explicitly asks. `zero source-map` connects graph nodes to source ranges. When a human edited source after a graph was captured, reconcile before relying on old node IDs:
|
||||
|
||||
```sh
|
||||
zero reconcile .zero/agent/app.before.program-graph --source <projection-or-package>
|
||||
```
|
||||
|
||||
`zero reconcile` reports unchanged, edited, inserted, deleted, ambiguous, and identity-changed nodes; ambiguous matches fail instead of assigning stale handles.
|
||||
|
||||
For readable Git diffs of `.graph` files, mark them with `*.graph diff=zero-graph` in `.gitattributes` and set `git config diff.zero-graph.textconv 'zero diff'` (`bin/zero diff` inside a Zero checkout). `zero diff` prints canonical review text for textconv, and `zero diff --fn <name>` scopes it to one function; keep using `zero query`, `zero inspect`, and `zero patch` for graph work.
|
||||
|
||||
`zero merge --base <base-zero.graph> --left <left-zero.graph> --right <right-zero.graph> <package>` combines independent node-hash edits and writes only the target store; run `export` separately if a human needs the refreshed projection. Build and run commands may also write a derived final-MIR cache in the native cache; agents should not patch `.zmir` files.
|
||||
@@ -0,0 +1,215 @@
|
||||
---
|
||||
name: language
|
||||
description: Compact zerolang syntax and semantics guide for agents.
|
||||
---
|
||||
|
||||
# zerolang Language
|
||||
|
||||
Use this when reading or writing Zero source. `.0` files are the human-readable projection syntax, not the package compiler input: package commands compile from `zero.graph` and refresh it automatically after `.0` edits. Read one function with `zero view --fn <name>` instead of whole files.
|
||||
|
||||
## Minimal Program
|
||||
|
||||
```zero
|
||||
pub fn main(world: World) -> Void raises {
|
||||
check world.out.write("hello from zerolang\n")
|
||||
}
|
||||
```
|
||||
|
||||
`pub fn` exports a function. `World` carries runtime capabilities. `raises` marks a fallible function. `check` calls a fallible operation and propagates failure.
|
||||
|
||||
## Declarations
|
||||
|
||||
- `use std.mem` or `use helpers`
|
||||
- `const answer: i32 = 42` (top-level consts work in functions and tests)
|
||||
- `type Point { x: i32, y: i32, }`
|
||||
- `enum Mode { fast, small, }`
|
||||
- `choice Result { ok: i32, err: String, }`
|
||||
- `fn answer() -> i32 { return 42 }`
|
||||
- `pub fn main(world: World) -> Void raises { ... }`
|
||||
- `test "name" { expect true }`
|
||||
|
||||
## Values, Mutation, And Control Flow
|
||||
|
||||
Use `let` by default and `var` only when a binding changes. Conditions are `Bool`; do not rely on truthy integers or strings. Operators are normal infix expressions: `a + b`, `a % b`, `a == b`, `a < b`, `a && b`. Comments start with `//`.
|
||||
|
||||
```zero
|
||||
fn sum_odds(n: i32) -> i32 {
|
||||
var i: i32 = 0
|
||||
var total: i32 = 0
|
||||
while i < n {
|
||||
i = i + 1
|
||||
if i % 2 == 0 {
|
||||
continue
|
||||
}
|
||||
if total > 100 {
|
||||
break
|
||||
}
|
||||
total = total + i
|
||||
}
|
||||
return total
|
||||
}
|
||||
```
|
||||
|
||||
`break` exits the nearest loop and `continue` skips to its next iteration.
|
||||
|
||||
## Types
|
||||
|
||||
Primitive and scalar types:
|
||||
|
||||
```text
|
||||
Bool Void String char Type
|
||||
i8 i16 i32 i64 isize
|
||||
u8 u16 u32 u64 usize
|
||||
f32 f64
|
||||
```
|
||||
|
||||
Bare integer literals adopt the other operand's integer type when in range, so `i * 12` works for `i: usize`. Use suffixes such as `_u8` or `_usize` only when no operand gives context, and `as` for intentional casts.
|
||||
|
||||
Core capability, resource, and helper types recognized by the compiler:
|
||||
|
||||
```text
|
||||
World WorldStream
|
||||
Fs File ByteBuf
|
||||
NullAlloc FixedBufAlloc PageAlloc GeneralAlloc
|
||||
Vec Duration RandSource ProcStatus ProcChild
|
||||
Address Net Conn Listener
|
||||
HttpMethod HttpClient HttpServer HttpResult HttpError HttpHeaderValue
|
||||
JsonDoc BufferedReader BufferedWriter FixedReader FixedWriter
|
||||
Env Args Clock Rand Proc Alloc
|
||||
Maybe<T> Span<T> MutSpan<T>
|
||||
ref<T> mutref<T> owned<T>
|
||||
```
|
||||
|
||||
## Shapes, Enums, And Choices
|
||||
|
||||
```zero
|
||||
let point: Point = Point { x: 1, y: 2 }
|
||||
let result: Result = Result.ok(42)
|
||||
```
|
||||
|
||||
Matches must be exhaustive unless they use the fallback arm `_`:
|
||||
|
||||
```zero
|
||||
match result {
|
||||
.ok(value) {
|
||||
expect value == 42
|
||||
}
|
||||
.err(message) {
|
||||
expect true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Errors
|
||||
|
||||
```zero
|
||||
fn value(i: i32) -> i32 raises [Odd] {
|
||||
if i % 2 == 0 {
|
||||
return i
|
||||
}
|
||||
raise Odd
|
||||
}
|
||||
|
||||
pub fn main(world: World) -> Void raises {
|
||||
let item: i32 = rescue value(3) err 1
|
||||
if item == 1 {
|
||||
check world.out.write("fallible ok\n")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`raises [Error]` restricts the error set. Plain `raises` is open. Calling a fallible function requires `check` or `rescue`.
|
||||
|
||||
## Borrowing And Memory Views
|
||||
|
||||
- `ref<T>` is a read-only borrow, passed with `&value`.
|
||||
- `mutref<T>` is a mutable borrow, passed with `&mut value`. Shape parameters such as `mutref<Point>` work, including field mutation and nested calls.
|
||||
- `[N]T` is a fixed array; `Span<T>` is a read-only view; `MutSpan<T>` is a writable view.
|
||||
- Returning a span backed by local fixed-array storage is rejected; return an owned value or keep the view local.
|
||||
- `Maybe<T>` represents absence; read `.value` only inside a visible `.has` guard, or use `check` / `rescue`. `var name: Maybe<String> = null` declares an absent local to assign or return later.
|
||||
- `owned<T>` marks explicit resource ownership.
|
||||
- One function's fixed locals are limited to 128 KiB (MEM003). Split large buffers into smaller buffers in helper functions, or process data in fixed-size chunks.
|
||||
|
||||
```zero
|
||||
fn bump(point: mutref<Point>) -> Void {
|
||||
point.x = point.x + 1
|
||||
}
|
||||
|
||||
pub fn main() -> Void {
|
||||
var storage: [4]u8 = [1, 2, 3, 4]
|
||||
let view: MutSpan<u8> = storage
|
||||
let first: u8 = storage[0]
|
||||
storage[0] = 9
|
||||
}
|
||||
```
|
||||
|
||||
Array and span indexing is bounds-checked at runtime; an out-of-range index traps with a signal exit and no output, so exercise boundary inputs before declaring a change done.
|
||||
|
||||
## Generics
|
||||
|
||||
```zero
|
||||
type Box<T: Type> {
|
||||
value: T,
|
||||
}
|
||||
|
||||
fn id<T: Type>(value: T) -> T {
|
||||
return value
|
||||
}
|
||||
|
||||
type FixedVec<T: Type, static N: usize> {
|
||||
len: usize,
|
||||
items: [N]T,
|
||||
}
|
||||
```
|
||||
|
||||
## Standard Library Call Shapes
|
||||
|
||||
Load `zero skills get stdlib` for the full signature catalog. Beyond the `std.mem`/`std.parse`/`std.rand`/`std.json` helpers shown below, it ships ready-made validators: `std.time` (RFC 3339 date/time incl. the exact leap-second rule), `std.inet` (IPv4/IPv6/hostname), `std.regex` (ECMA subset), and `std.unicode` (strict UTF-8). Check the catalog before hand-writing parsing or validation logic. Target-neutral helpers follow these shapes:
|
||||
|
||||
```zero
|
||||
pub fn main() -> Void {
|
||||
let bytes: Span<u8> = std.mem.span("zero")
|
||||
let n: usize = std.mem.len(bytes)
|
||||
let same: Bool = std.mem.eql("zero", "zero")
|
||||
|
||||
let parsed: Maybe<u16> = std.parse.parseU16("8080")
|
||||
if parsed.has {
|
||||
expect parsed.value == 8080
|
||||
}
|
||||
|
||||
var rng: RandSource = std.rand.seed(7_u32)
|
||||
let random: u32 = std.rand.nextU32(&mut rng)
|
||||
let count: Maybe<u32> = std.json.u32("{\"count\":42}", "count")
|
||||
expect same && random == 1025555898_u32 && count.has
|
||||
}
|
||||
```
|
||||
|
||||
Hosted helpers are capability-gated by target. There is no stdin; hosted programs take input from `std.args` and files through `std.fs`:
|
||||
|
||||
```zero
|
||||
pub fn main(world: World) -> Void raises {
|
||||
let first: Maybe<String> = std.args.get(1)
|
||||
if first.has {
|
||||
check world.out.write(first.value)
|
||||
}
|
||||
|
||||
var path_storage: [16]u8 = [0; 16]
|
||||
let path: String = check std.path.join(path_storage, ".zero", "x")
|
||||
let fs: Fs = std.fs.host()
|
||||
var file: owned<File> = check std.fs.createOrRaise(fs, path)
|
||||
check std.fs.writeAllOrRaise(&mut file, std.mem.span("hello\n"))
|
||||
}
|
||||
```
|
||||
|
||||
If unsure, run `zero check` instead of inventing syntax, and pair behavior changes with a `test` block:
|
||||
|
||||
```zero
|
||||
fn point_sum(point: Point) -> i32 {
|
||||
return point.x + point.y
|
||||
}
|
||||
|
||||
test "shape" {
|
||||
let point: Point = Point { x: 40, y: 2 }
|
||||
expect point_sum(point) == 42
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,163 @@
|
||||
---
|
||||
name: packages
|
||||
description: Create, inspect, and repair Zero packages and manifests.
|
||||
---
|
||||
|
||||
# Zero Packages
|
||||
|
||||
Use this when working with `zero.toml`, compatibility `zero.json`, package-local modules, package tests, or multi-file Zero projects.
|
||||
|
||||
## Create
|
||||
|
||||
For agent-authored packages, start graph-first:
|
||||
|
||||
```sh
|
||||
zero init
|
||||
zero patch --op 'addMain'
|
||||
```
|
||||
|
||||
`zero.graph` is the package graph store and compiler input. `.0` files are the
|
||||
human-readable projection; export them only when a human asks to review or edit
|
||||
the projection. `zero init` defaults to the current directory and uses that
|
||||
directory's folder name as the package name. Use `zero init app` when the
|
||||
user asks for a new subdirectory. It writes TOML metadata by default; use
|
||||
`zero init --manifest json [package]` only for explicit compatibility cases.
|
||||
Use `zero init --template cli|lib|package [package]` only when the user
|
||||
explicitly asks for starter files.
|
||||
|
||||
## Manifest
|
||||
|
||||
Minimal executable package in TOML:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "hello"
|
||||
version = "0.1.0"
|
||||
|
||||
[targets.cli]
|
||||
kind = "exe"
|
||||
main = "src/main.0"
|
||||
```
|
||||
|
||||
The target `main` path names the human-readable projection for source maps,
|
||||
export/import, and review. Normal package commands compile from `zero.graph`.
|
||||
|
||||
JSON is also accepted for compatibility, but new agent-authored packages should
|
||||
use TOML:
|
||||
|
||||
```json
|
||||
{
|
||||
"package": { "name": "hello", "version": "0.1.0" },
|
||||
"targets": { "cli": { "kind": "exe", "main": "src/main.0" } }
|
||||
}
|
||||
```
|
||||
|
||||
If both `zero.toml` and `zero.json` exist in the same package root, Zero uses
|
||||
`zero.toml`. Keep one manifest checked in unless the task is specifically
|
||||
testing precedence.
|
||||
|
||||
Pass either the package directory or manifest to commands:
|
||||
|
||||
```sh
|
||||
zero check
|
||||
zero check zero.toml
|
||||
zero run examples/systems-package
|
||||
```
|
||||
|
||||
## Module Imports
|
||||
|
||||
Package-local imports resolve from `src/`:
|
||||
|
||||
- `use helpers` resolves `src/helpers.0`
|
||||
- `use config.parser` resolves `src/config/parser.0`
|
||||
- `use config.parser` may also resolve `src/config/parser/mod.0`
|
||||
|
||||
Standard library imports use the same `use` form:
|
||||
|
||||
```zero
|
||||
use std.mem
|
||||
use std.parse
|
||||
```
|
||||
|
||||
Avoid implicit files. If an import is unknown, run:
|
||||
|
||||
```sh
|
||||
zero check
|
||||
zero inspect
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
Current packages support local path dependencies and registry metadata. Local
|
||||
dependencies must point at a directory containing `zero.toml` or compatibility
|
||||
`zero.json`; `zero.toml` takes precedence.
|
||||
|
||||
TOML dependency metadata:
|
||||
|
||||
```toml
|
||||
[dependencies.local-tools]
|
||||
path = "../local-tools"
|
||||
version = "0.1.0"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"local-tools": { "path": "../local-tools", "version": "0.1.0" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The resolver is declarative; it records deterministic lock facts under `.zero/package-locks/` and does not fetch remote package code.
|
||||
|
||||
Package compiler commands validate and compile from a checked-in `zero.graph` store, including target and package metadata, and can operate when `.0` source projections are missing. When the projection was edited, commands that consume the store (`zero check`, `zero build`, `zero run`, `zero test`, `zero query`, `zero view`, `zero diff`, and friends) refresh the stale store from source and note it on stderr (`ZERO_STALE=fail` makes that an error); they never rewrite `.0` files. When `zero.graph` is the newer side, for example right after `zero patch`, they keep using the graph and note that too; when both sides changed independently they fail with `RGP006` and offer `zero import` or `zero export` as repairs. Drift is classified by content (each store write records a source projection hash), never by file timestamps, so staged or cloned workspaces behave identically. Use `zero verify-projection` when drift must fail the workflow, and `zero export` only when a human-readable projection needs regeneration.
|
||||
|
||||
## Inspect
|
||||
|
||||
```sh
|
||||
zero inspect
|
||||
zero doc
|
||||
zero dev
|
||||
```
|
||||
|
||||
Use `--json` when a tool needs exact graph, doc, or dev fields. Useful `graph`
|
||||
facts include modules, source paths, import edges, public and private symbol
|
||||
counts, function effects, required capabilities, target facts, dependency
|
||||
facts, and package cache key inputs.
|
||||
|
||||
## Graph Authoring
|
||||
|
||||
For agent-authored packages, prefer the repository graph surface:
|
||||
|
||||
```sh
|
||||
zero init
|
||||
zero patch --op 'addMain'
|
||||
```
|
||||
|
||||
Inspect and patch existing packages through the graph. Create an artifact under
|
||||
`.zero/` only when another tool needs a file artifact:
|
||||
|
||||
```sh
|
||||
zero view
|
||||
zero patch --op 'addMain'
|
||||
```
|
||||
|
||||
Package-level patches write `zero.graph`; successful patch output includes the new graph hash and top-level symbols. Use `zero export` only to materialize `.0` for human review, and `zero import` after humans edit that projection; import accepts the package root or any source path inside it and updates the existing store in place. Keep derived graph artifacts out of the package source unless the user explicitly asks for them.
|
||||
|
||||
Repository graph stores are binary by default. Use `zero init --format text` or
|
||||
`zero import --format text [package]` only when the package
|
||||
intentionally needs a readable debug store. Normal reads auto-detect both
|
||||
encodings, and normal writes preserve an existing text or binary store. Stdlib
|
||||
`std/*.graph` stores are binary graph stores; `std/*.0` siblings are human
|
||||
projections and are not used as the stdlib compile source.
|
||||
|
||||
## Common Repairs
|
||||
|
||||
- `IMP001`: create the imported module, fix its path, or adjust `use`.
|
||||
- `IMP002`: break a direct import cycle.
|
||||
- `PKG001`: fix a local dependency path so it contains `zero.toml` or a compatibility `zero.json`.
|
||||
- `PKG002`: break a package dependency cycle.
|
||||
- `PKG003`: avoid resolving one package name to multiple versions.
|
||||
- `PKG004`: update target metadata or choose a supported target.
|
||||
|
||||
Prefer a package-local fix over moving unrelated files.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
---
|
||||
name: testing
|
||||
description: Write and run Zero test blocks.
|
||||
---
|
||||
|
||||
# Zero Testing
|
||||
|
||||
Use this when adding tests, debugging failing tests, or wiring Zero checks into CI and editor workflows.
|
||||
|
||||
## Test Blocks
|
||||
|
||||
Zero test blocks live beside source:
|
||||
|
||||
```zero
|
||||
fn add(left: i32, right: i32) -> i32 {
|
||||
return left + right
|
||||
}
|
||||
|
||||
test "addition works" {
|
||||
expect add(2, 3) == 5
|
||||
}
|
||||
```
|
||||
|
||||
`expect` requires a `Bool`. A false expectation fails the test.
|
||||
|
||||
Use `std.testing` helpers when a predicate should be explicit in the source:
|
||||
|
||||
```zero
|
||||
test "output shape" {
|
||||
expect std.testing.equalBytes("zero", "zero")
|
||||
expect std.testing.containsBytes("zerolang", "lang")
|
||||
}
|
||||
```
|
||||
|
||||
`std.testing` does not register tests or print output. It only returns `Bool`
|
||||
values for ordinary `expect` statements.
|
||||
|
||||
## Run
|
||||
|
||||
```sh
|
||||
zero test conformance/native/pass/test-blocks.graph
|
||||
zero test --filter addition conformance/native/pass/test-blocks.graph
|
||||
zero test conformance/packages/test-app
|
||||
```
|
||||
|
||||
Use `--filter` for a narrow loop. The filter matches test names by substring.
|
||||
|
||||
For packages, normal `zero test [package]` compiles from `zero.graph` and can
|
||||
run before `.0` projections exist:
|
||||
|
||||
```sh
|
||||
zero patch --op 'addTest name="addition works" call="add" arg0="2" arg1="3" expect="5" type="i32"'
|
||||
zero test
|
||||
zero test --filter addition
|
||||
```
|
||||
|
||||
Prefer `addTest` for one pure function call with literal arguments. Use
|
||||
`addTestBody name="..." ... end` only when the test needs custom body rows.
|
||||
Test labels are display names, not callable function names; do not rename them
|
||||
to `__zero_test_*`.
|
||||
If `zero test` reports an unknown function for a display label, do not rename
|
||||
the label to chase runner internals. Delete the malformed custom test and
|
||||
recreate simple pure coverage with `addTest`, or use behavior smoke checks for
|
||||
effectful paths.
|
||||
|
||||
If another tool hands you a derived ProgramGraph artifact, `zero test` can
|
||||
validate it. Do not create a standalone graph artifact for the ordinary package
|
||||
test loop; test the package path so the compiler reads `zero.graph` directly.
|
||||
|
||||
## JSON Fields
|
||||
|
||||
Use `zero test --json` when a tool or CI job needs exact fields. Useful fields:
|
||||
|
||||
- `testDiscovery`: how files and tests were found
|
||||
- `fixtures`: fixture inputs and snapshot metadata
|
||||
- `snapshotKey`: stable test snapshot contract
|
||||
- `discoveredTests`, `selectedTests`, `passedTests`, `failedTests`
|
||||
- `expectedFailures`, `unexpectedPasses`
|
||||
- `targetFacts`: selected target and capability facts
|
||||
- `results`: per-test name, status, duration, source location, and failure span
|
||||
- `stdout`, `stderr`, `durationMs`
|
||||
|
||||
Use JSON for machines and CI contracts. Normal test output is the default agent loop.
|
||||
|
||||
## Expected Failures
|
||||
|
||||
Expected-fail tests use one of these name markers:
|
||||
|
||||
- `xfail:`
|
||||
- `expected fail:`
|
||||
- `[xfail]`
|
||||
|
||||
Example:
|
||||
|
||||
```zero
|
||||
test "xfail: pending parser edge case" {
|
||||
expect false
|
||||
}
|
||||
```
|
||||
|
||||
An expected-fail test passes the command only when it fails as expected. If it starts passing, the command fails with `unexpectedPasses`.
|
||||
|
||||
## Agent Workflow
|
||||
|
||||
1. Add the smallest test that owns the behavior.
|
||||
2. Run a filtered test while editing.
|
||||
3. Run the containing package or fixture before finishing.
|
||||
4. Do not leave an expected-fail marker on a fixed bug.
|
||||
5. Use `zero check` first when the failure is a compile error; rerun with `--json` only if you need exact diagnostic fields.
|
||||
Reference in New Issue
Block a user