Skip to content

fix: stop re-paying for provider calls a provenance check discards - #302

Merged
Barsoomx merged 1 commit into
masterfrom
fix/distill-model-parity
Jul 29, 2026
Merged

fix: stop re-paying for provider calls a provenance check discards#302
Barsoomx merged 1 commit into
masterfrom
fix/distill-model-parity

Conversation

@Barsoomx

Copy link
Copy Markdown
Owner

A provenance check compared the model recorded for a provider call against stage.policy.model. Since #296 the gateway resolves the effective model per response kind, so as soon as a policy carried a per-kind override the two disagreed — every distillation call succeeded, was billed, and was then thrown away.

Measured on the stand before the revert: ~840 paid calls, zero useful output, 122 works climbing toward terminal at streak 7/12. All distill calls switched from gpt-5-mini to gpt-5-nano at 05:00 UTC when the override was set, and every one after that failed.

The failure was also invisible, which is why it ran for hours:

  • provider_call_record_missing is absent from _MODEL_POLICY_CODE_MAP, so it degraded to unexpected_exception — and UNEXPECTED retries, buying another call each time.
  • _classify_provider_error rebuilt ClassifiedWorkFailure field by field and dropped redacted_detail, so every persisted failure_reason on this path was empty.
  • _call_provider caught Exception with no logging at all.

Same shape as the 402 outage this campaign started with: the specific failure class is discarded, the generic one retries, and each retry re-pays.

Changes

Parity compares the record against the result, not against policy config. record.policy_id and record.policy_version on the lines above already pin the record to this stage's policy; re-deriving "the model" a second time only created a way for two computations to disagree. Resolving via resolve_model() would have worked too, but it stays time-dependent — if metadata changes between the call and the check it breaks again. The consistency check does not.

provider_call_record_missing → CONFIGURATION, so the stage goes BLOCKED. The call already succeeded and was billed; retrying cannot fix a configuration disagreement, it just buys another one. Blocked is visible and free. The distillation path already supplies a fingerprint (distillation_provider_stage.py:1237), so the CONFIGURATION contract is satisfied.

_classify_provider_error returns the translated failure whole, so failure_reason survives to the database.

_call_provider logs the exception it catches, with stage and request id.

One existing test asserted the old retry / unexpected_exception behaviour and now asserts blocked / provider_call_record_missing with a non-empty detail — a deliberate behaviour change, not a test tweak.

Not included

The stand was unblocked separately by removing the override with raw SQL, deliberately without bumping the policy version: stages pin policy_version and _refresh_live_policy (distillation_provider_stage.py:454) raises model policy version is stale on mismatch, so editing through the console would have failed all 121 pending works with a different error. After the revert, a forced retry produced 133 completed stages and zero failures.

Also unaddressed here: there is no cap on chunks per window. ENGRAM_DISTILL_MAX_CHUNKS does not exist in the code — only ENGRAM_DISTILL_CHUNK_CHAR_BUDGET bounds anything — and the largest window holds 701 real chunks, because each new window over a live session re-covers it from scratch. Legal today, but it means ~95 continuations for one work.

Verification

pytest -q engram3516 passed. ruff check engram → clean.

🤖 Generated with Claude Code

@Barsoomx

Copy link
Copy Markdown
Owner Author

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@codecov-commenter

codecov-commenter commented Jul 29, 2026

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

Affected Assets, Files, and Routes:

view changes for bundle: engram-frontend-client-array-push

Assets Changed:

Asset Name Size Change Total Size Change (%)
server/middleware-*.js 2.72kB 3.21kB 548.89% ⚠️
server/middleware-*.js -2.72kB 495 bytes -84.59%
static/d8Sfe25QoZVnaZEIZV8SM/_buildManifest.js (New) 1.51kB 1.51kB 100.0% 🚀
static/d8Sfe25QoZVnaZEIZV8SM/_ssgManifest.js (New) 77 bytes 77 bytes 100.0% 🚀
static/7pMvcZ29trInZFCKbbmb1/_buildManifest.js (Deleted) -1.51kB 0 bytes -100.0% 🗑️
static/7pMvcZ29trInZFCKbbmb1/_ssgManifest.js (Deleted) -77 bytes 0 bytes -100.0% 🗑️

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.03%. Comparing base (1d69340) to head (fd26d32).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #302      +/-   ##
==========================================
- Coverage   91.03%   91.03%   -0.01%     
==========================================
  Files         222      222              
  Lines       23195    23196       +1     
==========================================
  Hits        21116    21116              
- Misses       2079     2080       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@Barsoomx
Barsoomx merged commit 775a6d5 into master Jul 29, 2026
14 checks passed
@Barsoomx
Barsoomx deleted the fix/distill-model-parity branch July 29, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants