diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13c82144..98abed04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,17 @@ jobs: - name: TypeScript typecheck run: bun run typecheck + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install skills-ref (required by bun run validate for tier-1 spec checks) + run: | + pip install click strictyaml + echo "skills-ref==0.1.1 --hash=sha256:d35db5bb8de71ae301daf5ca9cb71f8a555e8c6f83a6d40e46a5bc09f8f461b5" > /tmp/skills-ref-req.txt + pip install --no-deps --require-hashes -r /tmp/skills-ref-req.txt + - name: Validate skill frontmatter run: bun run validate diff --git a/aibtc-news/aibtc-news.ts b/aibtc-news/aibtc-news.ts index a9f78b2e..500357b8 100644 --- a/aibtc-news/aibtc-news.ts +++ b/aibtc-news/aibtc-news.ts @@ -354,13 +354,14 @@ program const body: Record = { beat_slug: opts.beatId, + btc_address: headers["X-BTC-Address"], content: opts.content, }; if (opts.headline) body.headline = opts.headline; if (sources.length > 0) body.sources = sources; if (tags.length > 0) body.tags = tags; - if (disclosure !== undefined) body.disclosure = disclosure; + if (disclosure !== undefined) body.disclosure = typeof disclosure === "string" ? disclosure : JSON.stringify(disclosure); // Step 1: POST with auth headers — may return 200 (free) or 402 (x402 payment required) const signalsUrl = `${NEWS_API_BASE}/signals`; @@ -413,7 +414,7 @@ program const { getStacksNetwork } = await import("../src/lib/config/networks.js"); const { createFungiblePostCondition } = await import("../src/lib/transactions/post-conditions.js"); const { getHiroApi } = await import("../src/lib/services/hiro-api.js"); - const { getAccount } = await import("../src/lib/services/wallet-manager.js"); + const { getAccount } = await import("../src/lib/services/x402.service.js"); const paymentRequired = decodePaymentRequired(paymentHeader); if (!paymentRequired?.accepts?.length) { @@ -645,6 +646,8 @@ program const body: Record = { beat_slug: opts.beatId, + slug: opts.beatId, + created_by: headers["X-BTC-Address"], }; if (opts.name) body.name = opts.name; diff --git a/package.json b/package.json index 01c66c7e..655c8603 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Claude Code skills for Bitcoin/Stacks blockchain operations — flat SKILL.md + colocated TypeScript CLI scripts.", "type": "module", "scripts": { - "build": "bun build src/lib/index.ts --outdir dist", + "build": "bun build src/lib/index.ts --outdir dist --target bun", "typecheck": "tsc --noEmit", "manifest": "bun run scripts/generate-manifest.ts", "validate": "bun run scripts/validate-frontmatter.ts", diff --git a/scripts/validate-frontmatter.ts b/scripts/validate-frontmatter.ts index 210e5ebc..66448ed8 100644 --- a/scripts/validate-frontmatter.ts +++ b/scripts/validate-frontmatter.ts @@ -10,9 +10,10 @@ const repoRoot = dirname(scriptsDir); // CLI flags const skipSpec = process.argv.includes("--skip-spec"); -// Find the skills-ref binary: prefer local venv, fall back to PATH +// Find the agentskills binary: prefer local venv, fall back to PATH +// Note: skills-ref PyPI package >= 0.1.1 installs the CLI as `agentskills` (renamed from `skills-ref`) async function findSkillsRef(): Promise { - const localBin = join(repoRoot, ".venv-skills-ref/bin/skills-ref"); + const localBin = join(repoRoot, ".venv-skills-ref/bin/agentskills"); try { const stat = await Bun.file(localBin).stat(); if (stat.size > 0) return localBin; @@ -20,8 +21,8 @@ async function findSkillsRef(): Promise { // not found locally } // Fall back to PATH (cross-platform) - const pathResult = Bun.which("skills-ref"); - if (pathResult) return "skills-ref"; + const pathResult = Bun.which("agentskills"); + if (pathResult) return "agentskills"; return null; } @@ -145,7 +146,7 @@ if (!skipSpec) { skillsRefBin = await findSkillsRef(); if (skillsRefBin === null) { process.stderr.write( - "WARNING: skills-ref not found. Skipping tier-1 spec validation. Install with: pip install skills-ref\n" + "WARNING: agentskills not found. Skipping tier-1 spec validation. Install with: pip install skills-ref\n" ); } } @@ -153,7 +154,7 @@ if (!skipSpec) { // Print active tiers const tier1Active = !skipSpec && skillsRefBin !== null; console.log( - `Validation tiers: ${tier1Active ? "[tier-1: skills-ref]" : "[tier-1: SKIPPED]"} [tier-2: Zod]` + `Validation tiers: ${tier1Active ? "[tier-1: agentskills]" : "[tier-1: SKIPPED]"} [tier-2: Zod]` ); console.log("");