Skip to content

Commit 7a82dcb

Browse files
committed
feat(debug): override
1 parent 3587c82 commit 7a82dcb

22 files changed

Lines changed: 2056 additions & 311 deletions

.trellis/spec/frontend/debug-save-policy.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,85 @@
7575
- Apply `savePolicy` before choosing the pipeline source.
7676
- Load only the selected file's pipeline into the runtime override map.
7777

78+
## Scenario: Debug Runtime Override Draft
79+
80+
### 1. Scope / Trigger
81+
- Trigger: debug overview now accepts a temporary JSON override draft that participates in the cross-layer run request contract.
82+
- Applies when touching:
83+
- `src/features/debug/components/panels/OverviewPanel.tsx`
84+
- `src/features/debug/pipelineOverride.ts`
85+
- `src/stores/debugOverrideStore.ts`
86+
- `src/stores/debugRunProfileStore.ts`
87+
- `src/features/debug/hooks/useDebugModalController.ts`
88+
- `src/components/flow/nodes/nodeContextMenu.tsx`
89+
- `LocalBridge/internal/debug/protocol/types.go`
90+
- `LocalBridge/internal/debug/runtime/runtime.go`
91+
92+
### 2. Signatures
93+
- Frontend draft parser:
94+
- `parseDebugPipelineOverrideDraft(draft: string) -> { error?: string; overrides?: DebugPipelineOverride[] }`
95+
- Frontend request field:
96+
- `DebugRunRequest { overrides?: DebugPipelineOverride[] }`
97+
- Backend request field:
98+
- `protocol.RunRequest { Overrides []PipelineOverride }`
99+
- Backend merge entrypoint:
100+
- `runtime.PipelineOverride(root string, req protocol.RunRequest) (map[string]interface{}, error)`
101+
102+
### 3. Contracts
103+
- Draft shape:
104+
- The UI draft must use MaaFW-compatible partial pipeline JSON: `{ "<RuntimeName>": { ...partial pipeline... } }`.
105+
- Root value must be a JSON object.
106+
- Each key becomes one `DebugPipelineOverride.runtimeName`.
107+
- Each value must be an object; arrays and primitives are invalid.
108+
- Lifetime:
109+
- Override draft is page-lifecycle state only.
110+
- Do not persist it to localStorage / memory store.
111+
- Do not write it back into graph nodes, source JSON, or exported pipeline files.
112+
- Merge order:
113+
- Backend must resolve the base pipeline first using `savePolicy`.
114+
- Request overrides then deep-merge onto that base.
115+
- For conflicting fields, request override wins.
116+
- Nested objects merge recursively; arrays and scalar values replace the base value directly.
117+
- Entry paths:
118+
- Overview run buttons and node context-menu debug start must both consult the same parsed draft result before starting a run.
119+
120+
### 4. Validation & Error Matrix
121+
- Draft is invalid JSON -> frontend blocks run start with `debug.override.invalid_json`.
122+
- Draft root is not an object -> frontend blocks run start with a clear format error.
123+
- Any runtimeName is empty after trim -> frontend blocks run start with a clear runtime-name error.
124+
- Any runtime override value is not an object -> frontend blocks run start with a clear node-value error.
125+
- Base pipeline is nil / empty but request override exists -> backend must initialize a safe map and merge without panic.
126+
127+
### 5. Good / Base / Bad Cases
128+
- Good:
129+
- Draft is `{ "ShopEntry": { "next": ["NodeB"], "timeout": 5000 } }`; runtime starts and `ShopEntry` fields override the base pipeline.
130+
- Base:
131+
- Draft is `{}`; request may omit `overrides` or send an empty override list, and runtime behavior matches the unmodified base pipeline.
132+
- Bad:
133+
- Frontend accepts `"[]"` or `{ "ShopEntry": 1 }` and lets the run start, leaving LocalBridge to fail later.
134+
135+
### 6. Tests Required
136+
- Frontend verification:
137+
- Targeted eslint on touched debug files.
138+
- Static check that override draft store does not use `localStorage` / persisted memory.
139+
- Static or test verification that overview and node context-menu paths share the same invalid-draft guard.
140+
- Go unit tests for `runtime.PipelineOverride(...)`:
141+
- Assert request override deep-merges onto an existing base node.
142+
- Assert request override can add a new runtime node.
143+
- Assert nil/empty base pipeline plus request override does not panic.
144+
145+
### 7. Wrong vs Correct
146+
147+
#### Wrong
148+
149+
- Treat the draft as a persisted profile setting or silently allow invalid JSON until runtime.
150+
151+
#### Correct
152+
153+
- Keep the draft in ephemeral page state only.
154+
- Parse and validate before any run start.
155+
- Merge request overrides onto the resolved base pipeline in LocalBridge, with request values winning on conflict.
156+
78157
## Scenario: Debug Resource Bundle Resolution
79158

