Skip to content

Add a physics-verification layer for CatBot outputs (catgo_verify) - #541

Closed
leshenzhang wants to merge 5 commits into
mainfrom
ai-agent/verification-layer-v2
Closed

Add a physics-verification layer for CatBot outputs (catgo_verify)#541
leshenzhang wants to merge 5 commits into
mainfrom
ai-agent/verification-layer-v2

Conversation

@leshenzhang

Copy link
Copy Markdown
Collaborator

What

An additive physics-verification layer for CatBot's computational-chemistry outputs. It catches silent errors — a run that exits 0 with normal-looking numbers but wrong physics (e.g. a PAW/POTCAR reference mismatch that shifts ΔG by ~3 eV while the geometry looks perfect; a corrupted Hessian that n_imag cannot detect; ZPE zero-fill; a stale "reached required accuracy" flag; a job marked COMPLETED whose products never appeared).

Nothing existing is changed — two new stdlib-only modules plus hooks in both MCP server variants.

What's in it

  • verify_gates.py — 18 gates over 16 silent-error classes (PAW/NELECT self-consistency, physical-range, gas-phase entropy, ZPE completeness, force/energy convergence, opt-conv flag, products-exist, Hessian symmetry, stale freq geometry, residual imaginary, U_L window, relative MLIP force, min-pair parse, k-grid boundary, field/label provenance) + a verifiability layer (a claimed quantity whose provenance is absent is flagged UNVERIFIABLE, not passed silently) + workflow_consistency (cross-step DAG checks). Absent inputs are reported SKIP, never silently dropped.
  • verify_enforcement.py — tri-state {allow, prompt, forbidden} with strictest-wins (design borrowed from openai/codex execpolicy, Apache-2.0). A numeric result marks session state unverified; catgo_verify clears it; an HPC submit while a produced number is still unverified is FORBIDDEN — the agent is told to verify first instead of silently skipping the gate.
  • catgo_verify MCP tool wired into both server_claude_code.py (merged variant) and server.py (61-tool variant that catbot-plugin's mcp_server.py delegates to), so the plugin route gets the layer too.
  • catbot.md playbook rule + section instructing the agent to verify any numeric physical result before reporting it (FAIL = do not report as correct; UNVERIFIABLE = do not certify).

Design notes

  • Additive / zero-intrusion: no existing tool logic touched; the two new modules are pure stdlib and imported lazily, so a missing module never breaks other tools.
  • Enforcement borrowed from codex (Apache-2.0); cited in the module header.
  • catgo_verify is pure-local (no backend call).

Tests

  • verify_gates.py self-test: 18 gates, self-test cases all caught, 0 false alarms; absent inputs SKIP; require= raises on blind gates; verifiability flags a value in-range-but-no-provenance as UNVERIFIABLE.
  • Both variants live-checked: merged variant over stdio (21 tools, catgo_verify registered, real case returns FAIL); 61-tool variant dispatch + enforcement state machine (FAIL / UNVERIFIABLE / blocks submit / verify clears).

🤖 Generated with Claude Code

leshenzhang and others added 3 commits July 23, 2026 21:47
Ports the verification layer onto the latest main (was based on a branch
207 commits behind). Additive — two new stdlib-only modules plus hooks in
both server variants; no existing tool logic changed.

- verify_gates.py: 18 physics gates over 16 silent-error classes (PAW/NELECT
  self-consistency, physical-range, gas-phase entropy, ZPE zero-fill,
  force/energy convergence, opt-conv flag, products-exist, Hessian symmetry,
  stale freq geometry, residual imaginary, U_L window, relative MLIP force,
  min-pair parse, k-grid boundary, field/label provenance) + a verifiability
  layer (a claim lacking provenance is UNVERIFIABLE, not a silent pass) +
  workflow_consistency (cross-step DAG checks). Absent inputs are SKIP, never
  silently dropped.
- verify_enforcement.py: tri-state {allow/prompt/forbidden} (design borrowed
  from openai/codex execpolicy, Apache-2.0), strictest-wins — a numeric result
  marks state unverified; catgo_verify clears it; an HPC submit while unverified
  is FORBIDDEN.
- catgo_verify tool wired into BOTH server_claude_code.py (merged variant) and
  server.py (61-tool variant that catbot-plugin's mcp_server.py delegates to),
  so the plugin route gets the layer too. Both variants: precheck/postmark
  enforcement around dispatch, tool registered, live-tested.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CatBot now instructs the agent to run catgo_verify on any numeric physical
result before reporting it (FAIL = silent error, do not report as correct;
UNVERIFIABLE = missing provenance, do not certify), and notes that an HPC
submit with unverified numbers is blocked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- R1 enforcement was a no-op on the 61-tool server variant: its numeric tools
  are fine-grained (catgo_dos_*, catgo_catalysis_*, catgo_cohp_*, catgo_bands_*,
  catgo_energy, catgo_freq_*) and never matched the exact-name set. Match by
  PREFIX so both server variants are guarded. Verified end-to-end:
  catgo_catalysis_oer now arms the gate and an unverified submit is FORBIDDEN.
- R2 an empty catgo_verify (a result with no verifiable fields → all gates SKIP)
  could clear the unverified state and bypass enforcement. Clearing moved out of
  postmark into mark_verified(), called by the handler ONLY when coverage.ran > 0.
- R3 provenance was satisfied by key presence alone, so `ads_titels: None` (or [])
  was certified. _group_present now requires a non-empty value (None/[]/{}/"" fail).
- R4 added test_verify.py (14 tests incl. R1/R2/R3 regressions) + a scoped
  verify-python.yml CI workflow (pytest on the two modules).

All: pytest 14 passed; agentbench self-test + independent eval unchanged
(80% [65,90] corpus-informed, 8% false-alarm); AST anti-drift clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leshenzhang

Copy link
Copy Markdown
Collaborator Author

Thanks for the review — all four findings were real bugs at a trust boundary. Fixed in a278819:

  • R1 (enforcement no-op on the 61-tool variant): its numeric tools are fine-grained (catgo_dos_*, catgo_catalysis_*, catgo_cohp_*, catgo_bands_*, catgo_energy, catgo_freq_*), so the exact-name set {catgo_analyze, catgo_catalysis} never matched and the gate never armed. Now matched by prefix, covering both variants. Verified end-to-end: catgo_catalysis_oer producing a number makes an unverified catgo_workflow submit return FORBIDDEN.
  • R2 (empty verify clears state): clearing moved out of postmark into mark_verified(), called by the handler only when coverage.ran > 0. An empty catgo_verify (a result with no verifiable fields → all gates SKIP) no longer wipes the pending state.
  • R3 (provenance = key presence): _group_present now requires a non-empty value; None / [] / {} / "" no longer certify a claim.
  • R4 (no Python CI): added test_verify.py (14 tests, incl. R1/R2/R3 regressions) and a scoped verify-python.yml workflow running pytest on the two modules.

pytest 14 passed; the independent-corpus eval is unchanged (80% [65,90] corpus-informed, 8% false-alarm); AST anti-drift between the vendored copy and the eval source is clean.

leshenzhang and others added 2 commits July 25, 2026 04:03
…d standalone run

pytest imports test_verify.py through the catgo.mcp_tools package, whose
__init__ pulls server.py -> httpx/mcp; the CI env lacked them, so collection
failed with ModuleNotFoundError while the tests themselves are stdlib-only.
Install httpx+mcp for the import chain and also run the standalone
'python test_verify.py' path as a dependency-free double-check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leshenzhang

Copy link
Copy Markdown
Collaborator Author

Superseded by #546 — a clean single-commit resubmission on current main with all four review findings fixed and covered by regression tests + green CI. Closing this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant