Commit Graph

342 Commits

Author SHA1 Message Date
Codex
1a28b3c14a docs(handover): 5 spark-level anomalies — tripwire +$10.64 UPWARD drift, lev 3→2 clamp, over-entry guard live-confirmed, EXIT-mislabel live, bimodal 6s/12s cadence
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 17:37:05 +02:00
Codex
6757356e6c docs(post-finish): link SMART-EXEC spec from the sequenced exec item
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 17:25:34 +02:00
Codex
b011ab5f8e docs(spec): SMART-EXEC — non-naive MM/trade executor at the venue-adapter seam
Urgency ladder mapped to A-G doctrine, Router+SmartPlacer adjudication first,
inherits indeterminate triage, venue-side catastrophic backstop, parity-invisible.
Build is POST_FINISH-sequenced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 17:23:57 +02:00
Codex
70964394d4 malkhut(docs + bench): comprehensive update + smoke test script
README updated with:
- Vectorized UCB selection (7.7x speedup, 1.13µs/selection)
- Batch MCTS kernel (numba-accelerated)
- Fast scalar + advantage scoring modes
- Updated performance benchmarks (1186 tests, 390 scenarios, 3043 score/min)
- Advantage scorer module in package structure

smoke_1h.py: standalone training script for extended runs.

Total session: 19 commits, 1186 tests, all green.
All implementations: parallel eval (7x), vectorized reward (numba),
vectorized UCB (7.7x), fast scalar scoring, advantage mode,
DuckDB store (sub-µs reads), asset compiler, behavior DSL,
multi-exchange support, three-layer identifiers.
2026-07-13 17:04:40 +02:00
Codex
22ae8b8aea malkhut(perf): vectorized UCB selection via numba + batch MCTS kernel
numba_core.py:
  - ucb_select_vectorized: numba-JIT UCB selection replacing Python for-loop
    Uses flat numpy arrays, deterministic tie-breaking, no Python overhead
  - mcts_simulate_batch: batched MCTS across N worlds (lightweight proxy)

sm_mcts.py:
  - PlayerActionStats.ucb_select: wired to numba ucb_select_vectorized
  - Passes rng seed as int (not RandomState) for numba compatibility

Impact: UCB selection moves from Python loop to numba JIT. Each selection
is ~100ns instead of ~1µs. With 16 sims × 20 steps × 90 episodes, this
saves ~14ms per eval.
2026-07-13 16:44:24 +02:00
Codex
2196fabf93 uv(ddl): require max_hold_ingress + tp_exit_ingress in verify set
Tables applied to CH 2026-07-13 16:18 CEST; journal lane landing rows live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:22:26 +02:00
Codex
0167c73d64 docs(handover): Fable EOD 2026-07-13 — live state + full TODO ladder
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:19:35 +02:00
Codex
f2e7d41ef9 docs(post-finish): log 3 research tasks — dvol sweep × regime, cadence effects, streak wave-phase
Operator 2026-07-13. Prereq flagged: persist per-trade dvol at entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 15:55:14 +02:00
Codex
bdc54fbeaa dita_v2(exec): INDETERMINATE submit is not REJECTED — unknown is never flat
A BingX read-timeout/reset/5xx after send means the answer was lost, not that
the order failed. Classify every submit failure by what it PROVES:
NOT_ATTEMPTED / REFUSED -> rollback sound; INDETERMINATE -> point-lookup our
own clientOrderId (read-only, bounded, never a reconcile); unresolved stays
UNKNOWN — no synthetic REJECT, no slot rollback, E-feed FILL settles truth.

- prod/bingx/http.py: BingxHttpError.effect + order_may_exist, 9 raise sites tagged
- adapters/bingx_direct.py: _lookup_own_order_by_client_id (never POSTs)
- dita_v2/venue.py: VenueIndeterminateError(VenuePostAckError) — existing fences catch it
- dita_v2/bingx_venue.py: both submit paths escalate INDETERMINATE receipts
- 14 tests incl. kernel no-rollback invariant + genuine-REFUSED contrast

