(name: string, options: WorksetOpenOptions = {})
| 334 | } |
| 335 | |
| 336 | async open(name: string, options: WorksetOpenOptions = {}): Promise<void> { |
| 337 | let prepared: PreparedOpen | undefined; |
| 338 | |
| 339 | try { |
| 340 | if (options.json) { |
| 341 | throw new StoreError( |
| 342 | 'workset open hands this terminal to the chosen tool and has no JSON mode.', |
| 343 | 'workset_open_json_unsupported', |
| 344 | { |
| 345 | target: 'workset.tool', |
| 346 | fix: 'Inspect worksets with: openspec workset list --json', |
| 347 | } |
| 348 | ); |
| 349 | } |
| 350 | |
| 351 | // Regenerate the derived file FIRST (under the lock), so every |
| 352 | // cannot-drive failure below can name an existing, current file. |
| 353 | prepared = await withWorksetsLock(async (state): Promise<PreparedOpen> => { |
| 354 | const workset = getWorkset(state, name); |
| 355 | if (workset === null) { |
| 356 | throw worksetNotFoundError(name, state); |
| 357 | } |
| 358 | |
| 359 | const checks = await Promise.all( |
| 360 | workset.members.map(async (member) => ({ |
| 361 | member, |
| 362 | exists: await pathIsDirectory(member.path), |
| 363 | })) |
| 364 | ); |
| 365 | const surviving = checks |
| 366 | .filter((check) => check.exists) |
| 367 | .map((check) => check.member); |
| 368 | const skipped = checks |
| 369 | .filter((check) => !check.exists) |
| 370 | .map((check) => check.member); |
| 371 | |
| 372 | if (surviving.length === 0) { |
| 373 | throw new StoreError( |
| 374 | `No member folder of workset '${name}' exists on this machine.`, |
| 375 | 'workset_no_members_available', |
| 376 | { |
| 377 | target: 'workset.member', |
| 378 | fix: `Recompose it: openspec workset remove ${name} --yes && openspec workset create ${name} --member <path>`, |
| 379 | } |
| 380 | ); |
| 381 | } |
| 382 | |
| 383 | const codeWorkspacePath = getWorksetCodeWorkspacePath(name); |
| 384 | await writeFileAtomically( |
| 385 | codeWorkspacePath, |
| 386 | buildWorksetCodeWorkspaceJson(surviving) |
| 387 | ); |
| 388 | |
| 389 | return { workset, surviving, skipped, codeWorkspacePath }; |
| 390 | }); |
| 391 | |
| 392 | for (const member of prepared.skipped) { |
| 393 | console.error( |
no test coverage detected