Skip to content

feat: workspace discovery for monorepo support#451

Merged
BYK merged 1 commit into
mainfrom
feat-workspace-discovery
May 21, 2026
Merged

feat: workspace discovery for monorepo support#451
BYK merged 1 commit into
mainfrom
feat-workspace-discovery

Conversation

@BYK
Copy link
Copy Markdown
Owner

@BYK BYK commented May 21, 2026

Problem

Lore uses process.cwd() as the project path with no directory traversal. This fails for monorepo setups:

  1. Downward (primary pain point): User runs lore run from monorepo root (no .git). Sub-projects are bare directories under the root, each with their own .git and .lore.md. Lore never discovers these sub-project .lore.md files.

  2. Upward: User runs from a sub-project. Lore doesn't discover the monorepo root above, missing shared config.

Solution

Config-driven sub-project discovery

New workspaces field in .lore.json:

// Bare sub-projects directly under monorepo root:
{ "workspaces": ["project-a", "project-b", "shared-lib"] }

// Standard monorepo layout:
{ "workspaces": ["packages/*"] }

// Mixed:
{ "workspaces": ["packages/*", "tools/cli", "infra"] }

Supports literal relative paths and single-level globs. Mirrors package.json workspaces / pnpm-workspace.yaml conventions.

Upward discovery via discoverWorkspaceRoot()

Walks up from cwd checking for project markers at each level:

  1. .lore.json with workspaces field (strongest signal — user explicitly declared workspace root)
  2. VCS markers: .git, .hg, .svn, .jj, etc. (definitive)
  3. Workspace markers: pnpm-workspace.yaml, nx.json, turbo.json, etc. (definitive)
  4. Language markers: package.json, pyproject.toml, Cargo.toml, etc. (closest-wins, walk continues)

Stop boundary at homedir() — never claims $HOME as workspace root even if ~/.git exists (common dotfile managers).

Integration flow

At startup (initIfNeeded):

  1. Resolve project path (may walk up to find workspace root)
  2. Load .lore.json from resolved path
  3. If workspaces is configured, resolve glob patterns to sub-project dirs
  4. Import .lore.md from each sub-project into the root project's knowledge base (via importLoreFileAs)
  5. Watch sub-project .lore.md files for live changes (independent debounce timers per watcher)

Sub-project .lore.md files are read-only imports — entries are attributed to the root project so they're visible via forSession(). Lore does not write back to sub-project files.

Safety

  • Path traversal guard: resolveWorkspaces rejects ../ escapes — resolved paths must be under rootDir
  • Dot-prefix filtering: Glob expansion skips .git, .vscode, etc. (matches npm/pnpm behavior)
  • Homedir boundary: Walk stops before checking markers at $HOME
  • Hosted mode guards: Both functions return safe defaults, preventing filesystem traversal with client-controlled paths
  • Mtime fast-path: importLoreFileAs skips re-import when source file unchanged (mtime cache)

Files changed

File Change
packages/core/src/workspace.ts NEWdiscoverWorkspaceRoot() + resolveWorkspaces()
packages/core/src/config.ts Add workspaces field to schema
packages/core/src/agents-file.ts Add importLoreFileAs()
packages/core/src/index.ts New exports
packages/core/test/workspace.test.ts NEW — 31 tests
packages/gateway/src/cli/run.ts Use discoverWorkspaceRoot(process.cwd())
packages/gateway/src/config.ts Apply to cwd fallback
packages/gateway/src/pipeline.ts Sub-project import at startup + file watchers
packages/opencode/src/index.ts Apply workspace root to project path

Test plan

  • 31 unit tests covering both directions of discovery + edge cases
  • Typecheck clean across all 4 packages
  • Existing test suites (config, agents-file, git) pass with no regressions

@BYK BYK marked this pull request as ready for review May 21, 2026 18:39
@BYK BYK merged commit 0a0e9d4 into main May 21, 2026
7 checks passed
@BYK BYK deleted the feat-workspace-discovery branch May 21, 2026 18:40
@craft-deployer craft-deployer Bot mentioned this pull request May 21, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant