Monorepo Execution Controller

Overview

A new monorepo pack for the agentic-skills library that makes the full skill pipeline monorepo-aware. Instead of duplicating skills (like the -kanban variants), the pack uses an augmentation injection pattern — monorepo pack skills add pre/post steps to existing global skill contracts, injecting workspace detection, lane-spec generation, boundary guarding, and scoped shipping into the standard plan → execute → ship lifecycle.

The pack targets pnpm workspaces + Turborepo as the first-class monorepo stack, with detection via pnpm-workspace.yaml and turbo.json. When Turborepo is present, skills defer to turbo run for build/test/lint tasks to leverage its caching and dependency-aware ordering.

V1 ships four skills: mono-detect, mono-run, mono-ship, and mono-guard. V2 expands to planning, analysis, and migration skills.

Goals

Non-Goals

Detailed Design

Pack Structure

packs/monorepo/
├── PACK.md                          # Pack description, install instructions, skill list
├── claude/
│   ├── mono-detect/SKILL.md         # Workspace detection and package graph
│   ├── mono-run/SKILL.md            # Augmented /run with lane dispatch
│   ├── mono-ship/SKILL.md           # Scoped shipping with per-package validation
│   └── mono-guard/SKILL.md          # Pack-local reference to boundary enforcement
├── codex/
│   ├── mono-detect/SKILL.md
│   ├── mono-run/SKILL.md
│   ├── mono-ship/SKILL.md
│   └── mono-guard/SKILL.md
└── scripts/
    ├── mono-detect.sh               # Detect workspace manager, enumerate packages, build dep graph
    ├── lane-spec-validate.sh        # Validate lane-spec JSON against schema
    └── monorepo-validate.sh         # Pack-level validation (contracts, tags, detection)

Monorepo Detection (mono-detect)

mono-detect is the foundation skill. It detects the workspace structure and outputs a package graph that other skills consume.

Detection order:

  1. Check for pnpm-workspace.yaml → pnpm workspaces
  2. Check for turbo.json → Turborepo overlay
  3. If neither found, exit with "not a detected monorepo" and suggest /mono-migrate (v2)

Output: .agents/monorepo.json

{
  "workspace_manager": "pnpm",
  "build_orchestrator": "turborepo",
  "root": "/absolute/path",
  "packages": [
    {
      "name": "@scope/api",
      "path": "packages/api",
      "dependencies": ["@scope/shared-lib"],
      "devDependencies": ["@scope/test-utils"],
      "scripts": {
        "build": "tsc",
        "test": "vitest",
        "lint": "eslint ."
      }
    }
  ],
  "dependency_graph": {
    "@scope/api": ["@scope/shared-lib"],
    "@scope/web": ["@scope/shared-lib", "@scope/api"],
    "@scope/shared-lib": []
  },
  "turbo_pipelines": ["build", "test", "lint"],
  "detected_at": "2026-05-03T10:00:00Z"
}

Staleness: mono-detect re-runs if pnpm-workspace.yaml, turbo.json, or any package.json has a newer mtime than .agents/monorepo.json.

Structured Lane-Spec Artifact

Following the approval-packet pattern, lane specs use a JSON + committed Markdown mirror:

Machine-readable: .agents/lane-specs.json

{
  "phase": "Phase 22: API Auth Refactor",
  "source_roadmap_hash": "abc123",
  "lifecycle": "draft",
  "cross_cutting_steps": [
    {
      "step": "22.1",
      "description": "Update shared auth types",
      "packages": ["shared-lib"],
      "scope": "cross-cutting",
      "mode": "serial"
    }
  ],
  "lanes": [
    {
      "id": "api-auth",
      "step": "22.2",
      "description": "Refactor API auth middleware",
      "packages": ["api"],
      "owns": ["packages/api/src/auth/"],
      "must_not_edit": ["pnpm-lock.yaml", "turbo.json", "packages/web/", "packages/shared-lib/"],
      "depends_on": ["22.1"],
      "mode": "parallel"
    },
    {
      "id": "web-auth-ui",
      "step": "22.3",
      "description": "Update web auth components",
      "packages": ["web"],
      "owns": ["packages/web/src/auth/"],
      "must_not_edit": ["pnpm-lock.yaml", "turbo.json", "packages/api/", "packages/shared-lib/"],
      "depends_on": ["22.1"],
      "mode": "parallel"
    }
  ]
}

Lifecycle: draft → approved → dispatched → integrated | failed

Human-readable mirror: tasks/lane-specs.md (committed)

Package-Scope Tags

Specs and roadmap phases use YAML frontmatter to declare package scope:

---
packages: [api, web]
scope: cross-cutting
---

Valid scope values:

When scope is omitted, it defaults to package-scoped if packages has exactly one entry, or cross-cutting if it has multiple.

Augmented Execution: mono-run

mono-run augments /run with monorepo-aware dispatch. It does not replace /run — it wraps it with pre/post steps.

