2026-05-11-envelope-precedence-docs-drift
Fix: routing-gates precedence docstring + concept docs (drift)
Date: 2026-05-11 Status: shipped Slug: envelope-precedence-docs-drift Branch: fix/envelope-precedence-docs-drift Closes: the HIGH-severity finding from #293
Summary
The routing-gates applyTrustGates source-of-truth docstring claimed signal precedence was tier → xdr_risk → anomaly_score. The actual implementation evaluates xdr_risk → anomaly → tier. PR #293's stress tests caught the drift; this PR aligns the docstring and the two external concept docs that inherited the inverted order.
No behavior change — code was always correct; the docs were wrong.
What changed
src/security/trust-envelope/routing-gates.ts
The header docstring is reordered to match the actual if/else if chain at lines 114-130. The new docstring also explicitly names the source labels ("xdr_risk" / "anomaly" / "tier" / null) and notes that the label is "anomaly", not "anomaly_score" (a separate consistency finding from #293).
docs/concepts/trust-envelope.mdx
The "Signal precedence" block now lists XDR first, anomaly second, tier third. Adds an explicit note that scope filtering happens before the signal gates. Documents that source may be null and that the anomaly label is "anomaly", not "anomaly_score".
docs/concepts/agent-reputation.mdx
Same precedence reordering. Adds context on why XDR runs first (highest external reliability) and clarifies that the tier acts as the floor when neither XDR nor anomaly fired.
src/security/trust-envelope/__tests__/envelope-stress.test.ts
Two assertions had FINDING: comments documenting the drift. Now that the docs match the code, the comments are reframed to "this is the canonical order as of 2026-05-11" — the assertions still pass, the test now reads as positive coverage rather than a known-broken anchor.
Verification
pnpm tsgo— exit 0pnpm exec oxfmt --check/oxlint --type-aware— cleanpnpm test:fast— 7813/0 (no regression, stress suite still green)
What this PR does NOT do
Doesn't touch the other two findings from #293:
- MEDIUM:
spent_usdnot clamped in synth → next PR - MEDIUM: empty
br_scope.models=[]semantics → needs design call
The remaining stress-test assertions still carry FINDING: comments for those.
Lockstep
- TS / Python SDK / MCP — no public API surface change
- OpenAPI — no new routes
- Ship log — this file