Files
claw/docs/superpowers/plans/2026-04-12-tq-lineloss-ws-dual-transport-plan.md
木炎 c60cd308ca feat: service console auto-connect, settings panel, and batch of enhancements
- Auto-connect WebSocket on page load in service console
- Settings modal for editing sgclaw_config.json (API key, base URL, model, skills dir, etc.)
- UpdateConfig/ConfigUpdated protocol messages for remote config save
- save_to_path() for SgClawSettings serialization
- ConfigUpdated handler in sg_claw_client binary
- Protocol serialization tests for new message types
- HTML test assertions for auto-connect and settings UI
- Additional pending changes: deterministic submit, org units, lineloss xlsx export, browser script tool, and docs

🤖 Generated with [Qoder][https://qoder.com]
2026-04-14 14:32:46 +08:00

449 lines
18 KiB
Markdown

# TQ Lineloss WS Dual-Transport 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:** Add ws communication support for the existing `tq-lineloss-report.collect_lineloss` deterministic browser_script path on the `feature/claw-ws` branch while preserving the current pipe path and validated Zhihu ws behavior.
**Architecture:** Reuse the existing backend-neutral execution seam that already exists for deterministic submit and browser_script execution. Keep lineloss business parsing, canonical args, and artifact interpretation unchanged; only make the ws backend/protocol and submit-path verification complete enough for the same lineloss skill contract to run over both pipe and ws.
**Tech Stack:** Rust 2021, Cargo tests, existing `BrowserBackend` abstraction, `WsBrowserBackend`, `ws_protocol`, browser websocket contract in `docs/_tmp_sgbrowser_ws_api_doc.txt`, existing staged `browser_script` skill execution seam.
---
## Execution Context
- Follow @superpowers:test-driven-development for each behavior change.
- Follow @superpowers:verification-before-completion before claiming each task is done.
- Do **not** create a git worktree unless the user explicitly asks.
- This plan is **ws enablement only** for the already-added lineloss deterministic skill path.
- Do **not** redesign deterministic routing, org parsing, period parsing, staged skill packaging, or artifact contracts unless a failing ws-specific test proves a minimal compatibility fix is required.
- Do **not** modify validated Zhihu hotlist/export business behavior; only add regression coverage around it.
- Preserve the current pipe execution path as the control implementation.
- Preserve the current `BrowserBackend` seam; do not introduce a second lineloss-specific ws execution path.
## Scope Boundary
### In scope
- Make the existing lineloss deterministic `browser_script` skill path run through ws on this branch.
- Keep the same canonical tool args and returned artifact interpretation for both pipe and ws.
- Verify ws browser-script execution against the documented browser ws contract.
- Add focused tests for ws lineloss execution and regressions for Zhihu ws + pipe lineloss.
### Out of scope
- Changing lineloss trigger semantics (`。。。`).
- Changing org/unit normalization semantics or source dictionary shape.
- Changing period normalization semantics.
- Reworking staged skill docs or JS business collection logic beyond ws-compatibility necessities.
- Any Zhihu feature work.
- Any pipe-only cleanup/refactor.
- Any general scene-registry redesign.
## File Map
### Expected code changes
- Modify: `src/pipe/protocol.rs:49-78,130-165,192-209`
- keep `Action::Eval` encoding aligned with the current transport contract and lineloss skill expectations
- Modify: `src/pipe/browser_tool.rs:62-125`
- ensure eval response correlation and payload handling remain sufficient for deterministic lineloss execution
- Modify only if a focused test proves it is necessary: `src/compat/browser_script_skill_tool.rs:135-255`
- preserve browser_script contract; only make minimal output-shape handling fixes if eval payloads differ from the pipe baseline in a way current code cannot consume
- Modify only if a focused parity test proves it is necessary: `src/compat/direct_skill_runtime.rs:50-129`
- preserve shared backend-neutral execution helper behavior; no business logic changes
- Read and normally leave unchanged: `src/compat/deterministic_submit.rs:96-157`
- this is the business contract baseline and should not be rewritten for transport parity work
- Read and normally leave unchanged: `src/agent/mod.rs:242-285`
- this contains the current deterministic dispatch split used by this branch
### Expected test changes
- Modify: `tests/agent_runtime_test.rs`
- add/extend deterministic lineloss runtime coverage and parity assertions using the current runtime path
- Modify: `tests/compat_runtime_test.rs`
- add/extend focused pipe lineloss regression assertions so transport work cannot silently break pipe
- Modify only if end-to-end submit coverage truly needs it: `tests/runtime_task_flow_test.rs`
- verify broader submit-flow expectations remain intact
### Reference-only files
- Read only: `docs/superpowers/plans/2026-04-11-tq-lineloss-deterministic-skill-plan.md`
- Read only: `docs/superpowers/specs/2026-04-11-tq-lineloss-deterministic-skill-design.md`
- Read only: `docs/_tmp_sgbrowser_ws_api_doc.txt`
---
## Locked contracts
### Contract 1: Same lineloss deterministic business contract on both transports
The ws path must reuse the existing values produced by `src/compat/deterministic_submit.rs:84-95` and `src/compat/deterministic_submit.rs:135-166`:
- `expected_domain`
- `org_label`
- `org_code`
- `period_mode`
- `period_mode_code`
- `period_value`
- `period_payload`
No ws-specific lineloss args may be introduced in this slice.
### Contract 2: Same browser_script execution seam on both transports
The ws path must continue to use `execute_browser_script_skill_raw_output_with_browser_backend(...)` from `src/compat/direct_skill_runtime.rs:95-112`, which in turn uses the same browser_script tool path as pipe. Do not add a second lineloss-only ws runner.
### Contract 3: Same artifact interpretation on both transports
The ws path must produce output that remains consumable by `summarize_lineloss_output(...)` / `summarize_lineloss_artifact(...)` in `src/compat/deterministic_submit.rs:168-257` without transport-specific branching.
### Contract 4: Zhihu ws behavior must stay unchanged
The existing ws browser-script / export path already validated by `tests/agent_runtime_test.rs` and `tests/compat_runtime_test.rs` is a hard regression boundary. If a change breaks Zhihu tests, fix the ws seam instead of weakening Zhihu expectations.
### Contract 5: Pipe remains the baseline
For identical lineloss deterministic inputs, the pipe path should continue to succeed without requiring ws configuration.
---
### Task 1: Lock the ws contract with failing transport-level tests
**Files:**
- Modify: `tests/agent_runtime_test.rs`
- Modify: `tests/compat_runtime_test.rs`
- Read: `docs/_tmp_sgbrowser_ws_api_doc.txt`
- [ ] **Step 1: Add a failing ws lineloss deterministic runtime test**
Model it after the existing ws harness in `tests/agent_runtime_test.rs:69-166`, but target lineloss deterministic execution instead of Zhihu. The test should:
- configure `browserWsUrl`
- submit a deterministic lineloss instruction ending with `。。。`
- return a ws callback payload representing a lineloss `report-artifact`
- assert success summary includes canonical org, period, status, and rows
Suggested skeleton:
```rust
#[test]
fn ws_deterministic_lineloss_submit_executes_browser_script_and_summarizes_artifact() {
// arrange ws config + ws server + lineloss artifact callback
// act handle_browser_message_with_context(... SubmitTask ...)
// assert TaskComplete success summary contains canonical org/period/rows
}
```
- [ ] **Step 2: Add a failing pipe regression test for the same lineloss contract**
In `tests/compat_runtime_test.rs`, add a focused pipe-side assertion that the same deterministic lineloss instruction still succeeds through the current pipe seam and uses the same summary contract.
Suggested skeleton:
```rust
#[test]
fn pipe_deterministic_lineloss_submit_preserves_existing_summary_contract() {
// arrange MockTransport responses for browser_script eval
// act handle_browser_message_with_context(...)
// assert success summary matches canonical contract
}
```
- [ ] **Step 3: Add a failing ws regression assertion for Zhihu**
Add or tighten a Zhihu ws assertion proving ordinary Zhihu requests still use the existing ws path and do not get intercepted by lineloss deterministic logic.
- [ ] **Step 4: Run the three focused tests to confirm failure**
Run:
```bash
cargo test ws_deterministic_lineloss_submit_executes_browser_script_and_summarizes_artifact -- --exact
cargo test pipe_deterministic_lineloss_submit_preserves_existing_summary_contract -- --exact
cargo test ws_zhihu_submit_path_remains_unchanged_after_lineloss_transport_work -- --exact
```
Expected: at least the new ws lineloss test fails before the seam is completed.
- [ ] **Step 5: Commit**
```bash
git add tests/agent_runtime_test.rs tests/compat_runtime_test.rs
git commit -m "test: lock ws and pipe lineloss transport contracts"
```
---
### Task 2: Make the current eval transport contract explicitly satisfy browser-script requirements
**Files:**
- Modify: `src/pipe/protocol.rs:49-78,130-165,192-209`
- Modify: `src/pipe/browser_tool.rs:62-124`
- Modify only if tests prove necessary: `src/compat/browser_script_skill_tool.rs:99-180,214-255`
- Modify: `tests/pipe_protocol_test.rs`
- Modify: `tests/browser_tool_test.rs`
- Modify: `tests/browser_script_skill_tool_test.rs`
- [ ] **Step 1: Add failing protocol/result-contract tests first**
Extend or add focused tests to lock the current branch's real transport contract:
- `Action::Eval` remains supported by the line protocol and command encoding
- eval request/response correlation remains stable via `seq` matching for lineloss-style target URLs
- eval/browser_script result handling preserves the full JSON artifact string without truncation before deterministic lineloss summarization consumes it
Suggested skeletons:
```rust
#[test]
fn eval_action_remains_supported_in_protocol() {}
#[test]
fn browser_tool_matches_eval_response_by_seq_for_lineloss_flow() {}
#[test]
fn browser_script_tool_preserves_json_artifact_string_for_lineloss() {}
```
- [ ] **Step 2: Run the focused Task 2 tests to confirm failure**
Run:
```bash
cargo test eval_action_remains_supported_in_protocol -- --exact
cargo test browser_tool_matches_eval_response_by_seq_for_lineloss_flow -- --exact
cargo test browser_script_tool_preserves_json_artifact_string_for_lineloss -- --exact
```
Expected: at least one test fails if the current protocol/correlation/result handling is still insufficient for the lineloss artifact path.
- [ ] **Step 3: Implement the minimal transport-contract fix**
Allowed changes:
- adjust only the `Action::Eval` protocol/encoding support in `src/pipe/protocol.rs`
- adjust only request/response correlation in `src/pipe/browser_tool.rs`
- if and only if tests still prove it necessary, make a tiny result-shape/stringification fix in `src/compat/browser_script_skill_tool.rs`
- keep existing Zhihu-compatible behavior intact
Not allowed:
- adding lineloss-only transport fields
- adding a second lineloss-specific execution path
- changing deterministic lineloss business parsing or summary rules
- [ ] **Step 4: Re-run the focused Task 2 tests**
Run:
```bash
cargo test eval_action_remains_supported_in_protocol -- --exact
cargo test browser_tool_matches_eval_response_by_seq_for_lineloss_flow -- --exact
cargo test browser_script_tool_preserves_json_artifact_string_for_lineloss -- --exact
```
Expected: PASS.
- [ ] **Step 5: Re-run the focused ws lineloss runtime test from Task 1**
Run:
```bash
cargo test ws_deterministic_lineloss_submit_executes_browser_script_and_summarizes_artifact -- --exact
```
Expected: PASS.
- [ ] **Step 6: Commit**
```bash
git add src/pipe/protocol.rs src/pipe/browser_tool.rs src/compat/browser_script_skill_tool.rs tests/pipe_protocol_test.rs tests/browser_tool_test.rs tests/browser_script_skill_tool_test.rs
git commit -m "fix: align eval transport contract with lineloss browser script flow"
```
---
### Task 3: Make eval result-shape handling surface the lineloss artifact cleanly
**Files:**
- Modify: `src/pipe/browser_tool.rs:62-125`
- Modify only if tests prove necessary: `src/compat/browser_script_skill_tool.rs:159-180,248-255`
- Modify: `tests/browser_script_skill_tool_test.rs`
- [ ] **Step 1: Add a failing result-shape test**
Lock that an eval response carrying a JSON string report artifact is surfaced as the same browser_script tool output shape expected by `execute_browser_script_tool(...)`.
Suggested skeleton:
```rust
#[test]
fn ws_backend_eval_returns_text_payload_consumable_by_browser_script_tool() {
// arrange an eval response whose data.text is a JSON string artifact
// assert execute_browser_script_tool(...) returns the full artifact text without truncation
}
```
- [ ] **Step 2: Run the result-shape test to confirm failure**
Run:
```bash
cargo test ws_backend_eval_returns_text_payload_consumable_by_browser_script_tool -- --exact
```
Expected: FAIL only if current eval/result handling is not sufficient for full lineloss artifact output.
- [ ] **Step 3: Implement the minimal result-shape fix**
Allowed fixes:
- adjust `BrowserPipeTool::invoke(...)` only if response packaging itself is wrong
- if and only if still required, make a tiny output-shape compatibility fix in `src/compat/browser_script_skill_tool.rs` so JSON string `data.text` payloads are preserved identically to the pipe baseline
Not allowed:
- transport-specific lineloss parsing
- changes to deterministic business logic
- adding a second lineloss-specific execution path
- [ ] **Step 4: Re-run the result-shape test**
Run:
```bash
cargo test ws_backend_eval_returns_text_payload_consumable_by_browser_script_tool -- --exact
```
Expected: PASS.
- [ ] **Step 5: Re-run the focused ws lineloss runtime test from Task 1**
Run:
```bash
cargo test ws_deterministic_lineloss_submit_executes_browser_script_and_summarizes_artifact -- --exact
```
Expected: PASS.
- [ ] **Step 6: Commit**
```bash
git add src/pipe/browser_tool.rs src/compat/browser_script_skill_tool.rs tests/browser_script_skill_tool_test.rs
git commit -m "fix: make eval result shape match browser script contract"
```
---
### Task 4: Verify the current backend-neutral deterministic execution path without changing business rules
**Files:**
- Read baseline: `src/agent/mod.rs:242-285`
- Read baseline: `src/compat/deterministic_submit.rs:96-157`
- Modify only if a focused parity test proves it is necessary: `src/compat/direct_skill_runtime.rs:50-129`
- Modify: `tests/agent_runtime_test.rs`
- Modify: `tests/compat_runtime_test.rs`
- [ ] **Step 1: Add a failing integration test for backend-neutral parity**
Add a test proving these two current-branch paths produce the same lineloss summary contract for equivalent artifact payloads:
- pipe path via the existing deterministic submit flow in `tests/compat_runtime_test.rs`
- runtime path via `handle_browser_message_with_context(...)` deterministic submit routing in `tests/agent_runtime_test.rs`
Suggested skeleton:
```rust
#[test]
fn deterministic_lineloss_pipe_and_ws_paths_share_summary_contract() {}
```
- [ ] **Step 2: Run the parity test to confirm failure or gap**
Run:
```bash
cargo test deterministic_lineloss_pipe_and_ws_paths_share_summary_contract -- --exact
```
Expected: FAIL only if a remaining shared execution seam gap still exists.
- [ ] **Step 3: Apply the smallest shared execution fix if needed**
Allowed changes:
- tiny helper extraction or result handling in `src/compat/direct_skill_runtime.rs`
- no new lineloss-specific branch
- no change to deterministic lineloss business parsing or summary rules
- no change to configured direct-submit behavior for non-lineloss skills
- [ ] **Step 4: Re-run the parity test**
Run:
```bash
cargo test deterministic_lineloss_pipe_and_ws_paths_share_summary_contract -- --exact
```
Expected: PASS.
- [ ] **Step 5: Commit**
```bash
git add src/compat/direct_skill_runtime.rs tests/agent_runtime_test.rs tests/compat_runtime_test.rs
git commit -m "fix: preserve shared deterministic execution across pipe and ws"
```
---
### Task 5: Run the full focused verification set and stop if any Zhihu or pipe regression appears
**Files:**
- Reuse: `tests/agent_runtime_test.rs`
- Reuse: `tests/compat_runtime_test.rs`
- Reuse: `tests/runtime_task_flow_test.rs`
- [ ] **Step 1: Run focused ws + lineloss + Zhihu regression tests**
Run:
```bash
cargo test --test agent_runtime_test
cargo test --test compat_runtime_test
cargo test --test runtime_task_flow_test
```
Expected: PASS.
- [ ] **Step 2: Run targeted protocol/backend unit tests**
Run:
```bash
cargo test eval_action_remains_supported_in_protocol -- --exact
cargo test browser_tool_matches_eval_response_by_seq_for_lineloss_flow -- --exact
cargo test browser_script_tool_preserves_json_artifact_string_for_lineloss -- --exact
cargo test ws_backend_eval_returns_text_payload_consumable_by_browser_script_tool -- --exact
cargo test deterministic_lineloss_pipe_and_ws_paths_share_summary_contract -- --exact
```
Expected: PASS.
- [ ] **Step 3: Run the full Rust suite**
Run:
```bash
cargo test
```
Expected: PASS.
- [ ] **Step 4: Manual review of diff scope**
Confirm the diff only touches:
- current transport/result seam files (`src/pipe/protocol.rs`, `src/pipe/browser_tool.rs`)
- narrow shared browser_script/result compatibility helpers if strictly necessary
- tests
If diff includes Zhihu business logic, lineloss parsing rules, staged skill business JS, or unrelated cleanup, remove those changes before completion.
- [ ] **Step 5: Commit**
```bash
git add src/pipe/protocol.rs src/pipe/browser_tool.rs src/compat/browser_script_skill_tool.rs src/compat/direct_skill_runtime.rs tests/pipe_protocol_test.rs tests/browser_tool_test.rs tests/browser_script_skill_tool_test.rs tests/agent_runtime_test.rs tests/compat_runtime_test.rs
git commit -m "test: verify lineloss ws transport without regressing pipe or zhihu"
```
---
## Final verification checklist
- [ ] The same lineloss deterministic instruction works on pipe and ws.
- [ ] Pipe still works without any ws configuration.
- [ ] Eval transport support remains available for deterministic lineloss execution.
- [ ] Eval response payloads preserve the full lineloss artifact JSON string.
- [ ] `src/compat/deterministic_submit.rs` business rules remain transport-neutral.
- [ ] No ws-specific lineloss args were introduced.
- [ ] Zhihu ws tests still pass unchanged in behavior.
- [ ] No ordinary Zhihu request is intercepted by lineloss deterministic routing.
- [ ] No new transport-specific business branch was added for lineloss.
## Implementation notes
- Default to changing the current transport/result seam first: `src/pipe/protocol.rs` and `src/pipe/browser_tool.rs`.
- Treat `src/compat/browser_script_skill_tool.rs` and `src/compat/direct_skill_runtime.rs` as shared seams: change them only if a focused failing test shows a transport-neutral compatibility bug.
- If a proposed fix requires changing `src/compat/deterministic_submit.rs` business logic, stop and re-evaluate; that likely means the seam fix is happening at the wrong layer.
- If a proposed fix changes Zhihu expectations, stop and repair the seam instead.