This guide provides step-by-step instructions for adopting Harness Engineering practices in your project. Start with Level 1 and progress to higher levels as your team grows and tooling matures.
Time to implement: 1-2 weeks Effort: Moderate (writing documentation) Payoff: 20% improvement in onboarding, agent context
What you get:
- Clear knowledge map (AGENTS.md)
- Organized documentation structure
- Better agent context understanding
Who should start here: All teams
Time to implement: 2-4 weeks (after Level 1) Effort: High (setup and linter configuration) Payoff: 50% reduction in architectural violations, faster reviews
What you get:
- Automated enforcement of architectural rules
- Linter rules for common patterns
- Structural tests for dependencies
Who should start here: Teams building systems with 3+ interconnected services
Time to implement: 4-8 weeks (after Levels 1 & 2) Effort: Very high (agent setup, CI/CD configuration) Payoff: 70%+ agent autonomy, near-zero technical debt
What you get:
- Autonomous agent workflows
- Scheduled cleanup tasks
- Self-correcting development cycle
Who should start here: Teams ready for agent-driven development (after stable Level 2)
Create the documentation directory structure:
mkdir -p docs/{architecture,design-docs,exec-plans,guides}Structure:
docs/
├── core-beliefs.md # Product values, non-negotiables
├── architecture/
│ ├── layers.md # Your dependency model
│ ├── decisions/ # ADRs (Architecture Decision Records)
│ │ ├── 001-monorepo.md
│ │ ├── 002-typescript.md
│ │ └── README.md (index of ADRs)
│ └── diagrams/ # System diagrams (mermaid)
├── design-docs/ # Design before implementation
│ ├── user-authentication.md
│ ├── payment-processing.md
│ └── README.md (index)
├── exec-plans/ # Current work + timeline
│ ├── 2026-q1.md
│ └── current.md
├── guides/ # How to build things
│ ├── adding-a-new-feature.md
│ ├── testing-patterns.md
│ └── README.md (index)
└── standard/ # Harness Engineering Standard
├── index.md
├── principles.md
├── implementation.md
└── kpis.md
Create docs/core-beliefs.md with your team's non-negotiables:
# Core Beliefs
## Quality First
- All code must be tested
- Tests are written before or alongside implementation
- Code review is required for all changes
## Documentation as Code
- Decisions are documented in git
- No knowledge in Slack or shared drives
- README exists for every package/service
## Architectural Integrity
- Dependencies flow one-way (no cycles)
- Each layer has clear responsibilities
- Constraints are enforced mechanically
## Sustainable Pace
- No hero work required
- Features are completed end-to-end before starting next
- Technical debt is paid down weeklyCreate docs/architecture/layers.md:
# Architectural Layers
## Dependency ModelApplication / UI ↓ (imports from) Service Layer (business logic) ↓ Repository Layer (data access) ↓ Config Layer (environment, constants) ↓ Types Layer (shared types, interfaces)
## Layer Descriptions
### Types Layer
- **Location**: `src/types/`
- **Responsibility**: Shared types, interfaces, constants
- **Can import from**: Nothing (no upward imports)
- **Can be imported by**: Everyone
### Config Layer
- **Location**: `src/config/`
- **Responsibility**: Environment setup, configuration
- **Can import from**: Types
- **Can be imported by**: Everyone above
### Repository Layer
- **Location**: `src/repository/`
- **Responsibility**: Data access (database, external APIs)
- **Can import from**: Types, Config
- **Can be imported by**: Service layer only
### Service Layer
- **Location**: `src/services/`
- **Responsibility**: Business logic, orchestration
- **Can import from**: Types, Config, Repository
- **Can be imported by**: Application, other services (if needed)
### Application / UI Layer
- **Location**: `src/app/`, `src/ui/`
- **Responsibility**: User interface, routing, presentation
- **Can import from**: Types, Config, Service
- **Can be imported by**: Nothing (entry point)
## Enforcement
All layers are enforced:
- ESLint rule: `@harness-engineering/no-layer-violation`
- Structural test: `tests/architecture/layers.test.ts`
- Build will fail if violated
Create docs/architecture/decisions/README.md:
# Architecture Decision Records (ADRs)
ADRs document significant architectural decisions made during development.
They capture the "why" behind our choices.
## Format
Each ADR is a markdown file named `NNN-decision-title.md` where NNN is a sequence number.
## Template
```markdown
# ADR-001: Use TypeScript
## Context
We're building a microservice that will be maintained by multiple teams.
We need strong typing and IDE support.
## Decision
We will use TypeScript as our primary language.
## Rationale
- Type safety reduces bugs in production
- IDE support improves developer experience
- TypeScript compiles to JavaScript for deployment
## Consequences
- Build step required (TS → JS compilation)
- Team members need to learn TypeScript
- Slightly larger bundle size
## Alternatives Considered
- Python: Less suitable for type safety at scale
- Go: Would require rewriting supporting libraries
## Related Decisions
- ADR-002: Use Node.js runtime
- ADR-003: ESLint for linting
```- Create new file:
docs/architecture/decisions/NNN-title.md - Use template above
- Get review from architecture team
- Merge to main branch (archived for reference)
Create your first few ADRs:
- `001-why-monorepo.md` - Explain your repo structure
- `002-why-typescript.md` (or your language) - Explain tech stack
- `003-layered-architecture.md` - Explain your dependency model
### Step 5: Create AGENTS.md Knowledge Map
Create top-level `AGENTS.md` (from project root):
```markdown
# AGENTS.md - Knowledge Map
This file helps AI agents and new team members navigate the project.
Read this first to understand where to find information.
## About This Project
[Brief description: 2-3 sentences about what your project does]
## Core Documentation
**Must Read First**:
- Project vision and values: [docs/core-beliefs.md](docs/core-beliefs.md)
- How the project is organized: [docs/README.md](docs/README.md) (if exists)
**For Architecture Questions**:
- Layer definitions and dependency rules: [docs/architecture/layers.md](docs/architecture/layers.md)
- Why we made specific choices: [docs/architecture/decisions/](docs/architecture/decisions/)
**For Implementation Questions**:
- Design before starting work: [docs/design-docs/](docs/design-docs/)
- Step-by-step guides: [docs/guides/](docs/guides/)
- Examples: [examples/](examples/)
## Current Work
**What are we building now?**
- Current quarter plan: [docs/exec-plans/2026-q1.md](docs/exec-plans/2026-q1.md)
- Active issues: GitHub Issues (filter by `status:in-progress`)
## Code Structure
src/ ├── types/ # Shared types and interfaces ├── config/ # Configuration ├── repository/ # Data access layer ├── services/ # Business logic └── app/ # Application / UI
See [docs/architecture/layers.md](docs/architecture/layers.md) for full details.
## Development Workflow
1. Pick a task from [current work](docs/exec-plans/current.md)
2. Read relevant design doc if exists
3. Create feature branch: `feature/what-youre-building`
4. Follow patterns in [docs/guides/](docs/guides/)
5. Write tests alongside code
6. Open PR with self-review checklist (see template below)
**Self-Review Checklist Template** (include in PRs):
```markdown
## Self-Review
- [ ] Tests pass locally
- [ ] No linting errors
- [ ] No architectural violations (layers)
- [ ] Documentation updated if needed
- [ ] Commit message is clear
- Design doc: docs/design-docs/
- Implementation guide: docs/guides/adding-a-new-feature.md
- Example: examples/
- README.md - Clone and install
- docs/guides/local-setup.md - Detailed setup
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # With coverage- Questions about architecture? file an issue
- Need help? Check discussions
- Found a bug? Report it
- Package manager: pnpm
- Runtime: Node.js 22+
- Language: TypeScript 5.0+
- Linting: ESLint + Prettier
- Testing: Jest
- Monorepo tool: Turborepo
### Step 6: Create Implementation Guides
Create `docs/guides/adding-a-new-feature.md`:
```markdown
# Adding a New Feature
This guide walks through adding a complete feature end-to-end.
## Overview
A complete feature includes:
1. Design document
2. Implementation code with tests
3. Updated documentation
4. Deployment to staging/production
## Step 1: Write a Design Document
Create `docs/design-docs/your-feature.md`:
```markdown
# Design: Your Feature Name
## Problem
What problem are we solving?
## Proposed Solution
How will we solve it?
## Implementation Plan
1. Create service in `src/services/your-feature/`
2. Add API endpoint
3. Write tests
4. Deploy
## Testing Strategy
How will we verify this works?
## Risks & Mitigations
What could go wrong? How will we prevent it?
## Alternatives Considered
What other approaches did we consider?
src/services/your-feature/
├── index.ts # Main export
├── your-feature.service.ts
├── your-feature.test.ts
└── README.md
// your-feature.test.ts
describe('YourFeatureService', () => {
it('should create a thing', () => {
const result = yourFeatureService.create({...});
expect(result).toBeDefined();
});
});// your-feature.service.ts
export const yourFeatureService = {
create(input: Input): Result<Output, Error> {
// Validation
const validated = inputSchema.safeParse(input);
if (!validated.success) {
return { ok: false, error: validated.error };
}
// Implementation
const result = doWork(validated.data);
// Return result
return { ok: true, value: result };
},
};# Your Feature Service
## Overview
What does this service do?
## API
### `create(input: Input): Result<Output, Error>`
Create a new thing.
**Parameters**:
- `input.name` (string): Name of the thing
**Returns**:
- Success: `{ ok: true, value: Output }`
- Failure: `{ ok: false, error: Error }`
**Example**:
```typescript
const result = yourFeatureService.create({ name: 'My Thing' });
if (result.ok) {
console.log('Created:', result.value);
} else {
console.error('Failed:', result.error);
}
```Run tests: npm test -- your-feature.test.ts
## Step 3: Update AGENTS.md
Add your new feature to the knowledge map:
```markdown
## Features
- Your feature: [src/services/your-feature/](src/services/your-feature/)
Design doc: [docs/design-docs/your-feature.md](docs/design-docs/your-feature.md)
Include self-review checklist:
## Self-Review
- [ ] Design doc written and approved
- [ ] Implementation matches design
- [ ] Tests pass (>80% coverage for this feature)
- [ ] No architectural violations
- [ ] Documentation updated (README.md, design-docs, AGENTS.md)
- [ ] No linting errors
### Step 7: Set Up Documentation Navigation
Update root `README.md` to point to documentation:
```markdown
# [Your Project Name]
[Brief description]
## Quick Start
[Setup instructions]
## Documentation
- **New to the project?** Start with [AGENTS.md](AGENTS.md)
- **Want to understand our architecture?** Read [docs/architecture/layers.md](docs/architecture/layers.md)
- **Building a new feature?** Follow [docs/guides/adding-a-new-feature.md](docs/guides/adding-a-new-feature.md)
- **Looking for decisions made?** Check [ADRs](docs/architecture/decisions/)
[Other sections...]
Checklist:
-
docs/core-beliefs.mdcreated and reviewed -
docs/architecture/layers.mddocuments your layer model - 3-5 ADRs created (
docs/architecture/decisions/) -
AGENTS.mdcreated at project root -
docs/guides/adding-a-new-feature.mdprovides implementation guidance - All links in AGENTS.md and guides are valid
- README.md points to documentation
Test: Can a new team member read AGENTS.md and find what they need to get started?
Install dependencies:
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-pluginCreate .eslintrc.json:
{
"parser": "@typescript-eslint/parser",
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/no-explicit-any": "error",
"no-var": "error",
"prefer-const": "error",
"eqeqeq": ["error", "always"]
},
"overrides": [
{
"files": ["src/services/**/*.ts"],
"rules": {
"@harness-engineering/no-forbidden-imports": "error"
}
}
]
}Add to package.json:
{
"scripts": {
"lint": "eslint src/ --ext .ts",
"lint:fix": "eslint src/ --ext .ts --fix"
}
}Create eslint-rules/no-layer-violations.js:
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Enforce layer dependencies',
},
},
create(context) {
return {
ImportDeclaration(node) {
const fileName = context.getFilename();
const importPath = node.source.value;
// Check: Service cannot import from UI
if (fileName.includes('services/') && importPath.includes('ui/')) {
context.report({
node,
message: 'Service layer cannot import from UI layer',
});
}
// Check: Repository cannot import from Service
if (fileName.includes('repository/') && importPath.includes('services/')) {
context.report({
node,
message: 'Repository layer cannot import from Service layer',
});
}
// Add more layer rules as needed
},
};
},
};Create tests/architecture/circular-deps.test.ts:
import { detectCircularDepsInFiles } from '@harness-engineering/core';
import { glob } from 'glob';
import * as path from 'path';
describe('Architecture: Circular Dependencies', () => {
it('should have no circular dependencies', async () => {
const srcDir = path.join(__dirname, '../../src');
const files = await glob('**/*.ts', { cwd: srcDir, absolute: true });
const result = await detectCircularDepsInFiles(files, parser);
expect(result.ok).toBe(true);
if (result.ok) {
expect(result.value.cycles).toEqual([]);
}
});
});Create tests/architecture/layers.test.ts:
import { defineLayer, validateDependencies } from '@harness-engineering/core';
describe('Architecture: Layers', () => {
const layers = [
defineLayer({ name: 'ui', path: 'src/ui', allowedDependencies: ['services', 'types'] }),
defineLayer({ name: 'services', path: 'src/services', allowedDependencies: ['types'] }),
defineLayer({ name: 'types', path: 'src/types', allowedDependencies: [] }),
];
it('should have no layer violations', async () => {
const result = await validateDependencies({
layers,
rootDir: path.join(__dirname, '../../'),
parser,
});
expect(result.ok).toBe(true);
if (result.ok) {
expect(result.value.violations).toHaveLength(0);
}
});
});Create .github/workflows/architecture.yml:
name: Architecture Validation
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install
- run: npm run lint
architecture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install
- run: npm run test -- architecture/Create schema for API boundaries:
// src/services/user/user.schema.ts
import { z } from 'zod';
export const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
createdAt: z.date(),
});
export type User = z.infer<typeof UserSchema>;Use schema in API:
// src/app/api/users.ts
export async function getUser(req: Request) {
try {
const id = req.params.id;
const user = await userService.getById(id);
// Validate at boundary before returning
const validated = UserSchema.parse(user);
return res.json(validated);
} catch (error) {
return res.status(400).json({ error: error.message });
}
}Checklist:
- ESLint configured and passing
- Custom linter rules created for layer violations
- Structural tests for circular dependencies pass
- Boundary validation schemas created
- CI/CD validation added to GitHub Actions
- All PRs run architecture validation
- Documentation updated: docs/architecture/enforcement.md
Test: Try to violate a constraint (e.g., import from UI in services). CI should fail.
Create PR template (.github/pull_request_template.md):
## Description
[What changes are in this PR?]
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Refactoring
## Self-Review Checklist
- [ ] Tests pass (`npm test`)
- [ ] Linting clean (`npm run lint`)
- [ ] No architectural violations (layers)
- [ ] Documentation updated (AGENTS.md, guides, comments)
- [ ] No hardcoded secrets or sensitive data
- [ ] Performance: No N+1 queries or obvious regressions
- [ ] Error handling is comprehensive
- [ ] Commit messages are clear and follow conventions
## Peer Review Requested From
- [ ] @architecture-enforcer (for architectural changes)
- [ ] @documentation-maintainer (if docs changed)
- [ ] @test-reviewer (for significant logic changes)
## How to Test
[Instructions for reviewer to verify changes]
## Screenshots (if applicable)
[Add screenshots for UI changes]
## Notes for Reviewer
[Any context reviewer should know?]Create scripts/cleanup.sh:
#!/bin/bash
set -e
echo "Running cleanup checks..."
# Check for documentation drift
echo "Checking for doc drift..."
npm run check-doc-drift
# Check for dead code
echo "Checking for dead code..."
npm run detect-dead-code
# Check for pattern violations
echo "Checking for pattern violations..."
npm run check-patterns
echo "Cleanup checks passed!"Create GitHub Action (.github/workflows/cleanup.yml):
name: Weekly Cleanup
on:
schedule:
- cron: '0 2 * * 0' # Every Sunday at 2 AM
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install
- name: Run cleanup checks
run: npm run cleanup
- name: Create cleanup PR if needed
if: failure()
run: |
git config user.name "cleanup-bot"
git config user.email "cleanup@example.com"
git checkout -b cleanup/weekly
git add -A
git commit -m "chore: automated cleanup" || true
git push origin cleanup/weekly
# TODO: Create PR via GitHub APICreate telemetry configuration:
// src/telemetry.ts
// Note: harness does not ship an OpenTelemetry adapter.
// Use the @opentelemetry/sdk-node package directly for OTEL integration.
import { NodeSDK } from '@opentelemetry/sdk-node';
const sdk = new NodeSDK({
serviceName: 'your-service',
});
sdk.start();Use telemetry in agent feedback:
// src/feedback.ts
export async function reportAgentAction(action: AgentAction) {
const result = await logAgentAction(action);
if (!result.ok) {
console.error('Failed to log agent action:', result.error);
}
}Create agents/personas/architecture-enforcer.json:
{
"name": "Architecture Enforcer",
"role": "Validate architectural constraints on PRs",
"description": "Reviews PRs for layer violations, circular dependencies, and constraint breaches",
"skills": ["enforce-architecture", "check-mechanical-constraints"],
"triggers": ["on_pr"],
"tools": ["linter", "dependency-analyzer", "structural-tests"],
"reviewTargets": ["services", "repository", "config"],
"failurePolicy": "comment_and_request_changes"
}Create agents/personas/documentation-maintainer.json:
{
"name": "Documentation Maintainer",
"role": "Ensure documentation stays in sync with code",
"description": "Detects documentation drift and proposes updates",
"skills": ["detect-doc-drift", "align-documentation"],
"triggers": ["on_pr"],
"tools": ["doc-analyzer", "code-parser"],
"reviewTargets": ["all"],
"failurePolicy": "comment_with_suggestions"
}Create .github/workflows/agent-review.yml:
name: Agent Review
on: [pull_request]
jobs:
agent-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install
- name: Run architecture review
run: npm run agent-review -- --type architecture-enforcer
continue-on-error: true
- name: Run documentation review
run: npm run agent-review -- --type documentation-maintainer
continue-on-error: true
- name: Comment on PR
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '⚠️ Agent review found issues. Please check the logs above.'
})Checklist:
- PR template created with self-review checklist
- Cleanup agent running on schedule (weekly)
- Telemetry integration working
- Agent personas configured
- GitHub Action for agent review set up
- Agents can successfully review and comment on PRs
- Documentation updated: docs/guides/agent-feedback.md
Test: Create a PR with a constraint violation. Verify agent review catches it.
These conventions are referenced by skills and workflows. They are not mechanically enforced yet — they are documented standards that agents follow by convention. Future workflow gates (see the research roadmap) may add mechanical enforcement.
Convention: At phase boundaries (between skills, between milestones, between agent sessions), write a structured handoff document to .harness/handoff.md.
Purpose: When one skill/phase completes and another begins, context is lost. The handoff file preserves what was done, what was discovered, what's blocked, and what should happen next. Subsequent skills read this file as input context.
Schema:
# Handoff: [phase/skill name]
## Completed
- [what was done, with file paths]
- Example: Created `src/services/auth.ts` with JWT validation logic
- Example: Updated `docs/guides/authentication.md` with new flow diagram
## Discovered
- [unexpected findings, edge cases, dependencies found]
- Example: The existing UserService has a circular dependency with AuthService
- Example: Rate limiting is not implemented on the /login endpoint
## Blocked
- [what couldn't be completed and why]
- Example: Cannot add Redis caching — redis client package not in dependencies
- Example: Integration test requires database seed data that doesn't exist yet
## Test Results
- [pass/fail summary with command output]
- Example: 14/14 unit tests passing
- Example: 2/3 integration tests passing — `test-login-rate-limit` skipped (see Blocked)
## Next Steps
- [what the next skill/phase should do]
- Example: Run `harness-code-review` on the auth service changes
- Example: Address the circular dependency before adding cachingWhen to write a handoff:
- After completing a skill invocation that produces artifacts (code, docs, config)
- After a long-running agent session that spans multiple tasks
- When pausing work that another agent or session will resume
- After debugging sessions that discovered unexpected state
How skills use it:
- Skills that produce output write
.harness/handoff.mdas their final step - Skills that consume context read
.harness/handoff.mdas their first step (if it exists) - Each handoff overwrites the previous one — it captures the current state, not history
- For historical context, the anti-pattern log (below) and git history serve as the record
Convention: Maintain an append-only log at .harness/anti-patterns.md that records failed approaches, dead ends, and lessons learned during agent work.
Purpose: Agents exploring solutions (debugging, refactoring, architectural decisions) often try approaches that fail. Without a record, the same dead-end gets explored repeatedly — across sessions, across agents, across team members. The anti-pattern log prevents this waste.
Schema:
## [YYYY-MM-DD] [skill name]: [brief description]
**Tried:** [what was attempted]
**Failed because:** [why it didn't work]
**What worked instead:** [the successful approach]Example entries:
## 2026-03-15 harness-debugging: Fix circular dependency in auth module
**Tried:** Moved shared types into a `common/` directory and re-exported from both services.
**Failed because:** The re-export created an implicit dependency cycle that TypeScript caught at compile time — `common/` imported a type that transitively depended on `auth/`.
**What worked instead:** Extracted the shared interface into `src/types/auth-types.ts` (Types layer) with zero upward dependencies. Both services import from the Types layer, following the dependency model.
## 2026-03-14 harness-execution: Add Redis caching to user service
**Tried:** Used `ioredis` with default connection pooling.
**Failed because:** The test environment doesn't have Redis running, and the `ioredis` mock library doesn't support the `pipeline()` method we needed.
**What worked instead:** Created a `CachePort` interface in the Repository layer and a `RedisCacheAdapter` that implements it. Tests use an `InMemoryCacheAdapter`. The adapter pattern lets us swap implementations without changing service code.Rules:
- Append-only: Never delete entries. The history is the value.
- Skills read at start: Before exploring a solution, check if a similar approach was already tried and failed.
- Skills append at end: After recovering from a failed approach, record what happened.
- Keep entries brief: 3-5 sentences per entry. Link to relevant files instead of pasting code.
- Date and skill name are required: These make it searchable and attributable.
What belongs in the anti-pattern log:
- Failed debugging approaches
- Architectural dead ends
- Library/tool incompatibilities discovered
- Configuration mistakes and their fixes
- Performance optimizations that didn't work
What does NOT belong:
- Successful approaches (those go in handoff docs and git history)
- General best practices (those go in
docs/guides/best-practices.md) - Opinions or preferences (those go in ADRs)
Convention: Maintain a calibration file at .harness/review-learnings.md that records what review findings are valuable versus noisy for a specific project.
Purpose: Code review produces findings. Some findings catch real bugs; others are noise (project-specific patterns flagged as issues). Without calibration, the review skill wastes attention on known false positives and misses project-specific priorities.
Schema:
# Review Learnings
## Useful Findings
- [category]: [example] — [why this was valuable]
## Noise / False Positives
- [category]: [example] — [why this wasn't helpful]
## Calibration Notes
- [specific guidance for this project]Example:
# Review Learnings
## Useful Findings
- error-handling: Missing catch in async pipeline — caused silent failures in production
- type-safety: Implicit any in service boundaries — led to runtime type mismatches
- test-coverage: Untested error paths in payment flow — caught a real bug
## Noise / False Positives
- naming: Flagging single-letter variables in test helpers — these are conventional (e.g., `t`, `e`)
- error-handling: Missing error handling in CLI scripts — these exit on error by design
- docs: Missing JSDoc on internal utility functions — we document at module level, not function level
## Calibration Notes
- This project uses Result types everywhere — do not flag missing try/catch in functions that return Result<T, E>
- Test helpers intentionally use loose types for ergonomics — do not flag missing type annotations in test/
- The CLI package uses process.exit() intentionally — do not flag as an anti-patternMaintenance: Append new entries after each review cycle. Periodically prune entries that are no longer relevant (e.g., after a major refactor changes the codebase patterns).
Track adoption with these metrics:
# Lines of documentation / lines of code
docs_lines=$(find docs -name "*.md" -not -path "*/node_modules/*" | xargs wc -l | tail -1 | awk '{print $1}')
code_lines=$(find src -name "*.ts" | xargs wc -l | tail -1 | awk '{print $1}')
echo "Context Density: $(echo "scale=2; $docs_lines / $code_lines" | bc)"# Count enforced rules vs total rules
echo "Enforced rules: $(grep -r 'error' .eslintrc.json | wc -l)"
echo "Total rules: [manual count from all configs]"Track via GitHub:
- Count PRs where all commits are from bots (GitHub Actions, linter fixes)
- Calculate: (bot_commits / total_commits) * 100
Solution: Set up doc drift detection in cleanup agent
npm run detect-doc-driftProposes PRs when docs don't match code.
Solution: Create exceptions via ADR
- Document exception in
docs/architecture/decisions/NNN-exception.md - Add eslint-disable comment with ADR reference
- Maintain exception count (trend should decrease)
Solution: Ensure patterns are documented + mechanically enforced
- Design doc explains the pattern
- Examples in
/examples/show correct usage - Linter rule prevents wrong usage
- Structural test validates at build time
- Start with Level 1 - Documentation and AGENTS.md
- Validate with early adopters - Get feedback before Level 2
- Progress to Level 2 - Linters and mechanical constraints
- Measure KPIs - Context density, harness coverage, agent autonomy
- Progress to Level 3 - Agent feedback loop and entropy management
← Back to Principles | KPIs & Metrics →
Last Updated: 2026-03-16