Files
xianyu-hunter-hermes-skill/skill/xianyu-hunter-monitor/references/web-analysis-notifications-2026-05.md
T

4.5 KiB

Web Hermes Analysis + Notifications (2026-05)

Session learning from extending BOSS's local xianyu-hunter fork with Web-visible analysis and notification controls.

Product shape BOSS expects

When adding analysis/notification capability, make it visible in the Web dashboard, not only as backend APIs:

  • Header button: 通知设置.
  • Task controls: 执行分析 beside edit/duplicate/start/rerun/delete.
  • New task tab: Hermes 分析 with recommendation/caution/reject summary and item cards.
  • Product list should show analysis verdict badges and concise reasons inline.
  • Analysis should persist into data/tasks.json and generate a Markdown report under reports/.

Backend API pattern

Add a lightweight local analysis layer and notifier:

  • lib/analyzer.mjs
    • buildAnalysis(task, { limit }) returns { items, summary }.
    • renderAnalysisMarkdown(task, summary) writes reports/<task_id>-analysis.md.
    • Include item-level hermesAnalysis: { score, verdict, reason, flags, positives, analyzedAt }.
  • lib/notifier.mjs
    • GET /api/notify-config and PUT /api/notify-config backed by data/notify-config.json.
    • sendNotifications(task, summary, { force }) supports:
      • hermes-webhook: POST { message, target, source, taskId }.
      • bark: POST { title, body, group } to https://api.day.app/<key> or configured endpoint.
      • pushplus: POST { token, title, content, template:'txt' }.
      • webhook: generic JSON { title, message, taskId }.
  • server.mjs
    • POST /api/tasks/:id/analyze should call taskManager.analyzeTask, write report, persist summary, and optionally notify.

TaskManager persistence details

  • Add getTaskFull(id) for routes that need full in-memory task data.
  • Add setTaskAnalysis(id, analysis) that merges item hermesAnalysis into products.fineFiltered, stores task.hermesAnalysis, persists to disk, and emits task:updated.
  • Include hermesAnalysis in _serialize, _serializeFull, and _loadFromDisk.
  • Clear task.hermesAnalysis = null when resetting products/rerunning a task.
  • New/duplicated tasks should initialize hermesAnalysis: null.

Frontend implementation details

  • Bump asset query versions in index.html after changing CSS/JS to avoid stale browser cache (style.css?v=11, app.js?v=11, etc.).
  • public/app.js helpers:
    • analyzeTaskNow(id) calls POST /api/tasks/:id/analyze with { notify: true }, then refreshes task detail.
    • renderAnalysis() renders empty state, stat cards, report path, and scored item cards.
    • When rendering raw product rows, map analysis from products.fineFiltered by id; raw items often do not contain the merged hermesAnalysis directly.
  • Preserve notification channel id when saving from the form; otherwise repeated saves create new channel IDs.

Verification checklist

Run syntax checks:

cd /Users/chick/.Hermes/workspace/research/xianyu-hunter
node --check server.mjs
node --check lib/task.mjs
node --check lib/analyzer.mjs
node --check lib/notifier.mjs
node --check public/app.js

Restart exact stale listener if xianyu_ops.mjs stop says no-recorded-server but port is still occupied:

pid=$(lsof -nP -iTCP:3000 -sTCP:LISTEN -t || true)
[ -z "$pid" ] || kill "$pid"
node tools/xianyu_ops.mjs start --port 3000

Smoke test APIs:

curl -fsS http://127.0.0.1:3000/api/notify-config | python3 -m json.tool
curl -fsS http://127.0.0.1:3000/api/tasks -o /tmp/xh_tasks.json
TASK=$(python3 - <<'PY'
import json
j=json.load(open('/tmp/xh_tasks.json'))
print(j[0]['id'] if j else '')
PY
)
curl -fsS -X POST "http://127.0.0.1:3000/api/tasks/$TASK/analyze" \
  -H 'Content-Type: application/json' \
  -d '{"notify":false,"limit":10}' | python3 -m json.tool

Important pitfall: piping a large /api/tasks response directly into python3 - <<'PY' consumes stdin for the script, not JSON. Save curl output to a temp file first.

Model-specific scoring pitfall: E3-1245v3

For CPU searches like E3-1245v3, scoring must distinguish true target models from related models used as SEO keywords.

Rules added in lib/analyzer.mjs:

  • If the task query indicates E3-1245v3, require an exact-ish match: e3\s*-?\s*1245\s*[_-]?\s*v3.
  • Penalize titles whose main model is another E3 v3, e.g. E3-1275v3 ... 性能超 E3-1245v3, because the title may only use 1245v3 as a comparison/keyword.
  • Flag failure terms beyond obvious 坏/不亮/暗病, including 不能进系统.

This reduced false recommendations in the E3-1245v3 task from related CPUs and broken parts.