feat: add bitflow-hodlmm-zest-yield-loop (BFF Skills Comp Day 27 winner by @macbotmini-eng)#375
Conversation
arc0btc
left a comment
There was a problem hiding this comment.
Composed HODLMM-Zest yield-routing controller with checkpoint state — this is good infrastructure work. The safety framing is honest: only `idle-to-hodlmm` executes in v1; all Zest write routes block explicitly with clear `ZEST_CONFIRMED_WRITE_NOT_VERIFIED` codes rather than pretending to work. The checkpoint pattern (write-before-confirm, atomic rename via temp file) is solid and matches what we need for multi-leg DeFi writes.
What works well:
- Checkpoint durability: atomic write via `${finalPath}.${pid}.${Date.now()}.tmp` → rename. Exactly right for interrupted write recovery.
- `runPrimitive` enforces the single-JSON-object output contract and handles edge cases (empty stdout, non-zero exit without error status, timeout with SIGTERM).
- `checkpointPath` sanitizes wallet address before using it as a filename — no path traversal.
- The `CONFIRM_TOKEN = "ROUTE"` gate on both `run` and `resume` is enforced consistently.
- Economic gates for `idle-to-hodlmm`: APY-edge, freshness, and break-even are now live checks against the Bitflow API, not just echoed flags. The `HODLMM_DEPOSIT_GAS_SATS_APPROX` comment explaining the sats/uSTX unit mismatch fix is valuable history.
[blocking] `what-to-do/bitflow-hodlmm-zest-yield-loop.md` contradicts the controller's scope
The guide description says "capturing yield on both sides with… Zest borrow" and the prerequisites section references a Zest borrow leg. But `SKILL.md`, `AGENT.md`, and the code all explicitly state: "It does not borrow, create leverage, repay, or unwind debt." The Zest routes are blocked in v1 — there is no Zest borrow execution path.
A `what-to-do` guide describing what the skill actually does now, not aspirational v2 behavior:
description: Route idle sBTC into a HODLMM DLMM LP position, with optional Zest-side routing when the Zest write surface is verified. Enforces APY-edge and breakeven gates before broadcast.
The Zest borrow prerequisites block should either be removed or clearly marked as "future — not available in v1."
[suggestion] Redundant Bitflow API call in `buildPlan`
For an `idle-to-hodlmm` route, `detectSbtcSide` calls `BITFLOW_APP_POOLS_API` at line ~630, and then `fetchHodlmmPoolUniverse` calls the same URL at line ~670. That's two requests to the same endpoint with the same data. The universe already contains the token side — `detectSbtcSide` could accept the pre-fetched universe or the controller could defer the side check until after the universe fetch:
// In buildPlan, after fetchHodlmmPoolUniverse:
const poolEntry = poolUniverse.find((p) => p.poolId === opts.poolId);
if (poolEntry) {
context.hodlmmPoolCheck = { poolId: opts.poolId, sbtcSide: poolEntry.sbtcSide, ok: poolEntry.sbtcSide !== null };
} else {
// fall through to detectSbtcSide only if pool wasn't in universe
}
Not blocking — the duplicate call adds ~20ms round trip — but worth cleaning up before the next route type lands.
[suggestion] `buildPlan` mutates the `opts` input
opts.poolId = best.poolId;
opts.sbtcSide = opts.sbtcSide || best.sbtcSide || "auto";This mutates the caller's options object in place. The auto-pick is recorded in `economicCheck.autoPickedPoolId` already — callers reading `opts.poolId` after the call will silently see a different value than what they passed. Return the resolved pool/side alongside the plan instead of mutating input.
[suggestion] `isAllowedFirstTimeHodlmmDepositPreview` has a side effect
The function mutates `context.firstTimeHodlmmDeposit` as a side effect inside what reads like a predicate. Side effects inside condition checks are easy to miss. Extract the context write to the caller in `collectPreviewBlockers`.
[question] `zestStatusArgs()` passes `"--action=status"` as a flag to the `"run"` subcommand
preview.zestStatus = await runPrimitive(zest.entry!, "run", zestStatusArgs(), wallet, 90_000)This spawns `bun run run --action=status`. If `zest-yield-manager` uses Commander subcommands (like other skills), the subcommand should be `"status"` not `"run"`. This code path is unreachable in v1 (Zest routes are blocked), but worth confirming the correct shape before the next version unlocks them.
[nit] `breakevenBound = 30` is a magic constant inside `buildEconomicCheck`. Given every other threshold has a `DEFAULT_` constant and is `--flag` overridable, this one stands out. Consider `DEFAULT_BREAKEVEN_BOUND_DAYS = 30` and a `--breakeven-bound-days` option.
Operational note: We run `hodlmm-move-liquidity` in production and the atomic `move-relative-liquidity-multi` path is stable. The `--confirm` gate pattern in that skill is what this controller correctly extends to the composed layer. The `dependencyReport` approach (checking file existence at `skills//.ts` or `/.ts`) will correctly find our installed `hodlmm-move-liquidity` instance.
…7 winner) Submitted by @macbotmini-eng (Hex Stallion) via the AIBTC x Bitflow Skills Pay the Bills competition. Competition PR: BitflowFinance/bff-skills#582
e8e57fe to
7feeb51
Compare
bitflow-hodlmm-zest-yield-loop
Author: @macbotmini-eng (Hex Stallion)
Competition PR: BitflowFinance/bff-skills#582
PR Title: 📑 PR: feat(bitflow-hodlmm-zest-yield-loop): compose HODLMM-Zest route controller
This skill was submitted to the AIBTC x Bitflow Skills Pay the Bills competition, reviewed by judging agents and the human panel, and approved as a Day 27 winner.
Frontmatter has been converted to the aibtcdev/skills
metadata:convention. Command paths updated to match this repo root-level skill layout.Files
bitflow-hodlmm-zest-yield-loop/SKILL.md— Skill definition with AIBTC-format frontmatterbitflow-hodlmm-zest-yield-loop/AGENT.md— Agent behavior rules and guardrailsbitflow-hodlmm-zest-yield-loop/bitflow-hodlmm-zest-yield-loop.ts— TypeScript implementationAttribution
Original author: @macbotmini-eng. The
metadata.authorfield in SKILL.md preserves their attribution permanently.Automated by BFF Skills Bot on merge of PR #582.