( metadata: WorkspaceMetadata, runtime: Runtime, workspaceRootPath: string )
| 378 | } |
| 379 | |
| 380 | async function readSingleProjectContextInstructions( |
| 381 | metadata: WorkspaceMetadata, |
| 382 | runtime: Runtime, |
| 383 | workspaceRootPath: string |
| 384 | ): Promise<InstructionSet[]> { |
| 385 | // Read parent + sub-project AGENTS.md from the workspace's *own* checkout |
| 386 | // (via the runtime). For worktree/SSH/Docker flows the parent project's host |
| 387 | // path is a different checkout than the workspace branch — mixing the two |
| 388 | // would inject contradictory or stale guidance and prevent workspace-branch |
| 389 | // edits from overriding parent guidance. The workspace root is by |
| 390 | // construction the parent project's checkout, and any registered |
| 391 | // sub-project's relative path is stable across checkouts of the same repo. |
| 392 | // |
| 393 | // `workspaceRootPath` is the parent project's checkout root — *without* the |
| 394 | // sub-project segment appended (see `resolveWorkspaceRootPath`). The |
| 395 | // sub-project's AGENTS.md is read at `<root>/<subProjectRelativePath>`. |
| 396 | const subProjectRelativePath = metadata.subProjectPath |
| 397 | ? deriveSubProjectRelativePath(metadata.projectPath, metadata.subProjectPath) |
| 398 | : null; |
| 399 | |
| 400 | // path.relative emits host-native separators (e.g., "packages\\api" on Windows), |
| 401 | // but SSH/Docker/devcontainer runtimes read files via POSIX paths. Normalize to |
| 402 | // forward slashes and let the runtime joiner produce a runtime-correct path. |
| 403 | const subProjectInstructionsDir = subProjectRelativePath |
| 404 | ? runtime.normalizePath(subProjectRelativePath.replace(/\\/g, "/"), workspaceRootPath) |
| 405 | : null; |
| 406 | |
| 407 | const [parentInstructions, subProjectInstructions] = await Promise.all([ |
| 408 | readInstructionSetFromRuntime(runtime, workspaceRootPath, INSTRUCTION_SCOPE.WORKSPACE), |
| 409 | subProjectInstructionsDir |
| 410 | ? readInstructionSetFromRuntime( |
| 411 | runtime, |
| 412 | subProjectInstructionsDir, |
| 413 | INSTRUCTION_SCOPE.SUBPROJECT |
| 414 | ) |
| 415 | : Promise.resolve(null), |
| 416 | ]); |
| 417 | |
| 418 | return [parentInstructions, subProjectInstructions].filter( |
| 419 | (set): set is InstructionSet => set != null && set.combinedContent.trim().length > 0 |
| 420 | ); |
| 421 | } |
| 422 | |
| 423 | /** |
| 424 | * Compute the path of `subProjectPath` relative to `projectPath` for use under |
no test coverage detected