star-chart-search-enhancer/docs/superpowers/plans/2026-04-15-star-chart-after-search-rate-implementation.md

279 lines
8.9 KiB
Markdown

# Star Chart After Search Rate 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 minimal Chrome MV3 extension that captures the two after-search-rate metrics on Xingtu creator detail pages and logs one structured final result per route.
**Architecture:** The extension uses an isolated content script to manage route state, inject a page-context hook, receive `postMessage` results, and print deduplicated structured output. Shared pure utilities handle star ID parsing, route key generation, label normalization, result shaping, and JSON extraction so the network hook stays thin and testable.
**Tech Stack:** TypeScript, Vitest, tsup, Chrome Extension Manifest V3
---
## Implementation Notes
- Current workspace is **not** a git repository, so worktree and commit steps are replaced with explicit verification notes.
- Keep scope to the detail page experiment only.
- Follow TDD strictly: test first, verify red, implement minimal code, verify green.
## Planned File Map
- Create: `package.json`
- Create: `tsconfig.json`
- Create: `vitest.config.ts`
- Create: `scripts/build.mjs`
- Create: `src/manifest.json`
- Create: `src/content/index.ts`
- Create: `src/content/route-state.ts`
- Create: `src/page/hook.ts`
- Create: `src/page/network-interceptor.ts`
- Create: `src/shared/extract-after-search-rates.ts`
- Create: `src/shared/get-star-id.ts`
- Create: `src/shared/message-types.ts`
- Create: `src/shared/normalize-rate-label.ts`
- Create: `src/shared/result-types.ts`
- Create: `src/shared/route-key.ts`
- Create: `tests/extract-after-search-rates.test.ts`
- Create: `tests/get-star-id.test.ts`
- Create: `tests/route-key.test.ts`
- Create: `tests/content-bridge.test.ts`
- Create: `tests/page-hook.test.ts`
- Create: `README.md`
### Task 1: Bootstrap the Tooling and Build Layout
**Files:**
- Create: `package.json`
- Create: `tsconfig.json`
- Create: `vitest.config.ts`
- Create: `scripts/build.mjs`
- Create: `src/manifest.json`
- [ ] **Step 1: Write the failing build-shape test**
Create `tests/build-layout.test.ts` that asserts:
- `src/manifest.json` exists and includes one content script match for `https://*.xingtu.cn/ad/creator/author-homepage/*`
- build script copies manifest and emits `dist/manifest.json`
- [ ] **Step 2: Run the test to verify it fails**
Run: `npm test -- tests/build-layout.test.ts`
Expected: FAIL because project files and scripts do not exist yet
- [ ] **Step 3: Create the minimal tooling files**
Implement:
- `package.json` with `build`, `test`, and `test:run`
- `tsconfig.json`
- `vitest.config.ts`
- `scripts/build.mjs`
- `src/manifest.json`
- [ ] **Step 4: Run the test to verify it passes**
Run: `npm test -- tests/build-layout.test.ts`
Expected: PASS
- [ ] **Step 5: Verify build output**
Run: `npm run build`
Expected: `dist/manifest.json` exists and TypeScript entrypoints build without errors
- [ ] **Step 6: Commit**
Skip: repository is not initialized as git; record the verification output instead
### Task 2: Implement and Test Shared Extraction Utilities
**Files:**
- Create: `src/shared/extract-after-search-rates.ts`
- Create: `src/shared/get-star-id.ts`
- Create: `src/shared/normalize-rate-label.ts`
- Create: `src/shared/result-types.ts`
- Create: `src/shared/route-key.ts`
- Create: `tests/extract-after-search-rates.test.ts`
- Create: `tests/get-star-id.test.ts`
- Create: `tests/route-key.test.ts`
- [ ] **Step 1: Write the failing utility tests**
Add tests covering:
- parsing page star ID from matching and non-matching URLs
- route key creation with incrementing navigation sequence
- exact-key extraction
- label/value extraction with synonymous labels
- text fallback extraction in a bounded subtree
- partial match stays `success: false`
- unrelated payload returns `matched: false`
- [ ] **Step 2: Run the tests to verify they fail**
Run: `npm test -- tests/get-star-id.test.ts tests/route-key.test.ts tests/extract-after-search-rates.test.ts`
Expected: FAIL because utility modules do not exist yet
- [ ] **Step 3: Implement the minimal utilities**
Implement:
- URL parsing for `pageStarId`
- `routeKey` helper
- label normalization helper
- extraction function with `exact-key`, `label-value`, `text-fallback`, and `none`
- shared types for results
- [ ] **Step 4: Run the tests to verify they pass**
Run: `npm test -- tests/get-star-id.test.ts tests/route-key.test.ts tests/extract-after-search-rates.test.ts`
Expected: PASS
- [ ] **Step 5: Refactor only if needed**
Keep utility files focused and remove duplication without changing behavior
- [ ] **Step 6: Re-run the utility tests**
Run: `npm test -- tests/get-star-id.test.ts tests/route-key.test.ts tests/extract-after-search-rates.test.ts`
Expected: PASS
- [ ] **Step 7: Commit**
Skip: repository is not initialized as git; record the verification output instead
### Task 3: Implement and Test the Content Bridge
**Files:**
- Create: `src/content/index.ts`
- Create: `src/content/route-state.ts`
- Create: `src/shared/message-types.ts`
- Modify: `src/shared/result-types.ts`
- Create: `tests/content-bridge.test.ts`
- [ ] **Step 1: Write the failing content bridge tests**
Add tests covering:
- route state initialization from the current URL
- navigation sequence increment on route changes
- stale route messages are ignored
- duplicate final results are not logged twice
- a later success result can replace an earlier failure result
- [ ] **Step 2: Run the test to verify it fails**
Run: `npm test -- tests/content-bridge.test.ts`
Expected: FAIL because content bridge files do not exist yet
- [ ] **Step 3: Implement the minimal content bridge**
Implement:
- route state tracking
- page-hook injection via `<script src=chrome.runtime.getURL(... )>`
- `window.postMessage` listener with source/type guards
- final structured logging and dedupe policy
- [ ] **Step 4: Run the test to verify it passes**
Run: `npm test -- tests/content-bridge.test.ts`
Expected: PASS
- [ ] **Step 5: Verify route-state behavior stays green**
Run: `npm test -- tests/content-bridge.test.ts tests/route-key.test.ts`
Expected: PASS
- [ ] **Step 6: Commit**
Skip: repository is not initialized as git; record the verification output instead
### Task 4: Implement and Test the Page Hook and Network Interceptor
**Files:**
- Create: `src/page/hook.ts`
- Create: `src/page/network-interceptor.ts`
- Modify: `src/shared/extract-after-search-rates.ts`
- Modify: `src/shared/message-types.ts`
- Create: `tests/page-hook.test.ts`
- [ ] **Step 1: Write the failing page-hook tests**
Add tests covering:
- fetch wrapping reads only `response.clone()`
- original fetch result still resolves unchanged
- hook failures do not block the request
- matching payload posts a structured result message
- timeout produces one failure terminal result
- duplicate patching is prevented by a guard
- [ ] **Step 2: Run the test to verify it fails**
Run: `npm test -- tests/page-hook.test.ts`
Expected: FAIL because page hook files do not exist yet
- [ ] **Step 3: Implement the minimal page hook**
Implement:
- one-time patch guard
- fetch wrapper
- lightweight XHR wrapper
- candidate filtering
- timeout handling
- result posting to the content bridge
- [ ] **Step 4: Run the test to verify it passes**
Run: `npm test -- tests/page-hook.test.ts`
Expected: PASS
- [ ] **Step 5: Run the focused suite**
Run: `npm test -- tests/extract-after-search-rates.test.ts tests/content-bridge.test.ts tests/page-hook.test.ts`
Expected: PASS
- [ ] **Step 6: Commit**
Skip: repository is not initialized as git; record the verification output instead
### Task 5: Finalize Build and Manual Verification Instructions
**Files:**
- Modify: `README.md`
- Modify: `scripts/build.mjs`
- Modify: `src/manifest.json`
- [ ] **Step 1: Write the failing documentation assertion**
Extend `tests/build-layout.test.ts` or add `tests/readme.test.ts` to assert the README documents:
- how to install dependencies
- how to run tests
- how to build
- how to load the unpacked extension
- how to verify the console result on a Xingtu detail page
- [ ] **Step 2: Run the test to verify it fails**
Run: `npm test -- tests/build-layout.test.ts`
Expected: FAIL because README does not include the required instructions yet
- [ ] **Step 3: Implement the minimal documentation and polish build output**
Add:
- concise README setup and verification instructions
- any build copy adjustments needed for Chrome to load `dist/`
- [ ] **Step 4: Run the test to verify it passes**
Run: `npm test -- tests/build-layout.test.ts`
Expected: PASS
- [ ] **Step 5: Run the full verification suite**
Run: `npm test`
Expected: all tests PASS
- [ ] **Step 6: Run a fresh production build**
Run: `npm run build`
Expected: build exits 0 and `dist/` contains manifest plus extension scripts
- [ ] **Step 7: Commit**
Skip: repository is not initialized as git; record the verification output instead