Skip to content

DEM-PRODUCER-CANDLE (reactor): the structure axis stops being a constant - #90

Merged
Gio2050 merged 3 commits into
mainfrom
dem/candle-reactor
Aug 26, 2026
Merged

Gio2050 merged 3 commits into
mainfrom
dem/candle-reactor

Conversation

@Gio2050

@Gio2050 Gio2050 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Wave 2 of 4 — DEM-PRODUCER-CANDLE, step 3 of 3. Merge after afi-core dem/candle-core and afi-config dem/candle-config. CI is expected red until both land.

The producers (src/enrichment/candleStructure.ts, new)

Pure functions over the window the lane already fetches — no new fetch, no new provider, no new parameter:

  • brokeEmaWithBody — the latest bar's body closed on the counter-trend side of EMA20: bullish → close < ema20; bearish → close > ema20; range (no side to break against) → the body crossed EMA20 on that bar. Colour-free, one law per side. (An earlier draft made the trending branches colour-conditioned; review caught that it encoded two different notions of "broke with body". Fixed before this PR.)
  • Heikin-Ashi flat-back — the recurrence over the whole fetched window, seed (o+c)/2, epsilon 0: a bullish flat-back is an up HA bar with no lower wick (low ≥ haOpen), a bearish one a down HA bar with no upper wick. haFlatBackConfirmed iff its side agrees with the lane's own EMA trend law. AR-GOV reserved the predicate, the seeding convention and the epsilon by name to this filing; all three are decided here and recorded in the plugin manifest.

Both read the lane's computed trendBias — never a submitted direction.

The gate's headline: the structure axis stops being a constant

The SOL 15m seed computes brokeEmaWithBody = true, so on tv-neutral.* structure moves 0.4 → 0.15 and risk 0.2 → 0.0. Across the corpus structure now spans {0.4, 0.15} and risk {0.5, 0.2, 0.0} — the gate's "structure and risk axes proven non-constant over the fixture corpus", met on the goldens themselves.

Stated plainly: haFlatBackConfirmed is false on all twelve goldens by construction — every demo seed is a range regime, and a range has no side to confirm against. That branch is proven by KATs, not by the corpus, and INTENTIONAL_DIFFS.md says so rather than implying corpus coverage it does not have.

12 KATs; 764/764 green; typecheck green; every moved golden path itemized.

🤖 Generated with Claude Code

Gio2050 and others added 3 commits August 25, 2026 17:48
…act; goldens regenerated once, itemized

