Feedback¶
chronicle.feedback is a pair of submit-only sinks: submit for plain product feedback, report_error for a reproducible failure that should land in the bug pipeline. Both only write — the review surfaces (admin list, status transitions) live in the bridge, not the SDK.
Pick the right one¶
| You have | Method | Goes to |
|---|---|---|
| An impression, a gap, a feature request | submit |
POST /v1/feedback, no fingerprint, no triage |
| A failing call with a type/message/stack | report_error |
POST /v1/errors, fingerprinted and deduped |
A reproducible error is not feedback. If you have a message and a stack, reach for report_error so the failure gets fingerprinted and triaged instead of sitting in a free-form queue.
submit — product feedback¶
submit files non-bug feedback and returns the created feedback id. body_md is Markdown by contract (tables, fenced code, lists all render); operators read it in the admin bridge.
fid = chronicle.feedback.submit(
"The dataset API can't express **sharded** provenance across components.",
category="gap",
context={"sdk_method": "datasets.upload"},
)
category must be one of the values below — anything else raises ValueError before a request goes out.
category |
Use for |
|---|---|
feedback |
An impression or UX note (the default) |
gap |
"The surface can't express what I needed" |
feature_request |
An explicit ask |
context is identifiers only
Pass findability keys like experiment_id, skill, or sdk_method — never bodies, transcripts, or secrets. source defaults to "sdk"; skills pass "skill".
report_error — bug pipeline¶
report_error posts a reproducible error and returns None. The endpoint is fire-and-forget (the server replies 202 Accepted and this method discards the body), but HTTP failures still raise the usual APIError subclasses.
chronicle.feedback.report_error(
error_type="ConflictError",
message="experiment already committed",
stack=traceback.format_exc(),
request_method="POST",
request_path="/experiments/{id}/git", # a route template, not a literal path
response_status=409,
)
The SDK attaches a client-side fingerprint — the SHA-256 of error_type | message | normalized top stack frames — so the same failure reported twice collapses to one identity. The server recomputes its own fingerprint and treats yours as advisory. Prefer a route template for request_path; the server only strips obvious UUID/integer segments as a backstop.