80159
### 1. Scope / Trigger
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
2+
{"file": ".trellis/spec/frontend/index.md", "reason": "Frontend verification entrypoint"}
3+
{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Review panel/component contract changes"}
4+
{"file": ".trellis/spec/frontend/hook-guidelines.md", "reason": "Review controller/hook side effects and data flow"}
5+
{"file": ".trellis/spec/frontend/state-management.md", "reason": "Review Zustand persistence and state boundaries"}
6+
{"file": ".trellis/spec/frontend/type-safety.md", "reason": "Review runtime override payload typing and parsing"}
7+
{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "Review quality and validation expectations"}
8+
{"file": ".trellis/spec/frontend/debug-save-policy.md", "reason": "Review debug request contract compatibility"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
2+
{"file": ".trellis/spec/frontend/index.md", "reason": "Frontend spec entrypoint for debug override work"}
3+
{"file": ".trellis/spec/frontend/directory-structure.md", "reason": "Feature-first placement for DebugModal panel, hooks, and stores"}
4+
{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Panel/component composition and Monaco editor integration conventions"}
5+
{"file": ".trellis/spec/frontend/hook-guidelines.md", "reason": "DebugModal controller/hook orchestration expectations"}
6+
{"file": ".trellis/spec/frontend/state-management.md", "reason": "Zustand state rules for debug modal/profile persistence"}
7+
{"file": ".trellis/spec/frontend/type-safety.md", "reason": "Run request and override payload type changes"}
8+
{"file": ".trellis/spec/frontend/debug-save-policy.md", "reason": "Relevant debug runtime request contract around pipeline source selection"}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# 调试模块 override 功能需求梳理
2+
3+
## Goal
4+
5+
为调试模块补上一个可手工编辑的运行时 `override` 能力,用来替代旧 Interface `option -> pipeline_override` 对调试的影响,让 MPE 在不读取 Interface 的前提下,仍可在调试时模拟某个 Interface 的覆盖配置。
6+
7+
## What I already know
8+
9+
- 用户希望在调试模块新增一个 `override` 模块,放在中控台 `当前 / 最新运行` 下方。
10+
- 该模块默认收起,并内置 JSON 编辑器,方便直接编辑 override 内容。
11+
- 本次只新增中控台这一个 override 模块,不再额外补独立的“用户 override”输入层。
12+
- 该模块产出的 override 需要与调试运行基础 pipeline 合并后作为最终运行时 override 生效。
13+
- 当前调试概览面板在 [src/features/debug/components/panels/OverviewPanel.tsx](D:\_Projects\maa-pipeline-editor\src\features\debug\components\panels\OverviewPanel.tsx) 中,`当前 / 最新运行` 已是独立 `DebugSection`
14+
- 调试区块组件 [src/features/debug/components/DebugSection.tsx](D:\_Projects\maa-pipeline-editor\src\features\debug\components\DebugSection.tsx) 已支持 `collapsible``defaultCollapsed`
15+
- 仓库已引入 Monaco(`@monaco-editor/react`),现有 [src/components/modals/NodeJsonEditorModal.tsx](D:\_Projects\maa-pipeline-editor\src\components\modals\NodeJsonEditorModal.tsx) 可复用其中的编辑器、格式化、语法校验思路。
16+
- 当前 debug run 请求类型 [src/features/debug/types.ts](D:\_Projects\maa-pipeline-editor\src\features\debug\types.ts) 已有 `overrides?: DebugPipelineOverride[]` 字段。
17+
- 当前 `buildRunRequest()` 会把 `buildDebugSnapshotBundle()` 里的 `bundle.overrides` 带入请求,见 [src/stores/debugRunProfileStore.ts](D:\_Projects\maa-pipeline-editor\src\stores\debugRunProfileStore.ts)
18+
- 但后端 [LocalBridge/internal/debug/runtime/runtime.go](D:\_Projects\maa-pipeline-editor\LocalBridge\internal\debug\runtime\runtime.go) 当前 `PipelineOverride(root, req)` 并未消费 `req.Overrides`,所以前端新增 UI 后还需要补全真正的合并/生效逻辑。
19+
- 现有 `snapshot.ts` 中的 `bundle.overrides` 本质上是从导出的 pipeline 节点对象抽出的运行节点快照,而不是用户手填的附加 override 来源。
20+
21+
## Assumptions (temporary)
22+
23+
- 用户要的 JSON 内容应直接采用 MaaFW `pipeline_override` 兼容结构,即 `{ "<RuntimeName>": { ...partial node pipeline... } }`
24+
- override 仅作用于调试运行,不回写图节点、不改 JSON 源文件。
25+
- override 编辑值需要本地持久化,否则用户每次打开调试面板都要重输,体验较差。
26+
- 未指定展开态记忆行为时,默认只要求“首次渲染默认收起”;是否记忆上次展开态可作为实现时的次优先级细节处理。
27+
28+
## Requirements (evolving)
29+
30+
- 在调试中控台增加 `override` 区块,位置在 `当前 / 最新运行` 下方。
31+
- 区块默认折叠。
32+
- 区块内提供可编辑 JSON 的编辑器,至少支持语法校验与格式化。
33+
- 调试启动时,把该区块内容合并到最终运行时 pipeline override。
34+
- 合并语义为:基础 pipeline 在前,模块 override 在后覆盖同名节点/字段。
35+
- override 解析/校验失败时,应在前端阻止启动并给出明确错误。
36+
- 后端必须真正消费前端传入的 override,而不是仅保留类型字段。
37+
38+
## Acceptance Criteria (evolving)
39+
40+
- [ ] 中控台能看到默认折叠的 `override` 区块,位置在 `当前 / 最新运行` 下方。
41+
- [ ] 用户可编辑合法 JSON,并可一键格式化。
42+
- [ ] 非法 JSON 时,运行按钮启动被拦截,并看到明确报错。
43+
- [ ] 最终调试请求会带上合并后的 override,且后端实际使用它启动运行。
44+
- [ ] 当模块 override 命中基础 pipeline 的同一节点/字段时,以模块 override 的值为准。
45+
46+
## Out of Scope (explicit)
47+
48+
- 不恢复旧 Interface 导入/解析链路。
49+
- 不把 override 持久写回 pipeline 文件或节点属性面板。
50+
- 不在本任务中扩展 breakpoint / pause / continue 等其他调试设计。
51+
52+
## Technical Notes
53+
54+
- 现有 `OverviewPanel` 已适合放置一个新的 `DebugSection`
55+
- 现有 `DebugSection` 支持默认折叠,但不自带跨次持久化;若要记忆展开状态,需要额外接入 memory/profile store。
56+
- 当前 debug-vNext 主链里没有已生效的“用户 override”输入源;代码层面只有 `graphSnapshot` 导出的 pipeline 与未消费的 `req.overrides` 字段。
57+
- 本次实现可简化为单一来源合并:
58+
- 前端:`debugRunProfileStore.buildRunRequest()` 负责把中控台 override 序列化进请求。
59+
- 后端:`PipelineOverride(root, req)` 先拿基础 pipeline,再深合并请求内 override。
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"id": "debug-override-feature",
3+
"name": "debug-override-feature",
4+
"title": "调试模块 override 功能需求梳理",
5+
"description": "",
6+
"status": "in_progress",
7+
"dev_type": null,
8+
"scope": null,
9+
"package": null,
10+
"priority": "P2",
11+
"creator": "kqmain",
12+
"assignee": "kqmain",
13+
"createdAt": "2026-05-04",
14+
"completedAt": null,
15+
"branch": null,
16+
"base_branch": "main",
17+
"worktree_path": null,
18+
"commit": null,
19+
"pr_url": null,
20+
"subtasks": [],
21+
"children": [],
22+
"parent": null,
23+
"relatedFiles": [],
24+
"notes": "",
25+
"meta": {}
26+
}

0 commit comments

Comments
 (0)