Files
claw/docs/plans/2026-03-29-zhihu-hotlist-office-export-plan.md
2026-03-30 08:29:44 +08:00

445 lines
13 KiB
Markdown

# Zhihu Hotlist To Excel Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Make sgClaw reliably read Zhihu hotlist data through a Zhihu browser skill and export the collected structured result into a local `.xlsx` file through an independent Office skill.
**Architecture:** Keep zeroclaw as the core planner, but stop it from wandering across unrelated tools once a browser-attached skill is selected. The hotlist skill must produce a strict structured artifact, and the Office skill must consume that artifact through a dedicated `openxml_office` tool that wraps the sibling `openxml_cli` project. For the first delivery, reuse `openxml_cli template render` with a bundled `.xlsx` template instead of inventing a new workbook-construction API.
**Tech Stack:** Rust, vendored zeroclaw, sgClaw browser pipe, skill packages under `/home/zyl/projects/sgClaw/skill_lib`, sibling `openxml_cli`, JSON payload handoff, `.xlsx` template render, Python/Rust regression tests, real-provider smoke verification.
## Scope Guard
- In scope:
- browser-attached skill execution discipline
- `zhihu-hotlist` structured export artifact
- new `office-export-xlsx` skill
- new `openxml_office` runtime tool
- end-to-end acceptance for "读取知乎热榜数据,并导出 excel 文件"
- Out of scope:
- generic Office authoring platform
- arbitrary shell-based export flows
- browser-side file generation as the main export path
- broad multi-site data export before Zhihu hotlist is stable
## Current Findings To Preserve
- Real-provider validation already proved that `zhihu-hotlist`, `zhihu-navigate`, and `zhihu-write` can be selected through `read_skill`.
- The current failure mode is not "skill missing" but "tool discipline collapse":
- `file_read`, `glob_search`, and `shell` are attempted after `read_skill`
- `zhihu-write` can fill title/body but still exceeds max tool iterations
- `zhihu-navigate` succeeds for some intents but still detours through non-browser tools
- The sibling Office project already exists at `/home/zyl/projects/sgClaw/openxml_cli`.
- `openxml_cli` currently exposes `capabilities`, `template inspect`, `template validate`, and `template render`; it does not yet expose a direct "create workbook from scratch" command.
## Final Acceptance Contract
Input:
```text
读取知乎热榜数据,并导出 excel 文件
```
Required behavior:
1. sgClaw selects `zhihu-hotlist`.
2. sgClaw gathers hotlist rows through the SuperRPA browser interface only.
3. sgClaw converts the result into a structured JSON export payload.
4. sgClaw selects `office-export-xlsx`.
5. sgClaw calls `openxml_office`.
6. A local `.xlsx` file is produced and its path is returned.
Required logs:
- `read_skill zhihu-hotlist`
- browser actions only: `navigate`, `getText`, optionally `click`
- `read_skill office-export-xlsx`
- `call openxml_office`
Forbidden logs during the mainline path:
- `call shell`
- `call glob_search`
- `call file_read` on skill references or skill roots
- `docker run`
Required Excel content:
- one sheet named `知乎热榜`
- columns: `rank`, `title`, `heat`
- at least 10 hotlist rows
- exported values match the collected rows
## Task 1: Lock Browser-Attached Skill Runs To The Right Tools
**Files:**
- Modify: `/home/zyl/projects/sgClaw/claw/tests/compat_runtime_test.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/src/runtime/engine.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/src/runtime/tool_policy.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/src/compat/runtime.rs`
**Intent:**
- Once the task is clearly in a browser-attached Zhihu skill flow, the runtime must stop offering unrelated tools such as `shell`, `glob_search`, and arbitrary `file_read`.
**Step 1: Write the failing regression tests**
Add focused tests in `tests/compat_runtime_test.rs` for:
```rust
#[test]
fn zhihu_hotlist_skill_flow_does_not_expose_shell_or_glob_tools() {}
#[test]
fn browser_attached_export_flow_exposes_browser_and_office_tools_only() {}
```
Assertions to include:
- request tool list contains `superrpa_browser`
- request tool list contains `read_skill`
- request tool list does not contain `shell`
- request tool list does not contain `glob_search`
- request tool list does not contain generic `file_read` during the constrained browser skill phase
**Step 2: Run the focused tests to verify failure**
Run:
```bash
cargo test --test compat_runtime_test zhihu_hotlist_skill_flow_does_not_expose_shell_or_glob_tools -- --nocapture
cargo test --test compat_runtime_test browser_attached_export_flow_exposes_browser_and_office_tools_only -- --nocapture
```
Expected:
- fail because current runtime still exposes too many tools in browser-attached mode
**Step 3: Implement minimal constrained-tool policy**
Implement a browser-skill execution mode that:
- keeps `superrpa_browser`
- keeps compatibility alias `browser_action`
- keeps `read_skill`
- optionally keeps the new `openxml_office` tool only for export tasks
- removes `shell`, `glob_search`, and free-form `file_read` from the allowed tool list for these phases
Do this in `src/runtime/engine.rs` by deriving a narrower `allowed_tools` set from:
- runtime profile
- browser surface present flag
- instruction intent
- whether export mode is active
**Step 4: Re-run the focused tests**
Run the same commands.
Expected:
- both pass
## Task 2: Convert Zhihu Hotlist Skill To Structured Output First
**Files:**
- Modify: `/home/zyl/projects/sgClaw/skill_lib/skills/zhihu-hotlist/SKILL.md`
- Modify: `/home/zyl/projects/sgClaw/claw/tests/skill_lib_validation_test.py`
- Modify: `/home/zyl/projects/sgClaw/claw/tests/compat_runtime_test.rs`
**Intent:**
- The hotlist skill should stop ending with prose-only summaries. Its primary output must be a stable export artifact the Office skill can consume.
**Step 1: Write the failing tests**
Add tests that enforce:
- `zhihu-hotlist` prompt body contains an explicit `Export Artifact` section
- the artifact schema includes `sheet_name`, `columns`, and `rows`
- runtime regression checks can find those fields in the skill content when `read_skill` is used
**Step 2: Run tests to verify failure**
Run:
```bash
python3 -m unittest tests.skill_lib_validation_test
cargo test --test compat_runtime_test handle_browser_message_executes_real_zhihu_hotlist_skill_flow -- --nocapture
```
Expected:
- validation fails because the artifact contract is not yet required
**Step 3: Update `zhihu-hotlist`**
Add an `Export Artifact` section that requires this shape:
```json
{
"source": "https://www.zhihu.com/hot",
"sheet_name": "知乎热榜",
"columns": ["rank", "title", "heat"],
"rows": [[1, "标题", "344万"]]
}
```
Also add hard rules:
- no extra exploratory tools after the browser data is collected
- prose summary is secondary, structured artifact is primary
**Step 4: Re-run tests**
Expected:
- validation passes
## Task 3: Create The Office Export Skill Package
**Files:**
- Create: `/home/zyl/projects/sgClaw/skill_lib/skills/office-export-xlsx/SKILL.md`
- Create: `/home/zyl/projects/sgClaw/skill_lib/skills/office-export-xlsx/references/export-flow.md`
- Create: `/home/zyl/projects/sgClaw/skill_lib/skills/office-export-xlsx/assets/zhihu_hotlist_template.xlsx`
- Modify: `/home/zyl/projects/sgClaw/claw/tests/skill_lib_validation_test.py`
**Intent:**
- Add a fully separate Office skill that knows nothing about browser scraping and only turns structured table data into a local Excel file.
**Step 1: Write the failing validation test**
Extend `tests/skill_lib_validation_test.py` so discovery expects:
```python
EXPECTED_SKILL_NAMES = [
"office-export-xlsx",
"zhihu-hotlist",
"zhihu-navigate",
"zhihu-write",
]
```
Also require the new skill to mention:
- `openxml_office`
- `.xlsx`
- `sheet_name`
- `columns`
- `rows`
**Step 2: Run the validation test to verify failure**
Run:
```bash
python3 -m unittest tests.skill_lib_validation_test
```
Expected:
- fail because the new skill package does not exist yet
**Step 3: Create the skill package**
`SKILL.md` must define:
- when to use: local Office export from structured rows
- required input schema
- output: exported file path
- tool rule: only call `openxml_office`, do not use browser tools
`export-flow.md` must define:
- validate payload shape
- choose output path
- invoke `openxml_office`
- return file path and row count
The first workbook template should be a fixed `zhihu_hotlist_template.xlsx` with:
- sheet `知乎热榜`
- row 1 headers already present
- table fill anchored to a stable name or placeholder expected by `openxml_cli`
**Step 4: Re-run validation**
Expected:
- new skill passes audit
## Task 4: Add The `openxml_office` Runtime Tool
**Files:**
- Create: `/home/zyl/projects/sgClaw/claw/src/compat/openxml_office_tool.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/src/compat/mod.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/src/compat/runtime.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/src/runtime/tool_policy.rs`
- Test: `/home/zyl/projects/sgClaw/claw/tests/compat_openxml_office_tool_test.rs`
**Intent:**
- Wrap sibling `openxml_cli` as a first-class local tool instead of leaking Office export through shell prompting.
**Step 1: Write the failing tool test**
Create `tests/compat_openxml_office_tool_test.rs` with cases for:
- capability probe
- render request assembly for xlsx export
- rejection when rows/columns are missing
- stable JSON output containing `output_path`
**Step 2: Run the test to verify failure**
Run:
```bash
cargo test --test compat_openxml_office_tool_test -- --nocapture
```
Expected:
- fail because the tool does not exist
**Step 3: Implement minimal tool**
Tool contract:
```json
{
"action": "export_hotlist_xlsx",
"template_path": ".../zhihu_hotlist_template.xlsx",
"output_path": "/tmp/zhihu_hotlist.xlsx",
"sheet_name": "知乎热榜",
"columns": ["rank", "title", "heat"],
"rows": [[1, "标题", "344万"]]
}
```
Implementation rules:
- write the payload JSON to a temp file
- invoke sibling `openxml_cli template render --request <file> --json`
- return parsed JSON result and normalized `output_path`
- no free-form shell composition from model text
**Step 4: Re-run the focused tests**
Expected:
- pass
## Task 5: Wire Export Tasks To Use Two Skills In Sequence
**Files:**
- Modify: `/home/zyl/projects/sgClaw/claw/src/runtime/engine.rs`
- Modify: `/home/zyl/projects/sgClaw/claw/tests/compat_runtime_test.rs`
**Intent:**
- The single user instruction must naturally flow from hotlist capture into Office export, not end after the first skill.
**Step 1: Write the failing runtime test**
Add a focused regression test for:
```rust
#[test]
fn zhihu_hotlist_export_task_reads_hotlist_skill_then_office_skill() {}
```
Assertions:
- request stream includes `read_skill zhihu-hotlist`
- later includes `read_skill office-export-xlsx`
- office phase exposes `openxml_office`
- no `shell` is exposed in the constrained task path
**Step 2: Run the test to verify failure**
Run:
```bash
cargo test --test compat_runtime_test zhihu_hotlist_export_task_reads_hotlist_skill_then_office_skill -- --nocapture
```
Expected:
- fail because the task currently has no structured handoff to Office export
**Step 3: Implement minimal chaining support**
Do not add a hard-coded workflow engine.
Minimal implementation:
- strengthen prompt contract so export tasks require structured hotlist artifact
- include `openxml_office` in allowed tools for export intent
- keep browser-only tools for the collection phase and Office-only tool for the export phase
**Step 4: Re-run the test**
Expected:
- pass
## Task 6: Add Real Acceptance Harness And Scoring
**Files:**
- Create: `/home/zyl/projects/sgClaw/claw/tools/live_acceptance/run_zhihu_hotlist_excel_acceptance.py`
- Create: `/home/zyl/projects/sgClaw/claw/docs/acceptance/2026-03-29-zhihu-hotlist-excel.md`
**Intent:**
- Make the final acceptance repeatable with the real user config and a transparent score.
**Step 1: Write the script**
The script must:
- use `/home/zyl/.config/superrpa/Default/superrpa/sgclaw_config.json`
- boot local `target/debug/sgclaw`
- send one browser `submit_task`
- respond to browser commands with controlled fixture responses
- capture:
- loaded skills
- selected skills
- forbidden tool calls
- final summary
- exported file path
**Step 2: Define score rubric**
Rubric:
- `skill selection`: 30
- `tool discipline`: 25
- `hotlist data correctness`: 20
- `xlsx export success`: 20
- `final response quality`: 5
Automatic deductions:
- `shell` called: `-15`
- `glob_search` called: `-10`
- `file_read` on skill references: `-10`
- wrong skill selected first: `-15`
- export missing output path: `-20`
**Step 3: Run acceptance**
Run:
```bash
python3 tools/live_acceptance/run_zhihu_hotlist_excel_acceptance.py
```
Expected:
- prints total score and per-dimension breakdown
- stores final evidence in `docs/acceptance/2026-03-29-zhihu-hotlist-excel.md`
## Delivery Sequence
Execute in this order:
1. Task 1: constrain tools
2. Task 2: structure hotlist output
3. Task 3: add office skill package
4. Task 4: add `openxml_office`
5. Task 5: chain the two skills
6. Task 6: run acceptance and score
## Definition Of Done
- browser-attached hotlist tasks no longer wander into `shell`, `glob_search`, or ad-hoc `file_read`
- `office-export-xlsx` exists as an independent skill
- `openxml_office` exists as an explicit tool
- a single user task can collect hotlist data and export `.xlsx`
- acceptance score is at least `85/100`