diff --git a/README.md b/README.md index ff85912d..36d2aa4e 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ iloom #### Links to key sections -[How It Works](#how-it-works-the-multi-agent-workflow) • [Installation](#quick-start) • [Configuration](#configuration) • [Advanced Features](#advanced-features) • [Swarm Mode](#swarm-mode-epic-orchestration) • [Telemetry](#telemetry) • [Limitations](#system-requirements--limitations) • [Contributing](#contributing-to-iloom) +[How It Works](#how-it-works-the-multi-agent-workflow) • [Installation](#quick-start) • [Configuration](#configuration) • [Advanced Features](#advanced-features) • [Monorepo](#monorepo-support) • [Swarm Mode](#swarm-mode-epic-orchestration) • [Telemetry](#telemetry) • [Limitations](#system-requirements--limitations) • [Contributing](#contributing-to-iloom) ## How can your team trust the code your AI wrote, when you don't? @@ -688,6 +688,34 @@ Then use `il dev-server`, `il open`, or `il run` as normal. Docker Compose multi-service stacks are not yet supported — see [#332](https://github.com/iloom-ai/iloom-cli/issues/332) for the roadmap. For full configuration options and known limitations, see the [Complete Command Reference](docs/iloom-commands.md#docker-dev-server-mode). +### Monorepo Support + +iloom detects monorepo workspace configurations during `il init` and scopes commands to only the packages relevant to your current task. + +**Auto-detection:** iloom recognizes `pnpm-workspace.yaml` and `package.json` `workspaces` field, adding `"monorepo"` to your project capabilities automatically. + +**How it works:** + +1. **Package detection agent** runs before implementation (or after swarm completion in swarm mode) to determine which packages are affected by the current issue +2. **Scoped validation** — `il test`, `il lint`, `il compile`, and `il build` run only against the declared packages, using the correct filter syntax for your package manager (pnpm `--filter`, yarn `workspace`, npm `--workspace`) +3. **Scoped dev server** — `il dev-server` watches for the detection agent's decision and launches from the correct package subdirectory + +**Quick setup:** + +```bash +# Auto-detected during init +il init + +# Or add manually to .iloom/package.iloom.json +{ + "capabilities": ["monorepo", "web"] +} +``` + +Non-monorepo projects are completely unaffected — all commands behave identically to before. + +**-> [Complete Monorepo Guide](docs/monorepo-guide.md)** — Full details on detection, package scoping, dev server behavior, and troubleshooting. + ### Epic Planning and Decomposition The `il plan` command launches an interactive Architect session that helps you break down complex features into manageable child issues. @@ -820,7 +848,9 @@ This is an early-stage product. * ✅ **Node.js CLI Tools:** Full support with isolated binary generation. -* ✅ **Multi-Language Projects:** Python, Rust, Ruby, Go, and other languages via `.iloom/package.iloom.json`. +* ✅ **Multi-Language Projects:** Python, Rust, Ruby, Go, and other languages via `.iloom/package.iloom.json`. + +* ✅ **Monorepo Projects:** Automatic detection and scoped commands for pnpm, yarn, and npm workspaces. See [Monorepo Support](#monorepo-support) below. See all [known limitations](https://github.com/iloom-ai/iloom-cli/issues?q=is:issue+is:open+label:known-limitation) on GitHub. If you're feeling left out - you're absolutely right! The best way to complain about something is to fix it. So... diff --git a/docs/iloom-commands.md b/docs/iloom-commands.md index f8603228..f4408c75 100644 --- a/docs/iloom-commands.md +++ b/docs/iloom-commands.md @@ -800,8 +800,19 @@ il dev-server [identifier] [options] 1. Resolves the target loom 2. Loads environment variables from `.env` files -3. Executes dev script from `package.json` or `.iloom/package.iloom.json` -4. Runs in foreground (useful for debugging and manual testing) +3. Detects project capabilities (web, monorepo, CLI) +4. In monorepo mode: waits for `packagesToRun` to be set in loom metadata, then launches from the package subdirectory +5. Executes dev script from `package.json` or `.iloom/package.iloom.json` +6. Runs in foreground (useful for debugging and manual testing) + +**Monorepo Support:** + +When both `web` and `monorepo` capabilities are detected, `il dev-server` waits for the package detection agent to set `packagesToRun` in the loom metadata before launching. This ensures the dev server starts from the correct package subdirectory. + +- If `packagesToRun` is already set (detection agent ran before `il dev-server`), the server starts immediately. +- If `packagesToRun` is empty, `il dev-server` watches the metadata file (with 15-second polling fallback) and launches once the agent populates it. +- Only the first package in `packagesToRun` is used (multi-package dev servers are not supported in v1). +- Times out after 60 seconds with an actionable error message if the agent never runs. **Examples:** @@ -972,6 +983,10 @@ il build | Ruby | `bundle install` | `.iloom/package.iloom.json` | | Go | `go build ./...` | `.iloom/package.iloom.json` | +**Monorepo Support:** + +When `packagesToValidate` is set in the loom metadata, `il build` scopes execution to those specific packages using the package manager's workspace filter flag (`--filter` for pnpm, `--workspace` for npm, `--include` for yarn). Packages that do not define a `build` script are gracefully skipped. When `packagesToValidate` is empty or not set, `il build` runs at the project root as normal. + **Notes:** - Works with any language/framework via `.iloom/package.iloom.json` - Environment variables are automatically loaded before execution @@ -1031,6 +1046,10 @@ il lint feat/my-feature | Ruby | `rubocop` | `.iloom/package.iloom.json` | | Go | `golangci-lint run` | `.iloom/package.iloom.json` | +**Monorepo Support:** + +When `packagesToValidate` is set in the loom metadata, `il lint` scopes execution to those specific packages using the package manager's workspace filter flag (`--filter` for pnpm, `--workspace` for npm, `--include` for yarn). Packages that do not define a `lint` script are gracefully skipped. When `packagesToValidate` is empty or not set, `il lint` runs at the project root as normal. + **Notes:** - Works with any linter via `.iloom/package.iloom.json` - Environment variables are automatically loaded before execution @@ -1090,6 +1109,10 @@ il test feat/my-feature | Ruby | `bundle exec rspec` | `.iloom/package.iloom.json` | | Go | `go test ./...` | `.iloom/package.iloom.json` | +**Monorepo Support:** + +When `packagesToValidate` is set in the loom metadata, `il test` scopes execution to those specific packages using the package manager's workspace filter flag (`--filter` for pnpm, `--workspace` for npm, `--include` for yarn). Packages that do not define a `test` script are gracefully skipped. When `packagesToValidate` is empty or not set, `il test` runs at the project root as normal. + **Notes:** - Works with any test framework via `.iloom/package.iloom.json` - Environment variables are automatically loaded before execution @@ -1156,6 +1179,10 @@ il typecheck feat/my-feature | Rust | `cargo check` | `.iloom/package.iloom.json` | | Go | `go build ./...` (no-op compile) | `.iloom/package.iloom.json` | +**Monorepo Support:** + +When `packagesToValidate` is set in the loom metadata, `il compile` scopes execution to those specific packages using the package manager's workspace filter flag (`--filter` for pnpm, `--workspace` for npm, `--include` for yarn). Packages that do not define a `compile` or `typecheck` script are gracefully skipped. When `packagesToValidate` is empty or not set, `il compile` runs at the project root as normal. + **Notes:** - Works with any compiler/type checker via `.iloom/package.iloom.json` - Useful for catching type errors without running full test suite @@ -2162,10 +2189,49 @@ il init "configure neon database with project ID abc-123" - IDE preference (VS Code, Cursor, Windsurf, etc.) - Merge behavior (local, pr, draft-pr) - Permission modes -- Project type (web app, CLI tool, etc.) +- Project type (web app, CLI tool, monorepo, etc.) - Base port for development servers - Environment variable names +**Project Capabilities:** + +iloom detects and persists project capabilities in `.iloom/package.iloom.json` under the `capabilities` field. Valid values are: + +| Capability | Description | Auto-detected from | +|------------|-------------|-------------------| +| `"web"` | Web application with a dev server | React, Next.js, Vite, and other web framework dependencies | +| `"cli"` | Command-line tool with a `bin` entry | `bin` field in `package.json` | +| `"monorepo"` | Monorepo with multiple workspace packages | `pnpm-workspace.yaml` file OR `workspaces` field in `package.json` | + +Capabilities can also be set manually in `.iloom/package.iloom.json`: +```json +{ + "capabilities": ["monorepo"] +} +``` + +The `monorepo` capability is auto-detected during `il init` when either of these workspace configuration files are present: +- `pnpm-workspace.yaml` — used by pnpm workspaces +- `workspaces` field in `package.json` — used by yarn and npm workspaces + +**Monorepo Package Detection:** + +When the `"monorepo"` capability is set, iloom integrates a dedicated `iloom-monorepo-package-detector` agent into the workflow to determine which packages to run and validate. + +*How it works:* +- The detection agent explores the workspace structure, reads the issue context, and calls MCP tools to set `packagesToRun` and `packagesToValidate` on the loom metadata +- In **non-swarm mode**: the detection agent runs before the implementation agent begins +- In **swarm mode**: the detection agent runs after the swarm completes (called by the orchestrator), not by individual child agents + +*Package metadata reminder:* +When the `"monorepo"` capability is set, a UserPromptSubmit hook injects a reminder into each agent session: if the agent touches packages not already listed in `packagesToValidate`, it should call `mcp__recap__set_packages_to_validate` to update the list. + +*MCP tools used:* +- `set_package_to_run` — declare which package to run (dev server, etc.) +- `set_packages_to_validate` — declare which packages need test/lint/build validation + +When the project does not have the `"monorepo"` capability, no detection agent runs and no monorepo instructions appear in prompts. + **Jira Advanced Settings:** The following Jira settings can be configured in `.iloom/settings.json` under `issueManagement.jira`: diff --git a/docs/monorepo-guide.md b/docs/monorepo-guide.md new file mode 100644 index 00000000..465995e5 --- /dev/null +++ b/docs/monorepo-guide.md @@ -0,0 +1,142 @@ +# Monorepo Support in iloom + +This guide explains how iloom detects and works with monorepo projects, how package detection works, and how validation and dev server commands are scoped to specific packages. + +## What is Monorepo Support? + +Monorepo support means iloom is aware that your repository contains multiple packages in subdirectories and can scope its commands — validation, testing, linting, and the dev server — to only the packages relevant to a given loom's changes. This keeps CI-style commands fast and avoids running tests for packages that were not touched. + +## How Monorepo Detection Works + +iloom detects the `monorepo` capability automatically during `il init` by looking for workspace configuration files in the repository root: + +- **`pnpm-workspace.yaml`** — used by pnpm workspaces +- **`workspaces` field in `package.json`** — used by yarn and npm workspaces + +When either is present, iloom adds `"monorepo"` to the `capabilities` array in `.iloom/package.iloom.json`: + +```json +{ + "capabilities": ["monorepo", "web"] +} +``` + +You can also add `"monorepo"` manually to `.iloom/package.iloom.json` if auto-detection does not apply to your project layout. + +## The Package Detection Agent + +When the `monorepo` capability is set, iloom integrates a dedicated `iloom-monorepo-package-detector` agent into the workflow. + +**What it does:** + +1. The agent explores the loom's workspace, examines the issue context, and determines which packages were touched or need to run. +2. It calls MCP tools to write two arrays to the loom metadata file (`~/.config/iloom-ai/looms/.json`): + - `packagesToRun` — packages whose dev server should be started (relative paths from repo root, e.g., `./apps/web`) + - `packagesToValidate` — packages that `il test`, `il lint`, `il compile`, and `il build` should be scoped to (relative paths from repo root, e.g., `./packages/api`, `./apps/web`) + +**When it runs:** + +- **Non-swarm mode**: the detection agent runs before the implementation agent begins. +- **Swarm mode**: the detection agent runs after the swarm completes, called by the orchestrator. Individual child agents do not invoke it directly. + +**UserPromptSubmit hook reminder:** + +When `monorepo` capability is set, a `UserPromptSubmit` hook injects a reminder into each agent session: if the agent touches packages not already listed in `packagesToValidate`, it should call `mcp__recap__set_packages_to_validate` to update the list. + +## How `packagesToRun` and `packagesToValidate` Work + +Both fields are arrays of relative paths from the repository root. They live in the loom metadata file at `~/.config/iloom-ai/looms/.json`. + +| Field | Used by | Purpose | +|-------|---------|---------| +| `packagesToRun` | `il dev-server` | Which package's dev server to start | +| `packagesToValidate` | `il test`, `il lint`, `il compile`, `il build` | Which packages to scope validation to | + +These fields are set by the package detection agent. They can also be set manually via MCP tools (`mcp__recap__set_package_to_run`, `mcp__recap__set_packages_to_validate`) if you need to override the agent's decision. + +When a field is empty or not set, the corresponding command runs at the project root, covering the entire repository — the same behavior as for non-monorepo looms. + +## How Commands Are Scoped + +When `packagesToValidate` contains one or more packages, `il test`, `il lint`, `il compile`, and `il build` pass those packages to the package manager's workspace filter mechanism: + +| Package Manager | Filter syntax | +|-----------------|--------------| +| **pnpm** | `pnpm --filter ./pkg1 --filter ./pkg2 run