Files
claw/docs/superpowers/plans/2026-04-09-ws-branch-scene-cleanup-plan.md
木炎 81de162756 docs: add ws branch cleanup plan
Document the post-main cleanup steps for removing staged scene routing from the ws branch while preserving websocket and Zhihu flows.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 11:13:43 +08:00

22 KiB
Raw Blame History

WS Branch Scene Cleanup 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: Strip feature/claw-ws back to websocket plus Zhihu execution only by removing staged scene-skill routing, skill_staging-aware loading, and array-style skillsDir config behavior from this branch.

Architecture: Treat feature/claw-ws as a transport-focused branch, not a business-scene branch. Keep the browser websocket/callback submit path and the existing Zhihu direct workflows, but delete the fault-details / 95598 scene registry, scene-specific prompt injection, staged scene directory expansion, and scene-only docs/tests so the branch stays small and merges cleanly after the real scene implementation lands on main.

Tech Stack: Rust 2021, existing sgClaw compat/runtime/orchestration stack, websocket browser backend, callback-host service path, existing cargo test suite.


Preconditions

  • Execute this plan only after main already contains the desired clean scene-skill implementation.
  • Run it on feature/claw-ws, not on main.
  • Keep websocket and Zhihu behavior intact; this plan is cleanup, not a redesign.
  • Keep docs/_tmp_sgbrowser_ws_api_doc.txt; it remains the browser integration contract for this branch.

Scope Guardrails

  • Do not change the working Zhihu websocket flow in tests/agent_runtime_test.rs.
  • Do not remove src/browser/ws_backend.rs, src/service/server.rs, or Zhihu routes from src/compat/workflow_executor.rs.
  • Do not add a replacement scene abstraction on this branch.
  • Do not keep partial scene plumbing “for future use”; delete it completely if it is scene-only.
  • Do not keep array-style skillsDir tests or docs on this branch once the single-path cleanup is complete.

File Map

Delete

  • src/runtime/scene_registry.rs
    • staged scene registry, hard-coded skill_staging scene root, scene matching helpers
  • tests/scene_registry_test.rs
    • scene-registry-specific coverage that should disappear with the feature
  • docs/superpowers/specs/2026-04-06-scene-skill-runtime-routing-design.md
    • scene-routing design doc that no longer belongs on the ws-only branch
  • docs/superpowers/plans/2026-04-06-scene-skill-runtime-routing-plan.md
    • scene-routing implementation plan that no longer belongs on the ws-only branch

Modify

  • src/runtime/mod.rs
    • stop exporting deleted scene registry APIs
  • src/runtime/engine.rs
    • remove scene-contract prompt injection and staged scene skill loading
  • src/compat/workflow_executor.rs
    • remove FaultDetailsReport route detection/execution while keeping Zhihu routes
  • src/compat/orchestration.rs
    • keep direct Zhihu orchestration only; remove scene-driven primary routing triggers
  • src/config/settings.rs
    • collapse skillsDir config handling back to single-path semantics
  • src/compat/config_adapter.rs
    • remove scene-specific skills-dir helpers and keep one resolved skills dir
  • src/compat/runtime.rs
    • stop carrying scene-expanded skills dirs through compat runtime
  • src/agent/task_runner.rs
    • update runtime logging and runtime calls to the single skills-dir contract
  • tests/compat_runtime_test.rs
    • remove fault-details / 95598 assertions and keep Zhihu/direct-route coverage
  • tests/runtime_profile_test.rs
    • remove 95598 scene-contract expectations and keep normal browser-profile coverage
  • tests/compat_config_test.rs
    • remove scene-dir / array-config coverage and add single-path cleanup coverage
  • tests/agent_runtime_test.rs
    • only extend if one extra Zhihu keep-path regression is needed after the config cleanup

Keep As-Is Unless A Signature Change Forces A Tiny Edit

  • src/browser/ws_backend.rs
  • src/browser/callback_backend.rs
  • src/browser/callback_host.rs
  • src/service/server.rs
  • src/agent/mod.rs
  • tests/browser_ws_backend_test.rs
  • tests/service_ws_session_test.rs
  • tests/task_runner_test.rs

Task 1: Lock The Cleanup Contract In Failing Tests

Files:

  • Modify: tests/compat_runtime_test.rs

  • Modify: tests/runtime_profile_test.rs

  • Modify: tests/compat_config_test.rs

  • Reuse: tests/agent_runtime_test.rs

  • Step 1: Add the first failing route-removal test

