Releases: EmpireTwo/gaze
v0.10.0
What's Changed
- [agent] chore(gaze-mcp-core): refresh trybuild snapshot for current stable rustc diagnostic wording by @Naoray in #296
- [agent] fix(ner): surface backend errors so NER detection fails closed (P0 #908) by @Naoray in #293
- [agent] fix(restore+ner): byte-exact restore + token-boundary spans (P0 #923) by @Naoray in #295
- [agent] fix(ci): green the test gate under rustc 1.96.0 (clippy const-assert + trybuild snapshot) by @Naoray in #297
- [agent] feat(xtask): scrub-public-text pre-release gate (#407) by @Naoray in #294
- [agent] docs: update for fail-closed Recognizer::detect + restore/precision (P0 #908/#923) by @Naoray in #298
- [agent] chore(ner): remove dead #290 error plumbing + redundant tests (post-#293 audit) by @Naoray in #300
- [agent] release: v0.10.0 (NER fail-closed + byte-exact restore + scrub gate) by @Naoray in #301
Full Changelog: v0.9.1...v0.10.0
v0.9.1
What's Changed
- docs(readme): align all crate READMEs to v0.9.0 + correct release-process crate count by @Naoray in #267
- feat: add restore telemetry foundation by @Naoray in #261
- [agent] docs: add restore-boundary architecture by @Naoray in #260
- feat: enforce strict manifest-bound restore by @Naoray in #262
- feat: add restore-boundary raw PII audit events by @Naoray in #270
- feat(xtask): readme-version-check gate + wire into publish-crates workflow by @Naoray in #271
- docs(skills): add release orchestration skill by @Naoray in #272
- [agent] docs: surface gaze daemon mode (cli.md + README + adopter quickstart) by @Naoray in #273
- [agent] docs: surface gaze proxy / mcp / document (cli.md + getting-started + README) by @Naoray in #274
- [agent] docs: reframe gaze daemon as stdio server (LSP/MCP terminology) by @Naoray in #276
- [agent] docs+test: clarify Session = pseudonym namespace (closes #275) by @Naoray in #277
- [agent] docs(session): extract contract to session-contract.md + fix truncated words by @Naoray in #278
- [agent] feat(gaze-document): enforce agent/owner bundle partition at type + path level (closes #489) by @Naoray in #279
- [Aikido] AI Fix for Template Injection in GitHub Workflows Action by @aikido-autofix[bot] in #280
- [Aikido] AI Fix for 3rd party Github Actions should be pinned by @aikido-autofix[bot] in #281
- [Aikido] AI Fix for Path traversal attack possible by @aikido-autofix[bot] in #283
- ci/fix: restore green
test(gaze-mcp-core tool_ctx_seal trybuild) by @Naoray in #289 - fix(gaze-recognizers): NER detect() fail-closed + >512-token chunking (P0 never-leak) by @Naoray in #290
- feat(cli): accessibility output gate + tests (NLnet submit-gap business#31) by @Naoray in #287
- ci: enforce DCO sign-off on PRs by @Naoray in #288
- [agent] release: v0.9.1 by @Naoray in #291
New Contributors
- @aikido-autofix[bot] made their first contribution in #280
Full Changelog: v0.9.0...v0.9.1
v0.9.0
What's Changed
- docs(readme): anchor restore example on ghostwriter use case by @Naoray in #228
- docs(readme): polish ghostwriter section — ASCII flow + org typo by @Naoray in #229
- [agent] refactor(safety-net): bench matrix expansion (v0.9 #33c) by @Naoray in #230
- feat(safety-net): pin OPF source and snapshot by @Naoray in #231
- [agent] feat(cli): emit
entriesin plaintext JSON gaze clean response (#323) by @Naoray in #232 - [agent] chore(fixtures): replace @example.com with @example.invalid (#285) by @Naoray in #233
- [agent] docs(metrics): introduce metrics.md SSOT (#327) by @Naoray in #235
- feat(safety-net): ship Python kiji-runner reference wrapper (#33d partial) by @Naoray in #236
- [agent] refactor(audit): consolidate SqliteLogger leak-suspect method (#294) by @Naoray in #234
- [agent] feat(safety-net): pin OPF checkpoint bundle SHA (#33d follow-up) by @Naoray in #240
- [agent] refactor(api): rename redact_* → pseudonymize_* per north-star (#293) by @Naoray in #237
- [agent] feat(audit): NER-provenance schema migration (11 cols, additive) (#309) by @Naoray in #238
- [agent] feat(safety-net): score OPF direct-detector cells (#33d follow-up) by @Naoray in #241
- [agent] feat(safety-net): locale-aware Pass-3 dispatcher (#33e precursor) by @Naoray in #242
- [agent] docs(readme): correct ghostwriter flow (app owns lookup, LLM owns prose) by @Naoray in #246
- [agent] feat(safety-net): observer-residual cells + latency snapshot (#33d follow-up) (re-target #243) by @Naoray in #248
- [agent] feat(bench): end-to-end gaze pipeline benchmark (detection + perf) by @Naoray in #244
- [agent] feat(bench): multi-NER model leaderboard (#33d follow-up) by @Naoray in #245
- fix(ci): free preinstalled bloat to unblock ubuntu-latest disk-full by @Naoray in #249
- docs(readme): remove link to private demo repo by @Naoray in #251
- feat(pipeline): tier 4 — skip-gating + prefix cache (#370) by @Naoray in #252
- fix(v0.9.1): follow-up wave (5 HIGH findings) by @Naoray in #253
- docs(readme): qualify proxy scope — API-key path only by @Naoray in #254
- feat(kiji): in-process ort backend (#366) by @Naoray in #250
- feat(kiji): int8 dynamic quantization (#368) by @Naoray in #256
- feat(cli): gaze daemon mode (#367) by @Naoray in #255
- feat(bench): tiny-model leaderboard (#371) by @Naoray in #258
- feat(bench): runtime comparison — ort vs tract vs candle (#369) by @Naoray in #257
- release: v0.9.0-rc.1 by @Naoray in #259
- chore(scrub): remove absolute home paths by @Naoray in #265
- release: prepare v0.9.0 final by @Naoray in #263
Full Changelog: v0.8.1...v0.9.0
v0.9.0-rc.1
gaze v0.9.0-rc.1
TL;DR
v0.9.0-rc.1 shipped the v0.9 performance wave as a release candidate for adopter validation. The headline change was Kiji moving from a subprocess-backed safety net to in-process inference: warm p50 dropped from 323ms (subprocess) to 2.981ms (in-process ORT fp32), int8 warm p50 landed at 1.849ms, int8 cold start landed at 297ms, and the int8 bundle shrank from 249MB to 63MB with a 0.000 F1 recall delta across all locales/modes.
This was a performance and operations release, not a restore-contract release. Manifest restore semantics and the signed snapshot wire format stayed unchanged from v0.8.1, preserving the north-star contract: never leak PII, keep pseudonymization reversible, and make every token traceable.
Highlights
- Kiji became fast enough for agent loops (#250, #256, #258). In-process ORT removed the Python subprocess path from the hot loop, int8 quantization cut cold start to 297ms and bundle size to 63MB, and the tiny-model leaderboard validated Kiji int8 as the v0.9 default without recall loss.
- The pipeline stopped doing avoidable safety-net work (#252). Skip gates, the capitals heuristic, prefix cache, and length bucketing are opt-in, fail-closed performance controls. Best-case numeric input can reduce SafetyNet calls from 100% to 0%, and prefix-cache hit latency dropped -50.8%.
gaze daemonmade repeated CLI calls practical (#255). The daemon keeps a persistent JSONL stdio process alive across calls, eliminating full binary fork and model-load overhead while keeping multi-session isolation.- Runtime choice is now explicit (#257). ORT is the recommended default.
tractis the opt-in static-binary path for deployments where static linking matters more than the default runtime profile. - Benchmarking and trust artifacts caught up to the perf work (#244, #245, #248). The release added end-to-end pipeline measurement, a multi-NER model leaderboard, observer-residual safety-net cells, and latency snapshots grounded in the 150-fixture coverage-loop corpus.
Known limitations
- This is a release candidate, not final v0.9.0. The performance internals may still change before the final tag if adopter validation finds regressions.
- The new gates are opt-in controls. Adopters should validate their own workloads before enabling skip gating in production.
tractis available for the static-binary path, but ORT remains the recommended default runtime.- Some benchmark commands emit large JSON snapshots during CI; they are measurement artifacts, not release notes.
Adopter notes
- Upgrade as a pre-release:
0.9.0-rc.1means adopter-validation window. - Restore compatibility is unchanged from v0.8.1: signed snapshots and manifest restore semantics continue to work.
- For fastest Kiji local inference, use the int8 Kiji bundle and ORT runtime.
- For repeated CLI integration, prefer
gaze daemonover launching a fresh process per call. - For static-binary deployments, evaluate the opt-in
tractruntime and compare it against ORT on your target platform.
Download
- aarch64-darwin:
gaze-v0.9.0-rc.1-aarch64-apple-darwin.tar.gz - x86_64-linux:
gaze-v0.9.0-rc.1-x86_64-unknown-linux-gnu.tar.gz SHA256SUMS
Both binaries should be treated as release-candidate artifacts until final v0.9.0 is cut.
CHANGELOG
Full PR-by-PR detail: CHANGELOG.md.
What's Changed
- docs(readme): anchor restore example on ghostwriter use case by @Naoray in #228
- docs(readme): polish ghostwriter section — ASCII flow + org typo by @Naoray in #229
- [agent] refactor(safety-net): bench matrix expansion (v0.9 #33c) by @Naoray in #230
- feat(safety-net): pin OPF source and snapshot by @Naoray in #231
- [agent] feat(cli): emit
entriesin plaintext JSON gaze clean response (#323) by @Naoray in #232 - [agent] chore(fixtures): replace @example.com with @example.invalid (#285) by @Naoray in #233
- [agent] docs(metrics): introduce metrics.md SSOT (#327) by @Naoray in #235
- feat(safety-net): ship Python kiji-runner reference wrapper (#33d partial) by @Naoray in #236
- [agent] refactor(audit): consolidate SqliteLogger leak-suspect method (#294) by @Naoray in #234
- [agent] feat(safety-net): pin OPF checkpoint bundle SHA (#33d follow-up) by @Naoray in #240
- [agent] refactor(api): rename redact_* → pseudonymize_* per north-star (#293) by @Naoray in #237
- [agent] feat(audit): NER-provenance schema migration (11 cols, additive) (#309) by @Naoray in #238
- [agent] feat(safety-net): score OPF direct-detector cells (#33d follow-up) by @Naoray in #241
- [agent] feat(safety-net): locale-aware Pass-3 dispatcher (#33e precursor) by @Naoray in #242
- [agent] docs(readme): correct ghostwriter flow (app owns lookup, LLM owns prose) by @Naoray in #246
- [agent] feat(safety-net): observer-residual cells + latency snapshot (#33d follow-up) (re-target #243) by @Naoray in #248
- [agent] feat(bench): end-to-end gaze pipeline benchmark (detection + perf) by @Naoray in #244
- [agent] feat(bench): multi-NER model leaderboard (#33d follow-up) by @Naoray in #245
- fix(ci): free preinstalled bloat to unblock ubuntu-latest disk-full by @Naoray in #249
- docs(readme): remove link to private demo repo by @Naoray in #251
- feat(pipeline): tier 4 — skip-gating + prefix cache (#370) by @Naoray in #252
- fix(v0.9.1): follow-up wave (5 HIGH findings) by @Naoray in #253
- docs(readme): qualify proxy scope — API-key path only by @Naoray in #254
- feat(kiji): in-process ort backend (#366) by @Naoray in #250
- feat(kiji): int8 dynamic quantization (#368) by @Naoray in #256
- feat(cli): gaze daemon mode (#367) by @Naoray in #255
- feat(bench): tiny-model leaderboard (#371) by @Naoray in #258
- feat(bench): runtime comparison — ort vs tract vs candle (#369) by @Naoray in #257
- release: v0.9.0-rc.1 by @Naoray in #259
Full Changelog: v0.8.1...v0.9.0-rc.1
v0.8.1
gaze v0.8.1 — reversibility as the new default
TL;DR
v0.8.1 makes reversible pseudonymization the default safety-net behavior. When Pass-3 SafetyNet flags a suspect leak, the pipeline now attempts to promote the suspect to a manifest entry first (--safety-net-mode resolve), and only strips the span (--safety-net-fallback redact) if that promotion fails closed. Adopters who want hard-fail semantics keep opting into --safety-net-mode strict.
This is a minor release that ships behind the v0.8.0 manifest contract — bundle_version for SafeBundle adopters bumps from 1 to 2, but no breaking API changes in gaze, gaze-recognizers, gaze-audit, or gaze-mcp-*. v0.8.0 adopters can upgrade in place. If you're upgrading from v0.7.x: read UPGRADE.md first — v0.8.0 already flipped several defaults that v0.7.x users do not see in this CHANGELOG entry alone.
Defaults changed
--safety-net-mode resolveis the new default (wasstrict). Reversibility-first; falls back toredacton resolve failure. Strict mode is still available for hard-fail deployments via--safety-net-mode strict. Tolerant mode remains dev-only behindGAZE_ALLOW_TOLERANT=1opt-in. (Axes 1, 2.)--safety-net-fallback redactis the new default for the new fallback flag. Emits a:Redact_token and a typedFallbackReasonaudit row when SafetyNet promotion cannot complete. (Axes 1, 2.)- The published release binary now bakes
--features proxysogaze proxy {serve,start,stop,status,logs,restart}works without rebuild. Source builds are unchanged. (Axis 5.)
Example: keep the old behavior explicitly with
gaze clean --safety-net-mode strict --safety-net-fallback none input.txtHighlights
- SafetyNet
resolve+redact+ fallback flag impl (#223, axes 1+2+4). Suspect spans flagged by SafetyNet are now promoted to custom-recognizer matches and rejoin conflict resolution. On promotion failure (ValidatorVeto,AnchorMissing,OverlapConflict,ResidualSuspect), the typed fallback path kicks in — no more silent passthrough, no irreversible strip without a typed reason in the audit log. - gaze-document layout report v2 (#219 + #222, axis 1). Vector-PDF text-extraction fallback when PDFs have selectable text; multi-column segmentation in the post-processor; per-page confidence + low-confidence flagging against
low_confidence_threshold; table-cell preservation in markdown output; rotation/deskew preprocessing before OCR. SafetyNet has more structured text to work with, less to reconstruct. OcrBackendsingle-trait single-impl (#218 + #224, axes 4+5).gaze-documentnow exposes one OCR contract. Second-party backends (ocrs, Apple Vision, PaddleOCR) can slot in cleanly. LegacyOcrAdaptershims removed; magic-byte validation at theclean_with_ocr_backendboundary is now mandatory and fails closed viaDocumentError::UnsupportedInput.- Kiji model-SHA integrity (#221, axes 1+4). The
KijiDistilbertSafetyNetbackend's DistilBERT bundle SHA256 is pinned and verified at backend init. Mismatch fails closed viaSafetyNetError::ModelIntegrityMismatch { expected, actual }. Direct-vs-observer benchmark harness shipped; metric fields staynulluntil populated on a machine with the local Kiji runtime — gaze does not publish uncited benchmark numbers.
Schema changes
- SafeBundle
BundleReport.bundle_versionbumps1 → 2. New per-page fields:ocr_source,ocr_backend,confidence,low_confidence,column_count,page_index. New top-level field:low_confidence_threshold. v1 bundles continue to parse on read; new emission is always v2. Adopter-tooling-reading SafeBundle JSON must handle the v2 field set. gaze-auditrow schema delta: new nullable columnfallback_triggered: Option<FallbackReason>. Closed-enumFallbackReasonvariants:OverlapConflict,ValidatorVeto,AnchorMissing,ResidualSuspect. The existingdecided_bycolumn gains new variants:Redact,Resolve,Fallback. The column is nullable on pre-migration rows; existing queries continue to work.
Known limitations
- Kiji
cargo benchharness ships withnullmetric fields. Populating them requires a local Kiji runtime + pinned model directory. Axis 4: gaze does not publish uncited benchmark numbers. - Multi-backend SafetyNet bench (Kiji vs OpenAI Privacy Filter vs OpenMed) is a v0.9 thread, not v0.8.x.
Adopter notes
- Upgrading from v0.7.x? Read UPGRADE.md. Multi-hop migrations require attention to defaults that flipped at v0.8.0 and again at v0.8.1.
- Downstream tooling reads SafeBundle JSON? Handle the
bundle_version=2field. v1 reads work; v2 emission is non-optional. - You query the audit log? The new
fallback_triggeredcolumn is nullable on existing rows; newdecided_byvariants are closed-enum. - Custom OCR via
OcrAdapter? Port toOcrBackend(object-safe, same shape). - Pipeline expected
--safety-net-mode strictas default? Pass the flag explicitly.
Download
- aarch64-darwin:
gaze-v0.8.1-aarch64-apple-darwin.tar.gz - x86_64-linux:
gaze-v0.8.1-x86_64-unknown-linux-gnu.tar.gz SHA256SUMS
Both binaries are built with --features proxy --features document.
Changelog
Full PR-by-PR detail: CHANGELOG.md.
v0.8.0
TL;DR
The v0.8.0 wave shipped what v0.7 set up: ten validator-backed national-ID
recognizers (Aadhaar / NIR / Steuer-ID / BSN / CPF / CNPJ / NHS / SSN /
NINO / PAN) across five new locale packs, a unified core rulepack with
a safety_tier field that machine-encodes activation, versioned
recognizer lineage on every audit row, the new gaze-proxy crate that
puts a PII chokepoint in front of OpenAI / Anthropic / Gemini API calls,
and a 150-scenario coverage corpus that replaces the previous stochastic
templates. The gaze-proxy 0.8.0 crate is published alongside the rest
of the workspace.
Highlights
-
Multi-provider HTTP proxy with daemon mode. PR #212 introduces
thegaze-proxycrate. An adapter/driver pattern lets a single proxy
serve OpenAI's/v1/chat/completions, Anthropic's/v1/messages, and
Gemini's/v1beta/models/*:{generateContent,streamGenerateContent}
without translation. SSE streaming and tool-call argument
reconstruction are wired throughgaze::Pipeline, so a PII span that
arrives chunk-split inside atool_calls.function.argumentsfield is
accumulated and redacted before leaving the proxy. Daemon-mode
subcommands —gaze proxy {serve,start,stop,status,logs,restart}
plus opt-ininstall-launchd/install-systemd-user— mean the
adopter never has to remember the bind flags after the first
gaze proxy start. -
Seven checksum-backed locale validators. PR #207 added
ValidatorKindvariants for Aadhaar (Verhoeff), French NIR (MOD-97
variant), German Steuer-ID (MOD 11,10), Dutch BSN (MOD-11), Brazilian
CPF + CNPJ (MOD-11), and UK NHS numbers (MOD-11), with five new
locale packs atlocale-fr,locale-nl,locale-br,locale-in,
locale-uk. Every entity ships atsafety_tier = "safe_default",
so adopters in BR/FR/NL/IN/UK get coverage with a single--locale
flag. -
Three locale-gated regex recognizers. PR #208 added US SSN,
UK NINO, and Indian PAN assafety_tier = "locale_gated"cue-anchored
recognizers. They require an explicit locale to fire; no bare 9-digit
or 10-character shapes activate without the cue context. PAN extended
the existinglocale-inpack from Tier 2 in place. -
Bundle unification +
safety_tierfield. PR #201 collapsed the
core(6 recognizers) andcore-extended(10 recognizers) bundles
into a singlecorebundle. Each recognizer now declares
safety_tier ∈ {SafeDefault, LocaleGated, OptIn}, replacing the
v0.4.5 PR #58 surprise-activation behavior with a closed enum.
--rulepack-bundled core-extendedaliases to--rulepack-bundled core
with a deprecation warning; it will be removed in v0.10.0. -
Versioned recognizer lineage on every audit row. PR #203 added
Candidate.recognizer_version_id+RedactionEntry.recognizer_id+
recognizer_version_id(allOption<String>, additive). The
SQLite audit schema gains the two columns; pre-migration rows
receive alegacy_unversionedtag. The NER recognizer's bare
"ner"slug expanded toner.<model>.<vN>so safety-net
observers carry the model SHA + version inline. -
Kiji DistilBERT SafetyNet backend. PR #202 introduced an
observer-only Pass-3 backend that runs DistilBERT NER (26 PII classes,
Apache-2.0) alongside the existing OpenAI Privacy Filter. The
subprocess contract is identical: read clean text on stdin, emit a
JSON span array on stdout, never mutate the manifest. Activate via
gaze clean --safety-net-backend kiji-distilbert. Pinned-artifact
contract fails closed if any ofSHA256SUMS,labels.json,
model.onnx,tokenizer.jsonare missing. -
Replaced the coverage corpus. PR #205 deleted the 61 stochastic
status-quo templates and thefixture_variantsmechanism, replacing
them with 150 deliberate scenarios driven by thefakecrate as an
xtask-only dev dependency. Each scenario declares its expected
emissions withrecognizer_version_idfrom day one. Seed pinned in
a documentedCOVERAGE_CORPUS_SEEDconstant; baseline.json was
fully re-snapped. -
Two new repo-root docs. PR #206 added
UPGRADE.md(a per-minor
migration guide complementingCHANGELOG.md, covering v0.4 → v0.8).
PR #211 addedARCHITECTURE.md— a 14.8 KiB overview of how the
ten workspace crates fit together, with eight numbered Key Design
Decisions and a one-diagram pipeline view of the redact/restore path. -
Two new research docs. PR #210 is a coverage map of all 26 Kiji
PII classes against gaze's recognizers (6 beat-via-Tier-2, 1
beat-via-Tier-3, 16 observer-only-via-Tier-2.5, 3 parity, 0 deferred).
PR #209 is a two-mode benchmark methodology (direct-detector +
observer-residual, headlining strict span leak rate) with a
rule-floor snapshot pinned to corpus + Gaze tag.
Known limitations
- The Kiji benchmark in PR #209 ships rule-floor numbers only. The
Kiji direct-detector + observer-residual cells are markednot_run
because no pinned model SHA / frozen snapshot exists in the repo
yet; the supply-chain audit + pin is tracked as a v0.8.x follow-up. gaze-proxyships OpenAI / Anthropic / Gemini adapters at v0.8.0;
certificate management, PAC mode, Electron integration, and
transparent MITM stay out of scope (they belong ingaze-lens, not
the core proxy).LocaleAwareModeltrait + per-locale NER routing flips were
deferred from v0.8 Tier 2.5 to v0.8.1. The current per-locale
routing logic (4-tier locale chain) is unchanged.
Adopter notes
- The only action-required item is bundle unification:
--rulepack-bundled core-extendedusers see a deprecation warning;
adopters who relied on PR #58's no-policy surprise activation of
phone.national.{de,us}+postal.{de,us}must now pass an
explicit--localeflag.UPGRADE.mdwalks through this in detail. - All Tier 2 + Tier 3 entities are additive. Adopters in BR / FR / NL /
IN / UK / US-only / UK-only see no behavior change unless they
enable their locale. gaze-proxyis opt-in: build with--features proxyongaze-cli
andgaze proxy startafter first config.- The published
gaze-proxycrate joins the workspace at v0.8.0; the
total published-crate count rises from 9 to 10.
Download
The ten workspace crates publish to crates.io as gaze-types,
gaze-recognizers, gaze-audit, gaze-pii, gaze-assembly,
gaze-mcp-core, gaze-mcp-rmcp, gaze-document, gaze-proxy,
gaze-cli. Cargo dep snippet:
[dependencies]
gaze-pii = "0.8"For the proxy:
[dependencies]
gaze-pii = "0.8"
gaze-proxy = "0.8"CLI install (with proxy feature):
cargo install gaze-cli --features proxyFull CHANGELOG
See CHANGELOG.md § [0.8.0] for the
machine-readable changelog.
v0.8.0-rc.1
TL;DR
This is the first v0.8 pre-release. It lights up three of the v0.8 tiers — versioned recognizer lineage (Tier 1), bundle unification with explicit safety tiers (Tier 1.5), and a second NER-style observer at the Pass-3 chokepoint (Tier 2.5). Tier 2 (checksum-backed Aadhaar / NIR / Steuer-ID / BSN / CPF / CNPJ / NHS) and Tier 3 (regex SSN / NINO / PAN) follow in rc.2 and rc.3. The contract surface for Pipeline, Session, Policy, and the rulepack schema is unchanged from the v0.7 line. Existing v0.7.x adopters can upgrade with no policy edits.
Highlights
Versioned recognizer lineage (Tier 1, #203)
Every Candidate and RedactionEntry now carries an optional recognizer_id plus recognizer_version_id. PR #203 (commit 3c95304) threaded the lineage through the audit boundary in pipeline.rs so the version no longer drops at source. The SQLite audit schema gained nullable recognizer_id and recognizer_version_id columns; pre-migration rows were retrofitted to legacy_unversioned so historical queries still join cleanly. NER recognizer emissions stamped themselves with ner.<model>.<vN> from the artifact config metadata (ner.unknown.v0 was the closed fallback when the artifact carried no version). docs/architecture/locale-chain.md picked up a coverage matrix listing every bundled recognizer × supported locale × ValidatorKind. North-star axes 4 (trust/auditable) + 5 (adopter ergonomics).
Bundle unification + SafetyTier enum (Tier 1.5, #201)
PR #201 (commit 8ab9daf) folded the core and core-extended bundled rulepacks into a single core bundle. Each recognizer now declares a safety_tier field — SafeDefault, LocaleGated, or OptIn — backed by a #[non_exhaustive] Rust enum. No-policy activation gates on SafeDefault only, replacing the prior dual-bundle activation model with a single closed enum. The --rulepack-bundled core-extended CLI surface is deprecated (removal scheduled for v0.10.0): it now aliases to --rulepack-bundled core and auto-activates the LocaleGated tier with a tracing::warn! deprecation notice, preserving the v0.4.5 adopter behavior. North-star axes 1 (reliability — the dual-bundle footgun is gone), 4 (trust — tier metadata is part of the rulepack source of truth), and 5 (one bundle, one mental model).
KijiDistilbertSafetyNet backend (Tier 2.5, #202)
PR #202 (commit 0cd9ccc) added a second observer at the Pass-3 SafetyNet chokepoint. The new --safety-net-backend kiji-distilbert flag selects a DistilBERT NER subprocess that runs alongside (or instead of) the existing OpenAI Privacy Filter; the default remains openai-filter for source compatibility. The pinned-artifact contract is identical to the existing OpenAI filter — model dir must carry SHA256SUMS, labels.json, model.onnx, and tokenizer.json with 0o700 directory + 0o600 file permissions on Unix; missing artifacts (including a missing SHA256SUMS) fail closed with a typed CliError::SafetyNetArtifactMissing { backend, path } exit 2 before the subprocess spawns. scripts/fetch-kiji-safetynet-model.sh mirrors the existing NER fetcher. North-star axis 1 (defense in depth — second NER opinion at the chokepoint, observer-only, never mutates the manifest).
Known limitations
- This is a pre-release. Cargo's caret operator excludes pre-releases, so adopters depending on the rc need an exact pin:
gaze-pii = "0.8.0-rc.1"(not"0.8"). The same applies togaze-assembly,gaze-recognizers, and the rest of the workspace. - Tier 2 entities (Aadhaar / NIR / Steuer-ID / BSN / CPF / CNPJ / NHS) are not yet shipped. They land in rc.2 with checksum-backed validators.
- Tier 3 regex locales (SSN / NINO / PAN) land in rc.3.
- The Kiji-DistilBERT artifact bundle ships with a placeholder Hugging Face commit SHA in
scripts/fetch-kiji-safetynet-model.shpending first sign-off; pin the upstream model hash before relying on it in production. --rulepack-bundled core-extendedstill works in v0.8 but emits a deprecation warning; plan the cutover before v0.10.0.
Adopter notes
- No policy edits required. Existing
policy.tomlfiles load unchanged. The newsafety_tierfield is internal to the bundled rulepack source. RedactionEntryJSON shape is additive. New fields use#[serde(skip_serializing_if = "Option::is_none")]and emit nothing when None, so existing JSON consumers see no shape change.- SQLite audit DBs migrate forward in place. Pre-migration redaction rows pick up
recognizer_id = "legacy_unversioned"andrecognizer_version_id = NULL. The migration is idempotent. - Adopters who depended on the v0.4.5 PR #58 no-policy surprise activation for
phone.national.*orpostal.*recognizers should pass--locale=de-DEor--locale=en-USexplicitly, or supply a policy with the recognizer enabled. - Adopters wiring the Kiji safety net must run
scripts/fetch-kiji-safetynet-model.shto populate the artifact directory; the SHA256SUMS check is hard-fail by design.
Download
- CLI binaries:
cargo install --version 0.8.0-rc.1 gaze-cli - Library:
[dependencies] gaze-pii = "0.8.0-rc.1" gaze-assembly = "0.8.0-rc.1"
- Source:
git checkout v0.8.0-rc.1
CHANGELOG
Full entry: CHANGELOG.md [0.8.0-rc.1].
v0.7.2
v0.7.2 is a dogfooding-driven point release on the v0.7 line. It introduces a top-level schema_version field on policy.toml and threads the underlying loader cause through the gaze-cli PolicyConfig error envelope, both surfaced during a Pulseflow adopter demo on 2026-05-13. The release stays focused on Gaze's core contract: fail closed, preserve reversibility, and keep PII out of agent-visible surfaces.
TL;DR
Policy loading now declares its own schema_version and fails closed when an adopter's policy.toml targets an unsupported major.minor prefix, emitting a dedicated {"error":"PolicySchemaUnsupported","exit":2,"found":"...","supported":"0.1"} CLI envelope rather than the generic PolicyConfig shape. Every gaze-cli PolicyConfig map site now threads the loader cause through an additive optional detail field on the same JSON envelope, so adopters can see why a policy load failed without parsing free-form stderr. Existing 0.6.x and 0.7.x policy.toml files continue to load via a soft-default schema_version, so the upgrade is drop-in for current adopters.
Highlights
Policy schema versioning landed in PR #192. A new top-level schema_version field on policy.toml is parsed by gaze::Policy::load; the loader compares the major.minor prefix against gaze::SUPPORTED_POLICY_SCHEMA_MAJOR_MINOR and fails closed with the typed gaze::PolicyError::PolicySchemaUnsupported variant when the prefix does not match. The CLI maps this onto gaze_cli::CliError::PolicySchemaUnsupported and renders the dedicated {"error":"PolicySchemaUnsupported","exit":2,"found":"...","supported":"0.1"} envelope distinct from the generic PolicyConfig shape, so adopters can detect schema-version drift programmatically. Files written without schema_version resolve to gaze::DEFAULT_POLICY_SCHEMA_VERSION so existing 0.6.x and 0.7.x policies keep loading without edits. The change strengthens trust (auditable error variants tied to a specific schema contract) and adopter ergonomics (schema drift fails cleanly rather than producing a confusing parse error).
PolicyConfig error-envelope detail landed in PR #191. Every gaze-cli map_err(|_| PolicyConfig) site now threads the underlying loader cause through CliError::PolicyConfigDetail, populating an additive optional detail field on the existing {"error":"PolicyConfig","exit":2} envelope. The JSON shape stays additive — the error discriminator and exit code are unchanged — so downstream agents that key on the envelope keep parsing without code changes. The bare clap parse fallback intentionally remains detail-less so that raw argv noise does not leak into adopter-visible error metadata. The change strengthens adopter ergonomics (loader causes are now machine-readable instead of stderr-only) without weakening the closed error-variant guarantee.
Adopter notes
Policies that currently omit schema_version keep working unchanged. Adopters who want explicit schema pinning can add schema_version = "0.1" at the top of their policy.toml. Adopters who target a schema_version prefix that does not match 0.1 will see exit code 2 plus the PolicySchemaUnsupported envelope — the policy is rejected before any pipeline construction.
Agents that consume gaze-cli stderr-JSON for PolicyConfig envelopes will now receive an optional detail string carrying the loader cause. The field is additive: existing parsers that key on error and exit are unaffected.
Download
- Apple Silicon macOS: https://github.com/EmpireTwo/gaze/releases/download/v0.7.2/gaze-aarch64-apple-darwin
- Apple Silicon macOS SHA256: https://github.com/EmpireTwo/gaze/releases/download/v0.7.2/gaze-aarch64-apple-darwin.sha256
- Linux x86_64: https://github.com/EmpireTwo/gaze/releases/download/v0.7.2/gaze-x86_64-linux-gnu
- Linux x86_64 SHA256: https://github.com/EmpireTwo/gaze/releases/download/v0.7.2/gaze-x86_64-linux-gnu.sha256
Full CHANGELOG
https://github.com/EmpireTwo/gaze/blob/main/CHANGELOG.md#072---2026-05-13
v0.7.1
Added
- New OSS crate
gaze-documentfor document → safe-bundle generation.
Ships with PNG/JPG/PDF input support via Tesseract subprocess OCR (single-page
PDF rasterization via pdfium). Output is aSafeBundlecontaining redacted
Markdown + a restorablegaze::Manifest+ an OCR/PII report. Newgaze document clean <input> --out <dir>subcommand ongaze-cli(opt-in via--features document). - Validator-veto pre-resolver phase for validator-backed recognizer failures.
Invalid candidates are rejected before conflict resolution, then logged as
loser-only audit rows withdecided_by: ValidatorVetoand typed
validator_fail_reasonmetadata. See
docs/architecture/validator-veto.md. - Collision-family metadata and
FamilyPolicyTablefor cross-class recognizer
rivalries. Bundledcore-extendednow declares PAN-vs-IBAN and phone-family
metadata,ConflictTier::CollisionPolicyis audit-serializable, adopter
custom recognizers can declare non-reserved collision families, and
xtask family-policy-table-coherencevalidates bundled declarations. - Mandatory-anchor resolution for collision-family recognizers. Bundled locale
cue blocks under[locale.cues.<key>]can keep structural candidates on their
precise variant; missing anchors emit a family-level
PiiClass::Custom("family:<name>")token plusAmbiguityReason::NoAnchor.
xtask locale-cue-bundle-coherencevalidates bundled cue coverage. - Ambiguity side-channel and bundled audit migration for v0.7.x collision
handling.RedactionEntrycan carryValidatorFailReasonand
AmbiguityRecord;SqliteLoggermigratesvalidator_fail_reason,
ambiguity_record,collision_family, andcollision_variant; CLI audit
queries can filter ambiguity and collision metadata. See
docs/architecture/ambiguity-side-channel.md. gaze-documentopt-inmcpfeature exposesgaze_read_fileand
gaze_read_textTool impls that route document ingestion through
PiiEnvelope::dispatch. Returns{ clean_markdown, manifest_id, file_metadata }.gaze-cliopt-inmcpfeature exposesgaze mcp install --client=<name>,
gaze mcp doctor, andgaze mcp servesubcommands. Install writes client
JSON with the absolutecurrent_exe()path and an idempotent marker-fenced
skill section inAGENTS.md. Ships claude-code, claude-desktop, and cursor
at launch.
Changed
- [bundle-tokenization-drift]
core-extendedno-policy snapshot refreshed for
mandatory-anchor fallback on structural IBAN candidates without loaded locale
cue bundles.
Deprecated
Removed
Fixed
Security
v0.7.0 — mcp-core + mcp-rmcp + snapshot-binding correctness
Eighth-crate workspace release: gaze-mcp-core (transport-free PII chokepoint runtime) and gaze-mcp-rmcp (rmcp transport sink) land as real crates. v0.6.5 placeholder content is replaced with the real implementation.
Added
gaze-mcp-core— transport-free PII chokepoint runtime withTooltrait,ToolCtx,ToolRegistry,PiiEnvelope::dispatch,Frontend/DispatchHost,ManifestStore,AuthHook,SessionIdPolicy. Public tool structs marked#[non_exhaustive]per pre-1.0 SemVer policy. (#162)gaze-mcp-rmcp— rmcp transport sink that binds the chokepoint runtime to the rmcp protocol surface. (#174)gaze_pii::Session::export_with_extension(DocumentExtension)— opt-in document mode for OCR/PDF/transcript bundles. (#177)gaze_types::DocumentExtension,TextOrigin,CodecAuditRow,CodecCapabilitySet,ExtractionDensityPolicy. (#177)- CC-8 token-shape shadow guard at policy + rulepack regex paths — fails closed on patterns that shadow emitted token samples. (#162)
gaze-auditcolumnssnapshot_scheme,snapshot_alg,snapshot_key_versionfor cross-version audit verification. (#179)- Coverage feedback loop (Phases 0-5): synthetic corpus + integration test scaffold + info-only trend gate. (#176, #178)
Ipv4Parse,Ipv6Parse,EthEip55validator kinds;eth.addressincore-extended. Closes #440.
Changed
gaze_pii::Sessionsnapshot reference now binds the final emitted byte sequence rather than an earlier semantic object. Operator-bypass mutations post-snapshot are detectable. (#179)- Snapshot envelope: text-only
Session::export()stays v3; document-extendedSession::export_with_extension()emits v4. v0.6.x readers fail closed on v4. (#177) - Workspace bumped 0.6.6 → 0.7.0.
Fixed
gaze_pii::default_policyfalls back toTokenize(axis-1 fail-closed). (#175)
Architecture
- Strict additive SemVer pre-1.0 policy in force: new public types use
#[non_exhaustive]; behavioral changes ship behind opt-in flags until v1.0.0. - Audit-isolation gate (Dylint
gaze_module_isolationlint) remains canonical;gaze-auditis the only crate that depends onrusqlite.
Crates published
gaze-types, gaze-audit, gaze-recognizers, gaze-pii, gaze-assembly, gaze-mcp-core, gaze-mcp-rmcp, gaze-cli.