From 8fc1154dd276831cd1d1824b5badd8e926d78693 Mon Sep 17 00:00:00 2001 From: k9dreamer Date: Wed, 15 Jul 2026 10:57:47 -0400 Subject: [PATCH 1/3] feat(hodlmm-bin-guardian): detect grid-edge pinned pools; distinct PINNED action instead of unpassable slippage HOLD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Field audit F-5 (HIGH). At the grid edge the active bin freezes by contract design while the market moves — pool-vs-market divergence becomes structural and a slippage-gated monitor deadlocks (can neither repair nor exit). Observed live ~36h on dlmm_3, 2026-07-13. No official pinned signal exists in the API surface; detection is derived. Co-Authored-By: Claude Fable 5 --- hodlmm-bin-guardian/SKILL.md | 4 ++++ hodlmm-bin-guardian/hodlmm-bin-guardian.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/hodlmm-bin-guardian/SKILL.md b/hodlmm-bin-guardian/SKILL.md index 42c6964..fd6e1da 100644 --- a/hodlmm-bin-guardian/SKILL.md +++ b/hodlmm-bin-guardian/SKILL.md @@ -232,3 +232,7 @@ All outputs are strict JSON to stdout. Winner of AIBTC x Bitflow Skills Pay the Bills competition. Original author: @cliqueengagements Competition PR: https://github.com/BitflowFinance/bff-skills/pull/39 + +## PINNED detection (2026-07-15 field audit F-5) + +When the pool's active bin is at the grid edge (unsigned 0 or 1000) AND pool-vs-market divergence exceeds the slippage cap, the guardian emits a distinct `PINNED` action (plus `at_grid_edge` / `pinned` data fields) instead of an unpassable slippage HOLD. While pinned, pool price is frozen by contract design and the divergence is structural — do not rebalance or blind-swap; route to the exit/withdraw path (withdraw minimums remain enforceable) or escalate. There is no official pinned signal in the Bitflow API; this is derived from contract behavior. Observed live on dlmm_3 (2026-07-13): 1.4–4.8% structural divergence for ~36h that deadlocked slippage-gated automation. diff --git a/hodlmm-bin-guardian/hodlmm-bin-guardian.ts b/hodlmm-bin-guardian/hodlmm-bin-guardian.ts index 5ee23ab..9922f99 100644 --- a/hodlmm-bin-guardian/hodlmm-bin-guardian.ts +++ b/hodlmm-bin-guardian/hodlmm-bin-guardian.ts @@ -361,9 +361,23 @@ async function runGuardian(wallet?: string, poolId?: string): Promise<{ const canRebalance = refusals.length === 0; + // ── Grid-edge / pinning detection (2026-07-15 field audit F-5) ────────────── + // The DLMM active bin cannot move past the grid edge (dlmm-core: it only + // decrements while bin-id > MIN_BIN_ID, mirrored at MAX). At the edge the + // pool price freezes while the market keeps moving, so pool-vs-market + // "slippage" becomes STRUCTURAL — the slippage gate can never clear + // (observed live: 1.4–4.8% divergence for ~36h on dlmm_3, 2026-07-13, while + // the pool sat at unsigned bin 0). There is no official pinned signal + // anywhere in the Bitflow API surface; this detection is derived. + // Unsigned grid: 0 = raw −500 floor, 1000 = raw +500 ceiling. + const atGridEdge = active_bin_id <= 0 || active_bin_id >= 1000; + const pinned = atGridEdge && !slippageResult.ok; + let action: string; if (inRange === null) { action = `CHECK — ${positionNote}`; + } else if (pinned && !inRange) { + action = `PINNED — pool is at the grid edge (active bin ${active_bin_id}) with structural pool-vs-market divergence ${slippageResult.pct.toFixed(2)}%. The slippage gate cannot clear while pinned. Do NOT rebalance or blind-swap; route to the exit/withdraw path (withdraw minimums remain enforceable while pinned) or escalate to a human.`; } else if (inRange) { action = `HOLD — position in range at active bin ${active_bin_id}. APR (24h): ${apr24h.toFixed(2)}%.`; } else if (!canRebalance) { @@ -378,6 +392,8 @@ async function runGuardian(wallet?: string, poolId?: string): Promise<{ data: { in_range: inRange, active_bin: active_bin_id, + at_grid_edge: atGridEdge, + pinned: pinned, user_bin_range: userBinRange, can_rebalance: canRebalance, refusal_reasons: refusals.length > 0 ? refusals : null, From 85755c71a7ff29a9fd758bfc2299ed13f4e53a1b Mon Sep 17 00:00:00 2001 From: k9dreamer Date: Wed, 15 Jul 2026 11:48:40 -0400 Subject: [PATCH 2/3] review(arc0btc): add PINNED JSON example to SKILL.md; note new fields on existing examples Co-Authored-By: Claude Fable 5 --- hodlmm-bin-guardian/SKILL.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hodlmm-bin-guardian/SKILL.md b/hodlmm-bin-guardian/SKILL.md index fd6e1da..3d444ab 100644 --- a/hodlmm-bin-guardian/SKILL.md +++ b/hodlmm-bin-guardian/SKILL.md @@ -236,3 +236,24 @@ Competition PR: https://github.com/BitflowFinance/bff-skills/pull/39 ## PINNED detection (2026-07-15 field audit F-5) When the pool's active bin is at the grid edge (unsigned 0 or 1000) AND pool-vs-market divergence exceeds the slippage cap, the guardian emits a distinct `PINNED` action (plus `at_grid_edge` / `pinned` data fields) instead of an unpassable slippage HOLD. While pinned, pool price is frozen by contract design and the divergence is structural — do not rebalance or blind-swap; route to the exit/withdraw path (withdraw minimums remain enforceable) or escalate. There is no official pinned signal in the Bitflow API; this is derived from contract behavior. Observed live on dlmm_3 (2026-07-13): 1.4–4.8% structural divergence for ~36h that deadlocked slippage-gated automation. + +### Example PINNED output (fields added 2026-07-15; both `run` examples above predate `at_grid_edge`/`pinned`) + +```json +{ + "status": "success", + "action": "PINNED — pool is at the grid edge (active bin 0) with structural pool-vs-market divergence 2.74%. The slippage gate cannot clear while pinned. Do NOT rebalance or blind-swap; route to the exit/withdraw path (withdraw minimums remain enforceable while pinned) or escalate to a human.", + "data": { + "in_range": false, + "active_bin": 0, + "at_grid_edge": true, + "pinned": true, + "can_rebalance": false, + "refusal_reasons": ["price slippage 2.74% > 0.5% cap"], + "slippage_ok": false, + "slippage_pct": 2.74 + } +} +``` + +Normal (non-pinned) `run` output now also carries `"at_grid_edge": false, "pinned": false`. From 3f38ddaa3e6f300508f5632b2ee14bb2b5a41a75 Mon Sep 17 00:00:00 2001 From: k9dreamer Date: Wed, 15 Jul 2026 12:10:40 -0400 Subject: [PATCH 3/3] review(biwasxyz): update action vocabulary in SKILL.md table + AGENT.md schema; guard PINNED against degraded bins reads; bump version - Docs are the consumer contract for LLM agents: output table now lists PINNED and the at_grid_edge/pinned fields; AGENT.md schema and a PINNED section added. - Degraded-read guard: a bins response missing active_bin_id (defaulted 0) plus a missing price (pool price 0 => fake 100% divergence) previously became a confident false PINNED action recommendation; edge detection now requires the read to verifiably carry the active bin and a nonzero price. - .version 2.1.0 -> 2.2.0. Co-Authored-By: Claude Fable 5 --- hodlmm-bin-guardian/AGENT.md | 8 +++++++- hodlmm-bin-guardian/SKILL.md | 4 +++- hodlmm-bin-guardian/hodlmm-bin-guardian.ts | 11 +++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/hodlmm-bin-guardian/AGENT.md b/hodlmm-bin-guardian/AGENT.md index 332bf8c..d624fa9 100644 --- a/hodlmm-bin-guardian/AGENT.md +++ b/hodlmm-bin-guardian/AGENT.md @@ -41,10 +41,12 @@ Always return strict JSON: ```json { "status": "success | error", - "action": "HOLD | REBALANCE | CHECK | ", + "action": "HOLD | REBALANCE | PINNED | CHECK | ", "data": { "in_range": "boolean | null", "active_bin": "number", + "at_grid_edge": "boolean — active bin at unsigned grid edge (0 or 1000), only when the read verifiably carried it", + "pinned": "boolean — at_grid_edge AND slippage gate failing; pool price is frozen by contract design and divergence is structural", "user_bin_range": "{ min, max, count, bins } | null", "can_rebalance": "boolean", "refusal_reasons": "string[] | null", @@ -70,3 +72,7 @@ Always return strict JSON: "error": "null | { code, message, next }" } ``` + +## PINNED (added 2026-07-15) + +`PINNED` fires when the pool's active bin sits at the grid edge AND the slippage gate is failing — the divergence is structural (pool price frozen by contract design), so the slippage gate can never clear on its own. Do **not** rebalance or blind-swap while pinned; route to the exit/withdraw path (withdraw minimums remain enforceable) or escalate to a human. Guarded against degraded API reads: a bins response missing the active bin or its price cannot produce PINNED. diff --git a/hodlmm-bin-guardian/SKILL.md b/hodlmm-bin-guardian/SKILL.md index 3d444ab..c2bce3f 100644 --- a/hodlmm-bin-guardian/SKILL.md +++ b/hodlmm-bin-guardian/SKILL.md @@ -159,9 +159,11 @@ All outputs are strict JSON to stdout. | Field | Type | Description | |---|---|---| | `status` | `"success" \| "error"` | Overall result | -| `action` | `string` | `HOLD`, `REBALANCE`, or `CHECK` with reason | +| `action` | `string` | `HOLD`, `REBALANCE`, `PINNED`, or `CHECK` with reason | | `data.in_range` | `boolean \| null` | `null` if no wallet provided | | `data.active_bin` | `number` | Pool's current active bin ID | +| `data.at_grid_edge` | `boolean` | Active bin at the grid edge (unsigned 0 or 1000); only true when the bins read verifiably carried the active bin | +| `data.pinned` | `boolean` | At grid edge AND slippage gate failing — structural divergence; see PINNED | | `data.user_bin_range` | `{min,max,count,bins} \| null` | User's liquidity bin range | | `data.can_rebalance` | `boolean` | Whether all safety gates pass | | `data.refusal_reasons` | `string[] \| null` | Why REBALANCE is blocked | diff --git a/hodlmm-bin-guardian/hodlmm-bin-guardian.ts b/hodlmm-bin-guardian/hodlmm-bin-guardian.ts index 9922f99..1f124f7 100644 --- a/hodlmm-bin-guardian/hodlmm-bin-guardian.ts +++ b/hodlmm-bin-guardian/hodlmm-bin-guardian.ts @@ -370,7 +370,14 @@ async function runGuardian(wallet?: string, poolId?: string): Promise<{ // the pool sat at unsigned bin 0). There is no official pinned signal // anywhere in the Bitflow API surface; this detection is derived. // Unsigned grid: 0 = raw −500 floor, 1000 = raw +500 ceiling. - const atGridEdge = active_bin_id <= 0 || active_bin_id >= 1000; + // Degraded-read guard (reviewer catch): active_bin_id defaults to 0 when the + // bins response is missing the field, and a missing bin price makes pool + // price 0 => 100% fake "divergence" — which would manufacture a confident + // false PINNED (an action recommendation) out of a bad read. Only trust the + // edge test when the response actually carries the active bin and a price + // for it. + const activeBinReadOk = priceByBinId.has(active_bin_id) && (priceByBinId.get(active_bin_id) ?? 0) > 0; + const atGridEdge = activeBinReadOk && (active_bin_id <= 0 || active_bin_id >= 1000); const pinned = atGridEdge && !slippageResult.ok; let action: string; @@ -427,7 +434,7 @@ const program = new Command(); program .name("hodlmm-bin-guardian") .description("Monitor Bitflow HODLMM bins and output LP health status") - .version("2.1.0"); + .version("2.2.0"); program .command("doctor")