Skip to content

feat(hodlmm-risk): add HODLMM volatility risk monitoring skill#4

Open
sonic-mast wants to merge 112 commits into
mainfrom
feat/hodlmm-risk-v2
Open

feat(hodlmm-risk): add HODLMM volatility risk monitoring skill#4
sonic-mast wants to merge 112 commits into
mainfrom
feat/hodlmm-risk-v2

Conversation

@sonic-mast

@sonic-mast sonic-mast commented Mar 25, 2026

Copy link
Copy Markdown
Owner

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.


Open with Devin

cocoa007 and others added 30 commits March 4, 2026 16:34
* 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>
github-actions Bot and others added 6 commits March 23, 2026 16:31
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>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 6 potential issues.

View 8 additional findings in Devin Review.

Open in Devin Review

Comment thread scripts/scaffold-skill.ts
Comment on lines +34 to +44
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: []
---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread CONTRIBUTING.md Outdated
Comment thread bounty-scanner/bounty-scanner.ts
Comment thread maximumsats-wot/cli.ts
Comment thread src/lib/transactions/runestone-builder.ts Outdated
Comment on lines +472 to +478
// Supply: read LP token balance
const lpBalanceResult = await this.hiro.callReadOnlyFunction(
assetConfig.lpToken,
"get-balance",
[principalCV(userAddress)],
userAddress
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

devin-ai-integration[bot]

This comment was marked as resolved.

sonic-mast and others added 3 commits March 25, 2026 11:07
…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>
@sonic-mast sonic-mast force-pushed the feat/hodlmm-risk-v2 branch from f1a474a to 2e81a4e Compare March 25, 2026 18:52

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 new potential issues.

View 14 additional findings in Devin Review.

Open in Devin Review

Comment on lines +219 to +226
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 = 32 * P2TR + P2WPKH instead of correct 1 * P2TR + P2WPKH).

Suggested change
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
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread maximumsats-wot/cli.ts
Comment on lines +47 to +52
try {
const token = await getCredential("maximumsats-wot", "l402-token");
if (token) headers["Authorization"] = `L402 ${token}`;
} catch {
// No credential stored — proceed with free tier
}

@devin-ai-integration devin-ai-integration Bot Mar 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +386 to +395
// 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;

@devin-ai-integration devin-ai-integration Bot Mar 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/lib/transactions/runestone-builder.ts
Comment on lines +1571 to +1572
if (executableRoute.source === "hodlmm") {
return this.executeHodlmmSwap(account, executableRoute, fee);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

View 22 additional findings in Devin Review.

Open in Devin Review

Comment thread src/lib/transactions/runestone-builder.ts
Comment on lines +131 to +132
const cutoff = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
if (a.lastActiveAt && a.lastActiveAt >= cutoff) activeCount++;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Suggested change
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++;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread maximumsats-wot/cli.ts
* arc creds set --service maximumsats-wot --key l402-token --value "<token>:<preimage>"
*/

import { getCredential } from "../credentials/store.js";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 new potential issues.

View 22 additional findings in Devin Review.

Open in Devin Review

Comment on lines +113 to +122
const utxo = runeUtxos[i];
tx.addInput({
txid: utxo.txid,
index: utxo.vout,
witnessUtxo: {
script: taprootPayment.script,
amount: BigInt(utxo.value),
},
});
taprootInputIndices.push(i);

@devin-ai-integration devin-ai-integration Bot Mar 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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).

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +97 to +105
tx.addInput({
txid: inscriptionUtxo.txid,
index: inscriptionUtxo.vout,
witnessUtxo: {
script: taprootPayment.script,
amount: BigInt(inscriptionUtxo.value),
},
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.

Suggested change
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,
});
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +364 to 396
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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +448 to +450
private getSignedBinId(unsignedBinId: number): number {
return unsignedBinId - 500;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +416 to +419
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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

whoabuddy and others added 2 commits March 25, 2026 13:40
…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>
devin-ai-integration[bot]

This comment was marked as resolved.

@sonic-mast sonic-mast force-pushed the feat/hodlmm-risk-v2 branch from 793d526 to 382ac6d Compare March 26, 2026 21:03
arc0btc and others added 8 commits March 26, 2026 15:27
…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
@sonic-mast sonic-mast force-pushed the feat/hodlmm-risk-v2 branch from 97596b4 to 2bfd0d7 Compare March 28, 2026 04:44
…st.ts

Updates version, timestamp, and normalizes unicode characters.
Adds hodlmm-risk to manifest with correct arguments list.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 28 additional findings in Devin Review.

Open in Devin Review

Comment thread maximumsats-wot/cli.ts
}
try {
const token = await getCredential("maximumsats-wot", "l402-token");
if (token) headers["Authorization"] = `L402 ${token}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.