In tests/compat_runtime_test.rs, add a focused assertion proving the ws branch no longer recognizes the fault-details scene as a direct route:

#[test]
fn ws_cleanup_no_longer_detects_fault_details_scene_route() {
    use sgclaw::compat::workflow_executor::detect_route;

    assert_eq!(
        detect_route(
            "导出故障明细",
            Some("https://example.invalid/workbench"),
            Some("业务台账"),
        ),
        None,
    );
}
  • Step 2: Run the focused route test and verify it fails

Run:

cargo test --test compat_runtime_test ws_cleanup_no_longer_detects_fault_details_scene_route -- --nocapture

Expected: FAIL because FaultDetailsReport is still detected today.

  • Step 3: Add the second failing orchestration-gate test

In tests/compat_runtime_test.rs, add one focused assertion proving scene keywords no longer open the primary direct-orchestration path:

#[test]
fn ws_cleanup_scene_keywords_do_not_trigger_primary_orchestration() {
    assert!(!sgclaw::compat::orchestration::should_use_primary_orchestration(
        "请处理95598抢修市指监测",
        Some("https://95598.example.invalid/dispatch"),
        Some("95598抢修市指监测"),
    ));
}
  • Step 4: Run the orchestration-gate test and verify it fails

Run:

cargo test --test compat_runtime_test ws_cleanup_scene_keywords_do_not_trigger_primary_orchestration -- --nocapture

Expected: FAIL because the scene matcher still feeds primary orchestration today.

  • Step 5: Add the third failing runtime-instruction test

In tests/runtime_profile_test.rs, add a focused negative assertion proving browser-attached turns no longer receive the 95598 scene execution contract:

#[test]
fn ws_cleanup_browser_profile_does_not_inject_95598_scene_contract() {
    let engine = RuntimeEngine::new(RuntimeProfile::BrowserAttached);
    let instruction = engine.build_instruction(
        "请处理95598-repair-city-dispatch场景查看抢修市指派单并汇总当前队列",
        Some("https://95598.example.invalid/dispatch"),
        Some("95598抢修市指监测"),
        true,
    );

    assert!(!instruction.contains("95598-repair-city-dispatch.collect_repair_orders"));
}
  • Step 6: Run the runtime-profile test and verify it fails

Run:

cargo test --test runtime_profile_test ws_cleanup_browser_profile_does_not_inject_95598_scene_contract -- --nocapture

Expected: FAIL because src/runtime/engine.rs still injects the scene contract today.

  • Step 7: Add the fourth failing config-shape test

In tests/compat_config_test.rs, add one focused assertion proving ws cleanup goes back to a single configured skills path and no longer accepts array-style skillsDir JSON:

#[test]
fn ws_cleanup_rejects_array_style_skills_dir_config() {
    let root = std::env::temp_dir().join(format!("sgclaw-config-{}", uuid::Uuid::new_v4()));
    std::fs::create_dir_all(&root).unwrap();
    let config_path = root.join("sgclaw_config.json");
    std::fs::write(
        &config_path,
        r#"{
  "apiKey": "sk-test",
  "baseUrl": "https://api.deepseek.com",
  "model": "deepseek-chat",
  "skillsDir": ["skill_lib", "skill_staging"]
}"#,
    )
    .unwrap();

    assert!(sgclaw::config::SgClawSettings::load(Some(config_path.as_path())).is_err());
}
  • Step 8: Run the config-shape test and verify it fails

Run:

cargo test --test compat_config_test ws_cleanup_rejects_array_style_skills_dir_config -- --nocapture

Expected: FAIL because the current parser still accepts string-or-array skillsDir input.

  • Step 9: Re-run the existing Zhihu keep-path test as a safety baseline

Run:

cargo test --test agent_runtime_test production_submit_task_routes_zhihu_through_ws_backend_without_helper_bootstrap -- --nocapture

Expected: PASS, proving the behavior we want to keep is already covered before deletion starts.


Task 2: Remove Scene Registry, Scene Prompt Injection, And Fault-Details Routing

Files:

  • Delete: src/runtime/scene_registry.rs

  • Modify: src/runtime/mod.rs

  • Modify: src/runtime/engine.rs

  • Modify: src/compat/workflow_executor.rs

  • Modify: src/compat/orchestration.rs

  • Modify: tests/compat_runtime_test.rs

  • Modify: tests/runtime_profile_test.rs

  • Delete: tests/scene_registry_test.rs

  • Step 1: Remove the runtime scene module export surface

Update src/runtime/mod.rs so it no longer declares or re-exports scene registry items.

Target shape:

mod engine;
mod profile;
mod tool_policy;

pub use engine::{
    is_zhihu_hotlist_task,
    is_zhihu_write_task,
    task_requests_zhihu_article_publish,
    RuntimeEngine,
};
pub use profile::RuntimeProfile;
pub use tool_policy::ToolPolicy;
  • Step 2: Delete src/runtime/scene_registry.rs

Remove the file entirely. Do not leave a stub module or comments about future scene support.

  • Step 3: Remove scene-aware prompt injection from src/runtime/engine.rs

Delete:

  • the resolve_scene_skills_dir_path import
  • the DispatchMode / match_scene_instruction imports
  • REPAIR_CITY_DISPATCH_EXECUTION_PROMPT
  • build_scene_execution_contract(...)
  • the if let Some(scene_contract) = ... block inside RuntimeEngine::build_instruction(...)
  • staged scene directory loading inside load_runtime_skills(...)

The resulting instruction assembly should keep:

  • browser tool contract
  • Zhihu hotlist/export prompts
  • Zhihu publish guard
  • page context

Do not change Zhihu prompt text.

  • Step 4: Remove the fault-details route from src/compat/workflow_executor.rs

Shrink WorkflowRoute back to Zhihu-only variants:

pub enum WorkflowRoute {
    ZhihuHotlistExportXlsx,
    ZhihuHotlistScreen,
    ZhihuArticleEntry,
    ZhihuArticleDraft,
    ZhihuArticlePublish,
    ZhihuArticleAutoPublishGenerated,
}

Delete:

  • FAULT_DETAILS_SCENE_ID
  • the scene check at the top of detect_route(...)
  • WorkflowRoute::FaultDetailsReport
  • execute_fault_details_route(...)
  • any scene-only helpers used only by that path

Keep the Zhihu route order unchanged.

  • Step 5: Simplify src/compat/orchestration.rs to Zhihu-only direct routing

After the fault-details route is gone, keep should_use_primary_orchestration(...) and the two execute functions focused on:

  • Zhihu direct routes detected by detect_route(...)
  • existing Zhihu export/dashboard fallback behavior

Do not add new conditions.

  • Step 6: Remove scene-only tests and replace them with cleanup assertions

In tests/compat_runtime_test.rs and tests/runtime_profile_test.rs:

  • delete fault-details assertions that require the old route to exist
  • delete 95598 scene-contract assertions that require the old prompt injection to exist
  • keep the new negative cleanup tests from Task 1
  • keep the existing Zhihu assertions intact

Delete tests/scene_registry_test.rs completely.

  • Step 7: Run the focused cleanup tests

Run:

cargo test --test compat_runtime_test ws_cleanup_no_longer_detects_fault_details_scene_route -- --nocapture && cargo test --test compat_runtime_test ws_cleanup_scene_keywords_do_not_trigger_primary_orchestration -- --nocapture && cargo test --test runtime_profile_test ws_cleanup_browser_profile_does_not_inject_95598_scene_contract -- --nocapture

Expected: PASS.

  • Step 8: Re-run the focused Zhihu runtime tests

Run:

cargo test --test compat_runtime_test zhihu_ -- --nocapture

Expected: PASS, proving the Zhihu direct routes still work after the scene deletion.

  • Step 9: Commit Task 2
git add src/runtime/mod.rs src/runtime/engine.rs src/compat/workflow_executor.rs src/compat/orchestration.rs tests/compat_runtime_test.rs tests/runtime_profile_test.rs
git rm src/runtime/scene_registry.rs tests/scene_registry_test.rs
git commit -m "refactor: remove scene routing from ws branch"

Task 3: Collapse skillsDir Back To Single-Path Semantics

Files:

  • Modify: src/config/settings.rs

  • Modify: src/compat/config_adapter.rs

  • Modify: src/compat/runtime.rs

  • Modify: src/agent/task_runner.rs

  • Modify if needed: tests/agent_runtime_test.rs

  • Modify: tests/compat_config_test.rs

  • Step 1: Change config parsing to a single configured skills path

In src/config/settings.rs, replace the string-or-array parser with a single optional string field.