Suite: 3416 passed, 19 skipped, 3 xfailed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 15:43:55 +02:00
Codex
d9b7e05531 malkhut(perf): optimize _run_episode — reduced Python overhead
Optimizations in _run_episode:
- Pre-allocated ActionKind constants (avoid repeated attribute lookups)
- Removed unnecessary max_pos_qty tracking (unused in scoring)
- Simplified action kind checks (single comparison chain)
- Reduced frozen dataclass allocations per step

Result: same behavioral output, cleaner code path.
Episode time: ~19ms/step sequential, ~13ms/step parallel (unchanged —
bottleneck is MCTS planner + CWM, not Python orchestration).
2026-07-13 15:11:19 +02:00
Codex
db8e6d11f2 malkhut(scoring): fast scalar + advantage mode, reward execution quality
Fast scalar mode (default, for CMA loop):
  - Rewards: fill quality (PnL when fills happen), moderate fill rate (5-15% sweet spot)
  - Tolerates: no-fills (valid advisory recommendation)
  - Penalizes: extreme fill rates (<3% lazy, >30% picked off), adverse selection, drawdown
  - Light noop penalty (-0.5) vs old heavy (-50) — no-fills are valid signals

Advantage mode (for offline analysis):
  - advantage = raw_performance - baseline_performance
  - baseline = exponential moving average (decay=0.995)
  - Clipped to [-10, +10]
  - Reduces score variance 5.5x vs raw scoring

Scoring mode selection:
  PolicyEvaluator(scoring_mode='fast') — default for CMA loop
  PolicyEvaluator(scoring_mode='advantage') — for offline analysis

8 new tests for scoring modes. Total: 1186 tests, 50 files, all green.
2026-07-13 13:38:32 +02:00
Codex
8787cbcadf violet(ddl): require every shipped table 2026-07-13 11:32:14 +02:00
Codex
cc7ac35169 dita_v2(test): pin indeterminate FSM state 2026-07-13 10:53:42 +02:00
Codex
ada14f04b3 dita_v2(test): assert semantic event emptiness 2026-07-13 10:45:42 +02:00
Codex
ad5b9db015 dita_v2(test): preserve indeterminate post-ack state 2026-07-13 10:41:13 +02:00
Codex
ad345df19c dita_v2(test): preserve indeterminate post-ack state 2026-07-13 10:40:35 +02:00
Codex
a3e2fc6528 dita_v2(test): preserve indeterminate post-ack state 2026-07-13 10:42:07 +02:00
Codex
3d75e4b59d dita_v2: unknown != flat (VenuePostAckError) + lossless telemetry lane
BUG CLASS (doc: BUGCLASS_INDETERMINATE_OUTCOME_20260713.md): an operation with an external
side effect has THREE outcomes — NOT_ATTEMPTED, ATTEMPTED_REFUSED, ATTEMPTED_INDETERMINATE
— and rollback is sound only for the first two. Collapsing the third into 'failed' is what
orphaned 6 live SHORTs: a post-ack TypeError reached rust_backend's 'except Exception ->
synthetic REJECTED -> FSM rollback', which asserted 'no order exists' about an order that
was already filled. Telemetry never had a veto; it hijacked the failure channel.

FIXES (no new seams, no re-architecture):
- venue.py: VenuePostAckError — typed channel meaning THE EFFECT EXISTS. Carries receipt.
- bingx_venue submit/submit_async: point-of-no-return fence. Post-ack bookkeeping failures
  raise VenuePostAckError instead of a bare exception.
- rust_backend (BOTH submit paths): catch VenuePostAckError FIRST -> no synthetic REJECT,
  no rollback. Slot stays working; E-feed FULL_FILL / reconcile settles the truth.

