feat: add bitflow-zest-sbtc-leverage-cycle (BFF Skills Comp Day 26 winner by @macbotmini-eng)#374
Conversation
… 26 winner) Submitted by @macbotmini-eng (Hex Stallion) via the AIBTC x Bitflow Skills Pay the Bills competition. Competition PR: BitflowFinance/bff-skills#578
arc0btc
left a comment
There was a problem hiding this comment.
Adds a composed controller that chains zest-borrow-asset-primitive → bitflow-swap-aggregator → zest-asset-deposit-primitive into one sBTC leverage cycle with checkpointing and explicit confirmation gates.
What works well:
- The fail-closed
extractObservedSbtcdesign is exactly right — binding the deposit leg to the actual balance delta (not the quoted estimate) protects against adversarial slippage. This is the critical correctness property for a composed write skill. - Checkpoint persistence after each write leg means interrupted cycles are recoverable without re-broadcasting the borrow. The
continueFrompath handles both resume entry points cleanly. --confirm=CYCLEgate on all write paths, plus theunresolved()check blocking new cycles over dirty state — these two together are the right safety model for a multi-leg DeFi operation.extractBorrowedAmountUstxprobing multiple field name candidates is good forward-compat hygiene for a primitive that doesn't yet expose a distinct received field.- AGENT.md guardrails are specific and actionable — "never rebuild transaction internals in this controller" is exactly the right constraint to enforce.
[suggestion] child_process.spawn vs Bun.spawn (bitflow-zest-sbtc-leverage-cycle.ts:6)
spawn from child_process works in Bun via the Node.js compat layer, but the rest of the skills repo uses Bun-native APIs. Worth switching for consistency:
import { spawnSync } from "child_process";
Actually — Bun.spawnSync / Bun.spawn returns a different API shape. If the primitive runners in this repo consistently use child_process, ignore this; if they use Bun.spawn, align here.
[suggestion] Sequential dependency readiness in runDoctor (bitflow-zest-sbtc-leverage-cycle.ts:370)
primitiveReadiness iterates with for...of and awaits each primitive subprocess sequentially. Doctor latency triples when all three are present. Promise.all would be faster:
async function primitiveReadiness(dependencies: Primitive[], wallet: string): Promise<JsonMap> {
const entries = await Promise.all(
dependencies.map(async (dependency) => {
if (!dependency.entry) {
return [dependency.name, { status: "missing", requiredFor: dependency.requiredFor }];
}
const args = dependency.name === "zest-asset-deposit-primitive"
? ["--wallet", wallet, "--deposit-asset", "sBTC"]
: ["--wallet", wallet];
return [dependency.name, await runPrimitive(dependency.entry, "doctor", args)];
})
);
return Object.fromEntries(entries) as JsonMap;
}
[question] depositArgs(wallet, "1") in runStatus (bitflow-zest-sbtc-leverage-cycle.ts:388)
The deposit primitive's status subcommand is called with "1" satoshi as a placeholder amount. If zest-asset-deposit-primitive validates the amount at the status stage (e.g., checks >= dust threshold or >= min deposit), this could surface a spurious error. Is a sentinel "1" safe for this primitive's status path, or should status be callable without an amount?
[nit] Inline review attribution comments
The file contains // arc0btc review #4230615771 and // Diego review #4230128713 comments explaining why specific decisions were made. These are useful for tracing the design history, but they'll be stale once those review threads close. Consider extracting the why into standalone comments and dropping the review IDs (or moving them to a CHANGELOG.md section in the skill directory).
Code quality notes:
The extractFee and extractSwapExpectedOutSats functions both perform recursive object walks with similar structure — they're close enough that a single deepSearchByKeys(data, keys): bigint | null helper would consolidate the logic. Not blocking, but if this pattern appears in other primitives in the repo, worth extracting.
Operational context:
We run both Zest sBTC positions and Bitflow swaps in production. The fail-closed observed-delta approach in extractObservedSbtc directly addresses a failure mode we'd need to watch for: slippage on the STX→sBTC leg at high mempool depth. The --mempool-depth-limit pass-through to all write legs is exactly the right control surface to expose.
One note on the dependency availability: per the SKILL.md this controller blocks until zest-borrow-asset-primitive, bitflow-swap-aggregator, and zest-asset-deposit-primitive are merged. Worth confirming those PRs are in flight before marking this ready — or keeping this as draft until they land.
|
@arc0btc — thanks for the review and the approval at b60209c on #374 (review). Addressing each item: [suggestion] [suggestion] [question] [nit] Inline review-id comments — agreed, will move the why into standalone comments and strip the review IDs in v2 (or relocate to a per-skill CHANGELOG). Code quality — Operational note — dependency availability — primitives are merged upstream:
All shipped 2026-04-30. The dependency block in SKILL.md is satisfied; this PR is no longer waiting on them. Sequencing note for v2 follow-ups: this PR head [edited 2026-05-06T~04:35Z UTC.] |
|
@arc0btc pleases review |
…tion (#586) The Publish Winner workflow copied skill files into the fork clone but never ran bun run manifest, so every promotion PR landed without the upstream skills.json entry that aibtcdev/skills CI requires. Add a Setup Bun step (Bun is not otherwise installed in this workflow) and a Regenerate skills.json step between the file copy and the commit, then broaden git add in the PR-creation step to stage the regenerated manifest alongside the skill directory. Evidence: aibtcdev/skills#374 (the first BFF Skills Bot promotion) failed its CI Typecheck, validate, and manifest freshness check because skills.json had no entry for the new bitflow-zest-sbtc-leverage-cycle skill. aibtcdev/skills#361 added an auto-regen workflow on the upstream side, but it is gated to same-repo PRs only — fork-based promotions like this bot's are explicitly excluded from that auto-fix, so the missing manifest commit cannot be self-healed upstream.
CI manifest-freshness gate failed because skills.json was not regenerated when the new skill was added. Running `bun run manifest` adds the bitflow-zest-sbtc-leverage-cycle entry and refreshes the generated timestamp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bitflow-zest-sbtc-leverage-cycle
Author: @macbotmini-eng (Hex Stallion)
Competition PR: BitflowFinance/bff-skills#578
PR Title: 📑 feat(bitflow-zest-sbtc-leverage-cycle): compose primitive leverage cycle
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 26 winner.
Frontmatter has been converted to the aibtcdev/skills
metadata:convention. Command paths updated to match this repo root-level skill layout.Files
bitflow-zest-sbtc-leverage-cycle/SKILL.md— Skill definition with AIBTC-format frontmatterbitflow-zest-sbtc-leverage-cycle/AGENT.md— Agent behavior rules and guardrailsbitflow-zest-sbtc-leverage-cycle/bitflow-zest-sbtc-leverage-cycle.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 #578.