Diagnostics — opt-in error reporting¶
When Veracium hits a genuine error, it can send its local log to the maintainers so the bug can be diagnosed. This is a separate, more careful channel than telemetry: telemetry is content-free by construction, but a log can incidentally contain fragments of memory content (e.g. inside an exception message). So error reporting is local-first and never sends without consent.
How it works¶
- Local first. When a reporter is attached, genuine errors from
remember/recall/answer/maintainare written to a local, user-owned rotating log file — and the original error is re-raised unchanged. Reporting is strictly additive; it never swallows or delays the real exception. - Sending is consented. A log is transmitted only with advance permission (opt-in auto-send) or an explicit per-incident "yes". Default: neither.
- Transparent + redacted.
previewshows exactly what would be sent. A redaction pass (on by default) scrubs emails, phone/account/card-like number runs, and grouped amounts from the tail first. Redaction is best-effort — the real safeguard is that you see the payload and choose. - Anonymous + bounded. A random install id (shared with telemetry if you have one), minimal environment (Veracium / python / os), and only the log tail up to a byte cap (default 64 KB).
- No endpoint shipped. Veracium bundles no URL, so even "enabled" sends nothing until an endpoint is configured.
Degrade records (specs/0039)¶
Veracium degrades in a few places instead of failing, by design: the one
re-extraction retry that a provider fails, an extraction the provider answers in
prose, a volatility class outside the enum, a first answer with no usable
triples, a list member that is not a well-formed triple. None of those raises,
so none reached the error hook — until 0039. When a reporter is attached, each such
path now writes ONE WARNING line to the same local log, for example:
2026-09-10 10:46:03,125 WARNING op=remember degrade=retry_failed user_hash=0bfe935e70c3 cause=provider_error msg_len=11 msg_sha16=78b6a1c2d3e4f5a6
2026-09-10 10:46:04,010 WARNING op=remember degrade=volatility_defaulted user_hash=0bfe935e70c3 count=3
The record is content-free by construction, not by redaction: degrade and
cause are closed vocabularies (retry_failed, primary_failed, unparseable,
volatility_defaulted, member_skipped; provider_error, no_json,
instructions_type, shape, no_triples_key, bare_array), the provider's
exception class name is never recorded, and the only trace of a message or an
answer is its UTF-8 byte length and the first sixteen hex digits of its SHA-256 —
enough to match the provider's own log, not enough to read. A degrade record never
changes the operation's outcome and is never sent inline: it is left pending for
the next consented send. On the one path where the operation still raises (a
triples value that is null, a number or a boolean) the log carries the degrade
record and then the error record — two lines for one call; the error record is the
one that says the call failed.
The CLI attaches a reporter by default (as the MCP entry point always did), so
veracium remember leaves these records in $XDG_STATE_HOME/veracium/veracium.log
when local logging is enabled. veracium diagnostics path prints the location.
What a report contains¶
{
"schema_version": 1,
"install_id": "<random>",
"reason": "manual | auto:<op>",
"veracium_version": "0.1.0",
"python": "3.12.3",
"os": "Linux",
"redacted": true,
"log_tail": "…the last N KB of the local error log, redacted…"
}
log_tail is the sensitive part. It is Veracium's own log lines — timestamps, the
operation that failed, a hashed user id, and the Python traceback. Tracebacks show
Veracium's source lines (not memory content); the residual risk is an exception
message that quoted a value, which is why redaction + preview + consent apply.
Raw user ids are never logged — only a truncated SHA-256 hash of the id.
CLI¶
veracium diagnostics status # setting + resolved log path
veracium diagnostics path # just the log file location
veracium diagnostics preview # EXACTLY what a report would send (redacted)
veracium diagnostics report # send the current log now — asks first, shows the preview
# advance permission (auto-send on future errors):
veracium diagnostics prompt # the consent question
veracium diagnostics enable --endpoint https://your-collector.example/report
veracium diagnostics disable # revoke send (local logging is unaffected)
The MCP server attaches a reporter automatically (local logging on). Because its
stdio transport isn't a terminal it never prompts and never auto-sends unless you
granted advance permission with veracium diagnostics enable; otherwise the log
stays local until you run veracium diagnostics report.
Embedded in a host application¶
The host decides whether Veracium manages a log at all, and owns the consent UX.
from veracium import Memory
from veracium import diagnostics
reporter = diagnostics.load_reporter() # None if local logging is disabled
mem = Memory(llm=your_llm, diagnostics=reporter)
try:
mem.remember(user_id, text)
except Exception:
# veracium already logged it locally and re-raised. Offer to report:
preview = mem.diagnostics_preview() # show the user what would be sent
if user_agrees:
mem.report_error(interactive=False) # sends iff an endpoint is configured
raise
mem.report_error(interactive=…)— send the captured log, subject to consent (advance permission, or an interactive yes). No-ops if nothing was captured or no endpoint is set; never raises.mem.diagnostics_preview()— the exact (redacted) payload, orNoneif off.
If you granted advance permission (diagnostics.set_report_enabled(True,
endpoint=…)), Veracium auto-sends on error — throttled so an error loop can't flood
the endpoint.
Config file¶
Stored at $XDG_CONFIG_HOME/veracium/diagnostics.json; the log defaults to
$XDG_STATE_HOME/veracium/veracium.log (override with log_path). Fields:
{log_enabled, report_enabled, prompt_on_error, redact, endpoint, log_path,
install_id, max_report_bytes, report_min_interval_s, last_report}. Set
log_enabled: false to turn off local logging entirely.
Guarantees, restated¶
- The real error is always re-raised; reporting never hides a failure.
- Nothing is sent without consent (advance permission or an explicit yes).
- You can see the exact payload first (
preview); redaction is on by default. - Anonymous (random install id); no raw user ids in the log.
- A reporting failure never affects memory (the reporter never raises).