Mother Code DNA: Making Your Codebase Self-Aware
Mother Code DNA Documentation Drift Detection DependenciesEvery file in your codebase has a story. What it does. What depends on it. What would break if you changed it. But that story lives in one place: the heads of the developers who wrote it. When they leave, the story leaves with them.
Mother Code DNA is Thuban's answer to that problem. It's a structured comment block — embedded directly in each source file — that records the file's purpose, its dependencies, its dependents, and its blast radius. Think of it as a passport for every file in your codebase.
It's not generated documentation that lives in a wiki nobody reads. It's inline, machine-readable, version-controlled metadata that travels with the code and can be validated on every commit.
What Does a DNA Block Look Like?
A Mother Code DNA block is a structured comment at the top of a file. Here's a real example:
/**
* @thuban-dna
* @purpose Handles Stripe webhook events for subscription lifecycle
* @owner payments-team
* @created 2026-03-15
* @last-verified 2026-06-28
*
* @depends-on
* - src/services/stripe.ts (Stripe client initialisation)
* - src/models/subscription.ts (Subscription DB model)
* - src/utils/logger.ts (Structured logging)
* - src/config/billing.ts (Plan definitions, price IDs)
*
* @depended-by
* - src/routes/webhooks.ts (Mounts this handler at /webhooks/stripe)
* - src/jobs/sync-subscriptions.ts (Calls verifyWebhookSignature)
*
* @would-break
* - Changing the export signature breaks webhooks.ts route mounting
* - Removing verifyWebhookSignature breaks sync-subscriptions job
* - Changing event type strings breaks Stripe webhook filtering
*
* @ai-generated partial (handleInvoicePaid was Copilot-generated, reviewed 2026-04-02)
* @complexity high
* @test-coverage 84%
*/
Every field is intentional. Let's break them down.
The Anatomy of a DNA Block
@purpose
A one-line description of what this file does. Not what it is (that's the filename), but what it does. This is the field that new developers read first when they open a file they've never seen before.
Good: “Handles Stripe webhook events for subscription lifecycle”
Bad: “Stripe webhook handler” (too vague — what aspect of Stripe? What lifecycle events?)
@depends-on
A list of files this file imports from or relies on. Not every import — just the meaningful ones. Utility libraries like lodash don't need to be listed. But your Stripe client initialisation, your database models, your config files — those are the dependencies that matter.
* @depends-on
* - src/services/stripe.ts (Stripe client initialisation)
* - src/models/subscription.ts (Subscription DB model)
* - src/utils/logger.ts (Structured logging)
* - src/config/billing.ts (Plan definitions, price IDs)
Each entry includes a parenthetical note explaining why the dependency exists. This is critical. Knowing that billing.ts is a dependency tells you nothing. Knowing it provides “plan definitions and price IDs” tells you exactly what would break if someone refactored it.
@depended-by
The reverse of @depends-on. Which files import from this file? This is the field that answers the question every developer asks before refactoring: “What will I break if I change this?”
* @depended-by
* - src/routes/webhooks.ts (Mounts this handler at /webhooks/stripe)
* - src/jobs/sync-subscriptions.ts (Calls verifyWebhookSignature)
Without this field, a developer has to grep the entire codebase to find out who imports from this file. With it, the answer is right there in the file header.
@would-break
The most valuable field in the entire DNA block. It lists the specific changes that would cause downstream failures. Not “changing this file might break things” — but exactly what changes cause exactly what breakage.
* @would-break
* - Changing the export signature breaks webhooks.ts route mounting
* - Removing verifyWebhookSignature breaks sync-subscriptions job
* - Changing event type strings breaks Stripe webhook filtering
This is institutional knowledge that normally lives in a senior developer's head. When it's written down in the file itself, it survives team turnover, reorgs, and the inevitable “I'll just refactor this quickly” moment at 4pm on a Friday.
@ai-generated
Records whether the file (or parts of it) were AI-generated, and whether that code was reviewed. This field feeds directly into the AI Slop Index calculation.
* @ai-generated partial (handleInvoicePaid was Copilot-generated, reviewed 2026-04-02)
* @ai-generated full (entire file generated by Claude, reviewed 2026-05-10)
* @ai-generated none
@owner, @complexity, @test-coverage
Metadata fields that round out the picture. @owner identifies the team responsible. @complexity is a human assessment (low/medium/high) that helps prioritise review effort. @test-coverage records the last known coverage percentage for this file.
Why Not Just Use JSDoc / Docstrings?
JSDoc documents APIs. Mother Code DNA documents relationships. They solve different problems.
| Feature | JSDoc / Docstrings | Mother Code DNA |
|---|---|---|
| Documents function signatures | Yes | No |
| Documents file purpose | Rarely | Always |
| Maps dependencies | No | Yes |
| Maps reverse dependencies | No | Yes |
| Records blast radius | No | Yes |
| Tracks AI generation status | No | Yes |
| Machine-readable | Yes | Yes |
| Validates against reality | No | Yes (via Thuban) |
You should use both. JSDoc for your public API surface. Mother Code DNA for your file-level architecture.
Drift Detection: When DNA Goes Stale
Documentation rots. Everyone knows this. The README says the app runs on port 3000 but it was changed to 8080 six months ago. The architecture diagram shows a microservice that was merged back into the monolith.
Mother Code DNA has the same problem — unless you validate it. That's where Thuban's drift detection comes in.
# Run drift detection
npx thuban@latest scan . --check-dna
# Output:
DRIFT DETECTED in src/handlers/stripe-webhook.ts:
@depends-on lists src/config/billing.ts
but this file no longer imports from billing.ts
(removed in commit a3f8c21, 2026-06-15)
@depended-by is missing src/api/admin.ts
which imports verifyWebhookSignature since commit 7b2e9d4
@test-coverage says 84% but current coverage is 71%
(3 new functions added without tests)
Thuban compares the DNA block against the actual import graph, the actual file system, and the actual test coverage. When they diverge, it flags the drift with the specific commit that caused it.
This is the key difference between Mother Code DNA and a wiki page. DNA blocks are validated against reality on every scan. They can't silently rot because Thuban catches the drift.
Common drift patterns: A developer adds a new import but doesn't update @depends-on. A file gets a new consumer but @depended-by isn't updated. A function is refactored but @would-break still references the old signature. Thuban catches all three.
Dependency Mapping: The Graph View
Individual DNA blocks are useful. But the real power emerges when you read them together. Every @depends-on and @depended-by entry is an edge in a dependency graph. Thuban builds that graph automatically.
# Generate dependency graph from DNA blocks
npx thuban@latest scan . --dna-graph
# Output: dependency map
src/handlers/stripe-webhook.ts
→ depends on 4 files
← depended by 2 files
! blast radius: 6 files (2 direct + 4 transitive)
src/services/stripe.ts
→ depends on 2 files
← depended by 7 files
! blast radius: 14 files (7 direct + 7 transitive)
!! HIGH CENTRALITY — changes here affect 23% of codebase
The graph reveals architectural truths that are invisible at the file level:
- High-centrality files — files that many other files depend on. These are your riskiest refactoring targets.
- Orphan files — files with no
@depended-byentries. Either they're entry points, or they're dead code. - Circular dependencies — A depends on B, B depends on A. DNA blocks make these visible immediately.
- Dependency depth — how many layers of transitive dependencies exist. Deep chains are fragile.
How to Add DNA to an Existing Project
You don't have to DNA-tag every file at once. Here's the incremental approach that works:
Phase 1: Tag Your Critical Files (Day 1)
Start with the files that would cause the most damage if someone changed them without understanding the consequences. These are typically:
- Authentication and authorisation handlers
- Payment processing (Stripe, billing, invoicing)
- Database models and migrations
- API route definitions
- Configuration files (environment, feature flags)
# Let Thuban identify your highest-risk files
npx thuban@latest scan . --suggest-dna
# Output:
Recommended for DNA tagging (by centrality + complexity):
1. src/services/stripe.ts (7 dependents, high complexity)
2. src/middleware/auth.ts (12 dependents, high complexity)
3. src/models/user.ts (9 dependents, medium complexity)
4. src/config/database.ts (11 dependents, low complexity)
5. src/routes/api.ts (8 dependents, medium complexity)
Phase 2: Tag on Touch (Ongoing)
Add a team rule: if you modify a file, add or update its DNA block. This is the “boy scout rule” applied to documentation. Over time, every actively-maintained file gets a DNA block.
// Before your change — add the DNA block
/**
* @thuban-dna
* @purpose Validates and sanitises user input for the signup flow
* @owner growth-team
* @created 2026-01-20
* @last-verified 2026-06-29
*
* @depends-on
* - src/utils/validation.ts (Email and password validators)
* - src/config/auth.ts (Password policy rules)
*
* @depended-by
* - src/routes/auth.ts (POST /signup handler)
* - src/components/SignupForm.tsx (Client-side validation mirror)
*
* @would-break
* - Changing validateEmail signature breaks auth.ts and SignupForm
* - Removing password policy check breaks compliance requirements
*
* @ai-generated none
* @complexity medium
* @test-coverage 92%
*/
Phase 3: Validate in CI (Week 2)
Once you have DNA blocks on your critical files, add drift detection to your CI pipeline:
# .github/workflows/dna-check.yml
name: DNA Drift Check
on: [pull_request]
jobs:
check-dna:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check DNA drift
run: npx thuban@latest scan . --check-dna --strict
# Fails if any DNA block has drifted from reality
The --strict flag fails the build if any DNA block contains stale information. This ensures that DNA blocks stay accurate as the codebase evolves.
Phase 4: Generate Missing DNA (Month 2)
Once the team is comfortable with the format, use Thuban to generate DNA blocks for untagged files:
# Auto-generate DNA blocks from import analysis
npx thuban@latest scan . --generate-dna
# Thuban analyses the import graph and generates:
# - @depends-on from actual imports
# - @depended-by from reverse import analysis
# - @would-break from export usage patterns
# - @purpose from file name + content analysis
#
# Human review required — Thuban generates, you verify
Important: Auto-generated DNA blocks are a starting point, not a finished product. The @would-break field in particular requires human knowledge — Thuban can tell you what depends on a file, but only a developer knows what specific changes would cause breakage.
DNA for AI-Generated Code
Mother Code DNA is especially valuable for AI-generated code. When Copilot or Claude generates a file, the developer who accepted it should add a DNA block that records:
- That it was AI-generated — so future developers know to scrutinise it more carefully
- When it was reviewed — so the team can track review freshness
- What it depends on — because AI tools often import from modules that don't exist
- What would break — because AI-generated code often has undocumented assumptions
/**
* @thuban-dna
* @purpose Generates PDF invoices from subscription data
* @owner billing-team
* @created 2026-05-20
* @last-verified 2026-06-29
*
* @depends-on
* - src/services/stripe.ts (Fetches invoice data)
* - src/utils/pdf-generator.ts (PDFKit wrapper)
* - src/templates/invoice.ts (Invoice HTML template)
*
* @depended-by
* - src/routes/billing.ts (GET /invoices/:id/pdf)
* - src/jobs/monthly-invoices.ts (Batch PDF generation)
*
* @would-break
* - Changing generatePDF return type breaks billing route
* - Removing template dependency breaks PDF layout
* - Changing Stripe data shape requires template update
*
* @ai-generated full (Generated by Claude Code, reviewed by Sarah 2026-05-22)
* @complexity medium
* @test-coverage 67%
*/
The @ai-generated full tag tells every future developer: this entire file was written by an AI. Read it with extra care. Verify the imports. Test the edge cases. Don't assume a human thought through the error handling.
The Self-Documenting Codebase
The vision behind Mother Code DNA is a codebase that knows itself. Not through external documentation that rots, not through tribal knowledge that leaves with the team, but through structured metadata that lives in the code, travels with the code, and is validated against reality on every commit.
When a new developer joins the team, they don't need a two-week onboarding. They open a file, read the DNA block, and immediately know:
- What this file does
- What it depends on and why
- What depends on it
- What would break if they changed it
- Whether it was AI-generated
- Who owns it
- How well it's tested
That's not documentation. That's self-awareness.
Mother Code DNA turns tribal knowledge into version-controlled, machine-validated metadata.
Getting Started
You can start adding DNA blocks to your codebase today. No tooling required — it's just structured comments. But Thuban makes it powerful by validating those comments against reality.
Scan your codebase now
npx thuban@latest scan .
Thuban identifies your highest-risk files and suggests where to add DNA blocks first.
thuban.dev — Free for up to 100 files, 5 scans/month
Craig is the founder of Thuban. Every file in the Thuban codebase has a DNA block. The last drift detection run found zero stale entries. That's the standard.