Target shape:

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DeepSeekSettings {
    pub api_key: String,
    pub base_url: String,
    pub model: String,
    pub skills_dir: Option<PathBuf>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SgClawSettings {
    // ...
    pub skills_dir: Option<PathBuf>,
    // ...
}

And in RawSgClawSettings:

#[serde(rename = "skillsDir", alias = "skills_dir", default)]
skills_dir: Option<String>,

Delete deserialize_skills_dirs(...) entirely.

  • Step 2: Keep relative-path resolution, but only for one path

Replace resolve_configured_skills_dirs(...) -> Vec<PathBuf> with a single-path helper such as:

fn resolve_configured_skills_dir(raw: Option<String>, config_dir: &Path) -> Option<PathBuf> {
    raw.map(|value| value.trim().to_string())
        .filter(|value| !value.is_empty())
        .map(PathBuf::from)
        .map(|path| if path.is_absolute() { path } else { config_dir.join(path) })
}
  • Step 3: Collapse compat config adapter back to one resolved skills dir

In src/compat/config_adapter.rs:

  • keep zeroclaw_default_skills_dir(...)
  • change resolve_skills_dir(...) and resolve_skills_dir_from_sgclaw_settings(...) to return a single PathBuf
  • delete resolve_scene_skills_dir_from_sgclaw_settings(...)
  • delete resolve_scene_skills_dir_path(...)
  • delete any helper branches that append skill_staging/skills

Recommended shape:

pub fn resolve_skills_dir_from_sgclaw_settings(
    workspace_root: &Path,
    settings: &SgClawSettings,
) -> PathBuf {
    settings
        .skills_dir
        .as_ref()
        .map(|dir| normalize_configured_skills_dir(dir))
        .unwrap_or_else(|| zeroclaw_default_skills_dir(workspace_root))
}
  • Step 4: Update runtime callers to the single-path contract

In src/compat/runtime.rs and src/agent/task_runner.rs:

  • stop passing vectors of skills dirs around
  • update logging from skills dirs resolved to [...] to a single-path message such as skills dir resolved to ...
  • keep the rest of the runtime behavior unchanged

In src/runtime/engine.rs, if the method still needs a collection internally, convert the one path at the call site instead of preserving public multi-root plumbing.

  • Step 5: Replace config tests with single-path cleanup coverage

In tests/compat_config_test.rs:

  • keep single-string skillsDir resolution tests
  • remove resolve_scene_skills_dir_path_* coverage
  • remove array-acceptance expectations
  • keep the new rejecting-array test from Task 1

Add one focused positive test like:

#[test]
fn ws_cleanup_resolves_single_configured_skills_dir() {
    let root = std::env::temp_dir().join(format!("sgclaw-skills-{}", uuid::Uuid::new_v4()));
    std::fs::create_dir_all(root.join("skill_lib/skills")).unwrap();

    let settings = DeepSeekSettings {
        api_key: "key".to_string(),
        base_url: "https://api.deepseek.com".to_string(),
        model: "deepseek-chat".to_string(),
        skills_dir: Some(root.join("skill_lib")),
    };

    assert_eq!(
        resolve_skills_dir(&root, &settings),
        root.join("skill_lib/skills"),
    );
}
  • Step 6: Run the focused config tests

Run:

cargo test --test compat_config_test ws_cleanup_ -- --nocapture

Expected: PASS.

  • Step 7: Re-run the Zhihu websocket keep-path test

Run:

cargo test --test agent_runtime_test production_submit_task_routes_zhihu_through_ws_backend_without_helper_bootstrap -- --nocapture

Expected: PASS.

  • Step 8: Commit Task 3
git add src/config/settings.rs src/compat/config_adapter.rs src/compat/runtime.rs src/agent/task_runner.rs tests/compat_config_test.rs tests/agent_runtime_test.rs
git commit -m "refactor: restore single skills dir on ws branch"

Task 4: Remove Scene-Only Docs And Residual Test References

Files:

  • Delete: docs/superpowers/specs/2026-04-06-scene-skill-runtime-routing-design.md

  • Delete: docs/superpowers/plans/2026-04-06-scene-skill-runtime-routing-plan.md

  • Modify: tests/compat_runtime_test.rs

  • Modify: tests/runtime_profile_test.rs

  • Modify: tests/compat_config_test.rs

  • Step 1: Delete the two scene-only planning documents

Remove exactly these files:

  • docs/superpowers/specs/2026-04-06-scene-skill-runtime-routing-design.md
  • docs/superpowers/plans/2026-04-06-scene-skill-runtime-routing-plan.md

Keep the websocket/browser docs and Zhihu docs.

  • Step 2: Sweep remaining tests for scene-only names

Remove or rewrite any remaining test blocks that still require:

  • fault-details-report
  • 95598-repair-city-dispatch
  • resolve_scene_skills_dir_path
  • resolve_scene_skills_dir_from_sgclaw_settings
  • scene_registry

Do not delete Zhihu-related assertions during this sweep.

  • Step 3: Run a focused grep-style audit from the shell

Run:

git grep -n "fault-details-report\|95598-repair-city-dispatch\|resolve_scene_skills_dir_path\|resolve_scene_skills_dir_from_sgclaw_settings\|scene_registry" -- src tests docs

Expected: no matches in src/ or tests/; doc matches should be gone after the deletions.

  • Step 4: Commit Task 4
git add tests/compat_runtime_test.rs tests/runtime_profile_test.rs tests/compat_config_test.rs
git rm docs/superpowers/specs/2026-04-06-scene-skill-runtime-routing-design.md docs/superpowers/plans/2026-04-06-scene-skill-runtime-routing-plan.md
git commit -m "docs: remove ws-only scene planning artifacts"

Task 5: Verify The Branch Is Back To WS Plus Zhihu Only

Files:

  • Verify only unless a failing test proves one tiny follow-up fix is needed

  • Step 1: Run the retained Zhihu websocket regression

Run:

cargo test --test agent_runtime_test production_submit_task_routes_zhihu_through_ws_backend_without_helper_bootstrap -- --nocapture

Expected: PASS.

  • Step 2: Run websocket/backend focused coverage

Run:

cargo test --test browser_ws_backend_test -- --nocapture && cargo test --test service_ws_session_test -- --nocapture

Expected: PASS.

  • Step 3: Run direct-route/runtime Zhihu coverage

Run:

cargo test --test compat_runtime_test zhihu_ -- --nocapture && cargo test --test task_runner_test -- --nocapture

Expected: PASS.

  • Step 4: Run config/runtime verification after the single-dir cleanup

Run:

cargo test --test compat_config_test -- --nocapture && cargo test --test runtime_profile_test -- --nocapture

Expected: PASS.

  • Step 5: Build the affected binaries

Run:

cargo build --bin sgclaw --bin sg_claw --bin sg_claw_client

Expected: PASS.

  • Step 6: Audit the remaining branch diff against main

Run:

git diff --stat main...HEAD

Expected: the remaining meaningful differences are websocket/browser transport work and Zhihu-related behavior, not scene-routing or staged-scene config churn.

  • Step 7: Commit the final verification pass
git add src/config/settings.rs src/compat/config_adapter.rs src/compat/runtime.rs src/compat/workflow_executor.rs src/compat/orchestration.rs src/runtime/mod.rs src/runtime/engine.rs tests/compat_config_test.rs tests/runtime_profile_test.rs tests/compat_runtime_test.rs tests/agent_runtime_test.rs tests/task_runner_test.rs
git commit -m "test: verify ws branch cleanup preserves zhihu websocket flow"

Verification Checklist

Cleanup regressions

cargo test --test compat_runtime_test ws_cleanup_ -- --nocapture
cargo test --test runtime_profile_test ws_cleanup_ -- --nocapture
cargo test --test compat_config_test ws_cleanup_ -- --nocapture

Expected: scene detection, scene prompt injection, and array-style skillsDir behavior are gone.

Retained Zhihu websocket behavior

cargo test --test agent_runtime_test production_submit_task_routes_zhihu_through_ws_backend_without_helper_bootstrap -- --nocapture
cargo test --test browser_ws_backend_test -- --nocapture
cargo test --test service_ws_session_test -- --nocapture
cargo test --test compat_runtime_test zhihu_ -- --nocapture

Expected: websocket submit path and Zhihu direct workflows still pass.

Runtime/config verification

cargo test --test compat_config_test -- --nocapture
cargo test --test runtime_profile_test -- --nocapture
cargo test --test task_runner_test -- --nocapture

Expected: runtime/config plumbing is stable after the single-dir cleanup.

Build verification

cargo build --bin sgclaw --bin sg_claw --bin sg_claw_client

Expected: the branch still compiles cleanly.


Notes For The Engineer

  • The current scene support touches three different seams: runtime prompt injection, direct route detection/execution, and multi-root skillsDir plumbing. Remove all three; deleting only one leaves conflict-prone leftovers.
  • If collapsing skillsDir to Option<PathBuf> creates more churn than expected, keep the internal representation temporarily as a one-element collection, but the public config contract and tests on this branch must still go back to a single configured path.
  • Do not delete browser websocket or callback-host code just because it is adjacent to the scene work; this plan is about stripping scene behavior, not reworking transport.
  • If git diff --stat main...HEAD still shows scene-specific files after Task 5, stop and remove them before merging main back into this branch.