Keel
Grounding report.
Every verification edge in anthropic-quickstarts, classified by who produces the signal and whether the actor being verified can write to that producer.
| target | anthropic-quickstarts |
|---|---|
| revision | 370e18d4a20ff5fd4bc1a6bf11d5105b2383977c |
| generated | 2026-07-25T03:58:05.194Z |
anchored / (anchored + self_referential + unknown) = 10 / 10
Coverage (judged)
| node kind | judged |
|---|---|
| ci_step | 10 |
| script | 9 |
| test_target | 5 |
| review_gate | 1 |
ε-audit — not run
No verdict in this report carries a readable audit block, so nothing was re-decided and there is no agreement rate to report. This is not agreement, and it is not full agreement either: a rate over zero comparisons would state a measurement that was never taken. (“Readable” is load-bearing: a block can be present and state no comparison, and this state covers that too — see below if so.)
This run judged 25 of 62 gathered edges. Every number on this page describes that sample, not the whole surface — 37 gathered edges are absent from all of it. A cap is disclosed rather than smoothed: an undisclosed sample is how a ratio gets shopped.
Scope. Keel measures the shape of verification, not its quality. A repo can be 100% anchored with terrible tests. Anchoring says the signal comes from outside; it does not say the signal is sufficient.
Node graph — 25 node(s), in gather order
anchored — 10
The exit code comes from the TypeScript compiler and ESLint executing against the committed sources; an author cannot make a type-incorrect file report clean without editing the file or editing the committed tsconfig.json / .eslintrc.json (both of which are diffable). This edge is on a real gating path: amplify.yml's build phase runs `npm run build`, and a non-zero exit fails the AWS Amplify deploy. Documented limit — it is a compile-and-lint gate only; no test executes here, and `next build` says nothing about runtime behaviour.
producer the `next build` process — Next 14.2.5 runs `tsc` over tsconfig.json (`strict: true`, no `typescript.ignoreBuildErrors` escape in next.config.mjs) and ESLint over .eslintrc.json before emitting, and exits non-zero on the first type or lint error — actor can write to it: no
- customer-support-agent/package.json:10
- customer-support-agent/tsconfig.json:6 ("strict": true), :7 ("noEmit": true)
- customer-support-agent/next.config.mjs:1-15 (no typescript.ignoreBuildErrors / eslint.ignoreDuringBuilds)
- customer-support-agent/amplify.yml:9
- customer-support-agent/package.json:34 (next 14.2.5)
decided by agent · confidence 0.8
ESLint parses the committed .ts/.tsx files and exits non-zero on any error-level rule violation; the author cannot make a violating file report clean without changing the file or the committed .eslintrc.json. Documented limits, and they are why confidence is low: (a) `next lint` is verify-mode, not `--fix`, so it does not rewrite; (b) nothing in the repository invokes this script — no workflow covers customer-support-agent (build.yaml and tests.yaml both filter `paths:` to `.github/**` and `computer-use-demo/**`) and amplify.yml runs only `npm run build`; the same ESLint pass does, however, run inside `next build`, which IS on the Amplify deploy path.
producer the ESLint process invoked by `next lint`, resolving the committed .eslintrc.json (`extends: next/core-web-vitals`) — actor can write to it: no
- customer-support-agent/package.json:12
- customer-support-agent/.eslintrc.json:2
- .github/workflows/tests.yaml:4-12 (path filter excludes customer-support-agent)
- .github/workflows/build.yaml:5-14 (same path filter)
decided by agent · confidence 0.6
Descending the alias: this re-enters package.json:10, so the signal has exactly the causal path of `build` — the TypeScript compiler and ESLint decide the exit code from the committed files under a committed tsconfig.json with `strict: true`, and Amplify's build phase fails the deploy on non-zero. Same documented limit: compile-and-lint only, no behavioural assertion.
producer `npm run build` → the `next build` process, i.e. tsc + ESLint over the committed sources — actor can write to it: no
- customer-support-agent/package.json:17
- customer-support-agent/package.json:10 (the aliased target)
- customer-support-agent/amplify.yml:9
decided by agent · confidence 0.75
The hook exit codes come from analyzers running over the committed source at pinned revisions, so an author cannot make a lint error or a type error report clean without changing the file or changing a pinned rev in a reviewable diff. Two documented limits: (a) three of the six hooks (end-of-file-fixer, trailing-whitespace, `ruff --fix-only`, `ruff format`) are rewriters — pre-commit still fails when they modify a file, so they are falsifiable, but they assert formatting, not correctness; (b) enforcement is local-only — no workflow runs `pre-commit run --all-files` and there is no pre-commit.ci config, so a developer who never installs the hook, or who passes `git commit --no-verify`, is never touched by any of it.
producer the ruff (v0.6.7) and pyright (v1.1.384) processes that pre-commit installs from pinned upstream revs and executes against the staged computer-use-demo files; check-yaml additionally parses each YAML file with a real parser — actor can write to it: no
- .pre-commit-config.yaml:10-24 (ruff v0.6.7, pyright v1.1.384)
- .pre-commit-config.yaml:1 (files: ^computer-use-demo/)
- .github/workflows/tests.yaml (no pre-commit job)
- computer-use-demo/dev-requirements.txt:3 (pre-commit==3.8.0, installed locally)
decided by agent · confidence 0.7
This is configuration, not an invocation, so I traced its consumer: the only thing that reads THIS file is the pyright pre-commit hook (.pre-commit-config.yaml:21-24), which runs from the repo root. The CI pyright job does not read it — jakebailey/pyright-action@v1 runs with `working-directory: computer-use-demo` and therefore resolves computer-use-demo/pyproject.toml instead. So the producer is a real type checker whose verdict the author cannot forge, but the edge this config feeds is a bypassable local hook, not the merge gate. Confidence is deliberately low: anchored-with-low-confidence is the honest shape for a config block whose only consumer runs on developer machines. Second limit: `useLibraryCodeForTypes = false` suppresses inference from untyped dependencies, narrowing what the checker can detect.
producer the pyright type checker, when invoked from the repository root — its exit code is decided by static analysis of the computer-use-demo sources against the interpreter environment named by venvPath/venv — actor can write to it: no
- pyproject.toml:1-4
- .pre-commit-config.yaml:21-24 (pyright hook, run from repo root)
- .github/workflows/tests.yaml:40-42 (CI pyright uses working-directory: computer-use-demo)
- computer-use-demo/pyproject.toml:1-8 (the config CI actually resolves)
decided by agent · confidence 0.5 · confidence below 0.6 on an anchored verdict
The step's exit code is the linter's exit code over the checked-out source, and it is the only step in the `ruff` job that can fail, so it is the job's verdict on a pull request. A contributor cannot make a violating file pass without editing the file or adding a `[tool.ruff]` table (computer-use-demo/pyproject.toml currently declares none, so ruff runs its default E/F rule set). Documented limit, and the reason confidence is not higher: the action is referenced at the mutable tag `@v1`, not a commit SHA, so the implementation that actually runs is not pinned by this repository and is not present in the tree — I am reading the action's contract from its inputs (`src:`) rather than from its code.
producer the ruff binary the action installs, executing `ruff check` over the `computer-use-demo` source tree on the GitHub-hosted runner — actor can write to it: no
- .github/workflows/tests.yaml:21-23
- .github/workflows/tests.yaml:14-19 (the ruff job has only checkout + this step)
- .github/workflows/tests.yaml:3-6 (runs on pull_request touching computer-use-demo/**)
- computer-use-demo/pyproject.toml (no [tool.ruff] table — default rules)
decided by agent · confidence 0.7
The exit code comes from static analysis of the committed Python sources; a contributor cannot make a type error disappear without changing the code or changing a reviewable config key. It is the final and only assertion step of the `pyright` job, so it is what turns that job red on a pull request touching computer-use-demo/**. Two documented limits: the action is at the mutable tag `@v1` rather than a SHA, so its body is neither in the tree nor pinned; and the effective config sets `useLibraryCodeForTypes = false` and `reportPrivateImportUsage = false` in default (basic) mode, which narrows what the checker will flag.
producer the pyright type checker executing over computer-use-demo, resolving computer-use-demo/pyproject.toml's [tool.pyright] table and the .venv built two steps earlier — actor can write to it: no
- .github/workflows/tests.yaml:40-42
- .github/workflows/tests.yaml:24-28 (job defaults working-directory: computer-use-demo)
- computer-use-demo/pyproject.toml:1-8
- .github/workflows/tests.yaml:35-39 (venv + PATH the checker runs against)
decided by agent · confidence 0.7
I traced this config to a real invocation: tests.yaml:59 runs pytest in computer-use-demo on every pull request touching that directory, and the runner's exit code — decided by whether the committed loop_test.py / streamlit_test.py / tools tests raise — turns the job red. The config itself only sets pythonpath and asyncio_mode; it does not weaken any assertion. Documented limit (the oracle axis): the assertions were authored by the same contributors as the implementation, so execution independence holds while the specification does not — the suite proves the code does what the tests say, not that the tests say the right thing.
producer the CPython interpreter running the committed tests under pytest 8.3.3 — `pytest tests --junitxml=junit/test-results.xml` in the `pytest` job — actor can write to it: no
- computer-use-demo/pyproject.toml:10-12
- .github/workflows/tests.yaml:59
- .github/workflows/tests.yaml:43-47
- computer-use-demo/dev-requirements.txt:4-5 (pytest==8.3.3, pytest-asyncio==0.23.6)
- computer-use-demo/tests/ (loop_test.py, streamlit_test.py, tools/)
decided by agent · confidence 0.75
The suite is real — tests/ holds 16 test_*.py modules with executed assertions, and pytest's exit code is decided by the interpreter, which no contributor can write to without changing the code or the tests. The limit is enforcement, and it is severe enough that I am recording it here rather than in prose: NOTHING in this repository invokes it. Both workflows filter `paths:` to `.github/**` and `computer-use-demo/**`, the pre-commit config filters `files: ^computer-use-demo/`, and there is no Makefile, tox.ini or noxfile — the only invocation anywhere is `python -m pytest` in the subproject README. So the producer is anchored while the edge gates no merge; low confidence is the honest expression of that gap, and I have deliberately NOT filed it under not_a_check, which would have removed it from the denominator and inflated the score.
producer the CPython interpreter running the 16 committed test modules under pytest, when a developer invokes it by hand — actor can write to it: no
- computer-use-best-practices/pyproject.toml:46-47
- computer-use-best-practices/tests/ (16 test_*.py modules)
- computer-use-best-practices/README.md:427 (`python -m pytest`, manual)
- .github/workflows/tests.yaml:4-12 and .github/workflows/build.yaml:5-14 (path filters exclude this directory)
- .pre-commit-config.yaml:1 (files: ^computer-use-demo/)
decided by agent · confidence 0.45 · confidence below 0.6 on an anchored verdict
Four committed test modules are discovered by this config and their assertions are decided by the runtime; `--strict-markers` additionally makes an undeclared marker a hard error rather than a warning, so the config is falsifiable on its own terms. Same enforcement limit as computer-use-best-practices, verified the same way: no workflow covers browser-use-demo (both workflows filter to `.github/**` and `computer-use-demo/**`), build.sh only runs `docker build`, and there is no Makefile or tox config — so this suite gates no merge and its only documented invocation is `pytest tests/` in tests/README.md. Confidence is low for exactly that reason. Second limit: `--disable-warnings` and blanket `filterwarnings` ignores suppress deprecation signal the suite would otherwise surface.
producer the CPython interpreter running tests/test_*.py under pytest with `--strict-markers`, when a developer invokes it by hand — actor can write to it: no
- browser-use-demo/pytest.ini:1-40
- browser-use-demo/tests/ (test_integration.py, test_message_renderer.py, test_sampling_loop.py, test_streamlit_helpers.py)
- browser-use-demo/tests/README.md:19 (`pytest tests/`, manual)
- browser-use-demo/build.sh:5 (docker build only)
- .github/workflows/tests.yaml:4-12 (path filter excludes browser-use-demo)
decided by agent · confidence 0.45 · confidence below 0.6 on an anchored verdict
not_a_check — 15
The script starts Next.js in development mode and blocks serving requests until interrupted; it never terminates with a pass/fail verdict about the committed source. The only variation in its exit status comes from how the operator kills it, so no property of the code can make it succeed or fail. Nothing in amplify.yml or the three workflow files invokes it either.
producer the `next dev` development server process (a long-running HTTP server), plus two NEXT_PUBLIC_* env assignments — actor can write to it: not established
- customer-support-agent/package.json:9
- customer-support-agent/amplify.yml:6-13 (deploy runs `npm ci` then `npm run build`, never `dev`)
decided by agent · confidence 0.9
It serves an already-built .next directory over HTTP and runs until killed. It compares nothing, asserts nothing about correctness, and produces no terminating verdict; a broken application starts exactly as happily as a correct one.
producer the `next start` production server process — actor can write to it: not established
- customer-support-agent/package.json:11
decided by agent · confidence 0.9
Descending one hop: this is a pure alias for the dev-server script at package.json:9. A blocking development server terminates on operator interrupt, not on a property of the code, so it cannot report a verdict about anything.
producer `npm run dev`, which re-enters the `dev` script and starts the `next dev` server — actor can write to it: not established
- customer-support-agent/package.json:13
- customer-support-agent/package.json:9 (the aliased target)
decided by agent · confidence 0.9
Identical causal path to `dev`: a blocking HTTP dev server started with a different NEXT_PUBLIC_* flag combination. Feature-flag permutation changes what is rendered, not whether anything is evaluated — nothing is compared, so nothing can fail.
producer the `next dev` development server process, with the right sidebar feature flag off — actor can write to it: not established
- customer-support-agent/package.json:14
decided by agent · confidence 0.9
Same as `dev:left` — a long-running development server under a different NEXT_PUBLIC_* flag combination. It renders an application; it evaluates no property of the committed source and emits no pass/fail signal.
producer the `next dev` development server process, with the left sidebar feature flag off — actor can write to it: not established
- customer-support-agent/package.json:15
decided by agent · confidence 0.9
The fourth permutation of the same dev-server invocation. A server that runs until interrupted produces no terminating verdict, so there is no signal here to trace to a producer inside or outside the write boundary.
producer the `next dev` development server process, with both sidebar feature flags off — actor can write to it: not established
- customer-support-agent/package.json:16
decided by agent · confidence 0.9
The step's whole effect is to put files or a toolchain on the runner so later steps have something to act on. It reads nothing about the repository's correctness and emits no pass/fail verdict about the artefact — a failure here means the runner could not fetch or install, not that the code is wrong. The check in such a job is whatever executes afterwards, so this edge must not enter the ratio in either direction.
producer a GitHub Actions provisioning action (repository checkout, toolchain setup, or dependency cache restore) — actor can write to it: not established
- the step body is a bare `uses:` of a checkout/setup/cache action with no command of its own
decided by probe (ci-provisioning-action) · confidence 0.9
The step's whole effect is to put files or a toolchain on the runner so later steps have something to act on. It reads nothing about the repository's correctness and emits no pass/fail verdict about the artefact — a failure here means the runner could not fetch or install, not that the code is wrong. The check in such a job is whatever executes afterwards, so this edge must not enter the ratio in either direction.
producer a GitHub Actions provisioning action (repository checkout, toolchain setup, or dependency cache restore) — actor can write to it: not established
- the step body is a bare `uses:` of a checkout/setup/cache action with no command of its own
decided by probe (ci-provisioning-action) · confidence 0.9
The step's whole effect is to put files or a toolchain on the runner so later steps have something to act on. It reads nothing about the repository's correctness and emits no pass/fail verdict about the artefact — a failure here means the runner could not fetch or install, not that the code is wrong. The check in such a job is whatever executes afterwards, so this edge must not enter the ratio in either direction.
producer a GitHub Actions provisioning action (repository checkout, toolchain setup, or dependency cache restore) — actor can write to it: not established
- the step body is a bare `uses:` of a checkout/setup/cache action with no command of its own
decided by probe (ci-provisioning-action) · confidence 0.9
The command installs declared dependencies so that later steps can run. Without a lockfile-freezing flag the resolver will refresh a stale lock rather than error, so the step cannot report a discrepancy between the manifest and the lock; its non-zero exits mean the network or the index failed, not that the repository is wrong. The assertion in such a job lives in whatever executes against the installed environment afterwards.
producer a package manager's dependency resolver populating an environment — actor can write to it: not established
- the run command is a bare dependency install with no --locked/--frozen equivalent
decided by probe (unfrozen-dependency-install) · confidence 0.8
The step's whole effect is to prepend the virtualenv's bin directory to PATH so the following pyright/pytest step resolves the installed tools. It reads no property of the committed source and performs no comparison — a string append to a runner-managed file succeeds regardless of whether the code is correct. Any assertion in this job is made by the step that runs afterwards.
producer the runner's `echo` builtin appending a directory string to the GITHUB_PATH file — actor can write to it: not established
- .github/workflows/tests.yaml:39
- .github/workflows/tests.yaml:35-38 (the venv it is pointing at)
- .github/workflows/tests.yaml:40 (the step that consumes the PATH)
decided by agent · confidence 0.9
The step's whole effect is to put files or a toolchain on the runner so later steps have something to act on. It reads nothing about the repository's correctness and emits no pass/fail verdict about the artefact — a failure here means the runner could not fetch or install, not that the code is wrong. The check in such a job is whatever executes afterwards, so this edge must not enter the ratio in either direction.
producer a GitHub Actions provisioning action (repository checkout, toolchain setup, or dependency cache restore) — actor can write to it: not established
- the step body is a bare `uses:` of a checkout/setup/cache action with no command of its own
decided by probe (ci-provisioning-action) · confidence 0.9
The step's whole effect is to put files or a toolchain on the runner so later steps have something to act on. It reads nothing about the repository's correctness and emits no pass/fail verdict about the artefact — a failure here means the runner could not fetch or install, not that the code is wrong. The check in such a job is whatever executes afterwards, so this edge must not enter the ratio in either direction.
producer a GitHub Actions provisioning action (repository checkout, toolchain setup, or dependency cache restore) — actor can write to it: not established
- the step body is a bare `uses:` of a checkout/setup/cache action with no command of its own
decided by probe (ci-provisioning-action) · confidence 0.9
The whole file is one `mock.patch.dict` fixture and its yield — it contains no assert, no `def test_`, and no collection hook that can fail. It cannot turn the suite red; every assertion in this job lives in the test modules the fixture merely sets up. Worth naming rather than crediting: what it does do is substitute fabricated screen dimensions for the real environment, so it narrows what the tests it supports can observe.
producer an autouse pytest fixture that patches os.environ with HEIGHT/WIDTH/DISPLAY_NUM for the duration of every test — actor can write to it: not established
- computer-use-demo/tests/conftest.py:1-15
- computer-use-demo/tests/conftest.py:8-12 (mock.patch.dict of HEIGHT/WIDTH/DISPLAY_NUM)
decided by agent · confidence 0.75
The file defines fixtures and mutates sys.path; it contains no assert and no test function, so it can never turn a run red — the assertions live in the four test modules it feeds. It is also worth naming that these fixtures replace BrowserTool and every streamlit call with mocks, so the suite they support never exercises the real Playwright or Streamlit paths; that weakens the oracle of the tests downstream, but it is not itself a check.
producer pytest fixtures that patch streamlit's module surface and BrowserTool with MagicMock objects, plus a sys.path insert — actor can write to it: not established
- browser-use-demo/tests/conftest.py:1-60
- browser-use-demo/tests/conftest.py (mock_streamlit and mock_browser_tool fixtures; patch of browser_use_demo.tools.BrowserTool)
decided by agent · confidence 0.8
Crystallization curve
Run economics