docs: add multi-scene-kind generator design spec

Design for extending sg_scene_generate to support multiple scene kinds
(report_collection, monitoring) with manual type selection in Web UI,
relaxing the requirement for meta tags in third-party scene directories.

🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
木炎
2026-04-16 23:22:08 +08:00
parent f168f9f375
commit af8f261b79

View File

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