PINK: docs v7 + reset_and_seed startup fix — 451/451 tests green

- SYSTEM_BIBLE.md → v7.0: documents fee-sign fix (Defect A), opening-fee
  fix (Defect B), WARN-unfreeze, orphan prevention, reset_and_seed startup,
  and vel_div env-override.
- CAPITAL_BOOKKEEPING_DESIGN.md: status updated to PHASE-1 BUGFIXES APPLIED;
  sections 8.1-8.4 (applied fixes + 34-test coverage) were already present.
- rust_backend.py: expose dita_kernel_reset_and_seed() via _RustKernelLib +
  ExecutionKernel.reset_and_seed(); zeros stale K-accumulators at startup so
  K=E=live_capital → delta=0 → capital_frozen=False on every clean restart.
- pink_direct.py: call kernel.reset_and_seed(live_capital) after
  _restore_kernel_snapshot() so BingX is always the ledger of record.
- launch_dolphin_pink.py: DOLPHIN_PINK_VEL_DIV_THRESHOLD env-var override
  for on-exchange debugging; BLUE unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-08 12:33:50 +02:00
parent e38ec77221
commit 0eac51d2e9
5 changed files with 2470 additions and 7 deletions

View File

@@ -1,7 +1,7 @@
# PINK Capital & Trading Bookkeeping Refactor — Design Spec
**Status**: DESIGN (pre-implementation)
**Date**: 2026-06-07
**Status**: PHASE-1 BUGFIXES APPLIED (2026-06-08) — fee sign + opening-fee + WARN-unfreeze all fixed and green (34/34 tests). Multi-phase bookkeeping refactor remains pending.
**Date**: 2026-06-07 (design); 2026-06-08 (critical patch applied)
**Author**: Crush AI, per PINK operator directive
**Scope**: Refactor PINK to use DITAv2 kernel's accounting as the single bookkeeping authority, eliminate double-accounting, maintain BLUE observability compatibility

View File

@@ -174,6 +174,8 @@ class _RustKernelLib:
self.lib.dita_kernel_snapshot_json.restype = ctypes.c_void_p
self.lib.dita_kernel_set_seed_capital.argtypes = [ctypes.c_void_p, ctypes.c_double]
self.lib.dita_kernel_set_seed_capital.restype = ctypes.c_int
self.lib.dita_kernel_reset_and_seed.argtypes = [ctypes.c_void_p, ctypes.c_double]
self.lib.dita_kernel_reset_and_seed.restype = ctypes.c_int
self.lib.dita_kernel_set_exchange_config_json.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
self.lib.dita_kernel_set_exchange_config_json.restype = ctypes.c_int
self.lib.dita_kernel_calibrate_fee_json.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
@@ -293,6 +295,10 @@ class _RustKernelLib:
rc = self.lib.dita_kernel_set_seed_capital(handle, ctypes.c_double(seed))
return rc == 0
def reset_and_seed(self, handle: ctypes.c_void_p, capital: float) -> bool:
rc = self.lib.dita_kernel_reset_and_seed(handle, ctypes.c_double(capital))
return rc == 0
def set_exchange_config(self, handle: ctypes.c_void_p, config: Dict[str, Any]) -> bool:
encoded = _to_rust_bytes(config)
rc = self.lib.dita_kernel_set_exchange_config_json(handle, ctypes.c_char_p(encoded))
@@ -1071,6 +1077,15 @@ class ExecutionKernel:
"""Set the kernel's seed capital for K-value fold. Call once at init."""
_get_rust().set_seed_capital(self._backend, float(seed))
def reset_and_seed(self, capital: float) -> None:
"""Reset K-accumulators and re-seed from live exchange balance.
Replaces set_seed_capital() at the end of connect(): zeros k_realized_pnl,
all fee counters, and k_funding_net so K = E = capital → delta = 0 → unfrozen.
Preserves seen_account_event_ids (WS replay dedup) and fee calibration.
"""
_get_rust().reset_and_seed(self._backend, float(capital))
def set_exchange_config(self, config: Dict[str, Any]) -> None:
"""
Load the exchange fee schedule into the kernel's fee prediction model.

View File

@@ -321,10 +321,14 @@ class PinkDirectRuntime:
self.kernel.set_seed_capital(live_capital)
await self._seed_account_from_exchange()
# Restore fee calibration + account state from the previous session if the
# kernel was flat at save time. Must be AFTER set_seed_capital and reconcile
# so the snapshot can override our fresh seed with the last-known calibration.
# Restore fee calibration from the previous session if the kernel was flat
# at save time. Must be AFTER set_seed_capital so the snapshot can carry
# forward fee model parameters. Re-apply live_capital immediately after to
# ensure BingX is the ledger of record for capital — the snapshot's capital
# is stale (it reflects the exchange balance at the PREVIOUS session's last
# fill), whereas live_capital was just fetched from BingX right now.
_restore_kernel_snapshot(self.kernel, self.logger)
self.kernel.reset_and_seed(live_capital) # zeros stale accumulators; K=E=live_capital
# Start WS account stream (primary); poll failover handled inside stream.
self._account_stream_task = asyncio.create_task(