DEM-GOV §9 DEM-PRODUCER-PLAN (owner-authorized 2026-08-25; afi-governance
#55; §9 determinations D-2/D-4/D-5 in #56). Merge AFTER afi-core dem/plan-core
and afi-config dem/plan-config.

Source:
- uss/cpjMapper.ts: the submitted plan survives as uss.plan (afi.trade-plan.v1,
  decimal strings, validated against the governed contract) or is refused at
  ingest (typed error → 422 trade_plan_invalid). TV/MarkitTick untouched.
- enrichment/tradePlanVerification.ts (NEW): the D-DEM-5(6) law — every
  submitted level within [L − W, H + W] of the fetched window; plan geometry
  from prices only (D-DIR-3 by construction); R:R to the nearest target,
  4 dp; refusal = TradePlanVerificationError (NodeConfigurationError).
- providers/adapters/technicalLocalAdapter.ts: the producer — verifies the
  plan against ITS fetched candles and emits technical.plan (declared
  absences: no plan → no block; no stop/target → no R:R).
- pipeline/nodes/laneView.ts: viewTechnical projects plan verbatim.
- server.ts: 422 trade_plan_unverifiable (unwrapping NodeExecutionError.cause),
  422 trade_plan_invalid; both persisted:false.
- types/TradePlan.ts (NEW), types/UssLenses.ts, uss/ussValidator.ts: types.

Registries/pins: the three fixture trees mirror afi-config (mapping 1.1.0,
config, three implementationVersion moves, registration hash 5cb9b7a4…);
registryLoader/officialArtifactPins pins rotated (pluginSetHash 36f911f4…).

Goldens: the two plan-bearing CPJ fixtures re-authored inside the demo
envelope (old levels were unverifiable by the law this slot lands); 12
goldens regenerated ONCE; every moved path itemized in INTENTIONAL_DIFFS.md
(risk 0.9 → {0.5 via the provider's rr 1.4286 | 0.2 via the declared floor};
executionSummaryHash flips executed → degraded on the two goldens where the
floor is the first fired default; identity-hash class on all 12).
test/oracle/support/goldenDiff.mjs (NEW): the committed per-path differ.

Tests: verification KATs (band, geometry, absences, error class), carrier
(decimal strings, refusals), producer (role split, D-DIR-3 negative test,
refusal, kernel floor, envelope-covers-fixtures), error-table rows for both
422s (no record), seam suites re-oracled to the composition reference with
the mapping resolved by mappingRef from the fixture registry, golden
scorerInput captured at the rubric call. 756/756; typecheck; compiled-build
proofs (unavailable 503; Mongo persistence 10/10; oracle equivalence 7/7;
SIGTERM) green locally.

No scoring-law value moves. Sealed records untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n law

An adversarial review of the branch (7 lenses, findings independently
verified) found five real defects in the D-DEM-5(6) law. All five fixed here;
no golden byte moves (every fix is refusal-side or message-side).

- MAJOR: an entry RANGE was verified only at its conservative bound, so a
  range containing (or on the wrong side of) its own stop was ACCEPTED and an
  R:R emitted from one end. The stop must now clear the FAR bound as well:
  long -> stop < entryLow, short -> stop > entryHigh. Three refusal KATs (long
  straddle, short straddle, far bound EQUALS the stop) + the accept-side edge.
- MINOR: the inclusive band edge was false on non-integer windows (binary
  float: 1.1 - 0.2 = 0.9000000000000001 refused an entry of exactly "0.9").
  Relative tolerance (1e-12) at both edges + bounded-precision numbers in the
  refusal message; a non-integer-window KAT pins both edges.
- MINOR: a non-array takeProfits (or a non-object levels) threw a bare
  TypeError, escaping the 422 unwrap. Both refuse properly now, with KATs.
- MINOR: "half-up to 4 decimals" was not what Math.round(v*1e4)/1e4 does at
  binary ties. The law is documented as what it is (deterministic binary
  quantisation) and the unfavourable tie (0.00015 -> 0.0001) is pinned.
- MINOR: missing edge KATs added: empty takeProfits array (no-target case),
  degenerate entry range (min === max), exotic numeric strings, an
  overflow-to-Infinity decimal string, malformed candles; the hedged
  short-geometry regex is tightened to its exact message.

756 -> 764 tests, all green; typecheck green; goldens byte-unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DEM-GOV §9 DEM-PRODUCER-CANDLE (owner-authorized 2026-08-25; afi-governance
#55; determinations D-2/D-3 in #56) — the act D5-GOV D-D5-1 reserved. Merge
AFTER afi-core dem/candle-core and afi-config dem/candle-config, which merge
after the whole PLAN wave.

Source:
- enrichment/candleStructure.ts (NEW): the two producers as pure functions over
  the window the lane already fetches. brokeEmaWithBody = the latest bar's body
  closed on the counter-trend side of EMA20 (bullish: close < ema20; bearish:
  close > ema20; range: the body crossed EMA20 this bar) — colour-free, one law
  per side. Heikin-Ashi flat-back = the recurrence over the whole window, seed
  (o+c)/2, epsilon 0 (bullish: an up HA bar with low >= haOpen; bearish: a down
  HA bar with high <= haOpen), confirmed iff its side agrees with the lane's own
  EMA trend law. Both read the lane's computed trendBias, never a submitted
  direction (DIR-GOV D-DIR-3).
- enrichment/technicalIndicators.ts: emits the three facts with the bundle.
- pipeline/nodes/laneView.ts: viewTechnical projects them; the imported stub
  constant and its pin are DELETED.
- types/UssLenses.ts: lens payload widened.

Registries/pins: three fixture trees mirror afi-config (mapping 1.2.0, config,
three implementationVersion moves); the two pin tests rotated.

Goldens (regenerated ONCE, itemized in INTENTIONAL_DIFFS.md): the SOL 15m seed
(tv-neutral) computes brokeEmaWithBody TRUE, so structure 0.4 -> 0.15 and risk
0.2 -> 0.0 there; the other ten are unmoved in scored values. THE GATE IS MET:
structure is non-constant over the fixture corpus ({0.4, 0.15}) and so is risk
({0.5, 0.2, 0.0}). haFlatBackConfirmed is false on all twelve BY CONSTRUCTION
(every demo seed is a range regime) — recorded honestly; its branches are proven
by KATs, not by the corpus.

Tests: candleStructure.test.ts (12 KATs: every brokeEma branch incl. the
green-body-below and straddle cases, both flat-back sides, the exact-equality
no-wick edge, the doji, seed-independence at the 50-bar floor, both producers
together); fiveLaneAdapters' stub assertions rewritten to computed-fact
assertions (and that the stub export is GONE); guardrail fixture views carry
the required facts; the seam test's bare-technical probe updated (the candle
binds are required, so a bare namespace now refuses).

764/764; typecheck green. No scoring-law value moves.

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 f006d3e into main Aug 26, 2026
3 of 5 checks passed
@Gio2050
Gio2050 deleted the dem/candle-reactor branch August 26, 2026 04:16
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