Part 04 of 13

The Build Plan

Code rules as testable assertions, agent instruction files, and a Master PRD Index that decomposes 150+ features into a sequenced build order.

~8 minute read

Code Rules: The Constraint System

AI agents follow rules. But they only follow rules they can read. The constraint system is a set of files, checked into the repo, that every agent reads before writing code. Without these files, each agent session invents its own conventions.

There are two types of rule files: RULES.md (for the codebase) and CLAUDE.md or equivalent (for the AI agent's behavior).

RULES.md: Per-Package Constraints

Every package in the monorepo has its own RULES.md. The root RULES.md defines global constraints. Package-level files define local constraints. The agent reads both before working in that package.

What Makes a Good Rule

Every rule must be a testable assertion. Not "keep things organized" but "apps import from packages, never from other apps." The first is a suggestion. The second can be verified by a linter, an import restriction, or an architectural fitness test.

Linear Example: Root RULES.md
# Root Rules

## Import Boundaries
- Apps import from packages, never from other apps.
- packages/api is the sole bridge to infrastructure.
  Apps never import packages/db directly.
- packages/ui owns all shared UI components.
  No component is defined in an app directory.
- packages/ai is the sole LLM gateway.
  No app calls OpenAI/Anthropic directly.

## Tenant Isolation
- Every table with user data has a workspace_id column.
- Every query uses workspaceDb(workspaceId), never the raw db.
- Every tRPC mutation validates the resource belongs to
  the current workspace before modifying it.

## Naming Conventions
- Database tables: snake_case plural (issues, projects, cycles)
- TypeScript types: PascalCase (Issue, Project, Cycle)
- tRPC routers: camelCase (issue.list, issue.create)
- File names: kebab-case (issue-list.tsx, create-issue.ts)
- CSS tokens: kebab-case with double-dash (--color-accent)

## Testing
- No shallow assertions: toBeDefined(), toBeTruthy(),
  toBeFalsy() are banned as standalone assertions.
- Every async test uses expect.assertions(N).
- Every DB test verifies state with an independent query.
- Every new table has a tenant isolation test.
Linear Example: packages/db/RULES.md
# Database Package Rules

## Migrations
- Migrations are forward-only. No down migrations.
- If a migration needs reverting, write a new forward
  migration that undoes the change.

## Schema
- Every table has: id (uuid), workspace_id (uuid),
  created_at (timestamptz), updated_at (timestamptz).
- Use timestamptz, never timestamp (timezone-naive).
- Soft delete: use archived_at (timestamptz), never
  delete rows.

## RLS
- Every new table must have an RLS policy:
  workspace_id = current_setting('app.workspace_id')::uuid
- RLS is enabled on the table, not just defined.

Agent Instruction Files

Agent instruction files (CLAUDE.md for Claude Code, .cursorrules for Cursor, etc.) tell the AI agent how to behave in this specific project. They are different from code rules: code rules constrain what the code does, agent instructions constrain how the agent works.

What Agent Instructions Cover

Tiered Structure

Agent instructions are tiered: root-level for global behavior, directory-level for package-specific behavior. The agent reads both, with local instructions overriding global ones for that directory.

# Repository structure of agent instructions
.claude/           or equivalent for your agent
  CLAUDE.md        Root: global behavior, commands, project overview

packages/db/
  CLAUDE.md        DB-specific: migration workflow, schema conventions

packages/api/
  CLAUDE.md        API-specific: router patterns, error handling

packages/ui/
  CLAUDE.md        UI-specific: component structure, token usage, accessibility
Keep root instructions under 10,000 words. Agent instructions consume context window tokens. Bloated instructions leave less room for the actual task. Be specific and concise. Use tiered files so only relevant instructions load for the current working directory.

The Master PRD Index

The Master PRD Index is the complete roadmap. Every feature is a named unit with an ID, milestone assignment, category, dependencies, and test pair. This is the document that answers: "What do I build next?"

Structure

The index is organized by milestone. Each milestone has a name, a theme, and a list of units. Each unit has:

FieldDescription
IDUnique identifier: M[milestone]-U[number]. Example: M1-U03.
TitleDescriptive name: "Issue List View," "Notification Engine."
CategoryFrontend, Backend, or Full Stack.
Depends OnUnit IDs that must be complete before this unit starts.
Test PairWhich unit verifies this one (backend tested by its frontend unit).
StatusNot started, PRD written, Verified, In progress, Complete.
Linear Example: Master PRD Index (M0 and M1)

M0: Foundation (Auth + Workspace)

IDTitleCatDepends
M0-U01Auth Backend (Clerk integration)BackendNone
M0-U02Workspace CRUDBackendM0-U01
M0-U03Team CRUDBackendM0-U02
M0-U04Member Roles and PermissionsBackendM0-U02
M0-U05Auth UI (Login, Signup, Invite)FrontendM0-U01
M0-U06Workspace Settings UIFrontendM0-U02, M0-U05
M0-U07Team Settings UIFrontendM0-U03, M0-U05
M0-U08App Shell (Sidebar, Layout, Navigation)FrontendM0-U05

M1: Issue Data Model + List Views

IDTitleCatDepends
M1-U01Issue Data Model (tables, schema)BackendM0-U03
M1-U02Issue CRUD APIBackendM1-U01
M1-U03Issue List ViewFrontendM1-U02, M0-U08
M1-U04Issue Detail PageFrontendM1-U02, M0-U08
M1-U05Issue Filters and Saved ViewsFull StackM1-U03
M1-U06Issue Relations (blocks, related)BackendM1-U01
M1-U07Bulk ActionsFull StackM1-U03
M1-U08Comments and Activity FeedFull StackM1-U04
M1-U09M1 Integration TestsFull StackAll M1
M1-U10M1 ConsolidationFull StackM1-U09

Note that every milestone ends with an Integration Test unit and a Consolidation unit. These are not optional. They are first-class units in the build plan.

Sequencing Strategy

The build order follows three principles:

1. Backend before frontend. The API must exist before the UI can consume it. Backend units create tables, routers, and business logic. Frontend units create components that call those routers.

2. Core before periphery. Auth and workspace management before features. CRUD before advanced views. Data model before reporting.

3. Integration test + consolidation per milestone. Every milestone ends with cross-unit integration tests and a refactoring pass. This prevents technical debt from compounding across milestones.

The critical path is visible. By looking at the dependency graph, you can identify the longest chain of sequential units. This is the critical path. Parallelize everything that is not on it. In the Linear example, the critical path for M1 is: M0-U01 > M0-U02 > M0-U03 > M1-U01 > M1-U02 > M1-U03. Everything else (settings UI, roles, app shell) can be built in parallel.

What You Leave With

DocumentSizeKey Output
Root RULES.md1-2 pagesGlobal constraints: import boundaries, naming, testing, tenant isolation
Package RULES.md (per package)0.5-1 page eachPackage-specific constraints: migration rules, router patterns, component structure
Agent instruction files1-3 pages eachAgent behavior: read-before-working, commands, patterns, prohibitions
Master PRD Index5-15 pagesEvery unit across all milestones with IDs, dependencies, categories, status

This completes the foundation layer. You now have: product definition (Part 1), infrastructure decisions (Part 2), visual language (Part 3), and build plan (Part 4). Everything a PRD needs to reference exists. Part 5 begins the building phase: writing PRDs that AI agents can execute.