Skip to content

cloud-waste: the Critic layer, per ADR-0021 - #70

Merged
Nabzx merged 1 commit into
mainfrom
feat/critic-layer-68
Sep 4, 2026
Merged

Nabzx merged 1 commit into
mainfrom
feat/critic-layer-68

Conversation

@Nabzx

@Nabzx Nabzx commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Closes #68. Built for real, spent on by nobody - exactly what was locked. Checked the real anthropic SDK's actual types (ToolParam, ToolUseBlock.input is already a parsed dict) before writing against them. FakeCritic (canned, free) is the only thing any test/demo/CI here talks to; ClaudeCritic forces a tool call so a response always parses, parses defensively (a malformed reply degrades to 'proceed', never a crash), and is never invoked with a real key by anything in this repo - confirmed EPHOR_CRITIC_API_KEY unset throughout. The critique attaches to the Snapshot before it's hashed - zero changes to ephor.approvals/actions/effects, confirmed by a real verify_snapshot test on the combined record. README.md's 'no paid API' line gets its one precise exception named, not glossed over.

Built for real, spent on by nobody - exactly what was locked. Checked
the real anthropic SDK's actual types before writing anything against
them (ToolParam, ToolChoiceToolParam, ToolUseBlock.input is already a
parsed dict) rather than guessing at the shape.

- critic.py: Critique (concerns, recommendation, reasoning, model),
  a vendor-agnostic Critic Protocol, FakeCritic (canned, the only
  thing any test/demo/CI here talks to), and ClaudeCritic - a real
  implementation that forces a tool call so a response always
  parses, never a best-effort text scrape. Parses the LLM's response
  defensively (a malformed reply degrades to "proceed", it never
  crashes the detector).
- detector.py: an optional critic parameter, off by default - when
  passed, its critique is added to the Snapshot before it's hashed,
  so it's part of the same tamper-evident record as the proposal
  itself. No change to ephor.approvals/actions/effects, confirmed by
  a real test that verify_snapshot still passes on the combined
  record.
- demo.py: EPHOR_CRITIC_API_KEY set -> ClaudeCritic (a real, paid
  call, with a printed warning); unset -> FakeCritic, free, same
  shape as every other real-client opt-in in this project.

Nothing in this repo invokes ClaudeCritic with a real key - not in
tests, not in CI, not while building this. test_critic.py's
ClaudeCritic tests monkeypatch messages.create entirely; confirmed
EPHOR_CRITIC_API_KEY is unset throughout this work.

README.md's "no paid API" line gets its one precise exception named,
not glossed over, per ADR-0021's own noted consequence.

Nothing in ephor/, backend/, stripe-recovery/ or wallet-guard/
changed.
@Nabzx
Nabzx merged commit 6584fd9 into main Sep 4, 2026
7 checks passed
@Nabzx
Nabzx deleted the feat/critic-layer-68 branch September 4, 2026 00:55
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.

Build the Critic layer per ADR-0021, landing on cloud-waste

1 participant