Pre-execution injection:

  1. Run mono-detect if .agents/monorepo.json is stale or missing.
  2. Read the current phase's execution profile from tasks/roadmap.md.
  3. If the phase mode is agent-team and the project is a detected monorepo:
  4. a. Parse lane definitions from the execution profile. b. Generate .agents/lane-specs.json and tasks/lane-specs.md. c. Run /mono-guard pre-flight validation on the lane specs. d. Enter plan mode with the lane specs for user approval.

  5. If the phase mode is serial or the project is not a monorepo, delegate directly to /run.

Dispatch (after approval):

  1. Execute cross-cutting steps serially in the main agent first.
  2. For each parallel wave (lanes with satisfied depends_on):
  3. a. Launch worktree-isolated agents, one per lane. b. Each agent receives its owns, must_not_edit, and step instructions. c. If Turborepo is available, agents use turbo run <task> --filter=<package> for build/test/lint. d. Monitor all agents. On any failure: halt remaining agents, preserve all worktree state, update lane-spec lifecycle to failed, report which lane failed and why.

  4. After all parallel lanes complete successfully:
  5. a. Run /mono-guard post-integration to verify no boundary violations. b. Update lane-spec lifecycle to integrated. c. Hand off to /mono-ship or continue to next step.

Flags:

Augmented Shipping: mono-ship

mono-ship augments /ship with package-scoped validation and shipping.

Pre-ship injection:

  1. Run mono-detect if stale.
  2. Read .agents/lane-specs.json to understand which packages were modified.
  3. For each modified package:
  4. a. Run package-scoped tests: turbo run test --filter=<package> (or pnpm --filter <package> run test). b. Run package-scoped lint: turbo run lint --filter=<package>. c. Run package-scoped build: turbo run build --filter=<package>.

  5. Run transitive dependent tests: use the dependency graph from .agents/monorepo.json to test packages that depend on modified packages.
  6. If any validation fails, stop and report. Do not proceed to shipping.

Ship:

  1. Delegate to /ship for the actual commit/push/deploy cycle.
  2. Update tasks/lane-specs.md with shipping status.
  3. If --pipeline was used, plan the next phase via /roadmap.

Boundary Enforcement: mono-guard

The existing global /mono-guard skill handles lane boundary validation. The pack's mono-guard is a thin reference that ensures:

Cross-Cutting Execution Safety

Steps tagged scope: cross-cutting or touching packages listed in multiple lanes:

  1. Always execute serially in the main agent (never dispatched to parallel worktrees).
  2. Must complete before any parallel lanes that depends_on them.
  3. May modify shared packages, root config, and lockfiles (the main agent is the only context where lockfile writes are permitted).
  4. After completion, parallel lanes see the updated state via worktree creation from the post-cross-cutting commit.

Data Model

.agents/monorepo.json

.agents/lane-specs.json

tasks/lane-specs.md

Package-scope tags in existing files

Edge Cases

Test Plan

Script-based validation matching the existing repo validation pattern:

scripts/monorepo-validate.sh

Fixtures

Acceptance Criteria

Open Questions

V2 Roadmap

Skills planned for v2 (not in scope for this spec's implementation):

Skill Augments Purpose
mono-roadmap/roadmapAuto-tag phases with package scope from code analysis
mono-plan-phase/plan-phaseGenerate lane specs during phase decomposition
mono-spec-interview/spec-interviewScope-aware spec writing with package boundary prompts
mono-affected/affectedTransitive impact analysis with lane-spec integration
mono-debug/debugPackage-scoped debugging with cross-package trace
mono-trace/traceRequest tracing across package boundaries
mono-investigate/investigateScoped investigation with package-aware code search
mono-migrate(new)Single-app → monorepo migration with guided execution

Assumptions & Risks

Assumption Source Downstream Risk if Wrong
pnpm workspaces + Turborepo is sufficient for v1[from interview] Confirmed by userProjects using npm/yarn/Nx/Lerna cannot use the pack until support is added
Root-level specs/research/tasks with package tags is sufficient[from interview] Confirmed by userIf package isolation is needed later, migrating from root-level tags to per-package directories is a structural change
Augmentation injection pattern works without modifying global skills[inferred] Not yet validatedIf global skills don't have clean pre/post hook points, augmentation may require global skill changes
Worktree-isolated agents can share Turbo cache[inferred] Needs empirical testingIf cache is per-worktree, parallel execution loses Turbo's main benefit (caching)
Lane-spec JSON + Markdown mirror is worth the complexity[from interview] User chose this patternMaintaining two representations adds sync risk, though the approval-packet precedent suggests it works
Stop-all-lanes failure semantics are always correct[from interview] Confirmed by userFor independent packages, continuing other lanes might be more productive; strict stop may slow development
Single-app → monorepo migration is the only migration path needed[from interview] Confirmed by userMulti-repo → monorepo and monorepo restructuring are common; deferring may block users with those needs
Cross-cutting steps can always be identified by package-scope tags[inferred] Not yet validatedSome cross-cutting changes (e.g., shared type updates that affect all packages) may not be obvious from tags alone
mono-detect.sh can reliably build the dependency graph from package.json files[inferred] Standard approachWorkspace protocol aliases, file: dependencies, and conditional dependencies may produce incorrect graphs