ETH Alpha Comment Assistant Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Build a Chrome MV3 extension that ranks currently loaded X tweets for Chinese ETH opportunity commenting and drafts replies through the OpenAI Responses API.

Architecture: Keep all scoring, parsing, and prompt formatting in a pure src/core.js module that can run in Chrome and Node tests. Use content.js for X page DOM work, background.js for OpenAI calls and storage, and sidepanel.js for the user workflow.

Tech Stack: Chrome Extension Manifest V3, plain JavaScript, Chrome side panel API, OpenAI Responses API through fetch, Node built-in test runner.


Task 1: Core Behavior Tests

Files:

  • Create: package.json
  • Create: tests/core.test.js

  • Step 1: Add package scripts
{
  "name": "eth-alpha-comment-assistant",
  "version": "0.1.0",
  "private": true,
  "type": "commonjs",
  "scripts": {
    "test": "node --test"
  }
}
  • Step 2: Add tests for scoring, parsing, and prompt safety
const test = require('node:test');
const assert = require('node:assert/strict');
const core = require('../src/core.js');

test('scores ETH opportunity tweets above generic crypto tweets', () => {
  const eth = core.scoreTweet({
    id: '1',
    text: 'EigenLayer restaking points are live on an ETH L2 with a new airdrop campaign',
    metrics: { replies: 20, reposts: 40, likes: 300 },
    createdAt: Date.now() - 20 * 60 * 1000
  }, Date.now());

  const generic = core.scoreTweet({
    id: '2',
    text: 'Crypto markets are moving today',
    metrics: { replies: 20, reposts: 40, likes: 300 },
    createdAt: Date.now() - 20 * 60 * 1000
  }, Date.now());

  assert.equal(eth.label, 'strong');
  assert.ok(eth.score > generic.score);
});

test('penalizes suspicious giveaway and seed phrase bait', () => {
  const result = core.scoreTweet({
    id: '3',
    text: 'Free ETH giveaway connect wallet and enter seed phrase to claim guaranteed profit',
    metrics: { replies: 200, reposts: 800, likes: 2000 },
    createdAt: Date.now()
  }, Date.now());

  assert.equal(result.label, 'skip');
  assert.ok(result.warnings.length >= 2);
});

test('extracts response text from Responses API output shape', () => {
  const text = core.extractResponseText({
    output: [
      {
        content: [
          { type: 'output_text', text: '1. 第一条\n2. 第二条\n3. 第三条' }
        ]
      }
    ]
  });

  assert.equal(text, '1. 第一条\n2. 第二条\n3. 第三条');
});

test('normalizes generated comments and removes numbering', () => {
  const comments = core.normalizeCommentCandidates('1. 第一条\n2) 第二条\n- 第三条\n第四条');

  assert.deepEqual(comments, ['第一条', '第二条', '第三条']);
});

test('builds a Chinese prompt that forbids auto-publishing language', () => {
  const prompt = core.buildCommentPrompt({
    text: 'Base ecosystem incentives are heating up',
    author: '@alice',
    url: 'https://x.com/alice/status/1',
    metrics: { replies: 1, reposts: 2, likes: 3 }
  });

  assert.match(prompt, /中文/);
  assert.match(prompt, /不要承诺收益/);
  assert.match(prompt, /不要引导点击陌生链接/);
});

Task 2: Core Implementation

Files:

  • Create: src/core.js

  • Step 1: Implement pure functions

Create a UMD-style module exposing parseMetricText, scoreTweet, buildCommentPrompt, extractResponseText, and normalizeCommentCandidates.

  • Step 2: Run tests

Run: npm test

Expected: all tests/core.test.js tests pass.

Task 3: Chrome Extension Shell

Files:

  • Create: manifest.json
  • Create: src/background.js
  • Create: src/content.js
  • Create: src/sidepanel.html
  • Create: src/sidepanel.js
  • Create: src/options.html
  • Create: src/options.js
  • Create: src/styles.css

  • Step 1: Add MV3 manifest

Configure side panel, options page, storage permission, active tab scripting, X host permissions, and background service worker.

  • Step 2: Add content script

Scan loaded article[data-testid="tweet"] nodes, inject Alpha buttons, send selected tweets to the side panel, and fill reply text without clicking publish.

  • Step 3: Add background worker

Read settings from chrome.storage.sync, call OpenAI /v1/responses, parse candidates through core.js, and return structured errors.

  • Step 4: Add side panel and options UI

Show scan results, selected tweet details, generated comments, fill buttons, and settings fields.

Task 4: Verification

Files:

  • Read: all created files

  • Step 1: Run automated tests

Run: npm test

Expected: 5 passing tests.

  • Step 2: Validate JSON

Run: node -e "JSON.parse(require('fs').readFileSync('manifest.json','utf8')); JSON.parse(require('fs').readFileSync('package.json','utf8')); console.log('json ok')"

Expected: json ok.

  • Step 3: Syntax-check JavaScript

Run: node --check src/core.js && node --check src/background.js && node --check src/content.js && node --check src/sidepanel.js && node --check src/options.js

Expected: all commands exit with code 0.