What
packages/scraping/src/expect.ts — maxDrop compares a run's yield against a baseline that only exists if history: is declared. Declare expect: { maxDrop } without history: and the guard is inert: there is no baseline, so the alarm can never fire. Nothing refuses the combination at definition time, and nothing says so at runtime.
The two wrong fixes, and why
Record history unconditionally (the sweep's original proposal) — rejected with evidence. expect.test.ts:76-80 pins the current behaviour deliberately by name: "no expect declared is no alarm and no history written". And recording unchecked runs has a real cost: a stretch of silent zero-row runs would become the median a later maxDrop is measured against, so arming the guard later would arm it against a poisoned baseline.
Leave it as documentation — rejected by axiom 3. A convention that is not a build error does not exist, and this one is invisible: the scrape runs, the guard reports nothing, and the author believes they are protected.
The right fix
Refuse the combination where it is declared. expect.maxDrop present and history absent is a definition-time refusal with a stable code, a cause naming both fields, and an executable fix: — the shape assertIdempotencyScope and assertRateLimitScope already use elsewhere in the framework: a guarantee that cannot be shown to hold is refused where it is declared, rather than assumed at 3am.
Alternatively, make it unrepresentable in the type — history required whenever maxDrop is present — which is cheaper and catches it at compile time, with the runtime refusal as the JSON/JS backstop. That pairing is what @ultimat3/auth just did for mfa.required.
Why it was deferred
It needs a new X_SCRAPE_* error code, which needs a wiki/Error-Codes.md row and a regenerated framework.manifest.json. Both are coordinator-owned, and it surfaced during review of a security PR (#152) where scope growth was the wrong trade.
Raised by CodeRabbit on #152; the underlying gap was found by the multi-agent bug sweep, 2026-08-18.
What
packages/scraping/src/expect.ts—maxDropcompares a run's yield against a baseline that only exists ifhistory:is declared. Declareexpect: { maxDrop }withouthistory:and the guard is inert: there is no baseline, so the alarm can never fire. Nothing refuses the combination at definition time, and nothing says so at runtime.The two wrong fixes, and why
Record history unconditionally (the sweep's original proposal) — rejected with evidence.
expect.test.ts:76-80pins the current behaviour deliberately by name: "no expect declared is no alarm and no history written". And recording unchecked runs has a real cost: a stretch of silent zero-row runs would become the median a latermaxDropis measured against, so arming the guard later would arm it against a poisoned baseline.Leave it as documentation — rejected by axiom 3. A convention that is not a build error does not exist, and this one is invisible: the scrape runs, the guard reports nothing, and the author believes they are protected.
The right fix
Refuse the combination where it is declared.
expect.maxDroppresent andhistoryabsent is a definition-time refusal with a stable code, a cause naming both fields, and an executablefix:— the shapeassertIdempotencyScopeandassertRateLimitScopealready use elsewhere in the framework: a guarantee that cannot be shown to hold is refused where it is declared, rather than assumed at 3am.Alternatively, make it unrepresentable in the type —
historyrequired whenevermaxDropis present — which is cheaper and catches it at compile time, with the runtime refusal as the JSON/JS backstop. That pairing is what@ultimat3/authjust did formfa.required.Why it was deferred
It needs a new
X_SCRAPE_*error code, which needs awiki/Error-Codes.mdrow and a regeneratedframework.manifest.json. Both are coordinator-owned, and it surfaced during review of a security PR (#152) where scope growth was the wrong trade.Raised by CodeRabbit on #152; the underlying gap was found by the multi-agent bug sweep, 2026-08-18.