DevSpark Monorepo Support: Governing Multiple Apps in One Repository
Monorepos give teams atomic commits and unified history, but they introduce governance problems: mixed review rules, scope ambiguity, and AI agents that can't tell one app from another. DevSpark's multi-app support solves this with an explicit application registry, layered governance that can't weaken repo-wide rules, and dependency-aware scope analysis — all backward-compatible and opt-in.
DevSpark Series — 24 articles
- DevSpark: Constitution-Driven AI for Software Development
- Getting Started with DevSpark: Requirements Quality Matters
- DevSpark: Constitution-Based Pull Request Reviews
- Why I Built DevSpark
- Taking DevSpark to the Next Level
- From Oracle CASE to Spec-Driven AI Development
- Fork Management: Automating Upstream Integration
- DevSpark: The Evolution of AI-Assisted Software Development
- DevSpark: Months Later, Lessons Learned
- DevSpark in Practice: A NuGet Package Case Study
- DevSpark: From Fork to Framework — What the Commits Reveal
- DevSpark v0.1.0: Agent-Agnostic, Multi-User, and Built for Teams
- DevSpark Monorepo Support: Governing Multiple Apps in One Repository
- The DevSpark Tiered Prompt Model: Resolving Context at Scale
- A Governed Contribution Model for DevSpark Prompts
- Prompt Metadata: Enforcing the DevSpark Constitution
- Bring Your Own AI: DevSpark Unlocks Multi-Agent Collaboration
- Workflows as First-Class Artifacts: Defining Operations for AI
- Observability in AI Workflows: Exposing the Black Box
- Autonomy Guardrails: Bounding Agent Action Safely
- Dogfooding DevSpark: Building the Plane While Flying It
- Closing the Loop: Automating Feedback with Suggest-Improvement
- Designing the DevSpark CLI UX: Commands vs Prompts
- The Alias Layer: Masking Complexity in Agent Invocations
The Moment a Single Constitution Stops Being Enough
Some repositories contain one application. One build pipeline, one deployment target, one set of review rules — one constitution covers everything. DevSpark handled this well from day one.
Then I started using DevSpark on a repository with six services: two runtime APIs, an admin API, a React admin dashboard, a client-facing web application, and a QA test harness. Same git log, shared CI configuration, atomic commits that spanned multiple services. All the reasons teams choose monorepos in the first place.
The problem surfaced fast. A constitution that mandates "100% integration test coverage" makes sense for the production APIs. It's overkill for the QA harness. Security review requirements appropriate for the client-facing web app are noise for internal admin tooling. And when I asked AI coding agents to generate a plan or review a PR, they treated the entire repository as one undifferentiated codebase — producing specifications that conflated unrelated services and reviews that applied the wrong standards to the wrong code.
The governance model that worked beautifully for single-application repositories was creating friction in multi-application ones. Not because the model was wrong, but because it assumed a one-to-one relationship between repository and application.
Why Monorepos — and Why They Keep Winning
Before getting into what DevSpark does about it, it's worth understanding why monorepos are so popular in the first place and why the problems they create are worth solving rather than avoiding.
A monorepo is a single version-controlled repository that contains multiple applications, services, and libraries. Instead of one repo per deployable unit, a team maintains one repo that houses the entire related ecosystem. Google, Meta, Microsoft, and Uber all operate at monorepo scale — but you don't need to be at that scale to feel the pull. Even a team of five with three services and a shared library will eventually ask whether it makes more sense to keep everything together.
The appeal is real. A single commit can update an API contract and all its consumers at once — no coordinating merges across five repositories. The git log shows the full picture of how the system evolved, not just one slice of it. CI pipelines, linters, and dependency management are configured once instead of duplicated everywhere. Refactoring across service boundaries doesn't require synchronized PRs with their own merge conflicts and timing headaches. And new team members clone one repository instead of hunting down six.
These advantages compound. The more services you have, the more painful coordination becomes across separate repos, and the more attractive a monorepo looks.
The Governance Problem That Monorepos Create
But monorepos don't just contain code — they contain context boundaries. A client-facing React app and an internal QA harness live in the same repository, but they have fundamentally different security postures, testing expectations, and review requirements. An API serving production traffic needs different scrutiny than an admin tool used by three people internally.
When everything lives in one repo, five specific problems surface:
Mixed governance is the most visible. Your repository constitution says "all code requires security review," but the QA harness is a test fixture, not a production surface. Applying production-grade review to internal tooling wastes time without reducing risk.
Scope ambiguity appears every time a PR touches more than one directory. Which applications does it affect? Which review rules apply? Without an explicit answer, reviewers resort to guessing — or worse, applying the broadest possible rules to everything.
Dependency risk hides in shared libraries. When the authentication module changes, which of the six services consumes it? In separate repos, you'd see the dependency through package references. In a monorepo, the relationship is implicit unless someone maps it.
Context overload is the AI-specific dimension that made this problem personal. When I pointed AI coding agents at the monorepo and asked for a specification or a review, they treated it as one giant application. Plans mixed concerns from unrelated services. Reviews applied API standards to the frontend and frontend standards to the API. The agent had no way to know that different parts of the repository had different purposes, different owners, and different rules.
Configuration drift is the slow killer. Teams start adding per-app exceptions — this service skips linting, that one has relaxed test coverage. Without structure, these exceptions become an unmanageable patchwork that nobody fully understands.
How DevSpark Addresses This
DevSpark's approach rests on three principles: explicit scope, layered governance, and dependency awareness — all without requiring changes to repositories that don't need multi-app support.
Making Applications Explicit
The foundation is an application registry — a single JSON file at .documentation/devspark.json that declares every application in the repository. Each entry specifies an identifier, a directory path, a kind (API, web, library), an owner, a criticality level, which governance profiles it inherits, and what it depends on.
This registry is the single source of truth. DevSpark validates it on load: identifiers must be unique, paths must exist, profile references must resolve, dependency references can't form cycles. It fails fast on errors. The DevSpark Monorepo Guide has the full schema and a working example.
Once applications are declared, every DevSpark command can scope its behavior. Specifications target one app. PR reviews apply the right rules. AI agents receive context about what they're actually working on instead of treating the whole repository as one undifferentiated blob. That single file — declaring what exists and where it lives — eliminates the context overload problem almost entirely.
Layered Governance That Can't Weaken
The tempting approach would be to install a separate DevSpark constitution per application. That path leads to duplicated framework files, upgrade drift across applications, and cross-app reviews that don't share a common baseline.
Instead, DevSpark uses layered governance. Three tiers, each additive. At the base, the repository-wide constitution defines mandatory rules that apply everywhere — security standards, commit signing requirements, minimum test coverage. In the middle, profiles group rules by application class: all APIs inherit an api-profile with OpenAPI documentation requirements, all web apps inherit a web-profile with accessibility standards. At the top, individual applications can add their own overlays for requirements specific to that service.
The critical design rule: app-level governance can strengthen or extend repository-wide rules, but it can never weaken mandatory repo-wide rules. If the constitution says 80% test coverage is non-negotiable, no individual application can opt out. DevSpark enforces this through constitution weakening detection — scanning app constitutions for negation patterns that would relax mandatory rules, and flagging conflicts in validation output.
This means a repository with six applications doesn't need six copies of every prompt, every script, or every template. Most applications inherit shared defaults and profiles, adding only the specific overrides they need. The resolution order and profile composition details are documented in the full guide.
Dependency-Aware Scope
Declaring applications is valuable on its own, but the real payoff comes when DevSpark uses the declared dependsOn relationships to detect when a change to one application may affect others.
If the admin dashboard depends on the admin API, a change to the admin API's public contracts triggers a scope report that includes the dashboard as a downstream consumer. This isn't a guess — it's declared in the registry. DevSpark also infers dependencies by scanning import statements and build configuration files for cross-app references, labeling those separately as "inferred" so teams can decide whether to formalize them.
This extends into PR scope governance. When you open a pull request, DevSpark compares the declared scope — is this a single-app change, a cross-app change, or repository-wide infrastructure? — against the actual changed files and the dependency graph. If you say it's a single-app change but the files touch two applications, DevSpark flags the mismatch. No guessing, no silent scope creep.
Shared Libraries and Blast Radius
Not every entry in the registry is a deployable service. Authentication modules, API contracts, utility packages — these are modeled as library entries that participate in dependency tracking but aren't valid targets for deployment workflows.
This matters because shared library changes are often the highest-risk modifications in a monorepo. When the shared authentication module changes, DevSpark's dependency graph identifies every service that consumes it, surfacing the full blast radius before the PR is reviewed. Without this, a "small" change to a shared utility can silently break three production services.
Backward Compatibility — The Non-Negotiable Constraint
DevSpark already had hundreds of single-app users when monorepo support was designed. Breaking their workflows was not an option. Multi-app support is entirely opt-in. Repositories without a registry file continue to work exactly as they do today — no directory restructure, no configuration changes, no behavioral differences. A repository enters multi-app mode only when .documentation/devspark.json is created, either manually or through the /devspark.add-application command.
Three dedicated commands handle monorepo management: /devspark.add-application for registering new apps through a guided workflow, /devspark.list-applications for viewing the full registry, and /devspark.validate-registry for confirming everything is consistent. All three are optional — single-app repos never need them.
What Didn't Make the Cut — and Why
Several alternative approaches were evaluated during design. Installing a separate DevSpark instance per application would duplicate framework files and create upgrade drift. Using a single repo-wide constitution with no per-app overrides wouldn't reflect the real operational differences between production APIs and QA tooling. Inferring application context from the working directory or branch names would be brittle in CI and unreliable for cross-cutting reviews. And allowing app constitutions to fully override repo-wide governance would destroy the meaning of having repo-wide governance in the first place.
The layered model — explicit registry, additive governance, dependency-aware scope — avoids the worst trade-offs of each alternative. It's more work to set up than convention-based approaches, but it's less work to maintain than the patchwork of exceptions that conventions inevitably become.
App lifecycle commands (remove, rename, move, split) and shared package release orchestration are real needs that were deferred from the initial release. The foundation had to ship first. Registry validation, layered governance, and scope analysis address the most painful monorepo problems today — lifecycle management builds on top once the patterns are proven.
Getting Started
For teams ready to try monorepo support, the path is straightforward: register your first application with /devspark.add-application, repeat for each additional app, validate with /devspark.validate-registry, and start using --app {id} when running DevSpark workflows to scope them to a specific application.
The DevSpark Monorepo Guide covers the full specification — registry schema, profile composition rules, PR scope validation, on-disk layout, and working examples of everything discussed in this article.
Explore More
- DevSpark v0.1.0: Agent-Agnostic, Multi-User, and Built for Teams -- How canonical prompts, thin shims, and per-user personalization let team
- Why I Built DevSpark -- Building the tool I needed to survive the reality of brownfield developm
- Getting Started with DevSpark: Requirements Quality Matters -- Enforcing requirements quality before code generation
- DevSpark: Constitution-Driven AI for Software Development -- DevSpark aligns AI coding agents with project architecture and governanc
- DevSpark: Constitution-Based Pull Request Reviews -- How a well-written constitution for your codebase can power automated co
