Skip to content

feat(exceptions): stable error codes, remediation hints, and error reference (#635, #637)#699

Merged
dgenio merged 3 commits into
mainfrom
claude/github-issues-triage-i30tlj
Jun 14, 2026
Merged

feat(exceptions): stable error codes, remediation hints, and error reference (#635, #637)#699
dgenio merged 3 commits into
mainfrom
claude/github-issues-triage-i30tlj

Conversation

@dgenio

@dgenio dgenio commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the tightly-coupled "stable library error surface" pair in one PR: machine-readable error codes + remediation hints on the exception hierarchy (#635), and the error-reference page that documents them (#637). The two share one module (src/contextweaver/exceptions.py) — the page documents the codes the hints anchor to, so they are cleaner together than apart.

Fixes #635
Fixes #637

Changes

#635 — stable error codes + remediation hints

  • src/contextweaver/exceptions.py: every ContextWeaverError subclass gains a frozen class-level code (e.g. CW_CONFIG) and an optional instance hint with a class-level default_hint fallback. __str__ renders [code] message (hint: …).
  • Because the CLI already renders f"Error: {exc}" (__main__.main) and the gateway CLI uses typer.BadParameter(str(exc)), code + hint surface in CLI output automatically — no CLI changes needed.
  • Six high-traffic errors ship anchored default hints: ConfigError, CatalogError, ItemNotFoundError, DeterminismError, PathInvalidError, BudgetOverflowError.
  • tests/test_exceptions.py: frozen GOLDEN_CODES golden list + tests for uniqueness, exhaustiveness (introspects the module), and str()/hint rendering. A rename or a new code-less exception now fails CI.

#637 — error-reference page

  • New docs/errors.md: code-index table + per-exception section (stable code, raising modules from a raise-site audit, common causes, fix). Anchors are the lower-cased class name so the hints in Give library exceptions stable error codes and remediation hints #635 link straight to the right section.
  • mkdocs.yml nav entry; cross-linked from docs/troubleshooting.md.
  • Registered in scripts/gen_llms.py; regenerated llms.txt / llms-full.txt so the page lands in the agent-facing bundle.

Supporting

  • api/public_api.txt regenerated for the new hint constructor parameter (diff is exclusively the exception classes).
  • AGENTS.md documents the code/hint convention and the new-exception rule; CHANGELOG.md updated under ## [Unreleased].

How verified

All commands run in a clean .venv with pip install -e ".[dev]":

  • ruff check src/ tests/ examples/ scripts/ — All checks passed
  • ruff format --check … — 370 files already formatted
  • mypy src/ scripts/ — Success: no issues found in 177 source files
  • python -m pytest2594 passed, 31 skipped, 1 xfailed; the only failure is test_serve_dry_run_writes_catalog_diagnostic_event, which is environmental: contextweaver mcp serve --dry-run exits 0 but emits a tiktoken 403 Forbidden warning to stderr because this sandbox can't fetch the cl100k_base encoding (unrelated to error handling; fails identically on main).
  • python -m pytest tests/test_exceptions.py — 21 passed
  • scripts/gen_api_manifest.py --check, gen_llms.py --check, check_module_size.py, check_doc_snippets.py — all OK (exceptions.py is 285 lines, under the 300 ceiling)

Checklist

  • Tests added or updated for every new/changed public function
  • make ci targets pass locally (one environmental, network-only tiktoken failure noted above; make docs/example/demo not runnable here — mkdocs/extras absent — CI covers)
  • CHANGELOG.md updated under ## [Unreleased]
  • Docstrings added for all new public APIs (Google-style)
  • Public-API change? Regenerated api/public_api.txt with make api
  • Every modified module stays ≤ 300 lines (exceptions.py = 285)
  • Related issue linked in the summary above
  • Agent-facing docs updated (AGENTS.md + new docs/errors.md)

Notes for reviewers

  • Message format change: str(exc) now carries the [code] prefix. Blast radius was measured — only one test asserted exact equality (updated); pytest.raises(match=…) uses re.search, so substring matches are unaffected.
  • Out of scope (follow-up): Give library exceptions stable error codes and remediation hints #635's optional step of threading the originating library code into the gateway GatewayError mapping. That touches the recently-hardened tool_execute dispatch and is not part of either issue's acceptance criteria, so it's deferred to keep this PR focused.
  • No routing/scoring/tokenisation/pipeline changes, so the reproducibility/benchmark section is N/A.

Generated by Claude Code

claude added 2 commits June 14, 2026 17:24
…ference (#635, #637)

Implements the "stable library error surface" group as one change.

#635 — stable error codes + remediation hints:
- Every ContextWeaverError subclass now carries a frozen class-level `code`
  (e.g. `CW_CONFIG`) so callers branch on failures without string-matching,
  and an optional instance `hint` (with a class-level `default_hint` fallback).
- `__str__` renders `[code] message (hint: …)`, so existing CLI error
  rendering (`__main__.main`) and `typer.BadParameter(str(exc))` surface the
  code + hint automatically.
- Six high-traffic errors ship default hints that link into the error
  reference (ConfigError, CatalogError, ItemNotFoundError, DeterminismError,
  PathInvalidError, BudgetOverflowError).
- `tests/test_exceptions.py` freezes the codes against a golden list and
  asserts uniqueness, exhaustiveness, and str()/hint rendering — a rename or a
  new code-less exception now fails CI.

#637 — error-reference page:
- New `docs/errors.md`: a code index table plus a per-exception section
  (stable code, raising modules from a raise-site audit, common causes, fix),
  added to the mkdocs nav and cross-linked from the troubleshooting guide.
- Registered in `scripts/gen_llms.py` and regenerated `llms.txt` /
  `llms-full.txt` so the page lands in the agent-facing bundle.

Other:
- Regenerated `api/public_api.txt` for the new `hint` constructor parameter.
- AGENTS.md documents the code/hint convention and the new-exception rule.

Out of scope (follow-up): threading library codes into the gateway
`GatewayError` mapping (touches recently-hardened dispatch; not required by the
acceptance criteria).

https://claude.ai/code/session_01BeQyyFrL1PUhuDxa99sNuN
Copilot AI review requested due to automatic review settings June 14, 2026 17:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR stabilizes the library’s public error surface by adding machine-readable error codes and remediation hints to the ContextWeaverError hierarchy, and publishing a dedicated error-reference documentation page that those hints can link to.

Changes:

  • Added stable per-exception code values plus optional hint/default_hint plumbing and updated __str__ to render [code] message (hint: …).
  • Added tests that golden-list codes, enforce uniqueness/exhaustiveness via module introspection, and validate str()/hint rendering.
  • Added and registered a new docs/errors.md reference page (plus nav + LLM bundle wiring) documenting codes, causes, and fixes.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/contextweaver/exceptions.py Introduces code/hint/default_hint on the exception hierarchy and updates __str__ formatting.
tests/test_exceptions.py Adds golden-list and introspection-based tests to enforce stability and rendering of codes/hints.
docs/errors.md New error-reference page indexing codes and documenting each exception with causes/fixes.
docs/troubleshooting.md Cross-links troubleshooting guidance to the new error reference.
mkdocs.yml Adds the error reference page to the documentation navigation.
scripts/gen_llms.py Includes docs/errors.md in the generated LLM documentation bundle and index.
llms.txt Updates the LLM doc index to mention the error reference page.
llms-full.txt Regenerated bundle content to include the full docs/errors.md page.
api/public_api.txt Regenerates the public API manifest to reflect new hint parameters/signatures.
AGENTS.md Documents the new code/hint convention and the “new exception must add code+golden+docs” rule.
CHANGELOG.md Notes the new stable error codes/hints and the new error reference page under Unreleased.

@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

Benchmark delta (vs main)

Soft regression feedback only — this comment never blocks the PR.
Latency budget: ⚠️ when head > base × 1.3. Accuracy budget: ⚠️ when head < base - 1pp.

Routing summary (single backend × catalog sizes)

size recall@k (head Δ vs base) MRR (head Δ vs base) p99 (ms)
50 ✅ 0.5649 (+0.0000) ✅ 0.4978 (+0.0000) ✅ 0.412 (base 0.759)
83 ✅ 0.3825 (+0.0000) ✅ 0.3242 (+0.0000) ✅ 0.531 (base 1.134)
1000 ✅ 0.1475 (+0.0000) ✅ 0.1456 (+0.0000) ✅ 26.322 (base 41.711)

Per-backend × per-size matrix

backend size recall@k (Δ) MRR (Δ) p99 (ms)
bm25 100 ✅ 0.3825 (+0.0000) ✅ 0.3399 (+0.0000) ✅ 4.570 (base 8.140)
bm25 500 ✅ 0.2250 (+0.0000) ✅ 0.2165 (+0.0000) ✅ 22.293 (base 38.989)
bm25 1000 ✅ 0.1575 (+0.0000) ✅ 0.1525 (+0.0000) ✅ 66.596 (base 111.716)
embedding_hashing 100 ✅ 0.5175 (+0.0000) ✅ 0.4360 (+0.0000) ✅ 6.017 (base 7.225)
embedding_hashing 500 ✅ 0.2700 (+0.0000) ✅ 0.2674 (+0.0000) ✅ 32.564 (base 44.182)
embedding_hashing 1000 ✅ 0.2000 (+0.0000) ✅ 0.1931 (+0.0000) ✅ 74.328 (base 98.277)
embedding_st 100 skipped (skipped: missing sentence-transformers)
embedding_st 500 skipped (skipped: missing sentence-transformers)
embedding_st 1000 skipped (skipped: missing sentence-transformers)
fuzzy 100 skipped (skipped: missing rapidfuzz)
fuzzy 500 skipped (skipped: missing rapidfuzz)
fuzzy 1000 skipped (skipped: missing rapidfuzz)
tfidf 100 ✅ 0.3825 (+0.0000) ✅ 0.3220 (+0.0000) ✅ 0.762 (base 1.102)
tfidf 500 ✅ 0.2325 (+0.0000) ✅ 0.2314 (+0.0000) ✅ 7.136 (base 11.492)
tfidf 1000 ✅ 0.1475 (+0.0000) ✅ 0.1456 (+0.0000) ✅ 26.333 (base 50.755)

Context pipeline (per scenario)

scenario tokens dropped dedup
large_catalog 1480 (base 1514, Δ-34) 0 (base 0, Δ+0) 0 (base 0, Δ+0)
long_conversation 2500 (base 2548, Δ-48) 0 (base 0, Δ+0) 0 (base 0, Δ+0)
mixed_payload 488 (base 497, Δ-9) 0 (base 0, Δ+0) 0 (base 0, Δ+0)
short_conversation 487 (base 496, Δ-9) 0 (base 0, Δ+0) 0 (base 0, Δ+0)
stress_conversation 6590 (base 6651, Δ-61) 11 (base 7, Δ+4) 4 (base 4, Δ+0)
tiny_payload 256 (base 267, Δ-11) 0 (base 0, Δ+0) 0 (base 0, Δ+0)

Numbers come from make benchmark / make benchmark-matrix.
Latency is hardware-dependent — treat the markers as a rough guide.
See benchmarks/scorecard.md for the full picture.

…hint with the safe remediation

Audit follow-up on #635 hints:
- DeterminismError.default_hint now leads with providing a deterministic
  summarizer/extractor (the data-protective path) and qualifies disabling
  deterministic mode, matching docs/errors.md. DeterminismError is a
  fail-closed privacy guard, so the hint should not lead with removing it.
- PathNotFoundError gains its own default_hint anchored to
  #pathnotfounderror instead of inheriting CatalogError's #catalogerror
  anchor.
@dgenio dgenio merged commit a54e35f into main Jun 14, 2026
9 checks passed
@dgenio dgenio deleted the claude/github-issues-triage-i30tlj branch June 14, 2026 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants