(workspaceId: string, step: DevToolsStep)
| 206 | } |
| 207 | |
| 208 | async createStep(workspaceId: string, step: DevToolsStep): Promise<void> { |
| 209 | if (!this.enabled) { |
| 210 | return; |
| 211 | } |
| 212 | |
| 213 | assert(workspaceId.trim().length > 0, "DevToolsService.createStep requires a workspaceId"); |
| 214 | assert(step.runId.trim().length > 0, "DevToolsService.createStep requires step.runId"); |
| 215 | |
| 216 | await this.ensureLoaded(workspaceId); |
| 217 | const data = this.getOrCreateWorkspaceData(workspaceId); |
| 218 | |
| 219 | // Self-healing: if the run was cleared during an active stream, |
| 220 | // recreate it so steps aren't orphaned. |
| 221 | if (!data.runs.has(step.runId)) { |
| 222 | const autoRun: DevToolsRun = { |
| 223 | id: step.runId, |
| 224 | workspaceId, |
| 225 | startedAt: step.startedAt, |
| 226 | }; |
| 227 | data.runs.set(autoRun.id, autoRun); |
| 228 | await this.appendToFile(workspaceId, { type: "run", run: autoRun }); |
| 229 | this.emitWorkspaceEvent(workspaceId, { |
| 230 | type: "run-created", |
| 231 | run: this.buildRunSummary(data, autoRun.id), |
| 232 | }); |
| 233 | } |
| 234 | |
| 235 | data.steps.set(step.id, step); |
| 236 | await this.appendToFile(workspaceId, { type: "step", step }); |
| 237 | |
| 238 | this.emitWorkspaceEvent(workspaceId, { type: "step-created", step }); |
| 239 | if (data.runs.has(step.runId)) { |
| 240 | const summary = this.buildRunSummary(data, step.runId); |
| 241 | this.emitWorkspaceEvent(workspaceId, { type: "run-updated", run: summary }); |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | async updateStep( |
| 246 | workspaceId: string, |
no test coverage detected