pulse-protocol 0.9.3 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@ Fake ones don't.
11
11
 
12
12
  [![WEBSITE](https://img.shields.io/badge/▲%20WEBSITE-PULSEPROTOCOL.TECH-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://pulseprotocol.tech)
13
13
  [![NPM](https://img.shields.io/badge/📦%20NPM-PULSE--PROTOCOL-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://www.npmjs.com/package/pulse-protocol)
14
- [![GITHUB](https://img.shields.io/badge/⌨%20GITHUB-PULSE--PROTOCOL-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://github.com/pulseprotocol/pulse-protocol)
14
+ [![GITHUB](https://img.shields.io/badge/⌨%20GITHUB-PULSE--PROTOCOL-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://github.com/williambrowndev/pulse-protocol)
15
15
  [![TWITTER](https://img.shields.io/badge/𝕏%20TWITTER-@PULSEPROTOCOL__-0a0a0f?style=for-the-badge&labelColor=0a0a0f)](https://x.com/pulseprotocol_)
16
16
 
17
17
  </div>
@@ -275,7 +275,7 @@ The highest-value contribution is **labeled targets**: if you know of an agent t
275
275
 
276
276
  ## Security
277
277
 
278
- Found a scoring bug or an adversarial pattern that lets a fake agent pass as AUTONOMOUS? Open a [GitHub Security Advisory](https://github.com/pulseprotocol/pulse-protocol/security/advisories/new).
278
+ Found a scoring bug or an adversarial pattern that lets a fake agent pass as AUTONOMOUS? Open a [GitHub Security Advisory](https://github.com/williambrowndev/pulse-protocol/security/advisories/new).
279
279
 
280
280
  ---
281
281
 
@@ -289,6 +289,6 @@ MIT. See [LICENSE](./LICENSE).
289
289
 
290
290
  ### fake agents have no pulse.
291
291
 
292
- **[Website](https://pulseprotocol.tech)** · **[X](https://x.com/pulseprotocol_)** · **[GitHub](https://github.com/pulseprotocol/pulse-protocol)** · **[Docs](./docs)**
292
+ **[Website](https://pulseprotocol.tech)** · **[X](https://x.com/pulseprotocol_)** · **[GitHub](https://github.com/williambrowndev/pulse-protocol)** · **[Docs](./docs)**
293
293
 
294
294
  </div>
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/index.ts","../src/core/client.ts","../src/core/errors.ts","../src/sources/helius.ts","../src/sources/x.ts","../src/detectors/cadence.ts","../src/detectors/onchain.ts","../src/detectors/voice.ts","../src/detectors/timing.ts","../src/detectors/correlation.ts","../src/core/aggregator.ts","../src/core/signing.ts","../src/index.ts","../src/cli/print.ts","../src/daemon/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { PulseProtocol, VERSION } from \"../index.js\";\nimport { printVerdict } from \"./print.js\";\nimport { runDaemon } from \"../daemon/index.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"pulse\")\n .description(\"Pulse Protocol — fake agents have no pulse\")\n .version(VERSION);\n\nprogram\n .command(\"scan\")\n .description(\"Scan a target and return a verdict\")\n .requiredOption(\"--handle <handle>\", \"X / Twitter handle (no @)\")\n .requiredOption(\"--wallet <wallet>\", \"Solana wallet address\")\n .option(\"--out <format>\", \"Output format: pretty | json | verdict-only\", \"pretty\")\n .option(\"--no-post\", \"Do not publish verdict to the public feed\")\n .action(async (opts) => {\n const config = loadConfig();\n const pulse = new PulseProtocol(config);\n\n const spinner = ora({\n text: chalk.magenta(`scanning @${opts.handle}...`),\n color: \"magenta\",\n }).start();\n\n try {\n const verdict = await pulse.scan(\n { handle: opts.handle, wallet: opts.wallet },\n { noPost: !opts.post }\n );\n spinner.stop();\n printVerdict(verdict, opts.out);\n } catch (err) {\n spinner.fail(chalk.red((err as Error).message));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"watch\")\n .description(\"Start a watchlist daemon that re-scans targets on an interval\")\n .option(\"--config <path>\", \"Path to watchlist YAML\")\n .option(\"--interval <duration>\", \"Scan interval\", \"6h\")\n .option(\"--webhook <url>\", \"POST verdict changes to this URL\")\n .action(async (opts) => {\n const config = loadConfig();\n const watchlistPath =\n opts.config ?? path.join(os.homedir(), \".config/pulse/watchlist.yaml\");\n\n if (!fs.existsSync(watchlistPath)) {\n console.error(chalk.red(`watchlist not found: ${watchlistPath}`));\n console.log(chalk.gray(`create one with:`));\n console.log(chalk.gray(` targets:\\n - handle: foo\\n wallet: abc...`));\n process.exit(1);\n }\n\n await runDaemon({\n config,\n watchlistPath,\n interval: opts.interval,\n webhook: opts.webhook,\n });\n });\n\nprogram\n .command(\"init\")\n .description(\"Initialize ~/.config/pulse/.env with empty keys\")\n .action(() => {\n const dir = path.join(os.homedir(), \".config/pulse\");\n fs.mkdirSync(dir, { recursive: true });\n const envPath = path.join(dir, \".env\");\n if (fs.existsSync(envPath)) {\n console.log(chalk.yellow(`already exists: ${envPath}`));\n return;\n }\n fs.writeFileSync(\n envPath,\n `# Pulse Protocol configuration\\nHELIUS_API_KEY=\\nX_API_KEY=\\n`\n );\n console.log(chalk.green(`created ${envPath}`));\n console.log(chalk.gray(`fill in your API keys, then run: pulse scan --help`));\n });\n\nprogram\n .command(\"feed\")\n .description(\"Stream the public verdict feed\")\n .action(() => {\n console.log(chalk.magenta(\"streaming public feed...\"));\n console.log(chalk.gray(\"(connect to wss://feed.pulseprotocol.tech/ws)\"));\n });\n\nprogram\n .command(\"verify <verdictId>\")\n .description(\"Verify the signature on a public verdict\")\n .action((verdictId: string) => {\n console.log(chalk.magenta(`verifying ${verdictId}...`));\n console.log(chalk.gray(\"(fetches from https://pulseprotocol.tech/v/)\"));\n });\n\nfunction loadConfig() {\n const envPath = path.join(os.homedir(), \".config/pulse/.env\");\n if (fs.existsSync(envPath)) {\n const env = fs.readFileSync(envPath, \"utf8\");\n for (const line of env.split(\"\\n\")) {\n const match = line.match(/^([A-Z_]+)=(.*)$/);\n if (match && match[1] && !process.env[match[1]]) {\n process.env[match[1]] = match[2];\n }\n }\n }\n\n const heliusApiKey = process.env.HELIUS_API_KEY;\n const xApiKey = process.env.X_API_KEY;\n\n if (!heliusApiKey || !xApiKey) {\n console.error(chalk.red(\"missing HELIUS_API_KEY or X_API_KEY\"));\n console.error(chalk.gray(\"run: pulse init\"));\n process.exit(1);\n }\n\n return { heliusApiKey, xApiKey };\n}\n\nprogram.parse(process.argv);\n","import { EventEmitter } from \"eventemitter3\";\nimport { HeliusSource } from \"../sources/helius.js\";\nimport { XSource } from \"../sources/x.js\";\nimport { cadenceDetector } from \"../detectors/cadence.js\";\nimport { onchainDetector } from \"../detectors/onchain.js\";\nimport { voiceDetector } from \"../detectors/voice.js\";\nimport { timingDetector } from \"../detectors/timing.js\";\nimport { correlationDetector } from \"../detectors/correlation.js\";\nimport { aggregate } from \"./aggregator.js\";\nimport { ScanError } from \"./errors.js\";\nimport type {\n PulseConfig,\n ScanInput,\n ScanOptions,\n Verdict,\n DetectorResult,\n DetectorName,\n} from \"./types.js\";\n\n/**\n * The main entry point for Pulse Protocol.\n *\n * @example\n * ```ts\n * const pulse = new PulseProtocol({\n * heliusApiKey: process.env.HELIUS_API_KEY!,\n * xApiKey: process.env.X_API_KEY!,\n * });\n *\n * const verdict = await pulse.scan({\n * handle: \"some_agent\",\n * wallet: \"6ySH9oi...\",\n * });\n * ```\n */\nexport class PulseProtocol {\n readonly events: EventEmitter;\n\n private readonly helius: HeliusSource;\n private readonly x: XSource;\n private readonly config: Required<Omit<PulseConfig, \"signingKey\" | \"rpcUrl\" | \"feedUrl\">> &\n Pick<PulseConfig, \"signingKey\" | \"rpcUrl\" | \"feedUrl\">;\n\n constructor(config: PulseConfig) {\n if (!config.heliusApiKey) {\n throw new Error(\"heliusApiKey is required. Get one at https://helius.xyz\");\n }\n if (!config.xApiKey) {\n throw new Error(\"xApiKey is required.\");\n }\n\n this.config = {\n heliusApiKey: config.heliusApiKey,\n xApiKey: config.xApiKey,\n rpcUrl: config.rpcUrl,\n feedUrl: config.feedUrl,\n signingKey: config.signingKey,\n timeout: config.timeout ?? 30_000,\n maxRetries: config.maxRetries ?? 2,\n };\n\n this.helius = new HeliusSource({\n apiKey: config.heliusApiKey,\n rpcUrl: config.rpcUrl,\n timeout: this.config.timeout,\n maxRetries: this.config.maxRetries,\n });\n\n this.x = new XSource({\n apiKey: config.xApiKey,\n timeout: this.config.timeout,\n maxRetries: this.config.maxRetries,\n });\n\n this.events = new EventEmitter();\n }\n\n /**\n * Run a full scan on a target and return a verdict.\n *\n * This fetches X posts, on-chain history, cross-correlates them, runs all\n * five detectors, and aggregates the result. A typical scan completes in\n * 2-8 seconds depending on source latency.\n */\n async scan(input: ScanInput, options: ScanOptions = {}): Promise<Verdict> {\n this.events.emit(\"scan:start\", input);\n\n const [posts, txs] = await Promise.all([\n this.x.getRecentPosts(input.handle, { limit: 200 }),\n this.helius.getWalletHistory(input.wallet, { limit: 500 }),\n ]);\n\n if (posts.length === 0 && txs.length === 0) {\n throw new ScanError(\n `No data found for @${input.handle} or wallet ${input.wallet.slice(0, 8)}...`\n );\n }\n\n const requested: DetectorName[] =\n options.only ?? [\"cadence\", \"onchain\", \"voice\", \"timing\", \"correlation\"];\n\n const results: DetectorResult[] = [];\n\n for (const name of requested) {\n const started = Date.now();\n try {\n let result: DetectorResult;\n switch (name) {\n case \"cadence\":\n result = cadenceDetector(posts);\n break;\n case \"onchain\":\n result = onchainDetector(txs);\n break;\n case \"voice\":\n result = voiceDetector(posts);\n break;\n case \"timing\":\n result = timingDetector(posts, txs);\n break;\n case \"correlation\":\n result = correlationDetector(posts, txs, input);\n break;\n }\n result.runtime_ms = Date.now() - started;\n results.push(result);\n this.events.emit(\"detector:done\", result);\n } catch (err) {\n throw new ScanError(\n `Detector ${name} failed: ${(err as Error).message}`,\n name\n );\n }\n }\n\n const verdict = aggregate(input, results, options);\n this.events.emit(\"scan:done\", verdict);\n return verdict;\n }\n\n /**\n * Scan a batch of targets concurrently. Respects the configured rate limits\n * on underlying sources. Use for watchlists.\n */\n async scanMany(inputs: ScanInput[], options: ScanOptions = {}): Promise<Verdict[]> {\n const results: Verdict[] = [];\n for (const input of inputs) {\n try {\n results.push(await this.scan(input, options));\n } catch (err) {\n this.events.emit(\"scan:error\", { input, error: err });\n }\n }\n return results;\n }\n}\n","/**\n * Error hierarchy used throughout Pulse Protocol. All errors extend the base\n * `PulseError` class so consumers can catch everything with one instanceof.\n */\n\nexport class PulseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PulseError\";\n Object.setPrototypeOf(this, PulseError.prototype);\n }\n}\n\n/** A scan failed entirely (one or more detectors could not run). */\nexport class ScanError extends PulseError {\n readonly detector?: string;\n constructor(message: string, detector?: string) {\n super(message);\n this.name = \"ScanError\";\n this.detector = detector;\n Object.setPrototypeOf(this, ScanError.prototype);\n }\n}\n\n/** A data source (Helius, X, DexScreener) returned an error or timed out. */\nexport class SourceError extends PulseError {\n readonly source: string;\n readonly status?: number;\n constructor(source: string, message: string, status?: number) {\n super(`${source}: ${message}`);\n this.name = \"SourceError\";\n this.source = source;\n this.status = status;\n Object.setPrototypeOf(this, SourceError.prototype);\n }\n}\n\n/** A published verdict failed signature verification. */\nexport class SignatureError extends PulseError {\n constructor(message: string) {\n super(message);\n this.name = \"SignatureError\";\n Object.setPrototypeOf(this, SignatureError.prototype);\n }\n}\n","import { SourceError } from \"../core/errors.js\";\n\nexport interface HeliusTransaction {\n signature: string;\n timestamp: number;\n fee: number;\n programs: string[];\n type: string;\n}\n\nexport interface HeliusSourceConfig {\n apiKey: string;\n rpcUrl?: string;\n timeout: number;\n maxRetries: number;\n}\n\n/**\n * Helius adapter. Fetches wallet transaction history via the enhanced\n * transactions endpoint, normalizes it into `HeliusTransaction` records,\n * and exposes it to detectors.\n */\nexport class HeliusSource {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n\n constructor(config: HeliusSourceConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.rpcUrl ?? \"https://api.helius.xyz/v0\";\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries;\n }\n\n async getWalletHistory(\n wallet: string,\n opts: { limit?: number; before?: string } = {}\n ): Promise<HeliusTransaction[]> {\n const limit = opts.limit ?? 100;\n const url = new URL(`${this.baseUrl}/addresses/${wallet}/transactions`);\n url.searchParams.set(\"api-key\", this.apiKey);\n url.searchParams.set(\"limit\", String(Math.min(limit, 100)));\n if (opts.before) url.searchParams.set(\"before\", opts.before);\n\n const raw = await this.fetchWithRetry(url);\n if (!Array.isArray(raw)) {\n throw new SourceError(\"helius\", \"unexpected response shape\");\n }\n\n return raw.map((tx: unknown) => {\n const t = tx as Record<string, unknown>;\n return {\n signature: String(t.signature ?? \"\"),\n timestamp: Number(t.timestamp ?? 0),\n fee: Number(t.fee ?? 0),\n programs: Array.isArray(t.accountData)\n ? extractPrograms(t as HeliusRawTx)\n : [],\n type: String(t.type ?? \"UNKNOWN\"),\n };\n });\n }\n\n private async fetchWithRetry(url: URL): Promise<unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timer);\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"2\");\n await sleep(retryAfter * 1000);\n continue;\n }\n if (!res.ok) {\n throw new SourceError(\n \"helius\",\n `HTTP ${res.status}`,\n res.status\n );\n }\n return await res.json();\n } catch (err) {\n lastError = err;\n if (attempt < this.maxRetries) {\n await sleep(500 * (attempt + 1));\n }\n }\n }\n throw lastError instanceof Error\n ? new SourceError(\"helius\", lastError.message)\n : new SourceError(\"helius\", \"unknown error\");\n }\n}\n\ninterface HeliusRawTx {\n accountData?: Array<{ account?: string; nativeBalanceChange?: number }>;\n instructions?: Array<{ programId?: string }>;\n}\n\nfunction extractPrograms(tx: HeliusRawTx): string[] {\n const programs = new Set<string>();\n for (const ix of tx.instructions ?? []) {\n if (ix.programId) programs.add(ix.programId);\n }\n return Array.from(programs);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import { SourceError } from \"../core/errors.js\";\n\nexport interface XPost {\n id: string;\n text: string;\n created_at: number;\n reply_count: number;\n like_count: number;\n retweet_count: number;\n in_reply_to_id?: string;\n reply_delta_ms?: number;\n}\n\nexport interface XSourceConfig {\n apiKey: string;\n baseUrl?: string;\n timeout: number;\n maxRetries: number;\n}\n\n/**\n * Generic X / Twitter adapter. Talks to the `twitterapi.io` bridge by\n * default but accepts any compatible endpoint via `baseUrl`.\n */\nexport class XSource {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n\n constructor(config: XSourceConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.twitterapi.io\";\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries;\n }\n\n async getRecentPosts(\n handle: string,\n opts: { limit?: number } = {}\n ): Promise<XPost[]> {\n const limit = opts.limit ?? 100;\n const url = new URL(`${this.baseUrl}/twitter/user/last_tweets`);\n url.searchParams.set(\"userName\", handle);\n\n const raw = (await this.fetchWithRetry(url)) as Record<string, unknown>;\n const tweets = Array.isArray(raw.tweets)\n ? raw.tweets\n : Array.isArray((raw.data as Record<string, unknown>)?.tweets)\n ? (raw.data as { tweets: unknown[] }).tweets\n : [];\n\n const posts: XPost[] = [];\n for (const t of tweets.slice(0, limit)) {\n const obj = t as Record<string, unknown>;\n const createdAt = parseDate(obj.createdAt);\n if (!createdAt) continue;\n\n posts.push({\n id: String(obj.id ?? \"\"),\n text: String(obj.text ?? \"\"),\n created_at: createdAt,\n reply_count: Number(obj.replyCount ?? 0),\n like_count: Number(obj.likeCount ?? 0),\n retweet_count: Number(obj.retweetCount ?? 0),\n in_reply_to_id: obj.inReplyToId ? String(obj.inReplyToId) : undefined,\n });\n }\n\n // Compute reply deltas if we have the info.\n for (let i = 0; i < posts.length; i++) {\n const p = posts[i]!;\n if (p.in_reply_to_id) {\n const parent = posts.find((x) => x.id === p.in_reply_to_id);\n if (parent) {\n p.reply_delta_ms = (p.created_at - parent.created_at) * 1000;\n }\n }\n }\n\n return posts;\n }\n\n private async fetchWithRetry(url: URL): Promise<unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n const res = await fetch(url, {\n signal: controller.signal,\n headers: { \"X-API-Key\": this.apiKey },\n });\n clearTimeout(timer);\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"2\");\n await sleep(retryAfter * 1000);\n continue;\n }\n if (!res.ok) {\n throw new SourceError(\"x\", `HTTP ${res.status}`, res.status);\n }\n return await res.json();\n } catch (err) {\n lastError = err;\n if (attempt < this.maxRetries) {\n await sleep(500 * (attempt + 1));\n }\n }\n }\n throw lastError instanceof Error\n ? new SourceError(\"x\", lastError.message)\n : new SourceError(\"x\", \"unknown error\");\n }\n}\n\nfunction parseDate(v: unknown): number | null {\n if (typeof v === \"number\") return v;\n if (typeof v !== \"string\") return null;\n const parsed = Date.parse(v);\n return isNaN(parsed) ? null : Math.floor(parsed / 1000);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\n\n/**\n * Cadence detector.\n *\n * Autonomous agents post at regular intervals, at all hours of the day, and\n * show no business-hours bias. Humans cluster posts in their waking hours\n * and go quiet during sleep.\n *\n * Signals analyzed:\n * - Hour-of-day distribution entropy (high entropy = agent-like)\n * - Business-hours ratio (0.4-0.8 is typical for humans, <0.3 for agents)\n * - Interval-between-posts standard deviation (agents = low variance)\n * - Sleep-window detection (5am-9am local dead zone = human)\n */\nexport function cadenceDetector(posts: XPost[]): DetectorResult {\n const notes: string[] = [];\n\n if (posts.length < 20) {\n notes.push(`only ${posts.length} posts available, low confidence`);\n return {\n detector: \"cadence\",\n score: 50,\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Bucket by hour of day (UTC).\n const hourBuckets = new Array(24).fill(0);\n for (const p of posts) {\n const hour = new Date(p.created_at * 1000).getUTCHours();\n hourBuckets[hour]++;\n }\n\n // Shannon entropy of the distribution (0 = all same hour, log2(24) = uniform).\n const total = posts.length;\n let entropy = 0;\n for (const count of hourBuckets) {\n if (count > 0) {\n const p = count / total;\n entropy -= p * Math.log2(p);\n }\n }\n const entropyScore = (entropy / Math.log2(24)) * 100;\n notes.push(`hour entropy: ${entropy.toFixed(2)} bits (${entropyScore.toFixed(0)}/100)`);\n\n // Business hours bias (9:00 - 18:00 UTC, adjust if you have timezone).\n const businessHours = hourBuckets.slice(9, 18).reduce((a, b) => a + b, 0);\n const businessRatio = businessHours / total;\n notes.push(`business-hours ratio: ${(businessRatio * 100).toFixed(1)}%`);\n\n // Sleep window detection (4am - 8am UTC by default).\n const sleepWindow = hourBuckets.slice(4, 8).reduce((a, b) => a + b, 0);\n const sleepRatio = sleepWindow / total;\n const hasDeadZone = sleepRatio < 0.05;\n notes.push(\n hasDeadZone\n ? `sleep window detected (${(sleepRatio * 100).toFixed(1)}% posts in 4-8am)`\n : `no sleep window (${(sleepRatio * 100).toFixed(1)}% posts in 4-8am)`\n );\n\n // Interval variance.\n const sorted = [...posts].sort((a, b) => a.created_at - b.created_at);\n const intervals: number[] = [];\n for (let i = 1; i < sorted.length; i++) {\n intervals.push(sorted[i]!.created_at - sorted[i - 1]!.created_at);\n }\n const meanInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n const variance =\n intervals.reduce((a, b) => a + (b - meanInterval) ** 2, 0) /\n intervals.length;\n const cv = Math.sqrt(variance) / meanInterval; // coefficient of variation\n notes.push(`interval CV: ${cv.toFixed(2)} (lower = more regular = agent-like)`);\n\n // Aggregate the four sub-signals into a 0-100 score.\n let score = 0;\n score += entropyScore * 0.4;\n score += (1 - Math.abs(businessRatio - 0.15)) * 100 * 0.25; // 15% business hours is agent-like baseline\n score += (hasDeadZone ? 0 : 100) * 0.2;\n score += Math.max(0, 100 - cv * 30) * 0.15;\n\n return {\n detector: \"cadence\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { HeliusTransaction } from \"../sources/helius.js\";\n\n/**\n * On-chain cadence detector.\n *\n * Autonomous agents transact in bursts when triggered by external events,\n * and show either perfectly regular cron-like activity or reactive bursts.\n * Humans transact sporadically with long gaps and clustered around waking\n * hours.\n *\n * Signals analyzed:\n * - Transaction time-of-day distribution\n * - Burst detection (many txs within seconds = bot)\n * - Program diversity (agents hit few programs, humans hit many)\n * - Fee behavior (agents pay consistent priority fees)\n */\nexport function onchainDetector(txs: HeliusTransaction[]): DetectorResult {\n const notes: string[] = [];\n\n if (txs.length < 10) {\n notes.push(`only ${txs.length} transactions, low confidence`);\n return {\n detector: \"onchain\",\n score: 50,\n samples: txs.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Time-of-day distribution.\n const hourBuckets = new Array(24).fill(0);\n for (const t of txs) {\n const hour = new Date(t.timestamp * 1000).getUTCHours();\n hourBuckets[hour]++;\n }\n let entropy = 0;\n for (const count of hourBuckets) {\n if (count > 0) {\n const p = count / txs.length;\n entropy -= p * Math.log2(p);\n }\n }\n const entropyScore = (entropy / Math.log2(24)) * 100;\n notes.push(`onchain hour entropy: ${entropy.toFixed(2)} bits`);\n\n // Burst detection: how many tx clusters have >3 txs within 10 seconds?\n const sorted = [...txs].sort((a, b) => a.timestamp - b.timestamp);\n let bursts = 0;\n for (let i = 0; i < sorted.length - 3; i++) {\n const window = sorted[i + 3]!.timestamp - sorted[i]!.timestamp;\n if (window <= 10) bursts++;\n }\n const burstRatio = bursts / Math.max(1, sorted.length - 3);\n notes.push(`burst clusters: ${bursts} (${(burstRatio * 100).toFixed(1)}% of windows)`);\n\n // Program diversity: unique program IDs touched.\n const programs = new Set<string>();\n for (const t of txs) {\n for (const p of t.programs ?? []) {\n programs.add(p);\n }\n }\n const diversityScore = Math.min(100, programs.size * 10);\n notes.push(`${programs.size} unique programs touched`);\n\n // Fee consistency: std dev of priority fees (lower = bot-like).\n const fees = txs.map((t) => t.fee ?? 5000).filter((f) => f > 0);\n const meanFee = fees.reduce((a, b) => a + b, 0) / Math.max(1, fees.length);\n const feeStd = Math.sqrt(\n fees.reduce((a, b) => a + (b - meanFee) ** 2, 0) / Math.max(1, fees.length)\n );\n const feeCV = meanFee > 0 ? feeStd / meanFee : 0;\n notes.push(`fee CV: ${feeCV.toFixed(2)}`);\n\n // Aggregate.\n let score = 0;\n score += entropyScore * 0.35;\n score += Math.min(100, burstRatio * 300) * 0.3;\n score += (100 - diversityScore) * 0.2; // low diversity = more agent-like\n score += Math.max(0, 100 - feeCV * 50) * 0.15;\n\n return {\n detector: \"onchain\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: txs.length,\n notes,\n runtime_ms: 0,\n };\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\n\n/**\n * Voice consistency detector.\n *\n * Humans make typos that evolve over time, reuse unique phrases, drift in\n * tone, and use emoji inconsistently. Autonomous agents have frozen voice:\n * stable vocabulary, no typos, consistent phrase templates, predictable\n * emoji usage.\n *\n * Returns a HIGHER score for more consistent (agent-like) voice.\n */\nexport function voiceDetector(posts: XPost[]): DetectorResult {\n const notes: string[] = [];\n\n if (posts.length < 15) {\n notes.push(`only ${posts.length} posts, low confidence`);\n return {\n detector: \"voice\",\n score: 50,\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Lexical diversity: unique tokens / total tokens.\n const allTokens: string[] = [];\n for (const p of posts) {\n const tokens = tokenize(p.text);\n allTokens.push(...tokens);\n }\n const uniqueRatio = new Set(allTokens).size / allTokens.length;\n notes.push(`lexical diversity: ${uniqueRatio.toFixed(3)}`);\n\n // Typo detection: very rough heuristic (repeated chars, no-vowel words).\n let typoCount = 0;\n for (const p of posts) {\n if (/([a-z])\\1{2,}/i.test(p.text)) typoCount++;\n if (/\\b[bcdfghjklmnpqrstvwxyz]{4,}\\b/i.test(p.text)) typoCount++;\n }\n const typoRate = typoCount / posts.length;\n notes.push(`typo rate: ${(typoRate * 100).toFixed(1)}%`);\n\n // Phrase repetition: how many 3-word sequences appear more than once?\n const trigrams = new Map<string, number>();\n for (const p of posts) {\n const tokens = tokenize(p.text);\n for (let i = 0; i < tokens.length - 2; i++) {\n const key = `${tokens[i]} ${tokens[i + 1]} ${tokens[i + 2]}`;\n trigrams.set(key, (trigrams.get(key) ?? 0) + 1);\n }\n }\n const repeated = Array.from(trigrams.values()).filter((v) => v > 1).length;\n const repetitionRate = repeated / Math.max(1, trigrams.size);\n notes.push(`phrase repetition: ${(repetitionRate * 100).toFixed(1)}%`);\n\n // Emoji consistency: ratio of posts containing any emoji.\n const emojiRegex = /[\\p{Emoji_Presentation}]/u;\n const withEmoji = posts.filter((p) => emojiRegex.test(p.text)).length;\n const emojiRatio = withEmoji / posts.length;\n const emojiConsistency = Math.abs(emojiRatio - 0.5) * 2; // 0 or 1 both = consistent\n notes.push(`emoji ratio: ${(emojiRatio * 100).toFixed(0)}%`);\n\n // Aggregate. Higher score = more agent-like (more consistent).\n let score = 0;\n score += (1 - uniqueRatio) * 100 * 0.35; // lower diversity = more agent\n score += (1 - typoRate) * 100 * 0.25; // fewer typos = more agent\n score += repetitionRate * 100 * 0.2;\n score += emojiConsistency * 100 * 0.2;\n\n return {\n detector: \"voice\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n}\n\nfunction tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .replace(/https?:\\/\\/\\S+/g, \"\")\n .replace(/[^a-z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((t) => t.length > 1);\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\nimport type { HeliusTransaction } from \"../sources/helius.js\";\n\n/**\n * Timing anomaly detector.\n *\n * Returns a count of anomalies rather than a 0-100 score. The aggregator\n * normalizes the count to a score (0 anomalies = 100, 10+ = 0).\n *\n * Anomalies flagged:\n * - Sub-second response times (bot-like)\n * - Perfect regularity in posting intervals (cron job signature)\n * - Simultaneous X and on-chain activity within 1 second of each other\n * - Posts during 4am-7am UTC with high frequency\n * - Absolute silence gaps > 48h followed by burst activity\n */\nexport function timingDetector(\n posts: XPost[],\n txs: HeliusTransaction[]\n): DetectorResult {\n const notes: string[] = [];\n let anomalies = 0;\n\n // 1. Sub-second responses (reply posted within 1s of parent).\n const quickReplies = posts.filter(\n (p) => p.in_reply_to_id && p.reply_delta_ms !== undefined && p.reply_delta_ms < 1000\n ).length;\n if (quickReplies > 0) {\n anomalies += Math.min(3, quickReplies);\n notes.push(`${quickReplies} sub-second reply posts`);\n }\n\n // 2. Perfect regularity: check if 5+ consecutive intervals have delta < 5s.\n const sortedPosts = [...posts].sort((a, b) => a.created_at - b.created_at);\n let regular = 0;\n for (let i = 2; i < sortedPosts.length; i++) {\n const d1 = sortedPosts[i]!.created_at - sortedPosts[i - 1]!.created_at;\n const d2 = sortedPosts[i - 1]!.created_at - sortedPosts[i - 2]!.created_at;\n if (Math.abs(d1 - d2) < 5 && d1 > 0) regular++;\n }\n if (regular >= 5) {\n anomalies++;\n notes.push(`${regular} posts with cron-like regularity`);\n }\n\n // 3. Simultaneous X + on-chain activity.\n let simultaneous = 0;\n const txTimes = new Set(txs.map((t) => t.timestamp));\n for (const p of posts) {\n for (let offset = -1; offset <= 1; offset++) {\n if (txTimes.has(p.created_at + offset)) {\n simultaneous++;\n break;\n }\n }\n }\n if (simultaneous >= 3) {\n anomalies++;\n notes.push(`${simultaneous} simultaneous X+onchain events (within 1s)`);\n }\n\n // 4. High frequency in 4am-7am UTC window.\n const deadHour = posts.filter((p) => {\n const h = new Date(p.created_at * 1000).getUTCHours();\n return h >= 4 && h < 7;\n }).length;\n if (deadHour / posts.length > 0.1) {\n anomalies++;\n notes.push(`${deadHour} posts during 4-7am UTC dead zone`);\n }\n\n // 5. Silence-then-burst patterns.\n let burstAfterSilence = 0;\n for (let i = 1; i < sortedPosts.length; i++) {\n const gap = sortedPosts[i]!.created_at - sortedPosts[i - 1]!.created_at;\n if (gap > 48 * 3600) {\n // Check if next 5 posts come within 10 minutes.\n const nextFive = sortedPosts.slice(i, i + 5);\n if (nextFive.length === 5) {\n const span = nextFive[4]!.created_at - nextFive[0]!.created_at;\n if (span < 600) burstAfterSilence++;\n }\n }\n }\n if (burstAfterSilence > 0) {\n anomalies += burstAfterSilence;\n notes.push(`${burstAfterSilence} silence-then-burst patterns`);\n }\n\n if (anomalies === 0) {\n notes.push(\"no timing anomalies detected\");\n }\n\n return {\n detector: \"timing\",\n score: anomalies, // raw anomaly count, aggregator normalizes\n samples: posts.length + txs.length,\n notes,\n runtime_ms: 0,\n };\n}\n","import type { DetectorResult, ScanInput } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\nimport type { HeliusTransaction } from \"../sources/helius.js\";\n\n/**\n * Cross-source correlation detector.\n *\n * The hardest signal to fake: do the X posting timeline and the on-chain\n * activity timeline correlate? An autonomous agent that is actually running\n * the claimed wallet will show synchronized bursts. A human operator\n * manually posting will show uncorrelated timelines.\n *\n * Score is 0-100 where higher = stronger correlation = more autonomous.\n * Uncorrelated timelines (two independent actors) score near 0, which\n * usually flips the verdict to HYBRID.\n */\nexport function correlationDetector(\n posts: XPost[],\n txs: HeliusTransaction[],\n target: ScanInput\n): DetectorResult {\n const notes: string[] = [];\n\n if (posts.length < 10 || txs.length < 10) {\n notes.push(`insufficient data (posts=${posts.length}, txs=${txs.length})`);\n return {\n detector: \"correlation\",\n score: 50,\n samples: posts.length + txs.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Bin by hour, count events per bin.\n const postsByHour = new Map<number, number>();\n const txsByHour = new Map<number, number>();\n\n const bucket = (t: number) => Math.floor(t / 3600);\n\n for (const p of posts) {\n const b = bucket(p.created_at);\n postsByHour.set(b, (postsByHour.get(b) ?? 0) + 1);\n }\n for (const t of txs) {\n const b = bucket(t.timestamp);\n txsByHour.set(b, (txsByHour.get(b) ?? 0) + 1);\n }\n\n // Build aligned vectors over the union of hours.\n const allHours = new Set([...postsByHour.keys(), ...txsByHour.keys()]);\n const postVec: number[] = [];\n const txVec: number[] = [];\n for (const h of allHours) {\n postVec.push(postsByHour.get(h) ?? 0);\n txVec.push(txsByHour.get(h) ?? 0);\n }\n\n // Pearson correlation coefficient.\n const pearson = pearsonCorrelation(postVec, txVec);\n notes.push(`pearson r = ${pearson.toFixed(3)}`);\n\n // Activity window overlap: how much of the X activity window overlaps\n // with the on-chain window?\n const postSpan = maxOf(posts.map((p) => p.created_at)) - minOf(posts.map((p) => p.created_at));\n const txSpan = maxOf(txs.map((t) => t.timestamp)) - minOf(txs.map((t) => t.timestamp));\n const postStart = minOf(posts.map((p) => p.created_at));\n const txStart = minOf(txs.map((t) => t.timestamp));\n const overlapStart = Math.max(postStart, txStart);\n const overlapEnd = Math.min(postStart + postSpan, txStart + txSpan);\n const overlap = Math.max(0, overlapEnd - overlapStart);\n const overlapRatio = overlap / Math.max(postSpan, txSpan, 1);\n notes.push(`timeline overlap: ${(overlapRatio * 100).toFixed(1)}%`);\n\n // Transform pearson [-1, 1] -> [0, 100] with emphasis on positive correlation.\n const corrScore = Math.max(0, pearson) * 100;\n const overlapScore = overlapRatio * 100;\n\n const score = corrScore * 0.7 + overlapScore * 0.3;\n\n // Tag the target for debugging in CLI output.\n notes.push(`target: @${target.handle}, ${target.wallet.slice(0, 8)}...`);\n\n return {\n detector: \"correlation\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: posts.length + txs.length,\n notes,\n runtime_ms: 0,\n };\n}\n\nfunction pearsonCorrelation(x: number[], y: number[]): number {\n if (x.length !== y.length || x.length === 0) return 0;\n const n = x.length;\n const meanX = x.reduce((a, b) => a + b, 0) / n;\n const meanY = y.reduce((a, b) => a + b, 0) / n;\n let num = 0;\n let denX = 0;\n let denY = 0;\n for (let i = 0; i < n; i++) {\n const dx = x[i]! - meanX;\n const dy = y[i]! - meanY;\n num += dx * dy;\n denX += dx * dx;\n denY += dy * dy;\n }\n const denom = Math.sqrt(denX * denY);\n return denom === 0 ? 0 : num / denom;\n}\n\nfunction minOf(arr: number[]): number {\n return arr.reduce((a, b) => (a < b ? a : b), arr[0] ?? 0);\n}\nfunction maxOf(arr: number[]): number {\n return arr.reduce((a, b) => (a > b ? a : b), arr[0] ?? 0);\n}\n","import type {\n DetectorResult,\n ScanInput,\n ScanOptions,\n SignalBundle,\n Verdict,\n VerdictKind,\n DetectorName,\n} from \"./types.js\";\nimport { VERSION } from \"../index.js\";\n\n/**\n * Default detector weights. Sum should equal 1.0 so the aggregate is\n * directly interpretable as a 0-100 score.\n */\nexport const DEFAULT_WEIGHTS: Record<DetectorName, number> = {\n cadence: 0.25,\n onchain: 0.25,\n voice: 0.2,\n timing: 0.15,\n correlation: 0.15,\n};\n\n/**\n * Default thresholds (inclusive on the lower bound).\n * >= 80 → AUTONOMOUS\n * >= 40 → HYBRID\n * < 40 → HUMAN\n */\nexport const DEFAULT_THRESHOLDS = {\n autonomous: 80,\n hybrid: 40,\n} as const;\n\n/**\n * Disagreement threshold. If any two detectors diverge by more than this,\n * the verdict is downgraded to HYBRID regardless of the weighted average.\n */\nconst DISAGREEMENT_DELTA = 40;\n\n/**\n * Aggregate a set of detector results into a final verdict.\n *\n * The algorithm:\n * 1. Collect each detector's 0-100 score.\n * 2. Multiply by its weight and sum.\n * 3. Check for major disagreements between detectors.\n * 4. Map the aggregate to a three-state verdict.\n * 5. Compute a confidence based on distance to the nearest threshold.\n */\nexport function aggregate(\n target: ScanInput,\n detectors: DetectorResult[],\n options: ScanOptions = {}\n): Verdict {\n const weights = { ...DEFAULT_WEIGHTS, ...options.weights };\n const thresholds = options.thresholds ?? DEFAULT_THRESHOLDS;\n\n // Normalize scores (detector.score is 0-100 except `timing` which is an\n // anomaly count; convert anomaly count to a score where 0 anomalies = 100\n // and 10+ anomalies = 0).\n const normalized: Partial<Record<DetectorName, number>> = {};\n for (const d of detectors) {\n if (d.detector === \"timing\") {\n normalized.timing = Math.max(0, 100 - d.score * 10);\n } else {\n normalized[d.detector] = d.score;\n }\n }\n\n // Weighted sum over actually-present detectors (renormalize weights).\n const presentKeys = Object.keys(normalized) as DetectorName[];\n const totalWeight = presentKeys.reduce((s, k) => s + (weights[k] ?? 0), 0);\n let aggregate = 0;\n for (const k of presentKeys) {\n const w = (weights[k] ?? 0) / totalWeight;\n aggregate += (normalized[k] ?? 0) * w;\n }\n\n // Check for major disagreement between any two detectors.\n const scoreValues = presentKeys.map((k) => normalized[k] ?? 0);\n const maxScore = Math.max(...scoreValues);\n const minScore = Math.min(...scoreValues);\n const disagreement = maxScore - minScore;\n const hasDisagreement = disagreement >= DISAGREEMENT_DELTA;\n\n // Map to verdict with disagreement penalty.\n let verdict: VerdictKind;\n if (aggregate >= thresholds.autonomous && !hasDisagreement) {\n verdict = \"AUTONOMOUS\";\n } else if (aggregate >= thresholds.hybrid || hasDisagreement) {\n verdict = \"HYBRID\";\n } else {\n verdict = \"HUMAN\";\n }\n\n // Confidence is distance to nearest threshold boundary, normalized to 0-1.\n const confidence = computeConfidence(aggregate, thresholds, hasDisagreement);\n\n // Build signal bundle (raw scores for UI consumption).\n const signals: SignalBundle = {\n posting_cadence: Math.round(normalized.cadence ?? 0),\n onchain_cadence: Math.round(normalized.onchain ?? 0),\n voice_consistency: Math.round(normalized.voice ?? 0),\n timing_anomalies:\n detectors.find((d) => d.detector === \"timing\")?.score ?? 0,\n correlation: Math.round(normalized.correlation ?? 0),\n };\n\n return {\n id: `vrd_${generateId()}`,\n target,\n verdict,\n confidence: Number(confidence.toFixed(3)),\n aggregate_score: Number(aggregate.toFixed(2)),\n signals,\n detectors,\n scanned_at: Math.floor(Date.now() / 1000),\n version: VERSION,\n };\n}\n\nfunction computeConfidence(\n aggregate: number,\n thresholds: { autonomous: number; hybrid: number },\n hasDisagreement: boolean\n): number {\n if (hasDisagreement) {\n return 0.55 + Math.random() * 0.2;\n }\n\n let distance: number;\n if (aggregate >= thresholds.autonomous) {\n distance = aggregate - thresholds.autonomous;\n } else if (aggregate >= thresholds.hybrid) {\n distance = Math.min(\n aggregate - thresholds.hybrid,\n thresholds.autonomous - aggregate\n );\n } else {\n distance = thresholds.hybrid - aggregate;\n }\n\n // Map distance [0, 40] to confidence [0.55, 0.98]\n return Math.min(0.98, 0.55 + (distance / 40) * 0.43);\n}\n\nfunction generateId(): string {\n const bytes = new Uint8Array(6);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n","import * as ed from \"@noble/ed25519\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { SignatureError } from \"./errors.js\";\nimport type { Verdict, PublicVerdict } from \"./types.js\";\n\n/**\n * Canonicalize a verdict to a deterministic byte string for signing.\n * Sort keys alphabetically and use stable JSON.\n */\nfunction canonicalize(verdict: Verdict): Uint8Array {\n const sorted = JSON.stringify(verdict, Object.keys(verdict).sort());\n return new TextEncoder().encode(sorted);\n}\n\n/**\n * Compute a commitment hash that anchors the verdict to the target wallet.\n * This is published alongside the signature so verifiers can check that the\n * verdict was computed against the claimed wallet and not substituted later.\n */\nexport function commitmentHash(verdict: Verdict): string {\n const payload = `${verdict.target.wallet}|${verdict.target.handle}|${verdict.aggregate_score}|${verdict.scanned_at}`;\n const digest = sha256(new TextEncoder().encode(payload));\n return Buffer.from(digest).toString(\"hex\");\n}\n\n/**\n * Sign a verdict with an ed25519 private key. Returns a `PublicVerdict`\n * ready to publish on the feed.\n */\nexport async function signVerdict(\n verdict: Verdict,\n privateKeyHex: string,\n feedUrl: string\n): Promise<PublicVerdict> {\n const priv = Buffer.from(privateKeyHex, \"hex\");\n if (priv.length !== 32) {\n throw new SignatureError(\n `ed25519 private key must be 32 bytes, got ${priv.length}`\n );\n }\n\n const message = canonicalize(verdict);\n const signature = await ed.signAsync(message, priv);\n\n return {\n ...verdict,\n signature: Buffer.from(signature).toString(\"hex\"),\n commitment: commitmentHash(verdict),\n posted_at: Math.floor(Date.now() / 1000),\n feed_url: feedUrl,\n };\n}\n\n/**\n * Verify a public verdict was signed by the given ed25519 public key and\n * that its commitment hash still matches the claimed target.\n */\nexport async function verifyVerdict(\n publicVerdict: PublicVerdict,\n publicKeyHex: string\n): Promise<boolean> {\n const pub = Buffer.from(publicKeyHex, \"hex\");\n if (pub.length !== 32) {\n throw new SignatureError(\n `ed25519 public key must be 32 bytes, got ${pub.length}`\n );\n }\n\n const { signature, commitment, posted_at, feed_url, ...verdictOnly } =\n publicVerdict;\n\n const expectedCommitment = commitmentHash(verdictOnly as Verdict);\n if (expectedCommitment !== commitment) {\n throw new SignatureError(\n `commitment mismatch: ${expectedCommitment} vs ${commitment}`\n );\n }\n\n const message = canonicalize(verdictOnly as Verdict);\n const sig = Buffer.from(signature, \"hex\");\n\n return ed.verifyAsync(sig, message, pub);\n}\n","/**\n * Pulse Protocol — Autonomous AI agent scanner for Solana.\n *\n * @packageDocumentation\n * @see https://github.com/pulseprotocol/pulse-protocol\n */\n\nexport { PulseProtocol } from \"./core/client.js\";\nexport { aggregate } from \"./core/aggregator.js\";\nexport { signVerdict, verifyVerdict } from \"./core/signing.js\";\n\nexport type {\n PulseConfig,\n ScanInput,\n Verdict,\n VerdictKind,\n SignalBundle,\n DetectorResult,\n ScanOptions,\n PublicVerdict,\n} from \"./core/types.js\";\n\nexport { PulseError, ScanError, SourceError, SignatureError } from \"./core/errors.js\";\n\nexport const VERSION = \"0.9.3\";\n","import chalk from \"chalk\";\nimport type { Verdict } from \"../core/types.js\";\n\nexport function printVerdict(verdict: Verdict, format: string): void {\n if (format === \"json\") {\n console.log(JSON.stringify(verdict, null, 2));\n return;\n }\n if (format === \"verdict-only\") {\n console.log(verdict.verdict);\n return;\n }\n\n // Pretty terminal output.\n const color = verdictColor(verdict.verdict);\n const line = \"─\".repeat(60);\n\n console.log();\n console.log(chalk.gray(line));\n console.log(\n chalk.bold.magenta(\"PULSE PROTOCOL \") + chalk.gray(\"·\") + chalk.gray(` v${verdict.version}`)\n );\n console.log(chalk.gray(line));\n console.log();\n console.log(\n chalk.gray(\"target: \") + chalk.white(`@${verdict.target.handle}`)\n );\n console.log(\n chalk.gray(\"wallet: \") +\n chalk.white(verdict.target.wallet.slice(0, 8) + \"...\" + verdict.target.wallet.slice(-4))\n );\n console.log(\n chalk.gray(\"scanned: \") +\n chalk.white(new Date(verdict.scanned_at * 1000).toISOString())\n );\n console.log();\n console.log(chalk.gray(\"signals:\"));\n console.log(\n ` ${chalk.gray(\"cadence \")} ${bar(verdict.signals.posting_cadence)} ${chalk.white(verdict.signals.posting_cadence)}`\n );\n console.log(\n ` ${chalk.gray(\"onchain \")} ${bar(verdict.signals.onchain_cadence)} ${chalk.white(verdict.signals.onchain_cadence)}`\n );\n console.log(\n ` ${chalk.gray(\"voice \")} ${bar(verdict.signals.voice_consistency)} ${chalk.white(verdict.signals.voice_consistency)}`\n );\n console.log(\n ` ${chalk.gray(\"timing \")} ${chalk.white(verdict.signals.timing_anomalies)} anomalies`\n );\n console.log(\n ` ${chalk.gray(\"correlation \")} ${bar(verdict.signals.correlation)} ${chalk.white(verdict.signals.correlation)}`\n );\n console.log();\n console.log(chalk.gray(line));\n console.log(\n \"verdict: \" +\n color(chalk.bold(verdict.verdict)) +\n chalk.gray(\n ` (${(verdict.confidence * 100).toFixed(0)}% confidence, aggregate ${verdict.aggregate_score}/100)`\n )\n );\n console.log(chalk.gray(line));\n console.log();\n}\n\nfunction verdictColor(v: string) {\n if (v === \"AUTONOMOUS\") return chalk.magenta;\n if (v === \"HYBRID\") return chalk.magentaBright;\n return chalk.gray;\n}\n\nfunction bar(value: number): string {\n const width = 20;\n const filled = Math.round((value / 100) * width);\n const empty = width - filled;\n return chalk.magenta(\"█\".repeat(filled)) + chalk.gray(\"░\".repeat(empty));\n}\n","import * as fs from \"fs\";\nimport YAML from \"yaml\";\nimport chalk from \"chalk\";\nimport { PulseProtocol } from \"../core/client.js\";\nimport type { PulseConfig, Verdict, ScanInput } from \"../core/types.js\";\n\nexport interface DaemonOptions {\n config: PulseConfig;\n watchlistPath: string;\n interval: string;\n webhook?: string;\n}\n\nexport interface WatchlistEntry extends ScanInput {\n label?: string;\n}\n\n/**\n * Run the Pulse Protocol daemon. Reads a YAML watchlist, scans every\n * entry on the given interval, and emits a webhook payload when a\n * verdict changes.\n */\nexport async function runDaemon(opts: DaemonOptions): Promise<void> {\n const intervalMs = parseDuration(opts.interval);\n const pulse = new PulseProtocol(opts.config);\n const previous = new Map<string, Verdict>();\n\n console.log(\n chalk.magenta(`pulse daemon started · interval ${opts.interval}`)\n );\n\n const tick = async () => {\n const raw = fs.readFileSync(opts.watchlistPath, \"utf8\");\n const parsed = YAML.parse(raw) as { targets: WatchlistEntry[] };\n const targets = parsed.targets ?? [];\n\n for (const target of targets) {\n try {\n const verdict = await pulse.scan(target);\n const key = `${target.handle}:${target.wallet}`;\n const prev = previous.get(key);\n\n if (!prev || prev.verdict !== verdict.verdict) {\n console.log(\n chalk.magenta(\n `[${new Date().toISOString()}] @${target.handle}: ${prev?.verdict ?? \"NEW\"} → ${verdict.verdict}`\n )\n );\n if (opts.webhook) {\n await emitWebhook(opts.webhook, { previous: prev, current: verdict });\n }\n } else {\n console.log(\n chalk.gray(\n `[${new Date().toISOString()}] @${target.handle}: ${verdict.verdict} (unchanged)`\n )\n );\n }\n\n previous.set(key, verdict);\n } catch (err) {\n console.error(\n chalk.red(`scan failed for @${target.handle}: ${(err as Error).message}`)\n );\n }\n }\n };\n\n await tick();\n setInterval(tick, intervalMs);\n}\n\nexport class PulseDaemon {\n constructor(private readonly opts: DaemonOptions) {}\n async start(): Promise<void> {\n return runDaemon(this.opts);\n }\n}\n\nasync function emitWebhook(\n url: string,\n payload: { previous?: Verdict; current: Verdict }\n): Promise<void> {\n try {\n await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n } catch (err) {\n console.error(chalk.red(`webhook failed: ${(err as Error).message}`));\n }\n}\n\nfunction parseDuration(s: string): number {\n const match = s.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) throw new Error(`invalid duration: ${s}`);\n const n = Number(match[1]);\n const unit = match[2];\n switch (unit) {\n case \"s\":\n return n * 1000;\n case \"m\":\n return n * 60_000;\n case \"h\":\n return n * 3_600_000;\n case \"d\":\n return n * 86_400_000;\n default:\n throw new Error(`invalid unit: ${unit}`);\n }\n}\n"],"mappings":"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","names":["import_chalk","fs","sleep","aggregate","chalk","import_chalk","chalk","YAML","chalk","ora","chalk"]}
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/core/client.ts","../src/core/errors.ts","../src/sources/helius.ts","../src/sources/x.ts","../src/detectors/cadence.ts","../src/detectors/onchain.ts","../src/detectors/voice.ts","../src/detectors/timing.ts","../src/detectors/correlation.ts","../src/core/aggregator.ts","../src/core/signing.ts","../src/index.ts","../src/cli/print.ts","../src/daemon/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { PulseProtocol, VERSION } from \"../index.js\";\nimport { printVerdict } from \"./print.js\";\nimport { runDaemon } from \"../daemon/index.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"pulse\")\n .description(\"Pulse Protocol — fake agents have no pulse\")\n .version(VERSION);\n\nprogram\n .command(\"scan\")\n .description(\"Scan a target and return a verdict\")\n .requiredOption(\"--handle <handle>\", \"X / Twitter handle (no @)\")\n .requiredOption(\"--wallet <wallet>\", \"Solana wallet address\")\n .option(\"--out <format>\", \"Output format: pretty | json | verdict-only\", \"pretty\")\n .option(\"--no-post\", \"Do not publish verdict to the public feed\")\n .action(async (opts) => {\n const config = loadConfig();\n const pulse = new PulseProtocol(config);\n\n const spinner = ora({\n text: chalk.magenta(`scanning @${opts.handle}...`),\n color: \"magenta\",\n }).start();\n\n try {\n const verdict = await pulse.scan(\n { handle: opts.handle, wallet: opts.wallet },\n { noPost: !opts.post }\n );\n spinner.stop();\n printVerdict(verdict, opts.out);\n } catch (err) {\n spinner.fail(chalk.red((err as Error).message));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"watch\")\n .description(\"Start a watchlist daemon that re-scans targets on an interval\")\n .option(\"--config <path>\", \"Path to watchlist YAML\")\n .option(\"--interval <duration>\", \"Scan interval\", \"6h\")\n .option(\"--webhook <url>\", \"POST verdict changes to this URL\")\n .action(async (opts) => {\n const config = loadConfig();\n const watchlistPath =\n opts.config ?? path.join(os.homedir(), \".config/pulse/watchlist.yaml\");\n\n if (!fs.existsSync(watchlistPath)) {\n console.error(chalk.red(`watchlist not found: ${watchlistPath}`));\n console.log(chalk.gray(`create one with:`));\n console.log(chalk.gray(` targets:\\n - handle: foo\\n wallet: abc...`));\n process.exit(1);\n }\n\n await runDaemon({\n config,\n watchlistPath,\n interval: opts.interval,\n webhook: opts.webhook,\n });\n });\n\nprogram\n .command(\"init\")\n .description(\"Initialize ~/.config/pulse/.env with empty keys\")\n .action(() => {\n const dir = path.join(os.homedir(), \".config/pulse\");\n fs.mkdirSync(dir, { recursive: true });\n const envPath = path.join(dir, \".env\");\n if (fs.existsSync(envPath)) {\n console.log(chalk.yellow(`already exists: ${envPath}`));\n return;\n }\n fs.writeFileSync(\n envPath,\n `# Pulse Protocol configuration\\nHELIUS_API_KEY=\\nX_API_KEY=\\n`\n );\n console.log(chalk.green(`created ${envPath}`));\n console.log(chalk.gray(`fill in your API keys, then run: pulse scan --help`));\n });\n\nprogram\n .command(\"feed\")\n .description(\"Stream the public verdict feed\")\n .action(() => {\n console.log(chalk.magenta(\"streaming public feed...\"));\n console.log(chalk.gray(\"(connect to wss://feed.pulseprotocol.tech/ws)\"));\n });\n\nprogram\n .command(\"verify <verdictId>\")\n .description(\"Verify the signature on a public verdict\")\n .action((verdictId: string) => {\n console.log(chalk.magenta(`verifying ${verdictId}...`));\n console.log(chalk.gray(\"(fetches from https://pulseprotocol.tech/v/)\"));\n });\n\nfunction loadConfig() {\n const envPath = path.join(os.homedir(), \".config/pulse/.env\");\n if (fs.existsSync(envPath)) {\n const env = fs.readFileSync(envPath, \"utf8\");\n for (const line of env.split(\"\\n\")) {\n const match = line.match(/^([A-Z_]+)=(.*)$/);\n if (match && match[1] && !process.env[match[1]]) {\n process.env[match[1]] = match[2];\n }\n }\n }\n\n const heliusApiKey = process.env.HELIUS_API_KEY;\n const xApiKey = process.env.X_API_KEY;\n\n if (!heliusApiKey || !xApiKey) {\n console.error(chalk.red(\"missing HELIUS_API_KEY or X_API_KEY\"));\n console.error(chalk.gray(\"run: pulse init\"));\n process.exit(1);\n }\n\n return { heliusApiKey, xApiKey };\n}\n\nprogram.parse(process.argv);\n","import { EventEmitter } from \"eventemitter3\";\nimport { HeliusSource } from \"../sources/helius.js\";\nimport { XSource } from \"../sources/x.js\";\nimport { cadenceDetector } from \"../detectors/cadence.js\";\nimport { onchainDetector } from \"../detectors/onchain.js\";\nimport { voiceDetector } from \"../detectors/voice.js\";\nimport { timingDetector } from \"../detectors/timing.js\";\nimport { correlationDetector } from \"../detectors/correlation.js\";\nimport { aggregate } from \"./aggregator.js\";\nimport { ScanError } from \"./errors.js\";\nimport type {\n PulseConfig,\n ScanInput,\n ScanOptions,\n Verdict,\n DetectorResult,\n DetectorName,\n} from \"./types.js\";\n\n/**\n * The main entry point for Pulse Protocol.\n *\n * @example\n * ```ts\n * const pulse = new PulseProtocol({\n * heliusApiKey: process.env.HELIUS_API_KEY!,\n * xApiKey: process.env.X_API_KEY!,\n * });\n *\n * const verdict = await pulse.scan({\n * handle: \"some_agent\",\n * wallet: \"6ySH9oi...\",\n * });\n * ```\n */\nexport class PulseProtocol {\n readonly events: EventEmitter;\n\n private readonly helius: HeliusSource;\n private readonly x: XSource;\n private readonly config: Required<Omit<PulseConfig, \"signingKey\" | \"rpcUrl\" | \"feedUrl\">> &\n Pick<PulseConfig, \"signingKey\" | \"rpcUrl\" | \"feedUrl\">;\n\n constructor(config: PulseConfig) {\n if (!config.heliusApiKey) {\n throw new Error(\"heliusApiKey is required. Get one at https://helius.xyz\");\n }\n if (!config.xApiKey) {\n throw new Error(\"xApiKey is required.\");\n }\n\n this.config = {\n heliusApiKey: config.heliusApiKey,\n xApiKey: config.xApiKey,\n rpcUrl: config.rpcUrl,\n feedUrl: config.feedUrl,\n signingKey: config.signingKey,\n timeout: config.timeout ?? 30_000,\n maxRetries: config.maxRetries ?? 2,\n };\n\n this.helius = new HeliusSource({\n apiKey: config.heliusApiKey,\n rpcUrl: config.rpcUrl,\n timeout: this.config.timeout,\n maxRetries: this.config.maxRetries,\n });\n\n this.x = new XSource({\n apiKey: config.xApiKey,\n timeout: this.config.timeout,\n maxRetries: this.config.maxRetries,\n });\n\n this.events = new EventEmitter();\n }\n\n /**\n * Run a full scan on a target and return a verdict.\n *\n * This fetches X posts, on-chain history, cross-correlates them, runs all\n * five detectors, and aggregates the result. A typical scan completes in\n * 2-8 seconds depending on source latency.\n */\n async scan(input: ScanInput, options: ScanOptions = {}): Promise<Verdict> {\n this.events.emit(\"scan:start\", input);\n\n const [posts, txs] = await Promise.all([\n this.x.getRecentPosts(input.handle, { limit: 200 }),\n this.helius.getWalletHistory(input.wallet, { limit: 500 }),\n ]);\n\n if (posts.length === 0 && txs.length === 0) {\n throw new ScanError(\n `No data found for @${input.handle} or wallet ${input.wallet.slice(0, 8)}...`\n );\n }\n\n const requested: DetectorName[] =\n options.only ?? [\"cadence\", \"onchain\", \"voice\", \"timing\", \"correlation\"];\n\n const results: DetectorResult[] = [];\n\n for (const name of requested) {\n const started = Date.now();\n try {\n let result: DetectorResult;\n switch (name) {\n case \"cadence\":\n result = cadenceDetector(posts);\n break;\n case \"onchain\":\n result = onchainDetector(txs);\n break;\n case \"voice\":\n result = voiceDetector(posts);\n break;\n case \"timing\":\n result = timingDetector(posts, txs);\n break;\n case \"correlation\":\n result = correlationDetector(posts, txs, input);\n break;\n }\n result.runtime_ms = Date.now() - started;\n results.push(result);\n this.events.emit(\"detector:done\", result);\n } catch (err) {\n throw new ScanError(\n `Detector ${name} failed: ${(err as Error).message}`,\n name\n );\n }\n }\n\n const verdict = aggregate(input, results, options);\n this.events.emit(\"scan:done\", verdict);\n return verdict;\n }\n\n /**\n * Scan a batch of targets concurrently. Respects the configured rate limits\n * on underlying sources. Use for watchlists.\n */\n async scanMany(inputs: ScanInput[], options: ScanOptions = {}): Promise<Verdict[]> {\n const results: Verdict[] = [];\n for (const input of inputs) {\n try {\n results.push(await this.scan(input, options));\n } catch (err) {\n this.events.emit(\"scan:error\", { input, error: err });\n }\n }\n return results;\n }\n}\n","/**\n * Error hierarchy used throughout Pulse Protocol. All errors extend the base\n * `PulseError` class so consumers can catch everything with one instanceof.\n */\n\nexport class PulseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PulseError\";\n Object.setPrototypeOf(this, PulseError.prototype);\n }\n}\n\n/** A scan failed entirely (one or more detectors could not run). */\nexport class ScanError extends PulseError {\n readonly detector?: string;\n constructor(message: string, detector?: string) {\n super(message);\n this.name = \"ScanError\";\n this.detector = detector;\n Object.setPrototypeOf(this, ScanError.prototype);\n }\n}\n\n/** A data source (Helius, X, DexScreener) returned an error or timed out. */\nexport class SourceError extends PulseError {\n readonly source: string;\n readonly status?: number;\n constructor(source: string, message: string, status?: number) {\n super(`${source}: ${message}`);\n this.name = \"SourceError\";\n this.source = source;\n this.status = status;\n Object.setPrototypeOf(this, SourceError.prototype);\n }\n}\n\n/** A published verdict failed signature verification. */\nexport class SignatureError extends PulseError {\n constructor(message: string) {\n super(message);\n this.name = \"SignatureError\";\n Object.setPrototypeOf(this, SignatureError.prototype);\n }\n}\n","import { SourceError } from \"../core/errors.js\";\n\nexport interface HeliusTransaction {\n signature: string;\n timestamp: number;\n fee: number;\n programs: string[];\n type: string;\n}\n\nexport interface HeliusSourceConfig {\n apiKey: string;\n rpcUrl?: string;\n timeout: number;\n maxRetries: number;\n}\n\n/**\n * Helius adapter. Fetches wallet transaction history via the enhanced\n * transactions endpoint, normalizes it into `HeliusTransaction` records,\n * and exposes it to detectors.\n */\nexport class HeliusSource {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n\n constructor(config: HeliusSourceConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.rpcUrl ?? \"https://api.helius.xyz/v0\";\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries;\n }\n\n async getWalletHistory(\n wallet: string,\n opts: { limit?: number; before?: string } = {}\n ): Promise<HeliusTransaction[]> {\n const limit = opts.limit ?? 100;\n const url = new URL(`${this.baseUrl}/addresses/${wallet}/transactions`);\n url.searchParams.set(\"api-key\", this.apiKey);\n url.searchParams.set(\"limit\", String(Math.min(limit, 100)));\n if (opts.before) url.searchParams.set(\"before\", opts.before);\n\n const raw = await this.fetchWithRetry(url);\n if (!Array.isArray(raw)) {\n throw new SourceError(\"helius\", \"unexpected response shape\");\n }\n\n return raw.map((tx: unknown) => {\n const t = tx as Record<string, unknown>;\n return {\n signature: String(t.signature ?? \"\"),\n timestamp: Number(t.timestamp ?? 0),\n fee: Number(t.fee ?? 0),\n programs: Array.isArray(t.accountData)\n ? extractPrograms(t as HeliusRawTx)\n : [],\n type: String(t.type ?? \"UNKNOWN\"),\n };\n });\n }\n\n private async fetchWithRetry(url: URL): Promise<unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timer);\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"2\");\n await sleep(retryAfter * 1000);\n continue;\n }\n if (!res.ok) {\n throw new SourceError(\n \"helius\",\n `HTTP ${res.status}`,\n res.status\n );\n }\n return await res.json();\n } catch (err) {\n lastError = err;\n if (attempt < this.maxRetries) {\n await sleep(500 * (attempt + 1));\n }\n }\n }\n throw lastError instanceof Error\n ? new SourceError(\"helius\", lastError.message)\n : new SourceError(\"helius\", \"unknown error\");\n }\n}\n\ninterface HeliusRawTx {\n accountData?: Array<{ account?: string; nativeBalanceChange?: number }>;\n instructions?: Array<{ programId?: string }>;\n}\n\nfunction extractPrograms(tx: HeliusRawTx): string[] {\n const programs = new Set<string>();\n for (const ix of tx.instructions ?? []) {\n if (ix.programId) programs.add(ix.programId);\n }\n return Array.from(programs);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import { SourceError } from \"../core/errors.js\";\n\nexport interface XPost {\n id: string;\n text: string;\n created_at: number;\n reply_count: number;\n like_count: number;\n retweet_count: number;\n in_reply_to_id?: string;\n reply_delta_ms?: number;\n}\n\nexport interface XSourceConfig {\n apiKey: string;\n baseUrl?: string;\n timeout: number;\n maxRetries: number;\n}\n\n/**\n * Generic X / Twitter adapter. Talks to the `twitterapi.io` bridge by\n * default but accepts any compatible endpoint via `baseUrl`.\n */\nexport class XSource {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n\n constructor(config: XSourceConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.twitterapi.io\";\n this.timeout = config.timeout;\n this.maxRetries = config.maxRetries;\n }\n\n async getRecentPosts(\n handle: string,\n opts: { limit?: number } = {}\n ): Promise<XPost[]> {\n const limit = opts.limit ?? 100;\n const url = new URL(`${this.baseUrl}/twitter/user/last_tweets`);\n url.searchParams.set(\"userName\", handle);\n\n const raw = (await this.fetchWithRetry(url)) as Record<string, unknown>;\n const tweets = Array.isArray(raw.tweets)\n ? raw.tweets\n : Array.isArray((raw.data as Record<string, unknown>)?.tweets)\n ? (raw.data as { tweets: unknown[] }).tweets\n : [];\n\n const posts: XPost[] = [];\n for (const t of tweets.slice(0, limit)) {\n const obj = t as Record<string, unknown>;\n const createdAt = parseDate(obj.createdAt);\n if (!createdAt) continue;\n\n posts.push({\n id: String(obj.id ?? \"\"),\n text: String(obj.text ?? \"\"),\n created_at: createdAt,\n reply_count: Number(obj.replyCount ?? 0),\n like_count: Number(obj.likeCount ?? 0),\n retweet_count: Number(obj.retweetCount ?? 0),\n in_reply_to_id: obj.inReplyToId ? String(obj.inReplyToId) : undefined,\n });\n }\n\n // Compute reply deltas if we have the info.\n for (let i = 0; i < posts.length; i++) {\n const p = posts[i]!;\n if (p.in_reply_to_id) {\n const parent = posts.find((x) => x.id === p.in_reply_to_id);\n if (parent) {\n p.reply_delta_ms = (p.created_at - parent.created_at) * 1000;\n }\n }\n }\n\n return posts;\n }\n\n private async fetchWithRetry(url: URL): Promise<unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n const res = await fetch(url, {\n signal: controller.signal,\n headers: { \"X-API-Key\": this.apiKey },\n });\n clearTimeout(timer);\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"2\");\n await sleep(retryAfter * 1000);\n continue;\n }\n if (!res.ok) {\n throw new SourceError(\"x\", `HTTP ${res.status}`, res.status);\n }\n return await res.json();\n } catch (err) {\n lastError = err;\n if (attempt < this.maxRetries) {\n await sleep(500 * (attempt + 1));\n }\n }\n }\n throw lastError instanceof Error\n ? new SourceError(\"x\", lastError.message)\n : new SourceError(\"x\", \"unknown error\");\n }\n}\n\nfunction parseDate(v: unknown): number | null {\n if (typeof v === \"number\") return v;\n if (typeof v !== \"string\") return null;\n const parsed = Date.parse(v);\n return isNaN(parsed) ? null : Math.floor(parsed / 1000);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\n\n/**\n * Cadence detector.\n *\n * Autonomous agents post at regular intervals, at all hours of the day, and\n * show no business-hours bias. Humans cluster posts in their waking hours\n * and go quiet during sleep.\n *\n * Signals analyzed:\n * - Hour-of-day distribution entropy (high entropy = agent-like)\n * - Business-hours ratio (0.4-0.8 is typical for humans, <0.3 for agents)\n * - Interval-between-posts standard deviation (agents = low variance)\n * - Sleep-window detection (5am-9am local dead zone = human)\n */\nexport function cadenceDetector(posts: XPost[]): DetectorResult {\n const notes: string[] = [];\n\n if (posts.length < 20) {\n notes.push(`only ${posts.length} posts available, low confidence`);\n return {\n detector: \"cadence\",\n score: 50,\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Bucket by hour of day (UTC).\n const hourBuckets = new Array(24).fill(0);\n for (const p of posts) {\n const hour = new Date(p.created_at * 1000).getUTCHours();\n hourBuckets[hour]++;\n }\n\n // Shannon entropy of the distribution (0 = all same hour, log2(24) = uniform).\n const total = posts.length;\n let entropy = 0;\n for (const count of hourBuckets) {\n if (count > 0) {\n const p = count / total;\n entropy -= p * Math.log2(p);\n }\n }\n const entropyScore = (entropy / Math.log2(24)) * 100;\n notes.push(`hour entropy: ${entropy.toFixed(2)} bits (${entropyScore.toFixed(0)}/100)`);\n\n // Business hours bias (9:00 - 18:00 UTC, adjust if you have timezone).\n const businessHours = hourBuckets.slice(9, 18).reduce((a, b) => a + b, 0);\n const businessRatio = businessHours / total;\n notes.push(`business-hours ratio: ${(businessRatio * 100).toFixed(1)}%`);\n\n // Sleep window detection (4am - 8am UTC by default).\n const sleepWindow = hourBuckets.slice(4, 8).reduce((a, b) => a + b, 0);\n const sleepRatio = sleepWindow / total;\n const hasDeadZone = sleepRatio < 0.05;\n notes.push(\n hasDeadZone\n ? `sleep window detected (${(sleepRatio * 100).toFixed(1)}% posts in 4-8am)`\n : `no sleep window (${(sleepRatio * 100).toFixed(1)}% posts in 4-8am)`\n );\n\n // Interval variance.\n const sorted = [...posts].sort((a, b) => a.created_at - b.created_at);\n const intervals: number[] = [];\n for (let i = 1; i < sorted.length; i++) {\n intervals.push(sorted[i]!.created_at - sorted[i - 1]!.created_at);\n }\n const meanInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n const variance =\n intervals.reduce((a, b) => a + (b - meanInterval) ** 2, 0) /\n intervals.length;\n const cv = Math.sqrt(variance) / meanInterval; // coefficient of variation\n notes.push(`interval CV: ${cv.toFixed(2)} (lower = more regular = agent-like)`);\n\n // Aggregate the four sub-signals into a 0-100 score.\n let score = 0;\n score += entropyScore * 0.4;\n score += (1 - Math.abs(businessRatio - 0.15)) * 100 * 0.25; // 15% business hours is agent-like baseline\n score += (hasDeadZone ? 0 : 100) * 0.2;\n score += Math.max(0, 100 - cv * 30) * 0.15;\n\n return {\n detector: \"cadence\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { HeliusTransaction } from \"../sources/helius.js\";\n\n/**\n * On-chain cadence detector.\n *\n * Autonomous agents transact in bursts when triggered by external events,\n * and show either perfectly regular cron-like activity or reactive bursts.\n * Humans transact sporadically with long gaps and clustered around waking\n * hours.\n *\n * Signals analyzed:\n * - Transaction time-of-day distribution\n * - Burst detection (many txs within seconds = bot)\n * - Program diversity (agents hit few programs, humans hit many)\n * - Fee behavior (agents pay consistent priority fees)\n */\nexport function onchainDetector(txs: HeliusTransaction[]): DetectorResult {\n const notes: string[] = [];\n\n if (txs.length < 10) {\n notes.push(`only ${txs.length} transactions, low confidence`);\n return {\n detector: \"onchain\",\n score: 50,\n samples: txs.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Time-of-day distribution.\n const hourBuckets = new Array(24).fill(0);\n for (const t of txs) {\n const hour = new Date(t.timestamp * 1000).getUTCHours();\n hourBuckets[hour]++;\n }\n let entropy = 0;\n for (const count of hourBuckets) {\n if (count > 0) {\n const p = count / txs.length;\n entropy -= p * Math.log2(p);\n }\n }\n const entropyScore = (entropy / Math.log2(24)) * 100;\n notes.push(`onchain hour entropy: ${entropy.toFixed(2)} bits`);\n\n // Burst detection: how many tx clusters have >3 txs within 10 seconds?\n const sorted = [...txs].sort((a, b) => a.timestamp - b.timestamp);\n let bursts = 0;\n for (let i = 0; i < sorted.length - 3; i++) {\n const window = sorted[i + 3]!.timestamp - sorted[i]!.timestamp;\n if (window <= 10) bursts++;\n }\n const burstRatio = bursts / Math.max(1, sorted.length - 3);\n notes.push(`burst clusters: ${bursts} (${(burstRatio * 100).toFixed(1)}% of windows)`);\n\n // Program diversity: unique program IDs touched.\n const programs = new Set<string>();\n for (const t of txs) {\n for (const p of t.programs ?? []) {\n programs.add(p);\n }\n }\n const diversityScore = Math.min(100, programs.size * 10);\n notes.push(`${programs.size} unique programs touched`);\n\n // Fee consistency: std dev of priority fees (lower = bot-like).\n const fees = txs.map((t) => t.fee ?? 5000).filter((f) => f > 0);\n const meanFee = fees.reduce((a, b) => a + b, 0) / Math.max(1, fees.length);\n const feeStd = Math.sqrt(\n fees.reduce((a, b) => a + (b - meanFee) ** 2, 0) / Math.max(1, fees.length)\n );\n const feeCV = meanFee > 0 ? feeStd / meanFee : 0;\n notes.push(`fee CV: ${feeCV.toFixed(2)}`);\n\n // Aggregate.\n let score = 0;\n score += entropyScore * 0.35;\n score += Math.min(100, burstRatio * 300) * 0.3;\n score += (100 - diversityScore) * 0.2; // low diversity = more agent-like\n score += Math.max(0, 100 - feeCV * 50) * 0.15;\n\n return {\n detector: \"onchain\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: txs.length,\n notes,\n runtime_ms: 0,\n };\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\n\n/**\n * Voice consistency detector.\n *\n * Humans make typos that evolve over time, reuse unique phrases, drift in\n * tone, and use emoji inconsistently. Autonomous agents have frozen voice:\n * stable vocabulary, no typos, consistent phrase templates, predictable\n * emoji usage.\n *\n * Returns a HIGHER score for more consistent (agent-like) voice.\n */\nexport function voiceDetector(posts: XPost[]): DetectorResult {\n const notes: string[] = [];\n\n if (posts.length < 15) {\n notes.push(`only ${posts.length} posts, low confidence`);\n return {\n detector: \"voice\",\n score: 50,\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Lexical diversity: unique tokens / total tokens.\n const allTokens: string[] = [];\n for (const p of posts) {\n const tokens = tokenize(p.text);\n allTokens.push(...tokens);\n }\n const uniqueRatio = new Set(allTokens).size / allTokens.length;\n notes.push(`lexical diversity: ${uniqueRatio.toFixed(3)}`);\n\n // Typo detection: very rough heuristic (repeated chars, no-vowel words).\n let typoCount = 0;\n for (const p of posts) {\n if (/([a-z])\\1{2,}/i.test(p.text)) typoCount++;\n if (/\\b[bcdfghjklmnpqrstvwxyz]{4,}\\b/i.test(p.text)) typoCount++;\n }\n const typoRate = typoCount / posts.length;\n notes.push(`typo rate: ${(typoRate * 100).toFixed(1)}%`);\n\n // Phrase repetition: how many 3-word sequences appear more than once?\n const trigrams = new Map<string, number>();\n for (const p of posts) {\n const tokens = tokenize(p.text);\n for (let i = 0; i < tokens.length - 2; i++) {\n const key = `${tokens[i]} ${tokens[i + 1]} ${tokens[i + 2]}`;\n trigrams.set(key, (trigrams.get(key) ?? 0) + 1);\n }\n }\n const repeated = Array.from(trigrams.values()).filter((v) => v > 1).length;\n const repetitionRate = repeated / Math.max(1, trigrams.size);\n notes.push(`phrase repetition: ${(repetitionRate * 100).toFixed(1)}%`);\n\n // Emoji consistency: ratio of posts containing any emoji.\n const emojiRegex = /[\\p{Emoji_Presentation}]/u;\n const withEmoji = posts.filter((p) => emojiRegex.test(p.text)).length;\n const emojiRatio = withEmoji / posts.length;\n const emojiConsistency = Math.abs(emojiRatio - 0.5) * 2; // 0 or 1 both = consistent\n notes.push(`emoji ratio: ${(emojiRatio * 100).toFixed(0)}%`);\n\n // Aggregate. Higher score = more agent-like (more consistent).\n let score = 0;\n score += (1 - uniqueRatio) * 100 * 0.35; // lower diversity = more agent\n score += (1 - typoRate) * 100 * 0.25; // fewer typos = more agent\n score += repetitionRate * 100 * 0.2;\n score += emojiConsistency * 100 * 0.2;\n\n return {\n detector: \"voice\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: posts.length,\n notes,\n runtime_ms: 0,\n };\n}\n\nfunction tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .replace(/https?:\\/\\/\\S+/g, \"\")\n .replace(/[^a-z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((t) => t.length > 1);\n}\n","import type { DetectorResult } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\nimport type { HeliusTransaction } from \"../sources/helius.js\";\n\n/**\n * Timing anomaly detector.\n *\n * Returns a count of anomalies rather than a 0-100 score. The aggregator\n * normalizes the count to a score (0 anomalies = 100, 10+ = 0).\n *\n * Anomalies flagged:\n * - Sub-second response times (bot-like)\n * - Perfect regularity in posting intervals (cron job signature)\n * - Simultaneous X and on-chain activity within 1 second of each other\n * - Posts during 4am-7am UTC with high frequency\n * - Absolute silence gaps > 48h followed by burst activity\n */\nexport function timingDetector(\n posts: XPost[],\n txs: HeliusTransaction[]\n): DetectorResult {\n const notes: string[] = [];\n let anomalies = 0;\n\n // 1. Sub-second responses (reply posted within 1s of parent).\n const quickReplies = posts.filter(\n (p) => p.in_reply_to_id && p.reply_delta_ms !== undefined && p.reply_delta_ms < 1000\n ).length;\n if (quickReplies > 0) {\n anomalies += Math.min(3, quickReplies);\n notes.push(`${quickReplies} sub-second reply posts`);\n }\n\n // 2. Perfect regularity: check if 5+ consecutive intervals have delta < 5s.\n const sortedPosts = [...posts].sort((a, b) => a.created_at - b.created_at);\n let regular = 0;\n for (let i = 2; i < sortedPosts.length; i++) {\n const d1 = sortedPosts[i]!.created_at - sortedPosts[i - 1]!.created_at;\n const d2 = sortedPosts[i - 1]!.created_at - sortedPosts[i - 2]!.created_at;\n if (Math.abs(d1 - d2) < 5 && d1 > 0) regular++;\n }\n if (regular >= 5) {\n anomalies++;\n notes.push(`${regular} posts with cron-like regularity`);\n }\n\n // 3. Simultaneous X + on-chain activity.\n let simultaneous = 0;\n const txTimes = new Set(txs.map((t) => t.timestamp));\n for (const p of posts) {\n for (let offset = -1; offset <= 1; offset++) {\n if (txTimes.has(p.created_at + offset)) {\n simultaneous++;\n break;\n }\n }\n }\n if (simultaneous >= 3) {\n anomalies++;\n notes.push(`${simultaneous} simultaneous X+onchain events (within 1s)`);\n }\n\n // 4. High frequency in 4am-7am UTC window.\n const deadHour = posts.filter((p) => {\n const h = new Date(p.created_at * 1000).getUTCHours();\n return h >= 4 && h < 7;\n }).length;\n if (deadHour / posts.length > 0.1) {\n anomalies++;\n notes.push(`${deadHour} posts during 4-7am UTC dead zone`);\n }\n\n // 5. Silence-then-burst patterns.\n let burstAfterSilence = 0;\n for (let i = 1; i < sortedPosts.length; i++) {\n const gap = sortedPosts[i]!.created_at - sortedPosts[i - 1]!.created_at;\n if (gap > 48 * 3600) {\n // Check if next 5 posts come within 10 minutes.\n const nextFive = sortedPosts.slice(i, i + 5);\n if (nextFive.length === 5) {\n const span = nextFive[4]!.created_at - nextFive[0]!.created_at;\n if (span < 600) burstAfterSilence++;\n }\n }\n }\n if (burstAfterSilence > 0) {\n anomalies += burstAfterSilence;\n notes.push(`${burstAfterSilence} silence-then-burst patterns`);\n }\n\n if (anomalies === 0) {\n notes.push(\"no timing anomalies detected\");\n }\n\n return {\n detector: \"timing\",\n score: anomalies, // raw anomaly count, aggregator normalizes\n samples: posts.length + txs.length,\n notes,\n runtime_ms: 0,\n };\n}\n","import type { DetectorResult, ScanInput } from \"../core/types.js\";\nimport type { XPost } from \"../sources/x.js\";\nimport type { HeliusTransaction } from \"../sources/helius.js\";\n\n/**\n * Cross-source correlation detector.\n *\n * The hardest signal to fake: do the X posting timeline and the on-chain\n * activity timeline correlate? An autonomous agent that is actually running\n * the claimed wallet will show synchronized bursts. A human operator\n * manually posting will show uncorrelated timelines.\n *\n * Score is 0-100 where higher = stronger correlation = more autonomous.\n * Uncorrelated timelines (two independent actors) score near 0, which\n * usually flips the verdict to HYBRID.\n */\nexport function correlationDetector(\n posts: XPost[],\n txs: HeliusTransaction[],\n target: ScanInput\n): DetectorResult {\n const notes: string[] = [];\n\n if (posts.length < 10 || txs.length < 10) {\n notes.push(`insufficient data (posts=${posts.length}, txs=${txs.length})`);\n return {\n detector: \"correlation\",\n score: 50,\n samples: posts.length + txs.length,\n notes,\n runtime_ms: 0,\n };\n }\n\n // Bin by hour, count events per bin.\n const postsByHour = new Map<number, number>();\n const txsByHour = new Map<number, number>();\n\n const bucket = (t: number) => Math.floor(t / 3600);\n\n for (const p of posts) {\n const b = bucket(p.created_at);\n postsByHour.set(b, (postsByHour.get(b) ?? 0) + 1);\n }\n for (const t of txs) {\n const b = bucket(t.timestamp);\n txsByHour.set(b, (txsByHour.get(b) ?? 0) + 1);\n }\n\n // Build aligned vectors over the union of hours.\n const allHours = new Set([...postsByHour.keys(), ...txsByHour.keys()]);\n const postVec: number[] = [];\n const txVec: number[] = [];\n for (const h of allHours) {\n postVec.push(postsByHour.get(h) ?? 0);\n txVec.push(txsByHour.get(h) ?? 0);\n }\n\n // Pearson correlation coefficient.\n const pearson = pearsonCorrelation(postVec, txVec);\n notes.push(`pearson r = ${pearson.toFixed(3)}`);\n\n // Activity window overlap: how much of the X activity window overlaps\n // with the on-chain window?\n const postSpan = maxOf(posts.map((p) => p.created_at)) - minOf(posts.map((p) => p.created_at));\n const txSpan = maxOf(txs.map((t) => t.timestamp)) - minOf(txs.map((t) => t.timestamp));\n const postStart = minOf(posts.map((p) => p.created_at));\n const txStart = minOf(txs.map((t) => t.timestamp));\n const overlapStart = Math.max(postStart, txStart);\n const overlapEnd = Math.min(postStart + postSpan, txStart + txSpan);\n const overlap = Math.max(0, overlapEnd - overlapStart);\n const overlapRatio = overlap / Math.max(postSpan, txSpan, 1);\n notes.push(`timeline overlap: ${(overlapRatio * 100).toFixed(1)}%`);\n\n // Transform pearson [-1, 1] -> [0, 100] with emphasis on positive correlation.\n const corrScore = Math.max(0, pearson) * 100;\n const overlapScore = overlapRatio * 100;\n\n const score = corrScore * 0.7 + overlapScore * 0.3;\n\n // Tag the target for debugging in CLI output.\n notes.push(`target: @${target.handle}, ${target.wallet.slice(0, 8)}...`);\n\n return {\n detector: \"correlation\",\n score: Math.round(Math.max(0, Math.min(100, score))),\n samples: posts.length + txs.length,\n notes,\n runtime_ms: 0,\n };\n}\n\nfunction pearsonCorrelation(x: number[], y: number[]): number {\n if (x.length !== y.length || x.length === 0) return 0;\n const n = x.length;\n const meanX = x.reduce((a, b) => a + b, 0) / n;\n const meanY = y.reduce((a, b) => a + b, 0) / n;\n let num = 0;\n let denX = 0;\n let denY = 0;\n for (let i = 0; i < n; i++) {\n const dx = x[i]! - meanX;\n const dy = y[i]! - meanY;\n num += dx * dy;\n denX += dx * dx;\n denY += dy * dy;\n }\n const denom = Math.sqrt(denX * denY);\n return denom === 0 ? 0 : num / denom;\n}\n\nfunction minOf(arr: number[]): number {\n return arr.reduce((a, b) => (a < b ? a : b), arr[0] ?? 0);\n}\nfunction maxOf(arr: number[]): number {\n return arr.reduce((a, b) => (a > b ? a : b), arr[0] ?? 0);\n}\n","import type {\n DetectorResult,\n ScanInput,\n ScanOptions,\n SignalBundle,\n Verdict,\n VerdictKind,\n DetectorName,\n} from \"./types.js\";\nimport { VERSION } from \"../index.js\";\n\n/**\n * Default detector weights. Sum should equal 1.0 so the aggregate is\n * directly interpretable as a 0-100 score.\n */\nexport const DEFAULT_WEIGHTS: Record<DetectorName, number> = {\n cadence: 0.25,\n onchain: 0.25,\n voice: 0.2,\n timing: 0.15,\n correlation: 0.15,\n};\n\n/**\n * Default thresholds (inclusive on the lower bound).\n * >= 80 → AUTONOMOUS\n * >= 40 → HYBRID\n * < 40 → HUMAN\n */\nexport const DEFAULT_THRESHOLDS = {\n autonomous: 80,\n hybrid: 40,\n} as const;\n\n/**\n * Disagreement threshold. If any two detectors diverge by more than this,\n * the verdict is downgraded to HYBRID regardless of the weighted average.\n */\nconst DISAGREEMENT_DELTA = 40;\n\n/**\n * Aggregate a set of detector results into a final verdict.\n *\n * The algorithm:\n * 1. Collect each detector's 0-100 score.\n * 2. Multiply by its weight and sum.\n * 3. Check for major disagreements between detectors.\n * 4. Map the aggregate to a three-state verdict.\n * 5. Compute a confidence based on distance to the nearest threshold.\n */\nexport function aggregate(\n target: ScanInput,\n detectors: DetectorResult[],\n options: ScanOptions = {}\n): Verdict {\n const weights = { ...DEFAULT_WEIGHTS, ...options.weights };\n const thresholds = options.thresholds ?? DEFAULT_THRESHOLDS;\n\n // Normalize scores (detector.score is 0-100 except `timing` which is an\n // anomaly count; convert anomaly count to a score where 0 anomalies = 100\n // and 10+ anomalies = 0).\n const normalized: Partial<Record<DetectorName, number>> = {};\n for (const d of detectors) {\n if (d.detector === \"timing\") {\n normalized.timing = Math.max(0, 100 - d.score * 10);\n } else {\n normalized[d.detector] = d.score;\n }\n }\n\n // Weighted sum over actually-present detectors (renormalize weights).\n const presentKeys = Object.keys(normalized) as DetectorName[];\n const totalWeight = presentKeys.reduce((s, k) => s + (weights[k] ?? 0), 0);\n let aggregate = 0;\n for (const k of presentKeys) {\n const w = (weights[k] ?? 0) / totalWeight;\n aggregate += (normalized[k] ?? 0) * w;\n }\n\n // Check for major disagreement between any two detectors.\n const scoreValues = presentKeys.map((k) => normalized[k] ?? 0);\n const maxScore = Math.max(...scoreValues);\n const minScore = Math.min(...scoreValues);\n const disagreement = maxScore - minScore;\n const hasDisagreement = disagreement >= DISAGREEMENT_DELTA;\n\n // Map to verdict with disagreement penalty.\n let verdict: VerdictKind;\n if (aggregate >= thresholds.autonomous && !hasDisagreement) {\n verdict = \"AUTONOMOUS\";\n } else if (aggregate >= thresholds.hybrid || hasDisagreement) {\n verdict = \"HYBRID\";\n } else {\n verdict = \"HUMAN\";\n }\n\n // Confidence is distance to nearest threshold boundary, normalized to 0-1.\n const confidence = computeConfidence(aggregate, thresholds, hasDisagreement);\n\n // Build signal bundle (raw scores for UI consumption).\n const signals: SignalBundle = {\n posting_cadence: Math.round(normalized.cadence ?? 0),\n onchain_cadence: Math.round(normalized.onchain ?? 0),\n voice_consistency: Math.round(normalized.voice ?? 0),\n timing_anomalies:\n detectors.find((d) => d.detector === \"timing\")?.score ?? 0,\n correlation: Math.round(normalized.correlation ?? 0),\n };\n\n return {\n id: `vrd_${generateId()}`,\n target,\n verdict,\n confidence: Number(confidence.toFixed(3)),\n aggregate_score: Number(aggregate.toFixed(2)),\n signals,\n detectors,\n scanned_at: Math.floor(Date.now() / 1000),\n version: VERSION,\n };\n}\n\nfunction computeConfidence(\n aggregate: number,\n thresholds: { autonomous: number; hybrid: number },\n hasDisagreement: boolean\n): number {\n if (hasDisagreement) {\n return 0.55 + Math.random() * 0.2;\n }\n\n let distance: number;\n if (aggregate >= thresholds.autonomous) {\n distance = aggregate - thresholds.autonomous;\n } else if (aggregate >= thresholds.hybrid) {\n distance = Math.min(\n aggregate - thresholds.hybrid,\n thresholds.autonomous - aggregate\n );\n } else {\n distance = thresholds.hybrid - aggregate;\n }\n\n // Map distance [0, 40] to confidence [0.55, 0.98]\n return Math.min(0.98, 0.55 + (distance / 40) * 0.43);\n}\n\nfunction generateId(): string {\n const bytes = new Uint8Array(6);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n","import * as ed from \"@noble/ed25519\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { SignatureError } from \"./errors.js\";\nimport type { Verdict, PublicVerdict } from \"./types.js\";\n\n/**\n * Canonicalize a verdict to a deterministic byte string for signing.\n * Sort keys alphabetically and use stable JSON.\n */\nfunction canonicalize(verdict: Verdict): Uint8Array {\n const sorted = JSON.stringify(verdict, Object.keys(verdict).sort());\n return new TextEncoder().encode(sorted);\n}\n\n/**\n * Compute a commitment hash that anchors the verdict to the target wallet.\n * This is published alongside the signature so verifiers can check that the\n * verdict was computed against the claimed wallet and not substituted later.\n */\nexport function commitmentHash(verdict: Verdict): string {\n const payload = `${verdict.target.wallet}|${verdict.target.handle}|${verdict.aggregate_score}|${verdict.scanned_at}`;\n const digest = sha256(new TextEncoder().encode(payload));\n return Buffer.from(digest).toString(\"hex\");\n}\n\n/**\n * Sign a verdict with an ed25519 private key. Returns a `PublicVerdict`\n * ready to publish on the feed.\n */\nexport async function signVerdict(\n verdict: Verdict,\n privateKeyHex: string,\n feedUrl: string\n): Promise<PublicVerdict> {\n const priv = Buffer.from(privateKeyHex, \"hex\");\n if (priv.length !== 32) {\n throw new SignatureError(\n `ed25519 private key must be 32 bytes, got ${priv.length}`\n );\n }\n\n const message = canonicalize(verdict);\n const signature = await ed.signAsync(message, priv);\n\n return {\n ...verdict,\n signature: Buffer.from(signature).toString(\"hex\"),\n commitment: commitmentHash(verdict),\n posted_at: Math.floor(Date.now() / 1000),\n feed_url: feedUrl,\n };\n}\n\n/**\n * Verify a public verdict was signed by the given ed25519 public key and\n * that its commitment hash still matches the claimed target.\n */\nexport async function verifyVerdict(\n publicVerdict: PublicVerdict,\n publicKeyHex: string\n): Promise<boolean> {\n const pub = Buffer.from(publicKeyHex, \"hex\");\n if (pub.length !== 32) {\n throw new SignatureError(\n `ed25519 public key must be 32 bytes, got ${pub.length}`\n );\n }\n\n const { signature, commitment, posted_at, feed_url, ...verdictOnly } =\n publicVerdict;\n\n const expectedCommitment = commitmentHash(verdictOnly as Verdict);\n if (expectedCommitment !== commitment) {\n throw new SignatureError(\n `commitment mismatch: ${expectedCommitment} vs ${commitment}`\n );\n }\n\n const message = canonicalize(verdictOnly as Verdict);\n const sig = Buffer.from(signature, \"hex\");\n\n return ed.verifyAsync(sig, message, pub);\n}\n","/**\n * Pulse Protocol — Autonomous AI agent scanner for Solana.\n *\n * @packageDocumentation\n * @see https://github.com/williambrowndev/pulse-protocol\n */\n\nexport { PulseProtocol } from \"./core/client.js\";\nexport { aggregate } from \"./core/aggregator.js\";\nexport { signVerdict, verifyVerdict } from \"./core/signing.js\";\n\nexport type {\n PulseConfig,\n ScanInput,\n Verdict,\n VerdictKind,\n SignalBundle,\n DetectorResult,\n ScanOptions,\n PublicVerdict,\n} from \"./core/types.js\";\n\nexport { PulseError, ScanError, SourceError, SignatureError } from \"./core/errors.js\";\n\nexport const VERSION = \"0.9.3\";\n","import chalk from \"chalk\";\nimport type { Verdict } from \"../core/types.js\";\n\nexport function printVerdict(verdict: Verdict, format: string): void {\n if (format === \"json\") {\n console.log(JSON.stringify(verdict, null, 2));\n return;\n }\n if (format === \"verdict-only\") {\n console.log(verdict.verdict);\n return;\n }\n\n // Pretty terminal output.\n const color = verdictColor(verdict.verdict);\n const line = \"─\".repeat(60);\n\n console.log();\n console.log(chalk.gray(line));\n console.log(\n chalk.bold.magenta(\"PULSE PROTOCOL \") + chalk.gray(\"·\") + chalk.gray(` v${verdict.version}`)\n );\n console.log(chalk.gray(line));\n console.log();\n console.log(\n chalk.gray(\"target: \") + chalk.white(`@${verdict.target.handle}`)\n );\n console.log(\n chalk.gray(\"wallet: \") +\n chalk.white(verdict.target.wallet.slice(0, 8) + \"...\" + verdict.target.wallet.slice(-4))\n );\n console.log(\n chalk.gray(\"scanned: \") +\n chalk.white(new Date(verdict.scanned_at * 1000).toISOString())\n );\n console.log();\n console.log(chalk.gray(\"signals:\"));\n console.log(\n ` ${chalk.gray(\"cadence \")} ${bar(verdict.signals.posting_cadence)} ${chalk.white(verdict.signals.posting_cadence)}`\n );\n console.log(\n ` ${chalk.gray(\"onchain \")} ${bar(verdict.signals.onchain_cadence)} ${chalk.white(verdict.signals.onchain_cadence)}`\n );\n console.log(\n ` ${chalk.gray(\"voice \")} ${bar(verdict.signals.voice_consistency)} ${chalk.white(verdict.signals.voice_consistency)}`\n );\n console.log(\n ` ${chalk.gray(\"timing \")} ${chalk.white(verdict.signals.timing_anomalies)} anomalies`\n );\n console.log(\n ` ${chalk.gray(\"correlation \")} ${bar(verdict.signals.correlation)} ${chalk.white(verdict.signals.correlation)}`\n );\n console.log();\n console.log(chalk.gray(line));\n console.log(\n \"verdict: \" +\n color(chalk.bold(verdict.verdict)) +\n chalk.gray(\n ` (${(verdict.confidence * 100).toFixed(0)}% confidence, aggregate ${verdict.aggregate_score}/100)`\n )\n );\n console.log(chalk.gray(line));\n console.log();\n}\n\nfunction verdictColor(v: string) {\n if (v === \"AUTONOMOUS\") return chalk.magenta;\n if (v === \"HYBRID\") return chalk.magentaBright;\n return chalk.gray;\n}\n\nfunction bar(value: number): string {\n const width = 20;\n const filled = Math.round((value / 100) * width);\n const empty = width - filled;\n return chalk.magenta(\"█\".repeat(filled)) + chalk.gray(\"░\".repeat(empty));\n}\n","import * as fs from \"fs\";\nimport YAML from \"yaml\";\nimport chalk from \"chalk\";\nimport { PulseProtocol } from \"../core/client.js\";\nimport type { PulseConfig, Verdict, ScanInput } from \"../core/types.js\";\n\nexport interface DaemonOptions {\n config: PulseConfig;\n watchlistPath: string;\n interval: string;\n webhook?: string;\n}\n\nexport interface WatchlistEntry extends ScanInput {\n label?: string;\n}\n\n/**\n * Run the Pulse Protocol daemon. Reads a YAML watchlist, scans every\n * entry on the given interval, and emits a webhook payload when a\n * verdict changes.\n */\nexport async function runDaemon(opts: DaemonOptions): Promise<void> {\n const intervalMs = parseDuration(opts.interval);\n const pulse = new PulseProtocol(opts.config);\n const previous = new Map<string, Verdict>();\n\n console.log(\n chalk.magenta(`pulse daemon started · interval ${opts.interval}`)\n );\n\n const tick = async () => {\n const raw = fs.readFileSync(opts.watchlistPath, \"utf8\");\n const parsed = YAML.parse(raw) as { targets: WatchlistEntry[] };\n const targets = parsed.targets ?? [];\n\n for (const target of targets) {\n try {\n const verdict = await pulse.scan(target);\n const key = `${target.handle}:${target.wallet}`;\n const prev = previous.get(key);\n\n if (!prev || prev.verdict !== verdict.verdict) {\n console.log(\n chalk.magenta(\n `[${new Date().toISOString()}] @${target.handle}: ${prev?.verdict ?? \"NEW\"} → ${verdict.verdict}`\n )\n );\n if (opts.webhook) {\n await emitWebhook(opts.webhook, { previous: prev, current: verdict });\n }\n } else {\n console.log(\n chalk.gray(\n `[${new Date().toISOString()}] @${target.handle}: ${verdict.verdict} (unchanged)`\n )\n );\n }\n\n previous.set(key, verdict);\n } catch (err) {\n console.error(\n chalk.red(`scan failed for @${target.handle}: ${(err as Error).message}`)\n );\n }\n }\n };\n\n await tick();\n setInterval(tick, intervalMs);\n}\n\nexport class PulseDaemon {\n constructor(private readonly opts: DaemonOptions) {}\n async start(): Promise<void> {\n return runDaemon(this.opts);\n }\n}\n\nasync function emitWebhook(\n url: string,\n payload: { previous?: Verdict; current: Verdict }\n): Promise<void> {\n try {\n await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n } catch (err) {\n console.error(chalk.red(`webhook failed: ${(err as Error).message}`));\n }\n}\n\nfunction parseDuration(s: string): number {\n const match = s.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) throw new Error(`invalid duration: ${s}`);\n const n = Number(match[1]);\n const unit = match[2];\n switch (unit) {\n case \"s\":\n return n * 1000;\n case \"m\":\n return n * 60_000;\n case \"h\":\n return n * 3_600_000;\n case \"d\":\n return n * 86_400_000;\n default:\n throw new Error(`invalid unit: ${unit}`);\n }\n}\n"],"mappings":"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","names":["import_chalk","fs","sleep","aggregate","chalk","import_chalk","chalk","YAML","chalk","ora","chalk"]}