|
75 | 75 | - Apply `savePolicy` before choosing the pipeline source. |
76 | 76 | - Load only the selected file's pipeline into the runtime override map. |
77 | 77 |
|
| 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 | + |
78 | 157 | ## Scenario: Debug Resource Bundle Resolution |
79 | 158 |
|
80 | 159 | ### 1. Scope / Trigger |
|
0 commit comments