diff --git a/docs/superpowers/specs/2026-04-16-multi-scene-kind-generator-design.md b/docs/superpowers/specs/2026-04-16-multi-scene-kind-generator-design.md new file mode 100644 index 0000000..4d65d0b --- /dev/null +++ b/docs/superpowers/specs/2026-04-16-multi-scene-kind-generator-design.md @@ -0,0 +1,309 @@ +# Multi-Scene-Kind Generator Design + +> **Status:** Draft +> **Date:** 2026-04-16 +> **Author:** Qoder + +## Problem Statement + +`sg_scene_generate` 当前只支持 `report_collection` 类型的场景,强制要求场景目录的 `index.html` 包含 `sgclaw-scene-kind` 和 `sgclaw-tool-kind` meta 标签。 + +**现实情况**: +- 400+ 第三方场景目录**没有** meta 标签 +- 场景类型不单一:既有**报表收集类**(查询数据导出 Excel),也有**监测类**(定时检查状态、监控告警) +- 不可能要求所有第三方场景添加 meta 标签 + +**结果**:当前 `sg_scene_generate` 对真实场景目录完全无法使用。 + +## Goal + +扩展 `sg_scene_generate` 支持多种场景类型,让用户在 Web UI 上**手动选择场景类型**,而不是依赖场景目录中的 meta 标签。 + +## Non-Goals + +- 不实现 LLM 自动识别场景类型(后续增强) +- 不实现运行时自动推断场景类型 +- 不修改 `registry.rs` 的运行时校验逻辑(V1 仍只支持已注册的类型) +- 不实现完整的监测类参数解析器(生成简化模板,用户手动编辑) + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Web UI (HTML) │ +│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │ +│ │ 场景路径输入 │ │ 场景类型下拉框│ │ 分析/生成按钮 │ │ +│ └─────────────┘ └──────────────┘ └──────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Node.js Server │ +│ /analyze → LLM 提取 scene-id, scene-name │ +│ /generate → 调用 cargo run,传递 --scene-kind 参数 │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ sg_scene_generate (Rust CLI) │ +│ --scene-kind report_collection | monitoring │ +│ │ +│ analyzer.rs → 放宽 meta 校验,接受用户指定类型 │ +│ generator.rs → 根据类型选择不同模板 │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Implementation Details + +### 1. analyzer.rs — 放宽校验逻辑 + +**当前行为**: +- 强制要求 `sgclaw-scene-kind` meta 标签 = `report_collection` +- 强制要求 `sgclaw-tool-kind` meta 标签 = `browser_script` +- 缺失则报错退出 + +**新行为**: +- meta 标签**可选** +- 如果缺失,使用用户通过 `--scene-kind` 参数指定的类型 +- 如果用户未指定,默认为 `report_collection` +- `sgclaw-tool-kind` 默认为 `browser_script`(V1 只支持这一种) + +**枚举扩展**: +```rust +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SceneKind { + ReportCollection, + Monitoring, +} + +impl SceneKind { + pub fn from_str(s: &str) -> Option { + match s { + "report_collection" => Some(Self::ReportCollection), + "monitoring" => Some(Self::Monitoring), + _ => None, + } + } +} +``` + +**函数签名变更**: +```rust +// 改动前 +pub fn analyze_scene_source(source_dir: &Path) -> Result; + +// 改动后 +pub fn analyze_scene_source( + source_dir: &Path, + scene_kind_hint: Option, +) -> Result; +``` + +### 2. generator.rs — 多模板支持 + +**函数签名变更**: +```rust +// 改动前 +fn scene_toml(request: &GenerateSceneRequest, tool_name: &str, expected_domain: &str, target_url: &str) -> String; + +// 改动后 +fn scene_toml(request: &GenerateSceneRequest, analysis: &SceneSourceAnalysis, tool_name: &str) -> String; +``` + +**模板路由**: +```rust +fn scene_toml(request: &GenerateSceneRequest, analysis: &SceneSourceAnalysis, tool_name: &str) -> String { + match analysis.scene_kind { + SceneKind::ReportCollection => scene_toml_report_collection(request, analysis, tool_name), + SceneKind::Monitoring => scene_toml_monitoring(request, analysis, tool_name), + } +} +``` + +### 3. sg_scene_generate.rs — 新增 CLI 参数 + +**新增参数**: +``` +--scene-kind + 场景类型,默认 report_collection + - report_collection: 报表收集类(查询数据导出报表) + - monitoring: 监测类(定时检查状态、监控告警) +``` + +**用法示例**: +```bash +# 报表类(默认) +cargo run --bin sg_scene_generate -- \ + --source-dir "D:/desk/场景/营销报表" \ + --scene-id marketing-report \ + --scene-name "营销报表" \ + --output-root "./out" \ + --lessons "docs/superpowers/references/tq-lineloss-lessons-learned.toml" + +# 监测类 +cargo run --bin sg_scene_generate -- \ + --source-dir "D:/desk/场景/设备监测" \ + --scene-id device-monitor \ + --scene-name "设备监测" \ + --scene-kind monitoring \ + --output-root "./out" \ + --lessons "docs/superpowers/references/tq-lineloss-lessons-learned.toml" +``` + +### 4. 监测类模板设计 + +监测类场景差异较大,生成**简化模板**,用户后续手动编辑: + +```toml +[scene] +id = "" +skill = "" +tool = "monitor_" +kind = "browser_script" +version = "0.1.0" +category = "monitoring" + +[manifest] +schema_version = "1" + +[bootstrap] +expected_domain = "<从 analyzer 提取或空>" +target_url = "<从 analyzer 提取或空>" +requires_target_page = true + +[deterministic] +suffix = "。。。" +include_keywords = [""] +exclude_keywords = [] + +# 参数部分留空,用户手动编辑 +# [[params]] +# name = "xxx" +# resolver = "literal_passthrough" + +[artifact] +type = "monitoring-status" +success_status = ["ok", "running"] +failure_status = ["error", "timeout"] + +# 后处理留空,用户手动编辑 +``` + +### 5. Web UI 改动 + +**新增控件**: +```html +
+ + + 报表类:查询数据导出 Excel;监测类:定时检查状态 +
+``` + +**JavaScript 改动**: +```javascript +// generate() 函数增加 sceneKind 参数 +const sceneKind = document.getElementById('sceneKind').value; +const response = await fetch('/generate', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + sourceDir, + sceneId, + sceneName, + sceneKind, // 新增 + outputRoot, + lessons + }) +}); +``` + +### 6. Node.js Server 改动 + +**/generate 接口**: +```javascript +async function handleGenerate(req, res) { + const { sourceDir, sceneId, sceneName, sceneKind, outputRoot, lessons } = body; + // ... + const args = [ + "run", "--bin", "sg_scene_generate", "--", + "--source-dir", normalize(sourceDir), + "--scene-id", sceneId, + "--scene-name", sceneName, + "--scene-kind", sceneKind || "report_collection", // 新增 + "--output-root", normalize(outputRoot), + "--lessons", normalize(lessons), + ]; + // ... +} +``` + +## Compatibility Matrix + +| 场景目录 | meta 标签 | 用户选择 | 最终类型 | +|---------|----------|---------|---------| +| 有 meta | `report_collection` | 未选择 | `report_collection` | +| 有 meta | `report_collection` | `report_collection` | `report_collection` | +| 有 meta | `report_collection` | `monitoring` | `monitoring`(用户优先) | +| 无 meta | 无 | 未选择 | `report_collection`(默认) | +| 无 meta | 无 | `monitoring` | `monitoring` | + +**用户选择优先于 meta 标签**:因为用户比静态 meta 标签更了解场景的实际用途。 + +## File Changes Summary + +| 文件 | 改动类型 | 改动量 | +|------|---------|-------| +| `src/generated_scene/analyzer.rs` | 修改 | ~30 行 | +| `src/generated_scene/generator.rs` | 修改 | ~50 行 | +| `src/bin/sg_scene_generate.rs` | 修改 | ~20 行 | +| `frontend/scene-generator/sg_scene_generator.html` | 修改 | ~15 行 | +| `frontend/scene-generator/server.js` | 修改 | ~5 行 | +| `frontend/scene-generator/generator-runner.js` | 修改 | ~5 行 | +| `tests/scene_generator_test.rs` | 修改 | ~30 行 | +| `tests/fixtures/generated_scene/monitoring/index.html` | 新增 | ~20 行 | + +**总计**:~175 行改动,8 个文件。 + +## Testing Strategy + +### 单元测试 + +1. `analyzer_accepts_missing_meta_with_hint` — 缺失 meta 标签时,使用 hint 参数 +2. `analyzer_uses_meta_when_present` — 有 meta 标签时,使用 meta 值 +3. `generator_emits_report_collection_template` — 报表类模板正确 +4. `generator_emits_monitoring_template` — 监测类模板正确 + +### 集成测试 + +1. 无 meta 标签的场景目录 + `--scene-kind report_collection` → 生成成功 +2. 无 meta 标签的场景目录 + `--scene-kind monitoring` → 生成成功 +3. Web UI 选择监测类 → 生成的 scene.toml 包含 `category = "monitoring"` + +### 手动验证 + +1. 真实场景目录 `D:\desk\智能体资料\场景\营销2.0零度户报表数据生成` → 选择报表类 → 生成成功 +2. 真实监测类场景 → 选择监测类 → 生成成功 + +## Risks and Mitigations + +| 风险 | 影响 | 缓解措施 | +|------|------|---------| +| 监测类模板过于简化 | 用户需要大量手动编辑 | 文档说明 + 后续迭代优化 | +| 用户选错类型 | 生成错误模板 | UI 上提供清晰说明 | +| registry.rs 不支持 monitoring | 生成的包无法注册 | V1 只生成,运行时支持后续迭代 | + +## Open Questions + +1. 监测类场景的 `artifact.type` 应该是什么?当前设计为 `monitoring-status`,是否合适? +2. 监测类是否需要新的 resolver 类型? +3. 是否需要在前端 UI 显示更多类型说明? + +## References + +- `docs/superpowers/plans/2026-04-15-generated-scene-skill-platform-plan.md` — 原实现计划 +- `src/generated_scene/analyzer.rs` — 当前分析器 +- `src/generated_scene/generator.rs` — 当前生成器