Skip to content

Commit 99d37f6

Browse files
Split the CLI surface, add configuration, and close the defects an audit found
`run` used to mean "execute one of eight canned examples", which left no command for the common case: a topology you already know the shape of. The examples moved to `demo`; `run <graph.json|graph.toml>` admits and executes a file you wrote, through the same AdmissionChecker a planner's proposal goes through. A hand-written graph earns no exemption and cannot carry a node body. New: - `grapharc run --check-only` — admission as a linter. Validates a topology against a policy and executes nothing. - `grapharc.toml` — defaults for --registry/--policy/--model and the limits. flag > env > config > built-in, with every value reporting its layer in a `sources` block. Parent directories are NOT searched, deliberately: a run must not be governed by a file the operator did not know about. Relative paths in a config anchor to the config, not the working directory. - `grapharc.stdlib` — general-purpose node kinds, so a zero-config run needs no generated code. Phases, not operations: file access happens inside an agent-backed phase where tools are permission-checked per call. No phase is given run_command. `apply_change` is registered and denied by default. - Policy generation when nothing names a policy: written to `.grapharc/generated-policy.toml`, disclosed as `policy_source`, and read off disk on the next run so generation is a one-time state. A registry is never generated — policy is data, a registry is functions. - `cost_usd` on trace events, so observe.cost reports a recorded figure rather than an estimate whenever a backend supplied one. - A canonical architecture diagram (docs/diagrams/00-architecture.png) plus a trust-boundary view, both reproducible from architecture.py. Defects found by an adversarial end-to-end pass, each now with a test that fails without its fix: - `run` reported "ADMITTED and executed" and wrote only the admission event — Materializer takes a trace= and the call omitted it. - `run --run-id` was accepted and discarded, so metrics found nothing under it. - `--check-only` was a false linter: three topology classes passed admission and then hard-crashed. It now materialises before answering, and MaterializationError is reported rather than escaping as a traceback. - A comment claimed run's budget was bounded; Budget() is unlimited on every dimension and a 400,000-token worst case was admitted. --max-tokens added. - viz crashed on an unknown run id; models crashed on a mistyped backend with exit 1 where the help promises 2; demo --memory crashed on an unusable path. All four now answer as documents, which is what the CLI's help promises. - --config was on the shared parser, so all eleven commands accepted it and nine ignored it. Scoped to the three that resolve settings. - `memory` and `reviewer_model` were declared in config KEYS and read by nothing. - A key beside the [grapharc] table was silently dropped, so a stray policy = "strict.toml" was ignored and the run used the permissive default. - `sources.policy` reported "default" while `policy_source` said "generated-cached"; a reviewer reading sources alone would conclude no file was involved. - The sdist shipped tests/ but not docs/, and six cookbook modules read their page at import time — so pytest inside a release died with five collection errors. It now collects 1533. Recorded as known limits rather than silently patched: a bare model spec resolves to the paid claude-cli backend; .env walks up parent directories while grapharc.toml deliberately does not; serve --registry accepts either of two same-named classes. Removes ARCHITECTURE.md, ASSESSMENT.md, CHANGELOG.md and VISION.md, and untracks HANDOFF.md (an internal note carrying local paths). CI and the release workflow both asserted CHANGELOG.md was in the sdist and would have failed every release; HANDOFF.md kept shipping because ignore-vcs means .gitignore has no vote on the build. Both lists fixed, along with 28 inbound links, seven source docstrings that cited the removed design doc, and a PyPI project URL that would have 404'd. Also includes the OpenAI and Ollama gateway backends and the Ladybug memory store, which were in progress in the working tree. 1533 passed, 12 deselected. ruff clean. Wheel imports 102 submodules with [all]. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent a4235d7 commit 99d37f6

63 files changed

Lines changed: 5278 additions & 2247 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ jobs:
244244
names = {name.split("/", 1)[1] for name in root if "/" in name}
245245
246246
required = {
247-
"CHANGELOG.md",
248247
"CONTRIBUTING.md",
249248
"LICENSE",
250249
"MANIFEST.in",

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ jobs:
112112
root = tarfile.open(glob.glob("dist/*.tar.gz")[0]).getnames()
113113
names = {name.split("/", 1)[1] for name in root if "/" in name}
114114
115-
missing = sorted({"CHANGELOG.md", "LICENSE", "README.md", "pyproject.toml"} - names)
115+
missing = sorted({"LICENSE", "README.md", "pyproject.toml"} - names)
116116
if missing:
117117
sys.exit(f"refusing to publish: missing from the sdist: {missing}")
118118

.gitignore

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,38 @@ __marimo__/
216216

217217
# Streamlit
218218
.streamlit/secrets.toml
219+
220+
# ── GraphARC's own output ─────────────────────────────────────────────────────
221+
# Everything below is something a *run* produces, not something a person wrote.
222+
# Note: `[tool.hatch.build] ignore-vcs = true` in pyproject.toml means this file
223+
# has no vote on what ships in the wheel — the exclude list there is the
224+
# authority. Adding a path here cannot silently drop a subpackage from a build,
225+
# which it could before that was set.
226+
227+
# Traces. The audit format is JSONL and `--trace PATH` writes wherever it is
228+
# told, so a run started in the repo root leaves one behind. A trace that is
229+
# deliberately a test fixture can still be committed with `git add -f`.
230+
*.jsonl
231+
232+
# A policy generated because no `--policy`, no `grapharc.toml` and no existing
233+
# one was found. Generated rather than authored: the design is that you *promote*
234+
# it — read it, edit it, move it, pass `--policy` — instead of committing it from
235+
# where a tool dropped it. `grapharc.toml` itself is deliberately NOT ignored;
236+
# that one is yours and belongs in version control.
237+
.grapharc/
238+
239+
# Durable claim stores from `grapharc demo --memory PATH`, and the two sidecars
240+
# WAL mode creates alongside them.
241+
*.sqlite
242+
*.sqlite-wal
243+
*.sqlite-shm
244+
245+
# Scratch workspaces. `grapharc agent` defaults to a temp dir, but pointing
246+
# `--workspace` at the repo is the obvious thing to try.
247+
/workspace/
248+
/scratch/
249+
250+
# Claude Code's per-machine settings. Already covered by many people's global
251+
# ignore; named here so a fresh clone does not depend on that being true.
252+
.claude/settings.local.json
253+
HANDOFF.md

0 commit comments

Comments
 (0)