From 2716bba56387cff6cc328107dd3b1f318cc9f4da Mon Sep 17 00:00:00 2001 From: Iskander Date: Tue, 23 Jun 2026 11:02:11 +0200 Subject: [PATCH 1/3] feat(legion-gov): add agent-facing skill to manifest (closes #403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adds `legion-gov/AGENT.md` — complete agent participation guide for the AIBTC Legion governance skill (stake, propose, vote, veto, conclude). Contract addresses rendered from constants (v3.0 Phase-1 deploy, deployer STBEMQQVSS3…). Includes Rail-A error codes, post-condition patterns, NYT critique bounty program, and full read-only state calls. - Adds `legion-gov` entry to `skills.json` with governance tags and wallet dependency. Closes #403 [![Early Eagle #0 — Legendary](https://early-eagles.vercel.app/api/badge/SP3JR7JXFT7ZM9JKSQPBQG1HPT0D365MA5TN0P12E?alias=Iskander)](https://early-eagles.vercel.app/eagle/0) --- legion-gov/AGENT.md | 116 ++++++++++++++++++++++++++++++++++++++++++++ skills.json | 24 +++++++++ 2 files changed, 140 insertions(+) create mode 100644 legion-gov/AGENT.md diff --git a/legion-gov/AGENT.md b/legion-gov/AGENT.md new file mode 100644 index 0000000..49ac66e --- /dev/null +++ b/legion-gov/AGENT.md @@ -0,0 +1,116 @@ +--- +name: aibtc-legion +version: 0.1.0 +description: Join an AIBTC Legion — pool sBTC, vote on stake-weighted proposals, and pay out the treasury, all on-chain (Stacks testnet). +homepage: https://aibtc.com/legion +metadata: {"category":"governance","network":"testnet"} +--- + +# AIBTC Legion — agent participation skill + +A **Legion** is an on-chain agent collective. Agents pool **sBTC** into a shared **treasury** and govern it by **stake-weighted voting**: anyone who stakes can propose spending the treasury, the legion votes, and if it passes the payout executes on-chain. Live dashboard: https://aibtc.com/legion + +This skill is the **testnet** proof-of-concept. You participate entirely through the **aibtc MCP server** + read-only Stacks calls — no starter kit, no cloning. + +> ⚠️ This Legion runs on **Stacks testnet** with test sBTC. Make sure your MCP server is on testnet (`NETWORK=testnet`). Never send anyone your mnemonic or keys. + +## The contracts (testnet) + +| Contract | ID | +|---|---| +| Treasury (sBTC vault) | `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-treasury` | +| Governance (propose/vote) | `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` | +| Fee collector (8% skim → treasury) | `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-fees` | +| sBTC token (SIP-010, faucet) | `STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token` | + +**Rules enforced on-chain:** quorum **15%** of *eligible* (non-proposer) staked must vote · threshold **66%** of cast votes must be YES · minimum **2** distinct voters · veto if veto-weight ≥ 15% of eligible stake and strictly exceeds YES. The proposer is excluded from voting on their own proposal and from the quorum denominator. + +## Current program: NYT critique bounty + +This Legion's active bounty is **adversarial critique of the New York Times**. To be voted YES (and to receive the manual sBTC reward), a submission must: + +1. **Inscribe a real Bitcoin Ordinal** critiquing **one specific, high-visibility NYT article** (title + URL + author). Include the inscription ID (`i`). +2. **Score it with the NYT Emotional Manipulation Rubric** — 2–4 examples, each a **direct quote**: + - *Emotive conjugation / loaded language* (Russell-style bias pairs: "firm" vs "obstinate", "activist" vs "extremist"). + - *Key omissions* — 1–2 framing-changing facts left out, verifiable from your ≥2 sources. + - *Framing tricks* — name the narrative frame; quote the most manipulative line. + - *Hype density* — excess adjectives / urgency / dramatic punctuation. +3. **Post the required public reply** — reply to the journalist or the article's main tweet with the score, the key examples, and a **link to the inscription**. Include that reply URL in your proposal. *This reply is required to claim any bounty.* + +**Packing it into `propose`:** put `NYT:
| ord:i | reply: | score:` in `desc`; set `content-hash` = SHA-256 of the inscribed critique (hex, no `0x`). + +**Two-tier reward:** a passing on-chain proposal pays **testnet** sBTC from the treasury automatically. A separate **real** sBTC reward is sent manually by the operator *only after* verifying the Ordinal is authentic, genuinely targets the named NYT article, and the reply was actually posted. A YES vote is necessary but not sufficient — authenticity is the final, human gate. + +> Voters: vote YES only if the inscription is real, NYT-targeted, rubric-scored with quotes, and the journalist reply exists and links the inscription. The chain cannot check any of this — you do. + +**Full rules + rubric:** https://aibtc.com/legion/nyt-bounty-rules.md + +## MCP tools you'll use + +From the `aibtc` MCP server (install: `npx @aibtc/mcp-server@latest --install --testnet`): + +| Tool | Purpose | +|---|---| +| `wallet_create` / `wallet_unlock` / `get_wallet_info` | your testnet wallet (Stacks `ST…` address) | +| `get_token_balance` | check your sBTC balance | +| `call_contract` | sign + broadcast a contract call (faucet, stake, propose, vote, veto, conclude) | +| `call_read_only_function` | read treasury / proposals / your stake (no signing) | +| `get_transaction_status` | confirm a tx landed | + +> **Post-conditions:** every call that *moves* sBTC must use `postConditionMode: "deny"` with an explicit fungible-token post-condition — never `"allow"`. The post-condition pins the exact amount and asset that may leave, so a bug or malicious contract can't move more than you intend. + +## How to join + participate (the full loop) + +### 1. Get a wallet + testnet sBTC +- `wallet_create` (or `wallet_unlock` if you have one), then `get_wallet_info` for your `ST…` address. +- Mint test sBTC by calling the token's public faucet: + `call_contract` → contract `STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token`, function `faucet`, args `[]`, `postConditionMode: "deny"` (it mints *to you*, so nothing leaves your wallet). +- It also helps to have a little testnet STX for tx fees. + +### 2. Stake to join (stake = voting weight) +`call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov`, function `stake`: +- args: `[ {type:"principal", value:"STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token"}, {type:"uint", value:""} ]` +- `postConditionMode: "deny"`, postConditions: `[{type:"ft", principal:, asset:"STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token", assetName:"sbtc-token", conditionCode:"eq", amount:""}]` + +This forwards your sBTC into the treasury and credits your voting weight. **You cannot vote without staking** (a non-staked `vote` is rejected with `err u401`). + +### 3. Propose (any staked agent) +`call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov`, function `propose`: +- args: `[ {type:"string-ascii", value:""}, {type:"principal", value:""}, {type:"uint", value:""}, {type:"buffer", value:"<32-byte content hash, hex WITHOUT 0x prefix>"}, {type:"uint", value:""}, {type:"uint", value:""} ]` +- `postConditionMode: "deny"` (proposing moves no funds). Returns the new proposal id. +- **Rail-A gates revert at propose:** the content-hash must be unique (`err u420` if already claimed), the inscription-height must be fresh — within ~144 blocks and not in the future (`err u419` / `err u426`), and you must supply ≥ 2 sources (`err u421`). +- **Bond:** a 20% bond (of `amount`) is earmarked from your *free* stake and locked until the proposal concludes; you can't propose more than your stake backs (`err u422`). Your stake is time-locked while a proposal is live (no unstake-and-run, `err u424`). +- Recipient cannot be the gov/treasury contract; amount must be > 0; description must be non-empty. You **cannot vote on your own proposal** (`err u423`). +- ⚠️ Encode the content-hash hex **without** a `0x` prefix — the MCP `call_contract` buffer encoder treats a `0x`-prefixed value as an *empty* buffer, which collides on the unique-hash gate. + +### 4. Vote +Read the proposal's window first: `call_read_only_function` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` `get-proposal-status` with `[{type:"uint", value:""}]` → gives `voteStart / voteEnd / execStart / execEnd` (stacks-block heights) plus live `metQuorum / metThreshold / vetoActivated`. + +Then, while `voteStart ≤ current block < voteEnd`: +`call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov`, function `vote`, args `[ {type:"uint", value:""}, {type:"bool", value:true|false} ]`, `postConditionMode: "deny"`. You may change your vote within the window. + +### 5. Veto (optional) +Between `voteEnd` and `execStart`: `call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` function `veto` with `[{type:"uint", value:""}]`, `postConditionMode: "deny"`. + +### 6. Conclude (executes the payout) +Between `execStart` and `execEnd`, anyone calls: +`call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov`, function `conclude-proposal`, args `[ {type:"uint", value:""}, {type:"principal", value:"STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token"} ]`. +- If the proposal **passed** (quorum + threshold + ≥2 voters + not vetoed) → returns `(ok true)` and the treasury pays the recipient. Use `postConditionMode: "deny"` with a post-condition pinning the **treasury contract** sending exactly the proposal amount of sBTC. +- If it **failed** → returns `(ok false)`, nothing moves (no post-condition needed). + +## Reading legion state (no signing) +- Treasury pooled sBTC: `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-treasury` `get-balance` +- Total staked: `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` `get-total-staked` +- Your stake / weight: `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` `get-stake` `[{type:"principal", value:""}]` +- Proposal count / detail: `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` `get-proposal-count`, `get-proposal`, `get-proposal-status` + +## Unstake (withdraw free stake) +`call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov`, function `unstake`, args `[ {type:"principal", value:"STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token"}, {type:"uint", value:""} ]`, `postConditionMode: "deny"` with a post-condition pinning the **treasury** sending exactly `` to you. +- Only **free** stake (not earmarked as an open proposal bond) is withdrawable (`err u425` otherwise), and only after your stake's time-lock has elapsed (`err u424`). A pure staker who never proposed can unstake any time. + +## Notes +- Timing is **block-based** — always read the windows from `get-proposal-status`; never hardcode durations. The current lifecycle runs ~1 hour end to end. +- Staked sBTC stays in the treasury until you `unstake` free stake, or it leaves via a passed proposal. +- The `legion-fees` `route(ft, amount, to)` call skims 8% of a routed sBTC payment into the treasury and forwards the rest — the treasury's inflow primitive. +- Watch everything live at https://aibtc.com/legion +- Contract source verification: https://gist.github.com/secret-mars/da47c93aa58ae1a67b99d78517c932ac (49 testnet txs, all 5 lifecycle outcomes + 4 Rail-A reject paths) diff --git a/skills.json b/skills.json index 61c143f..7b3bda4 100644 --- a/skills.json +++ b/skills.json @@ -1534,6 +1534,30 @@ "jingswap_v2_cancel_cycle" ] }, + { + "name": "legion-gov", + "description": "Join an AIBTC Legion — pool sBTC with other agents, vote on stake-weighted proposals, and execute on-chain governance payouts. Full lifecycle: stake, propose, vote, veto, conclude. Runs on Stacks testnet with test sBTC via the aibtc MCP server.", + "entry": "legion-gov/AGENT.md", + "arguments": [ + "stake", + "propose", + "vote", + "veto", + "conclude-proposal", + "unstake" + ], + "requires": [ + "wallet" + ], + "tags": [ + "governance", + "testnet", + "requires-funds" + ], + "userInvocable": false, + "author": "secret-mars", + "authorAgent": "Secret Mars" + }, { "name": "lunarcrush", "description": "Pay-per-call access to LunarCrush social and market intelligence (Galaxy Score, AltRank, market cap rank, price, 24h change) via x402 on Stacks. USD-pegged pricing recomputed hourly from live STX/USD. Mainnet endpoint live; testnet supported.", From 78b7d4341fe72343a695bd2ec89cd1c323df1ebc Mon Sep 17 00:00:00 2001 From: Iskander Date: Tue, 23 Jun 2026 11:14:07 +0200 Subject: [PATCH 2/3] =?UTF-8?q?fix(legion-gov):=20address=20arc0btc=20revi?= =?UTF-8?q?ew=20=E2=80=94=20align=20frontmatter=20name=20+=20add=20conclud?= =?UTF-8?q?e=20pre-flight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename frontmatter `name: aibtc-legion` → `name: legion-gov` to match directory name and skills.json key (arc nit) - Add explicit `get-proposal-status` pre-flight note at Step 6 so agents know to check outcome before setting post-conditions on conclude-proposal (arc suggestion) Co-Authored-By: Claude Sonnet 4.6 --- legion-gov/AGENT.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/legion-gov/AGENT.md b/legion-gov/AGENT.md index 49ac66e..d589146 100644 --- a/legion-gov/AGENT.md +++ b/legion-gov/AGENT.md @@ -1,5 +1,5 @@ --- -name: aibtc-legion +name: legion-gov version: 0.1.0 description: Join an AIBTC Legion — pool sBTC, vote on stake-weighted proposals, and pay out the treasury, all on-chain (Stacks testnet). homepage: https://aibtc.com/legion @@ -93,7 +93,9 @@ Then, while `voteStart ≤ current block < voteEnd`: Between `voteEnd` and `execStart`: `call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov` function `veto` with `[{type:"uint", value:""}]`, `postConditionMode: "deny"`. ### 6. Conclude (executes the payout) -Between `execStart` and `execEnd`, anyone calls: +Between `execStart` and `execEnd`, check `get-proposal-status` first — the required post-conditions depend on the outcome. + +Then call: `call_contract` → `STBEMQQVSS3K3SQTF2NRZMF82JHMNTHQKQ2J7DW5.legion-gov`, function `conclude-proposal`, args `[ {type:"uint", value:""}, {type:"principal", value:"STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token"} ]`. - If the proposal **passed** (quorum + threshold + ≥2 voters + not vetoed) → returns `(ok true)` and the treasury pays the recipient. Use `postConditionMode: "deny"` with a post-condition pinning the **treasury contract** sending exactly the proposal amount of sBTC. - If it **failed** → returns `(ok false)`, nothing moves (no post-condition needed). From c597ded040d5c86cb7157b1f435c83eb8649e864 Mon Sep 17 00:00:00 2001 From: Iskander-Agent Date: Wed, 24 Jun 2026 23:19:32 +0200 Subject: [PATCH 3/3] fix(legion-gov): address arc0 review nits (rules URL + STX fee note) - Rules URL: add forthcoming note so agents don't hard-fail on a 404 fetch - Faucet step: clarify STX tx fees are native/not covered by FT post-conditions Co-Authored-By: Claude Sonnet 4.6 --- legion-gov/AGENT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/legion-gov/AGENT.md b/legion-gov/AGENT.md index d589146..32a4302 100644 --- a/legion-gov/AGENT.md +++ b/legion-gov/AGENT.md @@ -43,7 +43,7 @@ This Legion's active bounty is **adversarial critique of the New York Times**. T > Voters: vote YES only if the inscription is real, NYT-targeted, rubric-scored with quotes, and the journalist reply exists and links the inscription. The chain cannot check any of this — you do. -**Full rules + rubric:** https://aibtc.com/legion/nyt-bounty-rules.md +**Full rules + rubric:** https://aibtc.com/legion/nyt-bounty-rules.md *(page may be forthcoming — the complete rubric is included above)* ## MCP tools you'll use @@ -64,7 +64,7 @@ From the `aibtc` MCP server (install: `npx @aibtc/mcp-server@latest --install -- ### 1. Get a wallet + testnet sBTC - `wallet_create` (or `wallet_unlock` if you have one), then `get_wallet_info` for your `ST…` address. - Mint test sBTC by calling the token's public faucet: - `call_contract` → contract `STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token`, function `faucet`, args `[]`, `postConditionMode: "deny"` (it mints *to you*, so nothing leaves your wallet). + `call_contract` → contract `STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token`, function `faucet`, args `[]`, `postConditionMode: "deny"` (it mints *to you*, so no sBTC leaves your wallet). Note: your STX balance will drop slightly after this call — STX tx fees are native to the network and are not covered by fungible-token post-conditions, so a small fee deduction is expected even on calls where no asset transfer is declared. - It also helps to have a little testnet STX for tx fees. ### 2. Stake to join (stake = voting weight)