Skip to content

DEM-PRODUCER-HTF fix: a venue that cannot serve the window is an absence, not a failure - #93

Merged
Gio2050 merged 2 commits into
mainfrom
dem/htf-venue-capability
Aug 26, 2026
Merged

Gio2050 merged 2 commits into
mainfrom
dem/htf-venue-capability

Conversation

@Gio2050

@Gio2050 Gio2050 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What broke, and how it was found

The afi-gateway boundary proof — the one CI job that runs the reactor against the real coinbase feed — started returning 500 on every submission after the HTF slot merged.

Cause: coinbase has no weekly bar (ccxt's own timeframes table), so the registered 1w window's fetch threw and aborted the determination. This is not a test-environment quirk: any coinbase-backed composition would have been permanently unscoreable in production, which the slot never intended and which is not what D-DEM-5(4)(b) means by a producer that "may legitimately not emit" a fact.

The fix keeps two cases strictly apart

Conflating them would be exactly the fall-back your constraint forbids:

  • a timeframe the selected venue does not offer is a capability fact, known before any request is made → the window is not requested at all, no sub-block is emitted, and the registered mapping's declared absent member recodes it to neutral as a recorded default;
  • a fetch that fails for a timeframe the venue does offer is a real failure → still aborts the determination. Fail closed, never fall back.

PriceFeedAdapter now advertises supportedTimeframes (optional — absent means unknown, so every timeframe is attempted and nothing is silently skipped). The two ccxt adapters expose ccxt's own table.

Recorded, not hidden

INTENTIONAL_DIFFS.md gains residual (5): a coinbase-backed composition scores weeklyBias = neutral permanently, capping its structure at 0.6. blofin — the production feed — offers both 1d and 1w, so production is unaffected.

Three new tests: the unoffered window is never requested and lands as a declared absence; a fetch failure on an offered window still refuses; a feed with no capability table is treated as offering everything. Zero golden movement (the goldens run on the deterministic feed, which offers both windows). 794/794 green.

🤖 Generated with Claude Code

Gio2050 and others added 2 commits August 25, 2026 21:32
…NCE, not a failure

Found by the afi-gateway boundary proof (the one CI job that runs the reactor
against the REAL coinbase feed): every submission 500'd after HTF merged.

Cause, and why it is a real defect rather than a test-environment quirk:
coinbase has no weekly bar (ccxt's own timeframes table), so the registered
`1w` window's fetch threw and aborted the whole determination. Any
coinbase-backed composition would have been permanently unscoreable in
production too — which is not what the slot intended, and not what
D-DEM-5(4)(b) means by a producer that "may legitimately not emit" a fact.

The fix keeps the two cases strictly apart, because conflating them WOULD be
the fall-back the owner's constraint forbids:
- a timeframe the SELECTED VENUE does not offer is a CAPABILITY fact, known
  before any request is made: the window is not requested at all, no sub-block
  is emitted, and the registered mapping's declared `absent` member recodes it
  to neutral as a RECORDED default (D-DEM-5(4)(b));
- a fetch that FAILS for a timeframe the venue DOES offer is a real failure and
  still aborts the determination — fail closed, never fall back.

- adapters/exchanges/types.ts: PriceFeedAdapter advertises `supportedTimeframes`
  (optional; absent = unknown, so every timeframe is attempted and nothing is
  silently skipped). The two ccxt adapters expose ccxt's own table; the
  deterministic test feed advertises the fixture timeframes.
- technicalLocalAdapter: skips an unoffered window (logged), otherwise unchanged.
- htfProducer.test.ts: three new cases — the unoffered window is never
  REQUESTED and lands as a declared absence; a fetch failure on an offered
  window still refuses; a feed with no capability table is treated as offering
  everything.
- INTENTIONAL_DIFFS.md: recorded as residual (5) — a coinbase-backed
  composition scores weeklyBias=neutral permanently, capping its structure at
  0.6. blofin (the production feed) offers both windows.

Zero golden movement: goldens run on the deterministic feed, which offers both.
794/794 green; typecheck green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Residual (5): a venue that does not offer a registered higher-timeframe window
yields that bias as a declared absence for every signal it serves — coinbase
has no weekly bar, so a coinbase-backed composition caps structure at 0.6;
blofin (the production feed) offers both. The capability is checked before the
request; a genuine fetch failure still refuses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kilo-code-bot

kilo-code-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

Kilo Code Review could not run — your account is out of credits.

Add credits or switch to a free model to enable reviews on this change.

@Gio2050
Gio2050 merged commit 883dad6 into main Aug 26, 2026
3 of 4 checks passed
@Gio2050
Gio2050 deleted the dem/htf-venue-capability branch August 26, 2026 04:36
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.

1 participant