# 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<Self> {
        match s {
            "report_collection" => Some(Self::ReportCollection),
            "monitoring" => Some(Self::Monitoring),
            _ => None,
        }
    }
}
```

**函数签名变更**：
```rust
// 改动前
pub fn analyze_scene_source(source_dir: &Path) -> Result<SceneSourceAnalysis, AnalyzeSceneError>;

// 改动后
pub fn analyze_scene_source(
    source_dir: &Path,
    scene_kind_hint: Option<SceneKind>,
) -> Result<SceneSourceAnalysis, AnalyzeSceneError>;
```

### 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|monitoring>
    场景类型，默认 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 = "<scene-id>"
skill = "<scene-id>"
tool = "monitor_<scene-id>"
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 = ["<scene-name>"]
exclude_keywords = []

# 参数部分留空，用户手动编辑
# [[params]]
# name = "xxx"
# resolver = "literal_passthrough"

[artifact]
type = "monitoring-status"
success_status = ["ok", "running"]
failure_status = ["error", "timeout"]

# 后处理留空，用户手动编辑
```

### 5. Web UI 改动

**新增控件**：
```html
<div class="form-group">
  <label>场景类型</label>
  <select id="sceneKind">
    <option value="report_collection" selected>报表收集类</option>
    <option value="monitoring">监测类</option>
  </select>
  <span class="hint">报表类：查询数据导出 Excel；监测类：定时检查状态</span>
</div>
```

**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` — 当前生成器