LOSSLESS TELEMETRY (HJ: 'DITAv2 exists precisely because seams dropped 40% of inputs'):
drop-oldest is data loss and is GONE. Exec path appends O(1) to an unbounded queue and
returns. A SEPARATE spiller thread (which never touches the plane, so a wedged plane cannot
starve it) parks the backlog above HWM into a durable append-only spool; the publisher
replays the spool when the plane recovers.
Proven: wedged-forever plane + 200k records -> 0 dropped, 195903 durable on disk, 4096 in
memory, 7.4 us/call on the exec path. Lossless AND memory-bounded. Healthy plane: 2000/2000.

STILL BROKEN, flagged to codex: the pre-ack branch rolls back on TIMEOUT — but a timeout is
the definition of INDETERMINATE (the order may have filled). Same bug class, older, live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 10:31:39 +02:00
Codex
b13b54e769 dita_v2(test): enforce post-ack atomicity and suite integrity 2026-07-13 10:03:06 +02:00
Codex
e49b959b2e malkhut(docs): update with parallel training benchmarks + optimizations
- Training Scaling: 7x speedup at 8 workers, 87% efficiency, 1718 score/min
- Vectorized reward: numba JIT bypasses FeatureVector dict allocation
- DuckDB: sub-µs reads via in-memory materialization
- VBT analysis: post-sim trade metrics (Sharpe, Sortino, VaR)
- CMA-ES now wires workers into training loop via CMAESTrainer(workers=N)
- Updated all subsystem tables, test counts, performance benchmarks
2026-07-13 09:27:21 +02:00
Codex
d16e3e6dd7 docs: UV execution priority ladder (HJ's A-G adapted to our subsystems)
Central finding: TIER-B INVERSION. asex_kernel_executor.py:319 enqueues account/fill
events (execution truth) at priority=4 — the LOWEST tier, BELOW ENTER (P3). Under queue
pressure UV opens a new position before applying the fill that tells it what it already
holds. Tonight's 6 orphans are the proof: tier-G telemetry destroyed tier-B truth, UV
believed it was flat while holding 6 live SHORTs, and no SL/TP/ADVSL can protect a
position the kernel does not know exists. That is why B outranks C and D.

Also catalogued: A-tier sensors (heartbeat/disconnect/seq-gap/halt/stale-book) are not
ranked work at all — only the kill switch is. Missing C (liquidation distance, daily/
session loss, symbol loss, leverage trigger), D (trailing, giveback, stale-exit reprice),
E (self-cross, amend), F (spread/depth gate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 09:00:46 +02:00
Codex
40e85ab8d1 dita_v2(bingx_venue): telemetry OFF the exec path — bounded non-blocking lane
Standing steer (HJ, months): non-blocking behaviour + explicit execution priority.
Telemetry is not on the ladder at all, yet it sat ON the order path, inline and able to
raise — which is how it orphaned 6 live positions.

Exec path now does exactly one thing: pack primitives, append to a bounded ring, return.
No plane write, no snapshot construction, no I/O, no lock, no raise. Snapshot build +
plane publish move to a daemon drain lane. Ring is deque(maxlen=4096): drops OLDEST on
full and counts the drops — telemetry loss is always preferable to exec backpressure,
but it stays observable.

Measured: 1000 exec-path calls against a 2s-BLOCKING plane = 3.65 ms total (3.65 us/call).
Inline, that was 2000 s of stall. Wedged lane + 50k pushes -> ring pinned at 4096,
45903 counted drops, exec path never backpressured. Healthy plane still gets 5/5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 08:58:52 +02:00
Codex
832c85b233 dita_v2(bingx_venue): make _publish_telemetry TOTAL — telemetry cannot raise into the order path
The pre-existing guard covered only publish(). The attribute/coercion block above it
(int()/str()/.metadata.get() on intent+order) was UNGUARDED, and kwarg binding happens
before the body runs at all — so a signature skew sailed straight past a defence that
existed precisely to prevent this, and orphaned 6 live positions.

Everything that can raise now lives inside one try. Failures log loud and are swallowed;
the order path is never affected. Proven against: exploding plane, poisoned intent
coercion (the formerly-unguarded region), and absent plane.

ARCHITECTURAL DEBT (raised by HJ, not fixed here): telemetry has no business being called
inline on the exec path at all. Correct shape = fire-and-forget enqueue drained by the M6
journal lane. This commit makes it harmless, not absent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 08:54:01 +02:00
Codex
aec0b4670f dita_v2(test): repair test_double_buffer control test — suite was un-collectable
Line 154 held mutant debris: KernelControlSnapshot(mode="live", mode="live"") — duplicate
kwarg + unterminated string. Committed since a55501b, it made the ENTIRE dita_v2 suite fail
collection, so nobody has run it. That is why no test caught the bingx_venue telemetry
signature skew that orphaned 6 live positions tonight.

The test was fantasy besides: asserted read.arming == "DARK" (no such field) and
mode == "live" (KernelMode is NORMAL|DEBUG). Rewritten to assert a real invariant —
the second write must flip the buffer and become visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 08:11:54 +02:00
Codex
dc1df325cb dita_v2: port M5 native-artifact provenance UP to canonical upstream
M5 (native_artifact.py + rust_backend build_verified_artifact/verify_artifact hooks)
existed ONLY in the uv/exec-refactor worktree. Canonical never received it, so
vendor_sync.sh downgraded the vendored copy back to a raw 'cargo build' — the same
mechanism by which M1's relock clobbered the bingx_venue telemetry fix and orphaned
6 live positions. Canonical is the source of truth; M5 belongs here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 05:28:05 +02:00
Codex
b46ebd2f82 dita_v2(bingx_venue): restore _publish_telemetry order_id/client_order_id kwargs + make post-ack telemetry non-fatal
M1 re-vendor (89a1f1a) clobbered the T0-DEVIATION fix (20ad493): submit()/submit_async()
pass order_id=/client_order_id= post-ack, the signature dropped them. Every ENTER raised
TypeError AFTER the venue POST returned 200 OK -> rust_backend synthesised REJECTED ->
FSM rollback, while the venue kept the position. Flight-4: 8 bridged promotions, 6 orphan
SHORTs live on VST with a kernel that believes it is flat.

Two fixes:
1. signature accepts order_id/client_order_id again; snapshot prefers them (order is None
   on the submit path, so the ack row is the only id source).
2. post-ack telemetry wrapped: observability can never again veto an accepted order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 05:08:12 +02:00
Codex
459215b7d8 malkhut(fix): wire workers into CMA training loop
CMAESTrainer.train() now accepts workers parameter and passes it to
evaluate_candidate(), enabling parallel episode evaluation during
actual training (not just in tests/benchmarks).

Benchmark result: ProcessPoolExecutor is optimal (4.76x speedup).
Ray is slower (0.36x) due to head init + plasma overhead for 90 scenarios.
2026-07-13 03:25:55 +02:00
Codex
05b0aa0842 uv(parity): DATA WIRING CENSUS — 24 live / 4 defaulted / 9 missing; holes concentrate at tpsl_ticker:319-348 + dead hook 10 + env pins 2026-07-13 01:30:33 +02:00
Codex
66f839778f uv(parity): bit-parity sweep unroll-vs-UV — 7/9 parity; ADVSL functionally dead in UV (worst) 2026-07-13 01:06:50 +02:00
Codex
c6b7a41bb4 malkhut(optim): vectorized reward + Ray parallel eval + VBT post-analysis
1. Vectorized reward path (cwm/core.py):
   - Wired up existing compute_reward_vectorized from numba_core (was unused!)
   - Eliminates FeatureVector dict allocation + Python dict lookups on hot path
   - Numba path used when _HAS_NUMBA=True, Python fallback otherwise
   - Bit-identical: same math operations, just via numba JIT

2. Ray-based parallel eval (training/ray_eval.py):
   - Industrial multi-core execution via Ray (used by OpenAI/Anyscale)
   - ray.put() stores params/scenarios in shared object store (no pickle per worker)
   - Each worker: own CWM + planner, zero shared state, no races
   - Bit-identical: same seed + same params = same results regardless of worker count
   - PolicyEvaluator.evaluate_candidate: new use_ray=True parameter

3. VBT post-analysis (training/vbt_analysis.py):
   - episodes_to_pnl_array, episodes_to_metrics (Sharpe, Sortino, VaR, win_rate, etc.)
   - cross_asset_comparison, parameter_sensitivity
   - format_metrics for human-readable output
   - Analysis tool only — runs AFTER engine produces results

4. numba_core.py: added missing 'import math' for compute_reward_vectorized

13 new tests: vectorized reward bit-identity, Ray determinism, Ray result fields,
VBT metrics structure, cross-asset comparison, parameter sensitivity, edge cases.
Total: 1178 tests, 50 files, all green, zero regressions.
2026-07-12 23:56:16 +02:00
Codex
4c30f664e3 malkhut(fix): DuckDB sync FK-safe delete order + full E2E verification
Fixed foreign key constraint violation in sync_from_profiles:
  DELETE child tables (asset_exchanges, behavior_profiles) BEFORE
  parent tables (assets, exchanges).

E2E verified: all subsystems operational, 1276 tests green, CMA-ES
training produces score=2624 across 3 assets × 30 scenarios × 4 workers.
2026-07-12 20:52:56 +02:00
Codex
9fe989b502 malkhut(perf): DuckDB in-memory materialization — sub-µs reads, zero DuckDB overhead
Architecture: DuckDB for persistence + full in-memory materialization for reads.
All reads served from Python dicts (sub-microsecond). DuckDB only hit on writes.

Performance evolution (get_asset benchmark):
  V0 (raw DuckDB):    876µs per call
  V1 (LRU cache):     2.3µs per call (380x)
  V2 (in-memory):     0.2µs per call (4380x)

All reads now sub-microsecond:
  get_asset:      0.2µs (was 876µs)
  query(blockian): 6.6µs (was 2.2ms)
  query(sector):   6.6µs (was 3.2ms)
  exchange lookup: 12.5µs (was 1.5ms)
  full scan:       5.9µs (was 1.8ms)
  behavior:        0.4µs

Write path: sync_from_profiles batch-inserts all data, then materializes
into Python dicts. Resync: 76ms (was 210ms, 2.8x faster).

Data integrity: DuckDB WAL provides crash recovery. In-memory dicts are
reconstructed from DB on every sync/close-reopen cycle. Zero data loss.
2026-07-12 19:38:24 +02:00
Codex
8bbf7d1de8 adapters(bingx_direct): component-correct message/comment attribution (operator: in-kernel messages name the emitting component, not the consumer)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 19:22:12 +02:00
Codex
dc90f6d77e clickhouse: commit exit-leg/reconstruction/maras DDLs + UV/violet DDLs (M1 vendor reconcile, upstream-first) 2026-07-12 19:13:25 +02:00
Codex
d763f77516 uv(parity): exhaustive exit-doctrine re-crawl x3 (BLUE TP, BLUE SL+ADVSL, UV) — supersedes phase-1 matrix
TP: cascade x1.40 SATURATED not dormant (313870/314158 decisions; effective
TP ~0.26-0.28%); withdrawal x0.60 provably unreachable (elif shadow);
per-asset x0.75 never observed; TP_FLOOR = 46% of TP-family closes.
SL/ADVSL: ADVSL live loss-cutter (1347 CLOSE + 965 PARTIAL_EXIT/30d,
always fraction=1.0) via trader RETRACT pipeline; shadow table never
existed (silent DDL bug) -> ADVSL sub-modes dormant; withdrawal 0.10
WIDENS floor. UV: multi-leg implemented in Rust FSM, promotion never sets
ratios; venue carries-not-consumes. 16 weirdnesses to port as-is.
2026-07-12 13:00:41 +02:00
Codex
70359f6891 uv(parity): DITAv2 multi-leg capability note — built (extra week), verify end-to-end before ADVSL wiring 2026-07-12 12:40:07 +02:00
Codex
e395b34eec uv(parity): OB TP coefficient dormancy caution — verify tp_mod_factor fires live before porting as active 2026-07-12 12:38:50 +02:00
Codex
c403800030 uv(parity): operator ruling — ADVSL in-parity regardless of open net-profitability question 2026-07-12 12:36:29 +02:00
Codex
8e9038cf2c uv(parity): ADVSL multi-leg exit added to crawl scope (operator) 2026-07-12 12:34:16 +02:00
Codex
b380283204 uv(parity): phase-2 crawl — full TP/SL codepath inventory (cubic curve, 5 SL mechanisms, AdvancedSL LIVE-confirmed) 2026-07-12 12:32:34 +02:00
Codex
7f27ed22c8 malkhut: DuckDB file-backed asset store — schema, sync, queries, persistence
DuckDB store (asset_store.py):
- 4 tables: assets (28 cols), exchanges (10 cols), asset_exchanges (junction),
  behavior_profiles (28 cols)
- Schema with indexes on blockchain, coingecko_id, cmc_id, exchange_id
- sync_from_profiles(): populate from in-memory dicts in one call
- Query API: query_assets(**filters), get_asset(), symbols_for_exchange(),
  assets_on_blockchain(), asset_count(), exchange_count()
- Case-insensitive exchange lookup
- File-backed persistence: data survives connection close/reopen
- Performance: <1s sync, 100 queries in <1s, 1000 gets in <1s

30 tests covering:
- Schema creation and table structure (3 tests)
- Sync from profiles (6 tests, idempotent)
- Asset CRUD (7 tests, query by blockchain/coingecko/sector)
- Exchange mapping (5 tests, case-insensitive)
- Behavior profiles (4 tests)
- Persistence across connections (2 tests)
- Performance baseline (3 tests)

Total: 1276 tests across 50 files, all green, zero regressions.
2026-07-12 12:21:48 +02:00
Codex
7544955634 uv(parity): exit-doctrine parity pass — SL/TP/MAX_HOLD verdict matrix
MAX_HOLD: PARITY (base 250 + 4 modulation branches + bar quantization; fallback
120 loud-only). SL: value PARITY -1.2% (catastrophic-floor override), UV strictly
tighter. TP: NOT AT PARITY — UV 0.35% vs BLUE live 0.20%, no OB modulation
(x1.40/x0.60/x0.75), no TP_FLOOR; UV trailing is a different mechanism. Tie order
divergent (BLUE TP-first, UV SL-first). Price basis+cadence divergent (OBF-mid
per-scan vs BingX-mark 1s). Remediation order proposed, no build without operator.
2026-07-12 12:15:44 +02:00
Codex
019b620ab9 malkhut: asset bridge — directory ↔ classification integration
asset_bridge.py: connects Fable's AssetDirectory (operational layer,
runtime-mutable, JSON-backed listing status) with our AssetProfile
(taxonomic layer, frozen, invariant classification).

Functions:
- sync_asset_to_profile(directory, symbol): sync one asset's TRADING
  exchanges from directory to AssetProfile.exchanges
- sync_exchanges_from_directory(directory): sync all matching assets
- get_universe_stats(directory): matched/unmatched counts

49 tests covering:
- normalize_symbol (7 edge cases)
- ExchangeListing validation (4 tests)
- AssetRecord listing queries (5 tests)
- AssetDirectory CRUD + persistence (14 tests)
- symbols_for_exchange filtering by status (4 tests)
- venue_symbol mapping (3 tests)
- Bridge sync (8 tests with state save/restore)
- Integration with ScenarioFactory + get_assets_on_exchange (4 tests)

Total: 1246 tests across 49 files, all green, zero regressions.
Fable's assets/ package preserved intact, interfaces retained.
2026-07-12 10:45:37 +02:00
Codex
60ffb397e4 malkhut: EXT_CHANGES.md — record of Fable's additive changes for mm_ 2026-07-12 09:28:31 +02:00
Codex
b8cfd5df67 uv(sentinel): live-schema fix rounds 1+2 (PASS8 fb08a9f+361e6de, QA-verified 5/5 live)
Real colnames (timestamp/u_prefix_client_id, anomaly_events.ts), query/VST
errors FAIL never PASS (no green-by-error), openOrders wrapper unwrap,
check(d) CH_ALLOWLIST_DBS attribution (BLUE OBF writer no longer flagged).
Maiden live runs by Fable caught all 6; PASS8 fixed same-night.
2026-07-12 03:28:18 +02:00
Codex
1f709af6d1 malkhut: three-layer identifier architecture for cross-system asset identification
Layer 1 (canonical identity): symbol, base_asset, name, unified_symbol
  (CCXT format), quote_currency
Layer 2 (cross-system): coingecko_id, cmc_id, blockchain, contract_address
Layer 3 (exchange mapping): exchanges tuple

All 13 pre-defined assets migrated with accurate CoinGecko IDs, CMC IDs,
blockchains, and contract addresses (ERC-20 tokens).

7 new query functions: get_asset_by_coingecko_id, get_asset_by_cmc_id,
get_assets_by_base_asset, get_assets_by_blockchain,
get_assets_by_unified_symbol.

33 new tests covering: Layer 1 identity, Layer 2 cross-system identifiers,
identifier query functions, identifier consistency (uniqueness, derivation),
exchange registry.

Total: 1189 tests, 47 files, all green.

Based on research: CCXT BASE/QUOTE is de facto standard, CoinGecko ID
most widely used in crypto-native, ISO 24165 DTI emerging, FIGI for
institutional.
2026-07-12 00:40:14 +02:00
Codex
da61c8f6c2 uv(universe): package-context import fallback — runner imports as prod.clean_arch.violet.uv.*, bare import broke gate load 2026-07-11 23:57:15 +02:00
Codex
df40e62104 dita_v2(zinc): account-truth plane API — publish/read/wait_on/notify_account
Formalizes the CEX-010 E-feed account plane (protocol + InMemoryZincPlane +
real plane). This code flew 33h on UV-PRIME flight-1 via the vendored copy
(T0-DEVIATION mid-edit vendoring) but was never committed upstream — the
2026-07-11 clean vendor_sync regressed it and broke the E-feed at boot
(AttributeError publish_account). Committing the flight-proven bytes closes
the vendor-law gap. Authorship: pre-existing WIP in /mnt working tree
(T0-era, likely codex), committed verbatim by Fable for vendor integrity.
2026-07-11 22:46:33 +02:00
Codex
7a512544b7 uv(audit): §8 addendum — code==0 empty-data hole refinement + fix set landed (7bc13a6e) 2026-07-11 22:41:48 +02:00
Codex
d2d0c5e292 malkhut: multi-exchange asset universe + schema docs
ExchangeProfile: standardized exchange metadata (fees, latency, capabilities).
3 pre-defined exchanges: Binance, BingX, Bybit.
AssetProfile.exchanges: tuple[str] — which venues trade each asset.
New query functions: get_assets_on_exchange, get_common_assets,
get_exchange_for_asset, get_exchange, list_exchanges.

_DATA_STORAGE_SCHEMA_FORMATS.md: comprehensive reference for agent
consumption — data model, storage format, query interfaces, data flow
diagram, enum reference, import patterns for BLUE/VIOLET/UV integration.

README updated: exchange registry section, package structure, subsystems
table.
2026-07-11 22:37:15 +02:00