feat(hodlmm-risk): add HODLMM volatility risk monitoring skill#4
feat(hodlmm-risk): add HODLMM volatility risk monitoring skill#4sonic-mast wants to merge 112 commits into
Conversation
* feat: add nostr skill — protocol operations for AI agents Adds nostr skill with 7 subcommands: - post: Post kind:1 notes to relays (requires wallet) - read-feed: Read recent notes from relays - search-tags: Search by hashtag using NIP-12 #t filter - get-profile: Get kind:0 profile metadata - set-profile: Set kind:0 profile metadata (requires wallet) - get-pubkey: Derive Nostr pubkey via NIP-06 from BIP84 path - relay-list: List configured relay URLs Key derivation uses BIP84 m/84'/0'/0'/0/0 — same secp256k1 keypair as the BTC wallet. Uses nostr-tools + ws packages. * fix: address review feedback on nostr skill PR aibtcdev#73 - Rename 'NIP-06' references to 'BTC-shared key derivation' — we use m/84'/0'/0'/0/0 (BIP84), not m/44'/1237'/0'/0/0 (NIP-06). This is intentional (shared BTC+Nostr identity) but labeling was inaccurate. - Fix publishToRelays timeout race — pool.publish() returns Promise[] in nostr-tools v2+, so Promise.race received an array (non-thenable) and resolved immediately. Now spreads the array properly. - Fix set-profile field wipe — kind:0 is replaceable, so publishing with only --name would delete about/picture/etc. Now fetches existing profile and merges before publishing. Co-reviewed-by: arc0btc * chore: regenerate skills.json manifest --------- Co-authored-by: cocoa007 <cocoa007@users.noreply.github.com>
Add scan-project-board.md to what-to-do/ with a 6-step workflow: fetch open projects, match capabilities, claim, do work, report to founder, and update the board. Integrates into the autonomous loop Phase 2 (Observe) on a recommended every-5th-cycle cadence. Also updates setup-autonomous-loop.md Phase 2 table and See Also to reference the new skill, and adds it to INDEX.md. Closes aibtcdev#28 Co-authored-by: JackBinswitch-btc <JackBinswitch-btc@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: warmidris <265621832+warmidris@users.noreply.github.com>
* feat(dual-stacking): add Dual Stacking enrollment skill Adds a new skill for enrolling in Dual Stacking — earn BTC-denominated rewards (paid in sBTC) by simply holding sBTC. No lockup required. Contract: SP1HFCRKEJ8BYW4D0E3FAWHFDX8A25PPAA83HWWZ9.dual-stacking-v2_0_4 Subcommands: - check-status [--address]: enrollment state, APR range, min amount, cycle overview - enroll [--reward-address]: enroll in dual stacking (wallet required) - opt-out: opt out of dual stacking (wallet required) - get-rewards --cycle N [--address] [--rollback]: earned rewards for a cycle APR: ~0.5% APY (sBTC only) up to ~5% APY with stacked STX (10x multiplier) Minimum: 10,000 sats sBTC (0.0001 sBTC) * fix: remove invalid tags from dual-stacking SKILL.md * fix: address arc0btc review — parse cycleOverview, fix ClarityValue type, sync skills.json tags * fix: sync SKILL.md output schema with actual code, add trailing newline to skills.json - cycleOverview fields corrected: currentCycleId, snapshotIndex, snapshotsPerCycle (was incorrect: currentCycle, totalEnrolled, totalSbtcLocked) - apr output example now includes 'note' field matching code output - skills.json: add missing trailing newline Addresses review feedback from arc0btc and JackBinswitch-btc --------- Co-authored-by: sonic-mast <sonic-mast@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
) * feat(styx): add BTC→sBTC conversion skill via Styx protocol Headless BTC→sBTC deposits using @faktoryfun/styx-sdk: - pool-status, pools, fees, price (read-only queries) - deposit (full flow: reserve → build PSBT → sign → broadcast → update) - status, history (deposit tracking) Uses @scure/btc-signer for local PSBT construction and signing, mempool.space for broadcast. No browser wallet required. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(styx): add required YAML frontmatter to AGENT.md CI validator requires name, skill, and description fields in AGENT.md frontmatter. Missing these caused the validate step to fail. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(styx): add allowUnknownOutputs flag and fix OP_RETURN script handling - Enable allowUnknownOutputs flag in Transaction to properly handle OP_RETURN outputs - Fix OP_RETURN script decoding: SDK provides already-formatted script hex, don't re-encode - Add clarifying comment on opReturnData format Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * fix(styx): add ordinal protection, input validation, and status update retry - Filter ordinal UTXOs on mainnet via OrdinalIndexer to prevent destroying inscriptions (same pattern as btc/btc.ts and sbtc-deposit.service.ts) - Remove unused MAX_DEPOSIT_SATS import - Validate --fee priority against allowed values before casting - Use Math.round instead of Math.floor for float-to-sats conversion - Consolidate btcAmount conversion to single .toFixed(8) via parseFloat - Add retry on updateDepositStatus failure with recovery info output - Fix status command: use else-if chain instead of non-null assertion - Fix history command: explicit null check instead of null-dereference - Add network field to all subcommand outputs for consistency - Remove unused txid variable (broadcastTxid is the canonical reference) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(styx): address Copilot review feedback - Validate --btc-sender matches active wallet before reserving liquidity - Recompute change amount after filtering ordinal UTXOs to keep tx balanced - Merge status update warning into success JSON (single stdout object) - Cancel deposit reservation on post-reservation failure (best-effort cleanup) - Fix SKILL.md "How It Works" step 3 to match actual flow (no SDK-provided PSBT) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…nce (aibtcdev#85) Styx protocol requires the OP_RETURN output at index 0, but it was being added after the deposit output (index 1). This caused deposit tracking failures. Swap output ordering so OP_RETURN is added first. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add author attribution to skill frontmatter Add `author` (GitHub username) and `author_agent` (agent display name) fields to the SKILL.md frontmatter spec. This enables aibtc.com/skills to show who built each skill, turning skill-building into a reputation play. Changes: - CONTRIBUTING.md: document author and author_agent fields in frontmatter spec - scripts/generate-manifest.ts: parse and include author fields in skills.json - 5 existing SKILL.md files updated with actual authors from git history: - ceo: arc0btc / Trustless Indra - business-dev: pbtc21 / Tiny Marten - nostr: cocoa007 - wallet: whoabuddy / Trustless Indra - bitflow: whoabuddy / Trustless Indra - skills.json: regenerated with author metadata Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback on author attribution - CONTRIBUTING.md: clarify author field is "required for new skills" not universally required - skills.json: regenerate via bun run manifest (timestamp update only) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
* feat(scripts): add skill scaffolding script for new contributors Adds `bun run scaffold <skill-name>` which generates a complete skill directory with SKILL.md (frontmatter + docs template), AGENT.md (delegation rules template), and a Commander CLI entry file with printJson/handleError boilerplate. Validates kebab-case naming and prevents overwriting existing skills. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(scaffold): use empty defaults, add author fields, cleanup - Change requires/tags from hardcoded [wallet]/[l2] to empty [] with guidance in generated markdown body for contributors to fill in - Add author and author_agent placeholder fields to SKILL.md template - Remove unused kebabToCamel helper and programName variable - Use node: import prefix for consistency with other scripts - Replace emoji in console output with plain text Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
Add new onboarding skill for first-hour AIBTC setup automation with doctor, install-packs, and run subcommands. Supports optional registration + heartbeat check-in and curated skill-pack installs. Includes onboarding/SKILL.md, AGENT.md, onboarding.ts, workflow guide, signing.ts unlockWalletFromOptions helper, author attribution, and regenerated skills.json. Safety: wallet password flows via AIBTC_WALLET_PASSWORD env var (not CLI argv), finance pack is opt-in, community step is non-blocking. Co-Authored-By: k9dreamer <k9dreamer@gmail.com>
…v#92) Extends the nostr skill with two new subcommands for broadcasting aibtc.news signals to the Nostr network: - amplify-signal: fetch a signal by ID from aibtc.news and broadcast it as a formatted kind:1 note (auto-tags: #bitcoin, #aibtcnews, #nostr) - amplify-text: broadcast signal content directly without an API fetch Both commands use the BTC-shared key derivation (same identity as post), publish to the default relay set, and support --relays override. Updates SKILL.md, AGENT.md, and skills.json accordingly. Co-authored-by: Sonic Mast <sonic-mast@aibtc.dev>
aibtcdev#82) * feat: add yield-dashboard skill — cross-protocol DeFi yield aggregator Adds a read-only yield dashboard skill that aggregates DeFi positions across Zest Protocol, ALEX DEX, Bitflow, and STX stacking. Subcommands: - overview: total portfolio value, weighted APY, per-protocol breakdown - positions: detailed per-protocol position data - apy-breakdown: current APY rates across all protocols (pure market data) - rebalance: allocation suggestions based on risk-adjusted yield Uses on-chain read-only contract calls via Hiro API. No transactions, no API keys required. * fix: address review feedback — ESM imports, unit separation, aBTC label - Move standardPrincipalCV to top-level ES import (was inline require()) - Add valueUnit field to ProtocolPosition interface - Separate sats vs microSTX in overview output (no more mixed units) - Rename ALEX asset label from sBTC/STX to aBTC/STX (accurate trust model) - Add Known Limitations section to SKILL.md - Document Bitflow API fallback behavior * fix: CI tag, positions unit display, cleanup per review - tags: read → read-only (CI validation fix) - positions command: separate sats/microSTX display (was showing microSTX as BTC) - ALEX + stacking: apySource = 'static estimate, not live' - Remove unnecessary IIFE in Zest reader - Remove unused ZEST_V2_REWARDS constant * fix(yield-dashboard): regenerate skills.json manifest Run `bun run manifest` to include the yield-dashboard skill entry in skills.json, fixing the CI manifest freshness check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: cocoa007 <cocoa007@users.noreply.github.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(ordinals-p2p): add P2P ordinals trading skill via trade ledger Agent-to-agent ordinals trading CLI for ledger.drx4.xyz: - create-offer, counter, transfer, cancel, psbt-swap write operations - list-trades, get-trade, my-trades, agents read operations - BIP-137 authenticated writes with replay protection - Full SKILL.md + AGENT.md documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address review feedback on ordinals-p2p skill - Fix BIP-137 signing: use `as any` for format:"recovered" (v2 API supports it but types don't expose it) - Fix SKILL.md: BIP-322 → BIP-137 to match actual implementation - Make --tx-hash optional on transfer (supports sBTC/off-chain) - Add --address flag to my-trades (read-only without wallet) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add frontmatter to AGENT.md for CI validation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ordinals-p2p): use correct @noble/curves Signature API for BIP-137 secp256k1.sign() returns a Signature object with .recovery and .toCompactRawBytes(), not a raw byte array. The "format: recovered" option does not exist in @noble/curves. Fixes blocking review feedback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ordinals-p2p): address review suggestions - my-trades: graceful fallback when wallet locked without --address - Add parseIntSafe() to validate amount/parent args (NaN guard) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use @noble/hashes for SHA-256, add btcPrivateKey type guard Addresses review feedback: 1. Replace hashSha256Sync with @noble/hashes/sha256 for guaranteed Uint8Array output (no hex string ambiguity) 2. Add ensureBytes() guard on btcPrivateKey to handle both Uint8Array and hex string from wallet-manager 3. Import hexToBytes from @noble/hashes/utils Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat: multi-author support and full author attribution (aibtcdev#95, aibtcdev#93) Add bracket-list syntax for author/author_agent fields in SKILL.md frontmatter, with validation for parallel array lengths. Backfill author attribution across all 35 skills based on PR merge history. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ceo): correct author attribution to pbtc21/Tiny Marten Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…btcdev#102) * refactor(wallet): improve AGENT.md structure and fix null-assertion pattern Add five standard sections to AGENT.md: prerequisites, decision logic (table), safety checks, error handling (table), and output handling. This structure enables downstream agents to understand the skill without reading the full SKILL.md documentation. In wallet.ts, replace the `activeId!` non-null assertion pattern in unlock, export, and rotate-password with a safe `?? await` resolution followed by an early `return` after handleError. This removes TypeScript non-null assertions at runtime error boundaries. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(credentials): improve AGENT.md structure and fix parseAsync inconsistency Add five standard sections to AGENT.md: prerequisites, decision logic (table), safety checks, error handling (table), and output handling. Consistent structure across all infrastructure skill AGENT.md files enables agents to reason about skill selection and chaining. Change program.parseAsync to program.parse for consistency with wallet.ts and settings.ts — Commander.js handles async action handlers correctly with synchronous parse, making parseAsync unnecessary here. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(settings): improve AGENT.md structure with standard sections Add five standard sections to AGENT.md: prerequisites, decision logic (table), safety checks, error handling (table), and output handling. The settings skill has the most subcommands of the three infrastructure skills — the decision logic table makes subcommand selection clear for agents choosing between hiro API key vs stacks URL vs relay health checks. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(btc): standardize AGENT.md to 5-section format Rewrote AGENT.md to match the Phase 1 canonical structure: - Added Prerequisites section covering wallet unlock and mainnet constraints - Added Decision Logic table covering all 7 subcommands - Added Safety Checks with UTXO type, balance, and address verification - Added Error Handling table with exact error strings and fixes - Added Output Handling documenting key fields for downstream use - Fixed example invocation (--to → --recipient to match actual CLI flag) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ordinals): standardize AGENT.md to 5-section format Rewrote AGENT.md to match the Phase 1 canonical structure: - Added Prerequisites covering wallet unlock, BTC balance, and base64 encoding requirement - Added Decision Logic table covering all 5 subcommands - Added Safety Checks emphasizing two-step commit/reveal workflow and UTXO protection - Added Error Handling table with exact error strings from ordinals.ts - Added Output Handling documenting critical fields (commitTxid, revealAmount, feeRate) - Fixed example invocations (--content → --content-base64 to match actual CLI flags) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ordinals-p2p): standardize AGENT.md and fix non-null assertion AGENT.md: - Fixed frontmatter name field (ordinals-p2p → ordinals-p2p-agent) - Converted prose Decision Logic to proper table format covering all 9 subcommands - Expanded Error Handling table with Cause column and exact HTTP error messages - Added Output Handling section documenting trade.id extraction and status transitions - Added Example Invocations section with 3 bun run examples ordinals-p2p.ts: - Replaced non-null assertion (btcAddress!) with explicit null check and early return to match the null-safe pattern established in Phase 1 PATTERNS.md Co-Authored-By: Claude <noreply@anthropic.com> * refactor(taproot-multisig): standardize AGENT.md to 5-section format Rewrote AGENT.md from a long step-by-step guide to the canonical 5-section format while preserving all critical technical content: - Added concise intro paragraph with mainnet proof references - Added Prerequisites section (wallet unlock, signing skill dependency, mainnet note) - Added Decision Logic table for all 3 subcommands plus signing skill delegation - Added Safety Checks emphasizing internal vs tweaked key gotcha and blind-sign review - Added Error Handling table with exact error strings and resolution steps - Added Output Handling documenting internalPubKey sharing and isValid check - Preserved the critical BIP-86 internal vs tweaked key warning in Safety Checks - Kept 3 concise Example Invocations covering the main workflow steps Co-Authored-By: Claude <noreply@anthropic.com> * refactor(stx): standardize AGENT.md to 5-section format Rewrites the stx AGENT.md to include all required sections from PATTERNS.md: Prerequisites, Decision Logic table, Safety Checks, Error Handling table, and Output Handling. Previous file used Capabilities/When to Delegate/Key Constraints structure that blocked downstream agents from mapping errors to fixes or understanding which fields to extract. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(tokens): standardize AGENT.md and simplify address resolution Rewrites tokens AGENT.md with the 5-section format from PATTERNS.md: Prerequisites, Decision Logic table, Safety Checks, Error Handling table, and Output Handling. Adds safety guidance on checking decimals before specifying amounts, and verifying balance before transfer. Also simplifies the if/else address resolution blocks in get-balance and list-user-tokens to use the nullish coalescing pattern consistently with other skills in the codebase. Fixes the example invocation which used --to instead of --recipient. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(nft): standardize AGENT.md and simplify address resolution Rewrites nft AGENT.md with the 5-section format from PATTERNS.md: Prerequisites, Decision Logic table, Safety Checks, Error Handling table, and Output Handling. Adds ownership verification check before transfer and clarifies token ID format expectations. Simplifies the if/else address resolution block in get-holdings to use the nullish coalescing pattern. Fixes the example invocation which used --to instead of --recipient. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(bns): standardize AGENT.md and remove unused import Rewrites bns AGENT.md with the 5-section format from PATTERNS.md: Prerequisites, Decision Logic table, Safety Checks, Error Handling table, and Output Handling. Adds critical guidance on saving the preorder salt, waiting for confirmation between steps, and preferring claim-fast. Removes the unused getWalletManager import from bns.ts — only getAccount and getWalletAddress from x402.service were actually used. Co-Authored-By: Claude <noreply@anthropic.com> * docs(identity): rewrite AGENT.md to 5-section format Replaces the informal Capabilities/When to Delegate/Key Constraints structure with the canonical 5-section format: Prerequisites, Decision Logic table, Safety Checks, Error Handling table, Output Handling, and Example Invocations. Covers all 10 subcommands, operator vs owner permissions, transfer irreversibility, and hex encoding requirements. Co-Authored-By: Claude <noreply@anthropic.com> * docs(signing): rewrite AGENT.md to 5-section format; mark wallet-password as sensitive Replaces the informal Capabilities/When to Delegate/Key Constraints structure with the canonical 5-section format: Prerequisites, Decision Logic table (all 10 subcommands), Safety Checks, Error Handling table, Output Handling, and Example Invocations. Adds guidance on Schnorr blind-signing risk, Nostr key source selection, and SIP-018 domain binding. Also marks --wallet-password option as (sensitive) in both stacks-sign and btc-sign commands per CLI conventions. Co-Authored-By: Claude <noreply@anthropic.com> * docs(reputation): rewrite AGENT.md to 5-section format Replaces the informal Capabilities/When to Delegate/Key Constraints structure with the canonical 5-section format: Prerequisites, Decision Logic table (all 11 subcommands), Safety Checks, Error Handling table, Output Handling, and Example Invocations. Clarifies revoke-only-by- submitter constraint, approve-client permission requirements, WAD average interpretation, and cursor-based pagination behavior. Co-Authored-By: Claude <noreply@anthropic.com> * docs(validation): rewrite AGENT.md to 5-section format Replaces the informal Capabilities/When to Delegate/Key Constraints structure with the canonical 5-section format: Prerequisites, Decision Logic table (all 6 subcommands), Safety Checks, Error Handling table, Output Handling, and Example Invocations. Clarifies respond-only-by- validator constraint, progressive score updates, 0-100 range enforcement, and request-hash lookup workflow for validators. Co-Authored-By: Claude <noreply@anthropic.com> * chore: regenerate skills.json manifest Auto-generated from SKILL.md frontmatter after phase 4 AGENT.md updates. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(sbtc): audit improvements — AGENT.md 5-section rewrite, simplify fee resolution - Rewrote AGENT.md with full 5-section structure (Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling) per PATTERNS.md - Fixed incorrect example invocation: --to -> --recipient - Added Decision Logic table covering all 6 subcommands - Added Error Handling table with exact error strings and fixes - Added Output Handling section explaining status values and downstream fields - Replaced switch/case fee tier resolution with array lookup + index access, eliminating unreachable default branch Co-Authored-By: Claude <noreply@anthropic.com> * docs(dual-stacking): add missing AGENT.md with 5-section format dual-stacking had no AGENT.md. Created one covering prerequisites (10,000 sat minimum, mainnet-only, unlock for write ops), decision logic table for all 4 subcommands, safety checks (mid-cycle enrollment timing, opt-out irreversibility), error handling, and output handling. Co-Authored-By: Claude <noreply@anthropic.com> * docs(defi): rewrite AGENT.md to full 5-section format Previous AGENT.md used freeform sections (Capabilities, When to Delegate, Key Constraints) instead of the canonical 5-section format. Rewrote to include Prerequisites, Decision Logic table covering all 11 subcommands, Safety Checks (slippage, collateral ratio, units), Error Handling table, Output Handling, and correct example invocations using actual CLI flags. Co-Authored-By: Claude <noreply@anthropic.com> * docs(bitflow): rewrite AGENT.md to full 5-section format and fix example flags Previous AGENT.md used freeform sections and had incorrect example invocations (--from/--to flags that don't exist; correct flags are --token-x/--token-y). Rewrote to 5-section format covering all 11 subcommands, high-impact swap safety gate, Keeper order lifecycle, and correct example invocations using actual CLI flags. Co-Authored-By: Claude <noreply@anthropic.com> * docs(stacking): rewrite AGENT.md to full 5-section format and fix example flags Previous AGENT.md used freeform sections and had incorrect example invocations (--cycles and --pox-address flags that don't exist). Rewrote to 5-section format covering all 4 subcommands, Bitcoin address version table, prepare-phase timing requirements, and correct example invocations using actual CLI flags (--lock-period, --pox-address-version, etc.). Co-Authored-By: Claude <noreply@anthropic.com> * docs(pillar): rewrite AGENT.md to full 5-section format Previous AGENT.md used freeform sections. Rewrote to 5-section format covering both pillar.ts (browser-handoff) and pillar-direct.ts (agent direct) operation modes, full decision logic table for all subcommands, safety checks for boost/unwind slippage and collateral ratio monitoring, error handling for key/session/network errors, and output handling linking quote outputs to boost inputs. Co-Authored-By: Claude <noreply@anthropic.com> * fix(pillar): remove non-null assertion and replace direct fetch with shared hiro-api pillar-direct.ts key-unlock command used session!.pubkey non-null assertion after getActiveKey(), which is unsafe if unlock fails silently. Replaced with a null check and early return via handleError. pillar.ts position command used raw fetch() to call the Hiro API directly instead of the shared getHiroApi() service. Replaced with the shared service to be consistent with all other skills. Co-Authored-By: Claude <noreply@anthropic.com> * docs(stacks-market): rewrite AGENT.md to canonical 5-section format Replaces informal Capabilities/When-to-Delegate/Key-Constraints structure with the required Prerequisites, Decision Logic, Safety Checks, Error Handling, and Output Handling sections. Adds explicit LMSR quote-before- trade workflow, error table with exact CLI strings, and NETWORK=mainnet prefix on all example invocations. Co-Authored-By: Claude <noreply@anthropic.com> * fix(yield-hunter): canonical AGENT.md format and replace process.exit(1) with handleError Rewrites AGENT.md from informal to required 5-section structure: Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling. Adds explicit guardrails for autonomous financial operations — STX fee check, reserve reasoning, stop-before-withdraw guidance. In yield-hunter.ts, replaces printJson({error})+process.exit(1) patterns in start (already-running guard) and stop (no PID, stale PID) with handleError() and early return, consistent with canonical CLI patterns. Co-Authored-By: Claude <noreply@anthropic.com> * fix(yield-dashboard): canonical AGENT.md format and use handleError for mainnet guard Rewrites AGENT.md from informal to required 5-section structure: Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling. Explicitly documents known limitations (ALEX/Bitflow LP balance reads not yet implemented, static APY estimates) and the wallet-not-needed exception for apy-breakdown. In yield-dashboard.ts, replaces printJson({error})+process.exit(1) in overview, positions, and rebalance mainnet guards with handleError(new Error(...))+return, consistent with canonical CLI patterns. Removes stray blank line in readStackingPosition. Co-Authored-By: Claude <noreply@anthropic.com> * fix(query): canonical AGENT.md and deduplicated import - Rewrite AGENT.md with canonical 5-section structure: Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling - Fix example invocation: use --contract-id instead of deprecated --contract-address/--contract-name flags - Deduplicate NETWORK import (was split across two import statements from the same module) Co-Authored-By: Claude <noreply@anthropic.com> * fix(x402): canonical AGENT.md and try/catch coverage for sync actions - Rewrite AGENT.md with canonical 5-section structure: Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling - Add payment safety checks: verify sBTC/STX balance before executing paid endpoints, always probe before auto-approve - Wrap list-endpoints, openrouter-guide, and openrouter-models action handlers in try/catch so unexpected errors route through handleError rather than surfacing as unhandled exceptions Co-Authored-By: Claude <noreply@anthropic.com> * audit(nostr): fix tags, canonical AGENT.md, inline opts types - Remove incorrect `l1` tag — Nostr is not Bitcoin L1 - Rewrite AGENT.md to follow canonical 5-section structure with proper Decision Logic table, Safety Checks (key safety, post rate limits, BTC-shared keypair risks), Error Handling table with exact error strings, and Output Handling section - Add inline type annotations to all .action() opts parameters - Remove unnecessary `as string` casts now that opts is typed Co-Authored-By: Claude <noreply@anthropic.com> * audit(styx): canonical AGENT.md with full 5-section structure - Add opening paragraph explaining Styx vs native sBTC use case - Rewrite Decision Logic as proper table covering all 7 subcommands - Expand Safety Checks to include ordinal UTXO protection note, btc-sender wallet match requirement, and status-update recovery guidance - Add Error Handling table with exact error strings from the CLI - Add Output Handling section documenting all subcommand outputs and which fields to extract for downstream use Co-Authored-By: Claude <noreply@anthropic.com> * docs(aibtc-news): rewrite AGENT.md to canonical 5-section format All three aibtc-news skills (aibtc-news, aibtc-news-deal-flow, aibtc-news-protocol) now follow the 5-section structure established in phase 01: Prerequisites, Decision Logic table, Safety Checks, Error Handling table, Output Handling, and Example Invocations. Previous AGENT.md files used custom section names (Capabilities, When to Delegate Here, Key Constraints) that were inconsistent with the canonical pattern. Consistent structure allows downstream agents to locate information predictably across all skills. Co-Authored-By: Claude <noreply@anthropic.com> * docs(business-dev): rewrite AGENT.md and fix CLI error handling Rewrote AGENT.md to the canonical 5-section format (Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling, Example Invocations) replacing the previous custom structure. Fixed CLI error handling in business-dev.ts to use handleError() with return instead of printJson({ error }) + process.exit(1), which is the pattern established across all other skills. Also made program.parse() explicit with process.argv. Co-Authored-By: Claude <noreply@anthropic.com> * docs(ceo): rewrite AGENT.md to canonical 5-section format Rewrote AGENT.md to the canonical 5-section structure while preserving the full strategic framework content. The previous AGENT.md was the reference document itself with 13 numbered sections but no standardized agent navigation structure. The new format makes explicit that ceo is orchestration-only (no CLI), maps each strategic goal to the relevant section as Decision Logic, and documents how CEO framework outputs feed into other skills like business-dev and stx. Co-Authored-By: Claude <noreply@anthropic.com> * docs(onboarding): rewrite AGENT.md and fix parseAsync usage Rewrote AGENT.md from a minimal 4-section format to the canonical 5-section structure (Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling, Example Invocations). The previous AGENT.md had only decision rules, execution order, output contract, and guardrails — insufficient for agents navigating the skill. Fixed onboarding.ts to use program.parse(process.argv) instead of program.parseAsync(), which is the established pattern. Commander handles async action handlers correctly with parse(). Co-Authored-By: Claude <noreply@anthropic.com> * docs(stackspot): rewrite AGENT.md to canonical 5-section format Rewrote AGENT.md to the canonical 5-section structure (Prerequisites, Decision Logic, Safety Checks, Error Handling, Output Handling, Example Invocations) replacing the previous custom structure. Key improvements: explicit NETWORK=mainnet requirement in Prerequisites and all examples, PoX prepare phase timing guidance in Safety Checks, and complete Output Handling mapping so downstream agents know which fields to extract from each subcommand. Co-Authored-By: Claude <noreply@anthropic.com> * fix(aibtc-agents): fix stale workflow link in arc0btc README The arc0btc README referenced a what-to-do file as file-aibtc-news-signals.md which does not exist. The correct filename is file-news-signal.md. Fixes a broken cross-reference in the Workflows table. Co-Authored-By: Claude <noreply@anthropic.com> * fix(what-to-do): replace MCP tool name with bun run command in scan-project-board The scan-project-board guide instructed agents to use the send_inbox_message MCP tool by name. Per CLAUDE.md guidelines, workflow steps must use bun run CLI invocations rather than MCP tool names. Replaced with equivalent bun run x402/x402.ts send-inbox-message command. Co-Authored-By: Claude <noreply@anthropic.com> * docs: add missing scan-project-board workflow and agent entries to README The README workflow discovery table was missing the scan-project-board workflow which exists in what-to-do/ and is listed in INDEX.md. Also added the spark0btc and testnet-explorer agent entries to the community agents list which existed in aibtc-agents/ but were not referenced from the README. Co-Authored-By: Claude <noreply@anthropic.com> * fix(src): replace non-null assertions with null-safe guards in shared lib - sponsor-builder.ts: replace response.txid! with explicit null check and descriptive error so relay failures surface clearly instead of silently returning undefined as txid - defi.service.ts: add private getContracts() getter on ZestProtocolService that throws a descriptive error when contracts are null (mainnet-only check), replacing all this.contracts! non-null assertions with typed accessor Co-Authored-By: Claude <noreply@anthropic.com> * fix(src): replace console.info with console.error in fee.ts fallback log console.info in Bun/Node goes to stdout, which would pollute the JSON output of skill scripts that rely on clean stdout for JSON parsing. Use console.error so the fallback fee notice goes to stderr instead, matching the pattern used throughout the rest of the codebase. Co-Authored-By: Claude <noreply@anthropic.com> * fix(src): move HiroApiRateLimitError from type-only to value export HiroApiRateLimitError is a class, not just a type interface. Exporting it via 'export type' strips the runtime value, making instanceof checks fail for consumers who catch rate-limit errors. Move it to the value export alongside HiroApiService so it can be used as both a value and type. Co-Authored-By: Claude <noreply@anthropic.com> * chore(yield-dashboard): remove TODO markers from functional code Convert TODO comments in readZestPosition and readBitflowPosition to descriptive notes — the code is functional and returns valid data; the markers incorrectly implied broken stubs rather than known limitations. Also regenerate skills.json timestamp via bun run manifest. Co-Authored-By: Claude <noreply@anthropic.com> * refactor: final code simplification pass - sbtc.ts: use nullish coalescing for address resolution (consistent with other skills) - defi.service.ts: remove redundant ensureMainnet() guard in ZestProtocolService Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback - scan-project-board.md: fix send-inbox-message flags to match x402 CLI (--recipient-btc-address, --recipient-stx-address, --content) - yield-dashboard/AGENT.md: update error message to match actual handleError output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…v#103) Applies convention from issue aibtcdev#94 audit: src/lib/ uses node:-prefixed imports for portability. scripts/ already uses Bun-native APIs. Files changed: - src/lib/utils/storage.ts: fs/promises, path, os - src/lib/utils/encryption.ts: crypto - src/lib/services/signing-key.service.ts: fs/promises, path, os, crypto - src/lib/services/scaffold.service.ts: fs/promises, path - src/lib/services/x402.service.ts: crypto (named import) Fixes aibtcdev#94 Co-authored-by: strange-lux-agent <strange-lux-agent@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The transferIdentity function was calling the SIP-009 transfer function without a post-condition, allowing the transaction to succeed even if the NFT was not actually transferred from the sender. Add a createNftSendPostCondition asserting that sender sends the agent-identity NFT with the specified tokenId. Co-authored-by: Forge <forge@arc0btc.com>
…v#87) (aibtcdev#107) * fix(wallet): persist session across process boundaries (issue aibtcdev#87) When `wallet unlock` runs in one process, the session is held in-memory only. Any subsequent process (e.g. `bitflow swap`, `zest supply`) calls `getActiveAccount()` on a fresh WalletManager instance and gets null, forcing a fallback to CLIENT_MNEMONIC or an error. This change adds cross-process session persistence: - `storage.ts`: `writeSessionFile` / `readSessionFile` / `deleteSessionFile` encrypt account data with AES-256-GCM using a machine-local 256-bit key stored at `~/.aibtc/sessions/.session-key` (mode 0o600). The key never leaves the machine and cannot decrypt the keystore — only the short-lived session file. Session files respect the existing `autoLockTimeout` expiry. - `wallet-manager.ts`: `saveSessionToDisk()` is called at the end of a successful `unlock()`. `restoreSessionFromDisk(walletId)` reads and decrypts the session file, reconstructs the Account with correctly typed Uint8Array key fields, and restores the in-memory session. `lock()` now also calls `deleteSessionFile()` (best-effort) to clean up on explicit lock or auto-lock-timeout. - `x402.service.ts`: `getAccount()` now has a second fallback path between the in-process session check and CLIENT_MNEMONIC: it reads `activeWalletId` from config, then calls `restoreSessionFromDisk()`. If the session file is missing, expired, or tampered the function silently falls through to the existing CLIENT_MNEMONIC fallback — no behaviour change for existing users. Security notes: - Private keys are serialised to hex inside the encrypted ciphertext only; they are never written in plaintext - Session files are written with mode 0o600; the sessions directory is 0o700 - Decryption failure (tampered file or regenerated key) returns null cleanly - `.aibtc/` is already covered by .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address review feedback — race condition, version gate, path traversal guard - getOrCreateSessionKey: read back SESSION_KEY_FILE after rename so two racing processes converge on the winning key rather than each returning their own freshly generated bytes - readSessionFile: reject session files whose version != 1 before any decryption attempt, guarding against future format changes or truncated writes - getSessionFilePath: wrap walletId in path.basename() to prevent directory traversal when an attacker-controlled walletId contains "../" sequences Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ibtcdev#101) * feat(aibtc-news-classifieds): add classified ads and extended aibtc.news API skill New skill covering aibtc.news endpoints not in aibtc-news: - Classifieds: list, get, post (x402, 5000 sats sBTC) - Signals: get by ID, correct authored signals (BIP-322) - Beats: update metadata for owned beats (BIP-322) - Briefs: read latest/historical (x402, 1000 sats), inscribe, check inscription - Discovery: streaks, editorial skill resources 11 subcommands total. Uses x402.service for paid endpoints and signing skill for BIP-322 authenticated writes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(x402): detect sbtc-token contract identifier in detectTokenType The detectTokenType function only matched 'sbtc' (bare name) or '::token-sbtc' (legacy format). It missed the standard contract identifier form used by aibtc.news and other x402 endpoints: SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token Without this fix, sBTC payments were sent as STX transfers, causing the server to reject payment and return a second 402, triggering the "Payment retry limit exceeded" error. Fix: also match any asset string containing 'sbtc-token'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(manifest): regenerate skills.json to include aibtc-news-classifieds The classifieds skill files were added but skills.json needed regeneration after conflict resolution during rebase on main. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
…gs (aibtcdev#106) Register three Arc fleet agents in the AIBTC community registry: - iris0btc: Signal reader (markets, mempools, metrics, on-chain analytics) BTC bc1q6savz94q7ps48y78gg3xcfvjhk6jmcgpmftqxe STX SP215BXCEYDT5NXGMPJJKXQADYQXDX92QHN464Y87 - loom0btc: Integrator (APIs, webhooks, cross-chain bridges, pipelines) BTC bc1q3qa3xuvk80j4zqnf9e9p7dext9e4jlsv79wgwq STX SP3X279HDPCHMB4YN6AHBYX2Y76Q4E20987BN3GHR - forge0btc: Builder (implementation, features, services, products) BTC bc1q9hme5ayrtqd4s75dqq82g8ezzlhfj2m9efjz4h STX SP1BFDFJ3P2TGKF3QN5Z6BTTSSDAG4EXHXZZAYZBM All three run arc-starter on dedicated VPS instances, managed by Arc (arc0.btc) via fleet orchestration. Iris wallet was recreated before submission — new addresses used. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ibtcdev#117) getUserPosition() was reading current-a-token-balance from get-user-reserve-data — a field that doesn't exist in the response and always returns 0. Supply positions are held as LP token balances (zsbtc-v2-0, zaeusdc-v2-0, etc.), not in the reserve data struct. Fix: - Supply: call get-balance on the LP token contract (assetConfig.lpToken) - Borrow: use principal-borrow-balance (not current-variable-debt) Same approach confirmed in aibtcdev/aibtc-mcp-server v1.33.3 (aibtcdev#283, aibtcdev#285).
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(bitflow): unify SDK and HODLMM routing and ranking * fix(bitflow): clarify HODLMM units and output * docs(bitflow): clarify public API access and units
* feat(aibtc-agents): add SKILL.md and regenerate manifest Adds SKILL.md to the aibtc-agents directory so it is picked up by the manifest generator and appears in skills.json. The skill was added in v0.19.0 (feat: add iris0btc, loom0btc, forge0btc configs) but was missing a SKILL.md entry, so it did not appear in the published manifest. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(aibtc-agents): add arguments value to SKILL.md frontmatter Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(x402): add --headers flag to execute-endpoint for custom request headers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(x402): strengthen --headers type guard with unknown + null/array checks Use `unknown` for parsedHeaders to avoid implicit `any`, add explicit object-shape guard (non-null, non-array) before casting to Record<string,string>. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(x402): include --headers in retryWith suggestion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Bumps manifest from 0.30.0 → 0.32.0 by running `bun run manifest`. Includes 61 skills. Fixes stale version shown on landing-page skills catalog.
* feat(clarity): add clarity-patterns, clarity-check, clarity-test-scaffold, clarity-audit skills Add four new doc-only Clarity development skills that cover the full contract lifecycle: patterns reference, pre-deployment validation, test infrastructure scaffolding, and security auditing. Bundled patterns from whoabuddy/claude-knowledge make aibtcdev/skills the canonical Clarity reference. Closes aibtcdev#206. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(clarity): clarify doc-only usage in SKILL.md files Add doc-only disclaimer to Usage sections noting these are planned CLI interfaces, not yet implemented. Agents read the SKILL.md directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(clarity-patterns): bundle all pattern content and templates directly Replace index-only SKILL.md with full bundled content: 16 code patterns, 12 registry patterns, testing reference, cost limits, and 3 complete contract templates with source and tests. No external dependencies on whoabuddy/claude-knowledge — aibtcdev/skills is now the canonical source. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
| return `--- | ||
| name: ${name} | ||
| description: TODO — one-line description of what ${title} does | ||
| author: TODO — your GitHub username | ||
| author_agent: TODO — your agent name (or remove this line) | ||
| user-invocable: false | ||
| arguments: TODO — list subcommands separated by | | ||
| entry: ${name}/${name}.ts | ||
| requires: [] | ||
| tags: [] | ||
| --- |
There was a problem hiding this comment.
🔴 scaffold-skill.ts generates old flat frontmatter format incompatible with new YAML parser
The scaffold-skill.ts template generates SKILL.md with the old flat frontmatter format (top-level author, user-invocable, arguments, entry, requires, tags fields), but the generate-manifest.ts and validate-frontmatter.ts scripts were updated in this PR to expect the new agentskills.io spec format with a nested metadata: block. Skills scaffolded with bun run scaffold will fail frontmatter validation (bun run validate) because the Zod schema at scripts/validate-frontmatter.ts:77-81 requires a metadata object with nested fields like metadata.user-invocable, metadata.arguments, etc.
Prompt for agents
Update scripts/scaffold-skill.ts to generate SKILL.md frontmatter in the new agentskills.io spec format with a nested metadata: block. The skillMd() function at line 32-44 should produce:
---
name: ${name}
description: "TODO — one-line description of what ${title} does"
metadata:
author: "TODO — your GitHub username"
author-agent: "TODO — your agent name (or remove this line)"
user-invocable: "false"
arguments: "TODO — list subcommands separated by |"
entry: "${name}/${name}.ts"
requires: ""
tags: ""
---
This matches the format used by all other SKILL.md files in the PR and parsed by scripts/generate-manifest.ts and scripts/validate-frontmatter.ts.
Was this helpful? React with 👍 or 👎 to provide feedback.
| // Supply: read LP token balance | ||
| const lpBalanceResult = await this.hiro.callReadOnlyFunction( | ||
| assetConfig.lpToken, | ||
| "get-balance", | ||
| [principalCV(userAddress)], | ||
| userAddress | ||
| ); |
There was a problem hiding this comment.
🚩 Zest getUserPosition reads LP token balance via 'get-balance' but the function name may vary across Zest V1/V2
In src/lib/services/defi.service.ts:472-478, the code reads supply from the LP token contract using get-balance function name. The comment says this 'matches the fix confirmed in aibtcdev/aibtc-mcp-server v1.33.3'. However, the LP token contract function name varies — SIP-010 tokens use ft-get-balance (as seen in yield-dashboard.ts:170 using ft-get-balance), while get-balance is a wrapper some contracts provide. If assetConfig.lpToken points to a contract that only implements ft-get-balance, this call would fail. The existing Zest V1 LP token (zsbtc) likely has a get-balance wrapper, so this should work, but this is worth verifying against the actual on-chain contract.
Was this helpful? React with 👍 or 👎 to provide feedback.
…rmat (aibtcdev#232) fix: update scaffold, docs, and bounty-scanner for nested metadata format - Update CONTRIBUTING.md frontmatter example to nested metadata format - Fix bounty-scanner parseFrontmatter to handle nested metadata: blocks - Fix scaffold-skill to generate correct nested metadata format - Support both flat (legacy) and nested tag formats in bounty-scanner PR aibtcdev#232 by sonic-mast
… output is included (aibtcdev#230) fix(rune-transfer-builder): only set changeOutput pointer when change output is included Compute runeChangeSats before building Runestone so the change pointer is only set when the change output will actually be added to the transaction. When rune change sats are below dust threshold, the change output is omitted and the Runestone no longer points to a non-existent output index (which would burn the remaining runes). Fixes aibtcdev#229 PR aibtcdev#230 by gregoryford963-sys
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
f1a474a to
2e81a4e
Compare
| const actualOutputCount = 3 + (runeChangeSats >= DUST_THRESHOLD ? 1 : 0); | ||
| const finalVsize = | ||
| TX_OVERHEAD_VBYTES + | ||
| runeUtxos.length * P2TR_INPUT_BASE_VBYTES + | ||
| selectedFeeUtxos.length * P2WPKH_INPUT_VBYTES + | ||
| OP_RETURN_VBYTES + | ||
| (actualOutputCount - 1) * P2TR_OUTPUT_VBYTES + // non-OP_RETURN outputs | ||
| P2WPKH_OUTPUT_VBYTES; // one P2WPKH change |
There was a problem hiding this comment.
🟡 Rune transfer fee vsize calculation double-counts the BTC change output
In buildRuneTransfer, the final vsize formula (actualOutputCount - 1) * P2TR_OUTPUT_VBYTES + P2WPKH_OUTPUT_VBYTES counts the BTC change output twice: once as a P2TR output (included in actualOutputCount - 1) and again as the separate P2WPKH_OUTPUT_VBYTES term. When rune change IS included, actualOutputCount = 4 → the formula yields 3 * P2TR + P2WPKH, but the actual non-OP_RETURN outputs are only 2 P2TR (recipient + rune change) + 1 P2WPKH (BTC change). This overestimates the vsize by one P2TR_OUTPUT_VBYTES (~43 vbytes), causing users to overpay mining fees on every rune transfer. The same overcounting occurs when rune change is not included (actualOutputCount = 3 → 2 * P2TR + P2WPKH instead of correct 1 * P2TR + P2WPKH).
| const actualOutputCount = 3 + (runeChangeSats >= DUST_THRESHOLD ? 1 : 0); | |
| const finalVsize = | |
| TX_OVERHEAD_VBYTES + | |
| runeUtxos.length * P2TR_INPUT_BASE_VBYTES + | |
| selectedFeeUtxos.length * P2WPKH_INPUT_VBYTES + | |
| OP_RETURN_VBYTES + | |
| (actualOutputCount - 1) * P2TR_OUTPUT_VBYTES + // non-OP_RETURN outputs | |
| P2WPKH_OUTPUT_VBYTES; // one P2WPKH change | |
| const p2trOutputCount = 1 + (runeChangeSats >= DUST_THRESHOLD ? 1 : 0); // recipient + optional rune change | |
| const finalVsize = | |
| TX_OVERHEAD_VBYTES + | |
| runeUtxos.length * P2TR_INPUT_BASE_VBYTES + | |
| selectedFeeUtxos.length * P2WPKH_INPUT_VBYTES + | |
| OP_RETURN_VBYTES + | |
| p2trOutputCount * P2TR_OUTPUT_VBYTES + | |
| P2WPKH_OUTPUT_VBYTES; // one P2WPKH change |
Was this helpful? React with 👍 or 👎 to provide feedback.
| try { | ||
| const token = await getCredential("maximumsats-wot", "l402-token"); | ||
| if (token) headers["Authorization"] = `L402 ${token}`; | ||
| } catch { | ||
| // No credential stored — proceed with free tier | ||
| } |
There was a problem hiding this comment.
🔴 maximumsats-wot/cli.ts calls getCredential with wrong argument semantics — passes key name as password
getCredential at credentials/store.ts:215 takes (id: string, password: string) — the second parameter is the master encryption password. But maximumsats-wot/cli.ts:48 calls getCredential("maximumsats-wot", "l402-token"), passing the credential key name "l402-token" as the password parameter. This will always fail to decrypt the credential (AES-GCM auth tag mismatch), so the catch block silently swallows the error and the L402 token is never loaded from the credential store. The feature described in the SKILL.md ("store via arc creds set") will never work.
Was this helpful? React with 👍 or 👎 to provide feedback.
| // Restore the in-memory session so subsequent in-process calls also work | ||
| const now = new Date(); | ||
| this.session = { | ||
| walletId, | ||
| account, | ||
| unlockedAt: now, | ||
| expiresAt, | ||
| }; | ||
|
|
||
| return account; |
There was a problem hiding this comment.
🔴 restoreSessionFromDisk does not start auto-lock timer — restored sessions never auto-lock
In wallet-manager.ts:364-396, restoreSessionFromDisk() restores a session from disk and sets this.session with the deserialized account and expiresAt, but never calls this.startAutoLockTimer(). Compare to the unlock() method at wallet-manager.ts:287 which calls this.startAutoLockTimer(config.autoLockTimeout) after setting the session. This means any process that restores a session from disk (via getAccount() in x402.service.ts:298) will have an active session that never auto-locks, even when the user explicitly configured an auto-lock timeout. The expiresAt field is set on the session object but is never enforced without the timer, so the session remains active indefinitely in the restoring process.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if (executableRoute.source === "hodlmm") { | ||
| return this.executeHodlmmSwap(account, executableRoute, fee); |
There was a problem hiding this comment.
🚩 Bitflow swap ignores slippageTolerance parameter when routing through HODLMM
In src/lib/services/bitflow.service.ts:1562-1572, when the best executable route is HODLMM, the swap calls this.executeHodlmmSwap(account, executableRoute, fee) which does not pass the slippageTolerance parameter. Looking at executeHodlmmSwap (src/lib/services/bitflow.service.ts:1186-1224), it calls the DLMM core contract directly with no min-amount-out guard — the swap is executed at whatever price the pool offers. This means HODLMM swaps have no slippage protection. The SDK path does use slippage tolerance via getSwapParams. This is a meaningful behavioral difference between SDK and HODLMM execution paths that could result in worse-than-expected execution prices under volatile conditions.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const cutoff = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(); | ||
| if (a.lastActiveAt && a.lastActiveAt >= cutoff) activeCount++; |
There was a problem hiding this comment.
🟡 ISO string comparison for date-based active agent filtering is unreliable
In agent-lookup.ts:131-132, the "active agents" count uses lexicographic string comparison (a.lastActiveAt >= cutoff) between ISO 8601 date strings. While ISO 8601 strings are lexicographically sortable when they share the same timezone offset, the API's lastActiveAt field format is not guaranteed to use UTC ('Z' suffix) consistently. If the API returns timestamps with different timezone offsets (e.g., +00:00 vs Z), the comparison will produce incorrect results. Using new Date(a.lastActiveAt).getTime() >= new Date(cutoff).getTime() would be robust regardless of format. Additionally, cutoff is recomputed inside the loop every iteration, which is wasteful but not incorrect.
| const cutoff = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(); | |
| if (a.lastActiveAt && a.lastActiveAt >= cutoff) activeCount++; | |
| const cutoffMs = Date.now() - 7 * 24 * 60 * 60 * 1000; | |
| if (a.lastActiveAt && new Date(a.lastActiveAt).getTime() >= cutoffMs) activeCount++; |
Was this helpful? React with 👍 or 👎 to provide feedback.
| * arc creds set --service maximumsats-wot --key l402-token --value "<token>:<preimage>" | ||
| */ | ||
|
|
||
| import { getCredential } from "../credentials/store.js"; |
There was a problem hiding this comment.
🚩 credentials/store.js import in maximumsats-wot/cli.ts may not resolve correctly
At maximumsats-wot/cli.ts:19, there's an import from ../credentials/store.js. This file does not appear anywhere in the diff or existing codebase — the credentials skill uses credentials/credentials.ts as its entry point, and the credential store logic is in src/lib/utils/storage.ts. The getCredential function imported here likely does not exist at that path. This would cause a runtime import error when using the L402 credential fallback path. However, this may be an internal utility expected to exist in the agent's environment rather than this repo.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const utxo = runeUtxos[i]; | ||
| tx.addInput({ | ||
| txid: utxo.txid, | ||
| index: utxo.vout, | ||
| witnessUtxo: { | ||
| script: taprootPayment.script, | ||
| amount: BigInt(utxo.value), | ||
| }, | ||
| }); | ||
| taprootInputIndices.push(i); |
There was a problem hiding this comment.
🔴 Missing tapInternalKey on P2TR inputs in rune transfer builder causes invalid Taproot key-path signatures
The buildRuneTransfer function adds P2TR inputs for rune UTXOs without setting tapInternalKey in the input options. @scure/btc-signer requires tapInternalKey to compute the tweaked private key (d' = d + H_TapTweak(P) mod n) for key-path spending. Without it, signIdx will either throw or produce a signature against the un-tweaked internal key, which fails verification against the tweaked key embedded in the P2TR output script. This is confirmed by the pattern in child-inscription-builder.ts:587 which explicitly sets tapInternalKey: xOnlyParentPubKey for its P2TR key-path input — a fix documented in the CHANGELOG as "add tapInternalKey to parent input in buildChildRevealTransaction" (aibtcdev#207).
Was this helpful? React with 👍 or 👎 to provide feedback.
| tx.addInput({ | ||
| txid: inscriptionUtxo.txid, | ||
| index: inscriptionUtxo.vout, | ||
| witnessUtxo: { | ||
| script: taprootPayment.script, | ||
| amount: BigInt(inscriptionUtxo.value), | ||
| }, | ||
| }); | ||
|
|
There was a problem hiding this comment.
🔴 Missing tapInternalKey on P2TR input in inscription transfer builder causes invalid Taproot key-path signatures
Same issue as in the rune transfer builder: buildInscriptionTransfer adds the inscription P2TR input without tapInternalKey, so signIdx(taprootPrivateKey, inscriptionInputIndex) at inscription-transfer-builder.ts:204 will produce an incorrect or failing Taproot signature. The child-inscription-builder.ts:587 demonstrates the correct pattern by explicitly setting tapInternalKey for P2TR key-path inputs.
| tx.addInput({ | |
| txid: inscriptionUtxo.txid, | |
| index: inscriptionUtxo.vout, | |
| witnessUtxo: { | |
| script: taprootPayment.script, | |
| amount: BigInt(inscriptionUtxo.value), | |
| }, | |
| }); | |
| const taprootPayment = btc.p2tr(senderTaprootPubKey, undefined, btcNetwork); | |
| tx.addInput({ | |
| txid: inscriptionUtxo.txid, | |
| index: inscriptionUtxo.vout, | |
| witnessUtxo: { | |
| script: taprootPayment.script, | |
| amount: BigInt(inscriptionUtxo.value), | |
| }, | |
| tapInternalKey: senderTaprootPubKey, | |
| }); |
Was this helpful? React with 👍 or 👎 to provide feedback.
| async restoreSessionFromDisk(walletId: string): Promise<Account | null> { | ||
| const result = await readSessionFile(walletId).catch(() => null); | ||
| if (!result) return null; | ||
|
|
||
| const { account: s, expiresAt } = result; | ||
|
|
||
| // Reconstruct typed key buffers from hex | ||
| const account: Account = { | ||
| address: s.address, | ||
| btcAddress: s.btcAddress, | ||
| taprootAddress: s.taprootAddress, | ||
| privateKey: s.privateKey, | ||
| btcPrivateKey: fromHex(s.btcPrivateKey), | ||
| btcPublicKey: fromHex(s.btcPublicKey), | ||
| taprootPrivateKey: fromHex(s.taprootPrivateKey), | ||
| taprootPublicKey: fromHex(s.taprootPublicKey), | ||
| nostrPrivateKey: fromHex(s.nostrPrivateKey), | ||
| nostrPublicKey: fromHex(s.nostrPublicKey), | ||
| sponsorApiKey: s.sponsorApiKey, | ||
| network: s.network, | ||
| }; | ||
|
|
||
| // Restore the in-memory session so subsequent in-process calls also work | ||
| const now = new Date(); | ||
| this.session = { | ||
| walletId, | ||
| account, | ||
| unlockedAt: now, | ||
| expiresAt, | ||
| }; | ||
|
|
||
| return account; | ||
| } |
There was a problem hiding this comment.
🚩 Restored disk sessions do not start auto-lock timers
When restoreSessionFromDisk at src/lib/services/wallet-manager.ts:364-396 restores a session, it sets this.session but never calls this.startAutoLockTimer(), unlike the unlock() method at line 287 which does. This means a session restored from disk won't auto-lock within the current process even if autoLockTimeout is configured. The expiresAt field is preserved so getActiveAccount() should still check expiry, but the proactive timer-based lock won't fire. This may be intentional (cross-process sessions are short-lived by design) but is worth noting.
Was this helpful? React with 👍 or 👎 to provide feedback.
| private getSignedBinId(unsignedBinId: number): number { | ||
| return unsignedBinId - 500; | ||
| } |
There was a problem hiding this comment.
🚩 HODLMM signed bin ID conversion subtracts a fixed 500 offset
The getSignedBinId method at src/lib/services/bitflow.service.ts:448-450 converts unsigned bin IDs to signed by subtracting 500 (return unsignedBinId - 500). This is used when building the expected-bin-id argument for the HODLMM liquidity router contract's add-relative-liquidity-same-multi function. The offset of 500 is presumably a protocol convention for the DLMM contract, but it's a magic number with no documentation or reference to the on-chain contract source. If the contract uses a different offset, all liquidity adds would fail with an unexpected bin ID error.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const leafScriptSize = revealScript.tapLeafScript?.[0]?.[1]?.length || 0; | ||
| const revealWitnessSize = Math.ceil( | ||
| (revealScript.script?.byteLength || 0) / 4 | ||
| ); | ||
| ((leafScriptSize || revealScript.script?.byteLength || 0) / 4) * 1.25 | ||
| ) + WITNESS_OVERHEAD_VBYTES; |
There was a problem hiding this comment.
🚩 Nostr skill's tapLeafScript access pattern may not work with @scure/btc-signer v1.5+
In src/lib/transactions/inscription-builder.ts:416, the code accesses revealScript.tapLeafScript?.[0]?.[1]?.length to get the leaf script size for witness estimation. In @scure/btc-signer v1.5+, tapLeafScript from btc.p2tr() returns an array of {leafVersion, script, controlBlock} objects, not [controlBlock, leafScript] tuples. So [0]?.[1] on an object returns undefined, causing the fallback to revealScript.script?.byteLength (the P2TR output script, ~34 bytes). For small inscriptions the WITNESS_OVERHEAD_VBYTES = 80 buffer compensates, but for inscriptions larger than ~500 bytes, the fee allocated to the reveal would be significantly underestimated. This is a pre-existing issue (the old code had the same fallback) that the new code partially mitigates with the added overhead constant.
Was this helpful? React with 👍 or 👎 to provide feedback.
…dev#237) feat(paperboy): add paid signal distribution skill (docs-only) Cherry-pick paperboy/SKILL.md from aibtcdev#221 by pbtc21, converted to nested metadata format with arguments set to "reference" (doc-only, no CLI). Adds AGENT.md, README entry, and regenerated manifest. Closes aibtcdev#221 Co-Authored-By: pbtc21 <pbtc21@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
793d526 to
382ac6d
Compare
…btcdev#247) Port SharedNonceTracker from aibtc-mcp-server (PR #415) and implement the retry/error handling guidance from landing-page#522. The send-inbox-message command now handles 409 nonce conflict codes (SENDER_NONCE_DUPLICATE, SENDER_NONCE_STALE, SENDER_NONCE_GAP, NONCE_CONFLICT), 502/503 relay errors with backoff, and treats 201 paymentStatus "pending" as success. Nonce state is persisted to ~/.aibtc/nonce-state.json for cross-process sharing with the MCP server via merge-on-read. Closes aibtcdev#240 Ref: aibtcdev/landing-page#522 Ref: aibtcdev/aibtc-mcp-server#415 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…transfers (aibtcdev#244) * docs(erc8004): add AGENT.md with prerequisites, decision logic, safety checks, and error handling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(runes): guard against silent rune burn on partial transfer with low-sat UTXOs Add totalRuneAmount option to RuneTransferOptions. When provided and amount < totalRuneAmount (partial transfer), builder throws if rune UTXOs don't hold enough sats to include a change output, rather than silently burning the remaining runes. Also clarify the comment on the conditional change output to be unambiguous: 'only when the change output is included in the transaction'. Resolves arc0btc review feedback on PR aibtcdev#244. * nit(runes): clarify changeOutput comment — explicit 'in the transaction' * fix(runes): make totalRuneAmount required and clamp runeChangeSats The burn guard was opt-in (totalRuneAmount was optional), meaning callers outside runes.ts could still hit silent rune burns. Making it required ensures all callers get the safety check. Also clamps runeChangeSats to 0 to avoid confusing negative values in edge cases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: 369SunRay <369sunray@aibtc> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
…ase lifecycle (aibtcdev#250) * feat(nonce-manager): add cross-process Stacks nonce oracle skill Prevents mempool collisions when multiple skills send Stacks transactions concurrently. Uses mkdir-based file locking and ~/.aibtc/nonce-state.json for cross-process state sharing. Auto-syncs from Hiro API when stale. Includes acquire/release/sync/status subcommands, failure-kind distinction (broadcast vs rejected) for correct rollback behavior, and integration guidance for x402 error codes per landing-page#522. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(nonce-manager): unify nonce oracle into shared nonce-tracker Rewrites src/lib/services/nonce-tracker.ts to incorporate the acquire/release lifecycle and cross-process mkdir-based file locking from the nonce-manager skill. The nonce-store.ts is now a thin re-export layer. Key changes: - Primary API: acquireNonce/releaseNonce/syncNonce/getStatus - Cross-process safety via mkdir-based file lock (30s stale timeout) - Atomic temp+rename writes to prevent corruption - State schema v2 with migration from v1 (nextNonce replaces lastUsedNonce) - Uses shared Hiro API client instead of hardcoded URL - Compat wrappers for getTrackedNonce/recordNonceUsed/reconcileWithChain so x402-retry.ts continues working without changes - Adds mcp-tools field to SKILL.md frontmatter - Fixes AGENT.md integration example (removes undefined isPreBroadcastError) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Jason Schrader <whoabuddy@users.noreply.github.com>
…dev#251) BFF Skills Comp Day 2 winner by @locallaunchsc-cloud. Read-only HODLMM pool risk assessment — regime classification and LP safety signals for Bitflow HODLMM pools.
BFF Skills Comp Day 1 winner by @secret-mars. Autonomous sBTC yield management on Zest Protocol — supply, withdraw, claim rewards, and monitor positions with safety controls.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ast authorship - Add list-pools, assess-pool-drift, and regime-history subcommands - Update SKILL.md and AGENT.md with improved docs per arc0btc review feedback - Update skills.json manifest with correct arguments list - Rebased onto upstream/main to resolve merge conflict with aibtcdev#251
97596b4 to
2bfd0d7
Compare
…st.ts Updates version, timestamp, and normalizes unicode characters. Adds hodlmm-risk to manifest with correct arguments list.
| } | ||
| try { | ||
| const token = await getCredential("maximumsats-wot", "l402-token"); | ||
| if (token) headers["Authorization"] = `L402 ${token}`; |
There was a problem hiding this comment.
🚩 maximumsats-wot/cli.ts imports getCredential which requires a master password not provided in the call
Line 19 imports getCredential from ../credentials/store.js, and line 49 calls it as getCredential('maximumsats-wot', 'l402-token'). The credential store uses AES-256-GCM encryption with a PBKDF2-derived key from a master password. If getCredential requires a password parameter that isn't being passed here, this call would fail at runtime. The actual function signature should be verified — if it takes a password, the L402 token retrieval path will always throw.
Was this helpful? React with 👍 or 👎 to provide feedback.
Adds read-only volatility risk monitoring for Bitflow DLMM pools. No wallet required.
Subcommands: list-pools, assess-pool, assess-position, regime-history
Risk model: bin spread + reserve imbalance + active bin concentration → 0-100 score → calm/elevated/crisis.
Fail-safe: API errors default to crisis.
Closes aibtcdev#224
Note: Previous PR #2 was contaminated with files from other branches. This is a clean PR with only hodlmm-risk/ files.