diff --git a/docs/superpowers/specs/2026-06-16-geo-agent-article-optimizer-design.md b/docs/superpowers/specs/2026-06-16-geo-agent-article-optimizer-design.md index 3fe718c..9cf4c69 100644 --- a/docs/superpowers/specs/2026-06-16-geo-agent-article-optimizer-design.md +++ b/docs/superpowers/specs/2026-06-16-geo-agent-article-optimizer-design.md @@ -14,11 +14,16 @@ The MVP is a local web application: 2. System extracts a candidate fact card. 3. User confirms or edits the fact card. 4. Confirmed fact card is saved as a reusable local brand template. -5. System optimizes the article under fact-card constraints. -6. System runs quality gates. -7. Failed checks trigger targeted rewriting for up to two rounds. -8. User previews optimized content and QA report. -9. User downloads Markdown and a basic Word document. +5. System generates three optimization candidates under fact-card constraints: + `标准GEO版`, `去AI味版`, and `综合增强版`. +6. System runs quality gates for each candidate. +7. Failed checks trigger targeted rewriting for up to two rounds inside each + candidate path. +8. System scores each candidate for GEO quality and AI-flavor/style quality. +9. User compares all candidates side by side, with `综合增强版` highlighted as + the recommended default. +10. User downloads Markdown, Word, and QA artifacts for the selected candidate + or the full comparison. ## Explicitly Out Of Scope @@ -36,12 +41,15 @@ The MVP is a local web application: flowchart TD A["Input Article"] --> B["Auto Analyze"] B --> C["Confirm Fact Card"] - C --> D["Optimize Article"] - D --> E["Quality Check"] - E -->|Pass| F["Preview Result"] - E -->|Fail| G["Targeted Rewrite"] - G --> D - F --> H["Download Markdown / Word"] + C --> D["Generate Three Candidates"] + D --> E1["标准GEO版 QA"] + D --> E2["去AI味版 QA"] + D --> E3["综合增强版 QA"] + E1 --> F["Compare Results"] + E2 --> F + E3 --> F + F --> G["Select Candidate"] + G --> H["Download Markdown / Word / QA"] ``` ## Page Areas @@ -78,17 +86,24 @@ Fields: The user must resolve uncertain items before optimization starts. -### Optimized Result +### Candidate Comparison Display: +- Candidate label: `标准GEO版`, `去AI味版`, or `综合增强版`. +- Method summary that explains what this candidate optimized for. - Optimized title. - Summary. - Optimized body. -- Image suggestions. +- QA status and failed/warned rule count. +- GEO score. +- AI-flavor/style score. +- Timing. - Changed sections. -The UI should mark content that needs user confirmation. +The UI should mark content that needs user confirmation and should make +`综合增强版` visually identifiable as the recommended default without hiding the +other two candidates. ### Quality Report @@ -98,9 +113,11 @@ Display each gate as pass, warn, or fail, with evidence, reason, suggested fix, Downloads: -- `optimized.md` -- `optimized.docx` -- `qa_report.json` +- Selected candidate: `optimized.md`, `optimized.docx`, `qa_report.json`. +- Full comparison: `variant_comparison.json`. +- If all candidate files are exported together, use stable Chinese labels in the + metadata and ASCII-safe file names on disk, such as + `standard-geo.md`, `anti-ai-flavor.md`, and `integrated-enhanced.md`. ## Internal Agent Nodes @@ -110,11 +127,23 @@ The product is delivered as a simple web app, but the internals are split into e flowchart LR A["InputNormalizer"] --> B["FactExtractor"] B --> C["UserConfirmedFactCard"] - C --> D["ArticleOptimizer"] - D --> E["QualityInspector"] - E -->|fail| F["TargetedRewriter"] - F --> E - E -->|pass/warn| G["Exporter"] + C --> D["OptimizationVariantPlanner"] + D --> E1["标准GEO版 ArticleOptimizer"] + D --> E2["去AI味版 ArticleOptimizer"] + D --> E3["综合增强版 ArticleOptimizer"] + E1 --> F1["QualityInspector + StyleScorer"] + E2 --> F2["QualityInspector + StyleScorer"] + E3 --> F3["QualityInspector + StyleScorer"] + F1 -->|fail| G1["TargetedRewriter"] + F2 -->|fail| G2["TargetedRewriter"] + F3 -->|fail| G3["TargetedRewriter"] + G1 --> F1 + G2 --> F2 + G3 --> F3 + F1 --> H["VariantComparator"] + F2 --> H + F3 --> H + H --> I["Exporter"] ``` ### LLM Provider Integration @@ -133,12 +162,14 @@ DEEPSEEK_THINKING=disabled Rules: -- `src/lib/llm/client.ts` exposes `generateText`, `generateJson`, `isLlmConfigured`, and `getLlmProviderStatus`. +- `src/lib/llm/client.ts` exposes `generateText`, `generateJson`, + `generateValidatedJson`, `isLlmConfigured`, and `getLlmProviderStatus`. - `LLM_PROVIDER` defaults to `deepseek` when unset. - DeepSeek is accessed through the OpenAI-compatible SDK with `baseURL` set to `https://api.deepseek.com`. - `generateJson` must use JSON output mode and prompts that explicitly require valid JSON only. - Thinking mode is disabled by default for deterministic article rewrites and structured QA output. -- Missing credentials use deterministic local fallbacks so the MVP remains testable and usable without a live API key. +- Missing credentials and provider failures surface as explicit API errors; the + workflow must not silently fall back when the user expects live LLM behavior. - Provider errors are normalized inside the LLM client before they reach workflow nodes or API routes. ### InputNormalizer @@ -212,6 +243,49 @@ Forbidden: - Change industry. - Add exaggerated marketing promises. +### OptimizationVariantPlanner + +Purpose: create a fixed set of candidate methods for one confirmed fact card. + +The first comparison version always creates exactly three candidates: + +| Variant Key | Label | Method | +| --- | --- | --- | +| `standard_geo` | `标准GEO版` | Current GEO rewrite behavior: fact-card fidelity, platform fit, clear structure, and QA repair. | +| `anti_ai_flavor` | `去AI味版` | GEO rewrite plus localized Stop Slop rules to remove AI-flavored prose patterns. | +| `integrated_enhanced` | `综合增强版` | Balances GEO density, factual trust, platform fit, readability, and AI-flavor reduction. | + +Candidate generation may run sequentially in the first implementation to avoid +provider rate-limit problems and to keep progress events understandable. The +API response still returns the three candidates together for side-by-side +comparison. + +### Stop Slop / AI-Flavor Rules + +The `hardikpandya/stop-slop` repository is an MIT-licensed writing skill rather +than an installable runtime dependency. The original rules are mostly English +writing rules, so the product should not copy them blindly into Chinese article +optimization. + +The first implementation uses localized guidance derived from the rule intent: + +- Remove template openers and filler transitions, such as generic "本文将", + "值得注意的是", "从某种意义上", and repeated "通过...实现..." chains. +- Replace empty business language with concrete claims already present in the + fact card. +- Avoid formulaic contrast paragraphs that first list what something is not and + then reveal what it is. +- Avoid slogan-like short fragments that sound like pull quotes instead of + article prose. +- Prefer active, specific Chinese sentences with clear actors when the source + facts identify an actor. +- Vary paragraph length and sentence rhythm without using theatrical emphasis. + +If substantial text from the upstream Stop Slop files is copied into this +repository, add the MIT license notice to the committed artifact. A distilled +Chinese rule set written for this product can live in source without vendoring +the upstream repository. + ### QualityInspector Purpose: convert the document's issue list into executable quality gates. @@ -236,6 +310,53 @@ Examples: - Delete or mark unsupported claims for hallucination risk. - Warn instead of rewriting when image-text confidence is low. +### StyleScorer + +Purpose: score each candidate for AI-flavor risk and naturalness without turning +style concerns into hard QA failures. + +The first version returns a 0-50 score with five 0-10 dimensions: + +| Dimension | Question | +| --- | --- | +| `directness` | Does the article state concrete points instead of announcing them? | +| `rhythm` | Do sentence and paragraph lengths vary naturally? | +| `specificity` | Are claims concrete and tied to the fact card? | +| `trust` | Does the prose avoid exaggerated intimacy, sweeping claims, and unsupported certainty? | +| `density` | Can obvious filler be removed without losing meaning? | + +Scores below 35 should show a visible warning on the candidate card. They should +not block export. + +### GeoScore + +Purpose: reuse the existing GEO article performance rubric to score each +candidate for fact integrity, platform fit, search intent fit, answer density, +trust signal quality, and readability. + +The score is computed from the candidate article plus its QA report. It is a +comparison aid for the three candidates, not a publishing guarantee. + +### VariantComparator + +Purpose: assemble the candidate list for the API response and frontend. + +Each candidate result includes: + +- `variant_key` +- `variant_label` +- `method_summary` +- `article` +- `qa_report` +- `geo_score` +- `style_score` +- `rewrite_rounds` +- `timing` +- `is_recommended` + +`integrated_enhanced` is recommended by default unless it has a hard QA failure +and another candidate does not. + ## Quality Gates | Rule ID | Issue Prevented | First Version Behavior | @@ -276,15 +397,25 @@ Examples: The first version uses local SQLite plus an export folder. +The first implementation can reuse the existing `optimized_articles` and +`qa_reports` tables by saving each candidate as a normal article revision with +variant metadata inside the JSON payload. The matching QA report is saved +against that revision. A separate comparison-run table is out of scope until the +product needs historical side-by-side comparison beyond the immediate job +result. + ```text data/ app.db exports/ job_xxx/ - original.md optimized.md optimized.docx qa_report.json + variant_comparison.json + standard-geo.md + anti-ai-flavor.md + integrated-enhanced.md ``` ### `brand_template` @@ -358,6 +489,9 @@ One revision of optimized content. { "job_id": "job_xxx", "revision": 2, + "variant_key": "integrated_enhanced", + "variant_label": "综合增强版", + "method_summary": "同时优化GEO信息密度、事实可信度、平台适配和表达自然度。", "title": "Optimized title", "summary": "Optimized summary", "body_markdown": "Optimized body in Markdown", @@ -367,7 +501,22 @@ One revision of optimized content. "suggestion": "Use product dashboard screenshot; avoid unrelated people photos" } ], - "changed_sections": ["title", "first paragraph"] + "changed_sections": ["title", "first paragraph"], + "geo_score": { + "total": 8.1, + "rationale": "事实一致性与答案密度较好,平台适配仍需复核。" + }, + "style_score": { + "total": 42, + "dimensions": { + "directness": 8, + "rhythm": 8, + "specificity": 9, + "trust": 8, + "density": 9 + }, + "warnings": [] + } } ``` @@ -408,9 +557,13 @@ Examples: ### QA Failure -Hard failures block export. Warnings allow export with visible confirmation prompts. +Hard failures do not block export in the current product direction. The app must +preserve export files and show visible warnings so the user can review the +candidate manually. -Failed checks trigger targeted rewrite for up to two rounds. After two failed rounds, the app stops rewriting and shows manual review fields. +Failed checks trigger targeted rewrite for up to two rounds inside each +candidate. After two failed rounds, the app stops rewriting that candidate and +shows manual review fields. ## Acceptance Criteria @@ -420,9 +573,14 @@ The MVP is complete when: 2. System can extract a fact card and require user confirmation. 3. Confirmed fact card can be saved and reused as a local brand template. 4. System can generate an optimized article without changing confirmed facts. -5. System can generate a structured QA report for the 10 quality gates. -6. Hard failures block export until fixed or manually reviewed. -7. User can download Markdown and a basic Word document. +5. System can generate exactly three labeled candidates: `标准GEO版`, + `去AI味版`, and `综合增强版`. +6. System can generate a structured QA report for the 10 quality gates for each + candidate. +7. System can score and compare the three candidates for AI-flavor/style quality. +8. QA failures and low style scores remain visible but do not remove export links. +9. User can download Markdown, a basic Word document, QA JSON, and a comparison + JSON artifact. ## Minimum Test Samples