feat: add monorepo workspace configuration and auto-detection#23
feat: add monorepo workspace configuration and auto-detection#23digitarald merged 2 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds monorepo workspace support to AgentRC’s config/analysis pipeline so areas can be grouped under workspace roots, auto-detected, and used to scope eval sessions and generated artifacts across both the CLI and VS Code extension.
Changes:
- Extend
agentrc.config.jsonschema withworkspaces[]and add workspace auto-detection (detectWorkspaces()). - Flatten workspace areas into namespaced
Areaentries and propagate workspace scoping into eval scaffolding + eval runs. - Update
initto bootstrap anagentrc.config.jsonwith detected workspaces/areas and document the new configuration in README/examples/docs.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vscode-extension/src/types.ts | Re-exports new config/workspace types to keep extension aligned with CLI types. |
| vscode-extension/src/services.ts | Re-exports detectWorkspaces for extension feature reuse via the CLI service layer. |
| src/services/evaluator.ts | Adds per-eval-case workingDirectory support and passes it into Copilot SDK sessions with boundary checks. |
| src/services/evalScaffold.ts | Adds workingDirectory to eval case schema and scaffolding prompt guidance for workspace-scoped evals. |
| src/services/analyzer.ts | Implements workspace config parsing, workspace area flattening, and detectWorkspaces() logic. |
| src/services/tests/analyzer.test.ts | Adds tests for workspace config parsing, workspace detection, and workspace area flattening. |
| src/commands/init.ts | Bootstraps agentrc.config.json based on detected workspaces + standalone areas. |
| examples/agentrc.config.json | Adds a monorepo example config demonstrating areas, workspaces, and policies. |
| examples/README.md | Links to the new sample project config. |
| docs/plugins.md | Cross-references the new monorepo config example. |
| README.md | Documents workspace configuration and init auto-bootstrapping behavior. |
Comments suppressed due to low confidence (1)
src/services/analyzer.ts:1329
parentAreavalidation is currently done against a single global set of un-namespaced area names aggregated from all workspaces (and flat areas). If two workspaces contain the same area name, a workspace area can incorrectly “validate” aparentAreathat only exists in a different workspace, and then later flattening/namespacing will still produce a broken reference.
Consider validating workspace-area parentArea references within the same workspace’s areas (or validating against the post-namespacing names) to avoid cross-workspace name collisions.
// Validate parentArea references across all areas (flat + workspace)
const allConfigAreas = [...areas];
for (const ws of workspaces) {
allConfigAreas.push(...ws.areas);
}
const areaNames = new Set(allConfigAreas.map((a) => a.name.toLowerCase()));
for (const area of allConfigAreas) {
if (area.parentArea && !areaNames.has(area.parentArea.toLowerCase())) {
area.parentArea = undefined;
| if (depth >= maxDepth) return []; | ||
| const results: string[] = []; | ||
| let entries: string[]; | ||
| try { | ||
| entries = await safeReadDir(dir); | ||
| } catch { | ||
| return []; | ||
| } |
There was a problem hiding this comment.
findVSCodeDirs() stops scanning when depth >= maxDepth, which means with WORKSPACE_SCAN_MAX_DEPTH = 3 it never inspects directories at depth 3 (only 0–2). That makes the “depth 3” behavior in the PR description effectively off by one and can miss .vscode markers in deeper nested workspaces. Consider allowing scanning at depth === maxDepth and only preventing recursion beyond the limit. Also, the try/catch around safeReadDir() is redundant because safeReadDir already swallows errors and returns an empty array.
| if (depth >= maxDepth) return []; | |
| const results: string[] = []; | |
| let entries: string[]; | |
| try { | |
| entries = await safeReadDir(dir); | |
| } catch { | |
| return []; | |
| } | |
| if (depth > maxDepth) return []; | |
| const results: string[] = []; | |
| const entries = await safeReadDir(dir); |
| if (allPatterns.some((p) => p.split("/").includes(".."))) continue; | ||
| areas.push({ | ||
| name: e.name as string, | ||
| applyTo, |
There was a problem hiding this comment.
parseConfigAreas() validates that applyTo is a string or string[], but it does not actually normalize/trim the stored patterns. This allows entries like applyTo: " docs/**" or applyTo: ["src/**", " "] to be accepted, which can produce broken/ineffective glob matching downstream (frontmatter, area detection, etc.). Suggest trimming each pattern (and filtering/rejecting empty patterns) before pushing the area.
| if (allPatterns.some((p) => p.split("/").includes(".."))) continue; | |
| areas.push({ | |
| name: e.name as string, | |
| applyTo, | |
| const normalizedPatterns = allPatterns.map((p) => p.trim()).filter((p) => p.length > 0); | |
| if (normalizedPatterns.length === 0) continue; | |
| if (normalizedPatterns.some((p) => p.split("/").includes(".."))) continue; | |
| areas.push({ | |
| name: e.name as string, | |
| applyTo: Array.isArray(applyTo) ? normalizedPatterns : normalizedPatterns[0], |
Summary
Adds
workspacessupport toagentrc.config.jsonfor monorepo projects, enabling architects to define sub-project boundaries with scoped areas, auto-detection, and eval session scoping.Changes
Configuration (
agentrc.config.json)workspacesarray:{ name, path, areas[] }— groups areas under a sub-project directoryapplyTopatterns are relative to the workspace path., malformed entriesparseConfigAreas()extracted as shared validator for flat and workspace areasparentAreavalidation spans both flat and workspace areasAuto-detection (
detectWorkspaces()).vscodefolders as workspace markers (depth 3)Init command
agentrc.config.jsonwith detected workspaces and standalone areasEval integration
EvalCase.workingDirectory— per-case workspace scopingaskOnce()passesworkingDirectoryto Copilot SDKcreateSession()Area model
Area.workingDirectory— set for workspace areas, used in eval and instruction generationfrontend/app)Documentation
examples/agentrc.config.json: full monorepo exampledocs/plugins.md: cross-reference to config exampleTests
.)Verification
npm run typecheck— cleannpm run lint— cleannpm run test— 524/524 pass