Chapter 6: Setting Hard Boundaries: The Art of Explicit Scope Exclusion
By Muhammad Riaz
The "Helpful AI" Paradox
Large Language Models are fine-tuned via Reinforcement Learning from Human Feedback (RLHF) to be helpful, polite, and thorough. In conversational assistant contexts, these traits make models pleasant to interact with.
In automated software development, however, this eagerness to please becomes a distinct engineering liability: The "Helpful AI" Paradox.
When you prompt an AI coding assistant to build a feature without specifying hard boundaries, the model assumes that "completeness" requires building everything adjacent to the request.
-
Ask it to build a user profile form, and it generates a custom avatar image-cropping tool, installs an unrequested file-upload SDK, and writes an inline email validator.
-
Ask it to handle a simple Redis cache lookup, and it builds a custom full-blown micro-framework for cache invalidation, fallback tiers, and telemetry reporting.
This behavior is not a bug; it is an intrinsic property of autoregressive language generation. An LLM predicts the most statistically probable continuation of your request based on its massive training corpusβwhere full-stack tutorials and open-source frameworks bundle UI, business logic, abstractions, and dependencies together.
To keep AI agents on task, human software architects must master The Art of Explicit Scope Exclusion.
The Three Pillars of Scope Boundaries
Explicit Scope Exclusion is the discipline of defining what the AI is strictly forbidden from doing. It constructs a virtual sandbox around the AI agent, restricting its execution across three dimensions:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β THE THREE BOUNDARY PILLARS β
β β
β 1. DEPENDENCY BOUNDARIES ββ> Prohibiting unapproved libraries/packages β
β 2. FILE SYSTEM BOUNDARIES ββ> Restricting file read/write permissions β
β 3. ARCHITECTURAL BOUNDARIESββ> Locking design patterns & abstractions β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Dependency Boundaries: Eliminating Package Sprawl
One of the quickest ways an unguided AI degrades a production codebase is through Dependency Sprawl βinstalling third-party packages to solve minor problems easily handled by standard libraries or existing codebase utilities.
The Risk
Every new package added to package.json, requirements.txt, or Cargo.toml introduces:
-
Security Surface Area: Vulnerabilities in transitive dependencies (e.g., supply chain attacks).
-
Bundle Size Bloat: Increasing cold-start times or client download overhead.
-
Maintenance Overhead: Future framework upgrade conflicts.
Practical Specification Patterns
In your .spec.md file, replace vague instructions with explicit dependency rules:
<!-- BAD: Vague Dependency Instruction -->
"Use a standard library to handle date formatting and JWT parsing."
<!-- GOOD: Explicit Dependency Boundary -->
## Dependency Boundaries (STRICT)
- **ZERO New Dependencies:** The agent MUST NOT run `npm install`, `pip install`, or add any packages to `package.json`.
- **Approved Utilities Only:**
- Date manipulation MUST use native `Intl.DateTimeFormat` or existing app utility `src/utils/date.ts`.
- JWT verification MUST reuse existing utility `src/auth/jwtVerifier.ts`.
- **Violation Action:** Any generated code introducing a new package requirement will be automatically rejected during CI verification.
2. File System Boundaries: Locking Down Directory Access
When an AI agent runs in an autonomous CLI environment (such as Claude Code, Cursor Agent, or custom multi-agent runners), it possesses file system read and write privileges across your repository.
Without strict directory boundaries, an agent tasked with updating an API route might refactor shared global middleware, overwrite database seeds, or alter configuration files in adjacent directories.
The File Impact Map as a Sandbox
In your specification and planning artifacts, define strict file system permissions using three categories:
## File System Boundaries (File Impact Map)
### Permitted Writes (Agent MAY create or edit):
- `src/modules/billing/services/refund.service.ts`
- `tests/modules/billing/refund.service.test.ts`
### Read-Only Context (Agent MAY read, MUST NOT edit):
- `src/modules/billing/types/stripe.types.ts`
- `src/config/database.ts`
### Strictly Forbidden Paths (Agent MUST NOT read or edit):
- `src/core/auth/*`
- `prisma/migrations/*`
- `.env*`
- `.github/workflows/*`
When an agent is prompted with explicit path restrictions, modern tools enforce these boundaries at the tool-calling level, blocking the LLM from executing file-write commands on forbidden targets.
3. Architectural Boundaries: Preventing "Over-Engineering"
AI models tend to introduce abstractionsβsuch as Abstract Factory patterns, generic wrapper interfaces, or deeply nested inheritance hierarchiesβwhen simple, idiomatic code is required.
Architectural boundaries lock the AI into your projectβs established conventions.
Real-World Case Study: Over-Engineered Error Handling
A developer asked an AI agent to add input validation to a user registration form.
-
What the Unbounded AI Built: Created a custom 400-line validation engine with dynamic rule-chaining, custom decorators, and a global event-emitter bus to handle validation errors.
-
What the Codebase Actually Needed: A 15-line Zod schema check matching existing form controllers.
How to Spec Architectural Boundaries
Use the "Anti-Pattern Exclusion" section in your .spec.md:
## Architectural Boundaries & Anti-Pattern Exclusions
- **AP-1 (No Custom Abstractions):** DO NOT create new abstract base classes, generic wrapper types, or custom event buses.
- **AP-2 (Schema Standard):** Input validation MUST use existing Zod schemas in `src/schemas/auth.schema.ts`. DO NOT write custom regex or manual field-by-field validation checks.
- **AP-3 (Error Handling Consistency):** Errors MUST be thrown using the standard application exception classes (`AppError`, `ValidationError`) defined in `src/errors/`. DO NOT use generic `throw new Error()` or return custom error objects.
Crafting "Negative Directives" (The Art of Anti-Prompts)
In prompt engineering, instructions that tell a model what not to do are known as Negative Directives.
Due to how attention mechanisms operate in Transformers, negative directives work best when structured as Explicit Counter-Examples: stating what is forbidden and providing the required alternative immediately.
| Weak Boundary (Vague) | Strong Boundary (Explicit Counter-Example) |
|---|---|
| "Don't write complex code." | Forbidden: Custom caching algorithms. Required: Call cache.get(key) from src/services/redis.ts. |
| "Don't change global styles." | Forbidden: Edits to src/styles/globals.css. Required: Use existing Tailwind CSS utility classes inline. |
| "Avoid hardcoding settings." | Forbidden: String literals or API keys in application logic. Required: Import values from src/config/env.ts. |
Practical Exercises: Boundary Enforcement
-
Conduct a Dependency Audit: Open your current project's package manifest (
package.json,requirements.txt, etc.). Identify how many packages were added by AI tools over the last month that duplicate existing functionality or native capabilities. -
Draft a Sandbox Profile for a Feature: Take a feature currently on your sprint board. Create a 10-line text block titled
ScopeExclusion Checklistthat explicitly lists: - 2 forbidden npm/pip packages. - 3 forbidden directory paths. - 1 architectural pattern to avoid. -
Run a Stress Test: Pass a prompt to your AI tool specifying a feature, accompanied by your
Scope Exclusion Checklist. Observe whether the AI respects the constraints or attempts to bypass them.
Next Steps
Now that you know how to lock down scope, dependencies, and file access, we must address system integrity at the data level.
In Chapter 7, we will explore Contracts, Schemas, and System Invariants βlearning how to define airtight API contracts, JSON schemas, and invariant assertions that force AI tools to write integration-ready code on the first attempt.