release: v0.36.0 — BA-20 decisive judge + calibration harness + judgeToAnnotation - #29
Merged
Conversation
Productizes bareguard's measured E6i design as a caller-side judge (caller-side
by law: bareguard's Axis-B detector never calls an LLM). No bareguard change.
- src/judge.js: judge({request, artifact, provider, maxTokens?, onLlmResult?})
→ {verdict:'honored'|'broke', where:{field,stated,returned,evidence}|null,
truncated, parseError, costUsd, usage, model, raw}. E6i verdict verbatim +
floor tiebreak; mechanical where (contract 6); truncation/parse-error as
distinct flagged outcomes floored to broke + excluded from denominators;
honest-null cost (unknown tiers red, no _default fabrication); typed
ValidationError (lib=bare-agent); HaltError re-throws. No dead model/effort
knobs (the http providers honor neither). Composes around a provider.
- src/judge-calibration.js: frozen E6i clear-case set (byte-equivalent to
bareguard's fixture, sha256 a840832…) + a 5-style INJECTION_BATTERY as a
separate admission gate; pure unanimity scoring over usable samples;
constantHonored negative control MUST fail the set.
- test/fixtures/e6i-cases.frozen.json vendored + hash-pinned for criterion-1
comparability; test asserts byte-equivalence + unanimity-not-majority.
- 34 judge tests, mutation-proven; full suite 1076 pass / 0 fail / 2 skip;
typecheck + build:types exit 0.
Validated live on claude-haiku-4-5 (poc/ba20-*.mjs), all 6 acceptance
criteria exercised on the wire: clear-case 7/7, €280 honored 5/5, injection
battery 5/5 all styles, 0 unpriced, negative control 2/7, and a forced
max_tokens:8 cutoff (criterion 5). Mechanical-vs-verbatim A/B Δ=0 at N=8.
Injection resistance established at haiku-4.5 only (UNRESOLVED weaker tiers).
Docs synced: CHANGELOG [0.36.0], CLAUDE.md (component + exports), context.md
(wiring + gate.annotate {surface,verdict,where,meta} mapping + field budgets),
PRD §22. Version bump held for the release phase.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gnmz6puuaZrv4NmSr1FpfT
Adds the caller-side wiring the bareguard maintainer session assigned to
bareagent (hamr's lane ruling: bareguard is the harness, bareagent the LLM
caller). A PURE function in the existing adapter — no gate call, no bareguard
import (structural, like the Gate typedef), so the peer-dep boundary holds.
- src/bareguard-adapter.js: judgeToAnnotation(verdict, opts?) → {surface,
verdict, where, meta}. surface = verdict !== 'honored' (load-bearing
fail-open). where = one-line mechanical address. meta = {field, stated,
returned} only; evidence opt-in via {includeEvidence:true}. Bounds
DEFENSIVELY against the sink's SILENT caps (verdict 80 / where 300 chars /
meta 1000 BYTES all-or-nothing) with a VISIBLE …[clipped] marker, so the
mechanical facts survive the meta ceiling instead of being wiped with the
evidence (loud partial beats silent total loss). Bounds at BOTH points
(regardless of any upstream bound — it is the last code before a sink that
clips silently and never throws). Caps via opts.limits so bareagent never
hardcodes bareguard's PIPE_BUF numbers.
- Corrected sink shape to the shipped {surface, verdict, where, meta} (the
{kind,...,text} sketch never shipped) across CHANGELOG/CLAUDE.md/context.md.
- Exported from `bare-agent` and `bare-agent/bareguard`.
- +9 tests incl. the defensive-bound guarantee (huge evidence → meta ≤1000B
AND field/stated/returned survive AND visible marker), mutation-proven.
Full suite 1085 pass / 0 fail / 2 skip; typecheck + build:types exit 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gnmz6puuaZrv4NmSr1FpfT
…ToAnnotation
Narrow the judgeToAnnotation "facts survive the meta ceiling" guarantee per the
bareguard maintainer's follow-up (2026-08-12): it holds for the drained fact and
the humanChannel event (the source bound the adapter can reach), NOT the persisted
audit row when a redactor is configured — redaction runs downstream of the adapter
and expands every match into a longer [REDACTED:...] tag, so a meta built entirely
from in-budget values can still blow the audit line's atomic-append cap and be
replaced wholesale (measured on the shipped gate: a 355-byte legal meta persisted
as {_truncated:true,bytes:6977}). No adapter-side bound prevents that. Also noted:
an unserializable meta becomes {_unserializable:true} (a distinct marker, same total
loss), and the audit clip DOES carry a marker unlike the silent source clip. The
guard is unchanged and correct against the source bound; this narrows an overstated
claim across CHANGELOG / CLAUDE.md / context.md / PRD + the source comment.
Version bump 0.35.0 -> 0.36.0 (MINOR: new public exports judge, calibrate + the
calibration harness, judgeToAnnotation).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gnmz6puuaZrv4NmSr1FpfT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BA-20 — decisive return-time judge + calibration harness + judgeToAnnotation (v0.36.0)
Productizes bareguard's measured E6i decisive judge as a bare-agent primitive (the judge LLM call belongs here — bareguard only annotates, never calls a model).
New public surface (→ MINOR)
judge({request, artifact, provider, ...}) → {verdict:'honored'|'broke', where, truncated, parseError, costUsd, usage, model, raw}— verbatim request vs one structured egress artifact → decisive binary + mechanicalwhere {field, stated, returned, evidence}. E6i verdict prose ported verbatim; artifact treated as untrusted data; floor tiebreak (cannot-confirm-honored →broke); truncation/parse-error distinct flagged outcomes excluded from graded denominators; honest-nullcostUsd.calibrate+CALIBRATION_CASES/INJECTION_BATTERY/scoreCase/gradeRun/constantHonored— the judged-floor admission harness: a frozen vendored E6i fixture (sha256(cases)=a840832…, 7 scored + 1 ungraded ambiguous) graded by unanimity, plus a 5-style injection battery as a separate admission gate, plus aconstantHonorednegative control that MUST fail.judgeToAnnotation(verdict, opts?)— purejudge→gate.annotaterender{surface, verdict, where, meta}; never calls the gate, imports no bareguard; bounds defensively vs the sink's silent caps with a visible…[clipped]marker.Validation
claude-haiku-4-5via the HTTP AnthropicProvider: clear-case 7/7, €280 compliant read honored 5/5, injection battery resisted 5/5 each style, 0 unpriced, negative control 2/7.Docs-honesty narrowing (this release commit)
Reconciled with the bareguard maintainer: the
judgeToAnnotation"facts survive the meta ceiling" guarantee is scoped — it holds for the drained fact + humanChannel event (the source bound), not the persisted audit row under a configured redactor (downstream redaction-expansion can still wipemetawholesale). Narrowed across CHANGELOG / CLAUDE.md / context.md / PRD + the source comment. The guard is unchanged and correct against the source bound.Gates
/ship: tests + typecheck + build:types clean; no secrets; no debug leftovers./security: clean — library primitive; ReDoS-safe regexes; proto-pollution-guarded cost lookup; typed errors; injection resistance documented haiku-4.5-only./diff-review: exports wired; no bugs/dead code/loose ends.🤖 Generated with Claude Code
https://claude.ai/code/session_01Gnmz6puuaZrv4NmSr1FpfT