Clarify algorithmic cost of nested error projection

This commit is contained in:
2026-11-05 15:49:32 +00:00
parent 7203e5d6a1
commit beb18cc9d6

View File

@@ -139,6 +139,26 @@ exponential repeated text/traversal. Even one ordinary error repeats its cause
unnecessarily. This is introduced by the new join, not required to preserve the unnecessarily. This is introduced by the new join, not required to preserve the
owning category. owning category.
**Algorithmic analysis:** Let `d` be the number of enclosing operations, with a
fixed-size leaf diagnostic and fixed-size per-operation context. The ordinary
mapped cause already wraps the previous error, yet the join also stores that
previous error as another child. Its formatted length therefore follows
`L(d) = 2*L(d-1) + O(1)`, giving `Theta(2^d)` output bytes. The cause graph needs
only `O(d)` distinct error objects, but standard `errors.Is`/`errors.As` traverse
both paths without remembering previously visited objects. An unsuccessful
search consequently follows `W(d) = 2*W(d-1) + O(1)` as well. The mapper itself
performs such unsuccessful category/type searches, so this is not limited to
callers that log the final diagnostic.
Retaining one already-mapped cause path removes the avoidable branching:
formatted length becomes `L(d) = L(d-1) + O(1)`, and an individual formatting or
unsuccessful search over that corrected ordinary chain can be linear in `d`.
This is a structural alternative, not a request for error-graph memoization,
new nesting limits, or exact timing/allocation guarantees. It does not assert
that a sequence of `d` separate public operations, each processing its own
growing error, has linear total cost. Arbitrary consumer error implementations
also retain their own costs.
**Required correction:** Retain the owning category and each necessary cause **Required correction:** Retain the owning category and each necessary cause
without adding an original cause that the projection already retains. Preserve without adding an original cause that the projection already retains. Preserve
`errors.Is`/`errors.As`, specialized capacity/provider/retry projections, and `errors.Is`/`errors.As`, specialized capacity/provider/retry projections, and
@@ -319,3 +339,49 @@ no implementation or permanent test changes were made. All provider behavior
was controlled offline. The prior full-suite/vet evidence above remains was controlled offline. The prior full-suite/vet evidence above remains
applicable to the unchanged implementation; this follow-up adds focused applicable to the unchanged implementation; this follow-up adds focused
integration evidence rather than a new release gate. integration evidence rather than a new release gate.
## Algorithmic Follow-Up Coverage
A further source-based review at `7203e5d` focused on algorithmic correctness,
efficiency, and scalability of the implemented stages. It confirms the
exponential behavior in finding 3 and adds the recurrence and refactoring
opportunity there, rather than creating a duplicate finding. No additional
distinct algorithmic or ordinary-correctness finding was identified in this
pass. All five existing findings remain open.
The review used the plan and roadmap to exclude deliberate algorithm choices:
the small-to-large evidence merge, owned provider overlay, bounded feedback
encoding and prefix selection, namespace binary searches, declared-schema
location compilation, trusted-copy traversal policies, and selected ownership
copies were not reopened. In particular, the chosen unqualified-list scan and
schema-location strategy are not reported as new optimization requests.
For the remaining implementation glue:
- Source helpers map records once before ConfigKit's handoff, without the old
recursive compatibility expansion. ConfigKit's own processing is outside
this review's implementation scope.
- Extracted record validators use a backend-ID index rather than scanning every
backend for each profile. Prompt input duplicate detection uses a set; input
and message capture process their records once, with one final definition
hash and one lazily shared metadata snapshot. Existing sorted inventory
construction and dependency/template work are separate costs, not disguised
linear-time guarantees.
- The response-error recorder adds constant metadata work per read. The
authentication recognizer parses a fixed number of document levels/fields,
so its processing is linear in the consumed body size, not multiplied by
arbitrary input depth through a custom recursive recognizer.
- Generation accounting updates a fixed number of usage/event fields per
attempt and appends captured attempt records with amortized constant append
cost. Storing `A` requested attempt records requires `O(A)` space. Error
classification additionally pays for the supplied cause graph, including
finding 3; arbitrary collaborator/callback work is not constant-time.
- The repair request uses the original message prefix plus a bounded-count
suffix, not an accumulating conversation from every prior repair. Repeated
prefix processing follows the amount of message data actually resubmitted;
it is not an unintended growing-history algorithm.
The complexity finding follows from current source and the standard library's
error-tree traversal. No new benchmarks, real-world performance collection,
provider calls, implementation changes, or public complexity guarantees were
introduced. Existing validation evidence above applies to the unchanged code.