惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
Forbes - Security
Forbes - Security
WordPress大学
WordPress大学
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
Spread Privacy
Spread Privacy
D
Darknet – Hacking Tools, Hacker News & Cyber Security
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
P
Privacy International News Feed
A
About on SuperTechFans
T
Tailwind CSS Blog
I
InfoQ
S
Securelist
云风的 BLOG
云风的 BLOG
罗磊的独立博客
Recent Announcements
Recent Announcements
T
The Exploit Database - CXSecurity.com
B
Blog RSS Feed
V
Visual Studio Blog
Know Your Adversary
Know Your Adversary
The GitHub Blog
The GitHub Blog
Jina AI
Jina AI
腾讯CDC
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队
AWS News Blog
AWS News Blog
博客园 - 【当耐特】
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
F
Full Disclosure
S
Secure Thoughts
博客园 - 司徒正美
J
Java Code Geeks
Y
Y Combinator Blog
Google Online Security Blog
Google Online Security Blog
GbyAI
GbyAI
N
News and Events Feed by Topic
Help Net Security
Help Net Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Project Zero
Project Zero
T
Tenable Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tor Project blog
MyScale Blog
MyScale Blog
Scott Helme
Scott Helme
小众软件
小众软件
K
Kaspersky official blog

jonno.nz

Ukraine’s Drone Advantage Is an Engineering Loop — jonno.nz Prove the Machine Wrong — jonno.nz I Parsed Every Law New Zealand Has Ever Passed — jonno.nz Your Show HN dies in 7 hours — jonno.nz The Fastest Repealers in the West — jonno.nz Six Years, $228 Million, Zero Metres of Track The holes that kill you are the ones you never tested What Happens When a Worm Drives Claude? The Laws of Human Nature Conscious Minimalism The dent and the crater I Built a Read-Later Chrome Extension Because Pocket Died Product market fit isn't a stage, it's a gauntlet Change management Three Ways to Look at Time What an hour of your attention is worth Teaching a Neural Network to Watch Crime Like Video OpenHealth – Chat with Apple Health Data, Anywhere Claude Code Can Now Spawn Copies of Itself in Isolated VMs The Future of Security Is an Open-Source Model That Detects and Acts on Threats I Spent 29 Hours Debugging iptables to Boot VMs in 4 Seconds Can You Beat Last Month? Claude Code Running Claude Code in 4-Second Disposable VMs Stealing NanoClaw Patterns for Web Apps and SaaS What if your browser built the UI for you? — jonno.nz What the Data Actually Shows How I Built an SMS Gateway with a $20 Android Phone
Open-Source Agent That Teaches Claude Code Your Architecture
John Gregoriadis · 2026-04-15 · via jonno.nz

AI has made building software cheap. A solo founder with Claude Code or Cursor can ship an MVP in a weekend that would've taken a small team a month two years ago. I've watched this happen across the NZ startup scene. Ideas that used to die in the "can we afford to build it" phase now get built over a long weekend.

This is mostly great. Velocity is what startups need. Cost of testing an idea is now close to zero, and the business prioritises speed.

The catch shows up when the idea works.

AI builds for right now. It optimises for the current prompt, the current file, the current feature. It doesn't think about what happens when your billing service needs to handle 10x the volume, or when your email notifications need to move from inline calls to a queue. It doesn't plan for the evolutionary pressure your system will face once it has users.

That's the gap I've been thinking about, and it's what led me to build domain-agents.

Give the tools their credit

I want to be fair to the current generation of AI coding assistants. They're not stupid about finding code.

Claude Code runs an agentic search loop (grep, glob, file reads) iterating through your codebase to find what's relevant. Boris Cherny (who created Claude Code) has said they tried RAG with a local vector database early on and dropped it because agentic search outperformed it. Cursor takes a different approach: it chunks your codebase, generates embeddings, and stores them for semantic search so you can find code by concept rather than keyword. Copilot combines semantic indexing with LSP-powered reference tracing from VS Code.

The search works. If you ask Claude Code to find your billing service, it'll find it. Ask Cursor for authentication logic and the embeddings will surface it even if the code never uses the word "authentication."

None of them understand the architecture those files live in.

All the information needed to understand domain relationships sits in the code: import graphs, interface signatures, dependency patterns. These tools don't extract or structure it that way. They find files one at a time. They don't map out that your billing service depends on the email service, that BillingService is consumed by two other domains, or that changing its interface is a cross-domain event. The information is in the codebase. Nobody's pulling it together.

And every session starts from zero. The AI learned your architecture yesterday and forgot it today.

Evolutionary architecture for the AI era

My thesis: cheap AI-built MVPs plus expensive scaling problems point toward evolutionary architecture with domain-based boundaries.

The idea isn't new. The reason it matters now is.

In an evolutionary architecture, you focus on clean interfaces between business domains. Your email service exposes a contract like sendEmail(to, subject, body), and the rest of the system calls that interface. Behind the interface, the implementation evolves through stages as your scaling needs change:

graph LR
    A["Inline\n(direct call)"] --> B["Async\n(fire & forget)"]
    B --> C["Queued\n(BullMQ/SQS)"]
    C --> D["Separate Service"]
    D --> E["Distributed"]

Day one, sendEmail is a function that calls Resend directly. Inline, synchronous, dead simple. When traffic picks up, you drop the await and let it run in the background. Later, you introduce BullMQ or SQS. Eventually it becomes its own service. The interface stays put. Only the implementation behind it changes.

This is the kind of evolution AI coding assistants are terrible at planning for. They'll inline that email call because it works right now. They have no concept of where this domain sits on its scaling trajectory.

Where domain-agents fits in

domain-agents is a CLI tool that runs static analysis on TypeScript codebases, discovers business domains, and generates AI agent context files for Claude Code and Cursor.

domain-agents discover .    # Analyse codebase → proposal.json
domain-agents init .        # Generate agents/*.md + AGENTS.md
domain-agents hooks claude  # Wire into Claude Code (rules + MCP server)
domain-agents hooks cursor  # Wire into Cursor (.mdc rules)

After setup, opening src/billing/invoice.ts in Claude Code loads the billing domain agent into context. The AI now knows: billing depends on email (coupling score 0.23), exposes BillingService consumed by 2 other domains, sits at the "inline" scaling stage with a path toward async queuing, and has 3 tracked tech debt items.

It plans work accordingly. The context was loaded before the first prompt, no search required.

Five signals, not one

The discovery engine runs 5 analysis passes because no single signal identifies business domains on its own.

Directory structure works for greenfield projects (src/auth/, src/billing/) but fails for legacy MVC apps. Import graphs capture coupling but not business intent. Package dependencies hint at external integrations but miss internal domains.

graph TD
    S["Structure Analysis"] --> O["Signal Orchestrator"]
    I["Import Graph\n(TS Compiler API)"] --> O
    N["Naming Patterns"] --> O
    D["Dependency Mapping\n(npm → domain hints)"] --> O
    IF["Interface Detection"] --> O
    O --> M["Merge Pipeline"]
    M --> R["Domain Proposal"]

Structure detects whether the codebase is feature-organised, layer-organised, mixed, or flat. Import graph uses the TypeScript Compiler API to parse each .ts file, resolve imports, and build a directed edge graph. Type-only imports get weighted at 0.3 because they're a weaker coupling signal than value imports. Naming patterns extract domain prefixes: auth.controller.ts → "auth". Dependency mapping maps npm packages to domain hints (stripe → billing, @sendgrid/mail → email). Interface detection identifies files imported across domain boundaries and calculates coupling scores between domain pairs.

Each pass produces weighted signals. The orchestrator combines them with confidence scoring: average signal strength plus a bonus for signal count, capped at 0.99. Layer-organised codebases get an 0.85 multiplier because they're harder to discover.

Most real codebases aren't clean

Feature-organised codebases are easy. The directory structure is the domain. But most real codebases look like this:

src/
  controllers/
    auth.controller.ts
    billing.controller.ts
  services/
    auth.service.ts
    billing.service.ts
  models/
    invoice.model.ts
    user.model.ts

Here auth.controller.ts, auth.service.ts, and auth.routes.ts all belong to the "auth" domain despite living in three different directories. domain-agents uses naming pattern extraction cross-referenced with import graph cohesion to cluster these. The auth.* files form a tight import cluster, which confirms the naming signal.

Merging is the hard bit

Raw signals produce too many small, overlapping clusters. The orchestrator runs a multi-phase normalisation pipeline.

Plurals merge: journals + journal → whichever has more files. Compound names consolidate: bank-balance + bank-statement + bank-transactionbank-accounts (the largest cluster). Small clusters merge into their strongest import target, but only if they have a dominant dependency: more than 40% of imports from one target, and that target is at least 2x larger. This prevents cascading, where A merges into B, B gets bigger and attracts C, C pulls in D.

Files that import from 3+ domains get moved to "unassigned." These are coupling hotspots: middleware, orchestrators, shared handlers. Assigning them to one domain would mislead the AI, so the tool surfaces them for a human decision. That's the right call for architectural boundaries.

The E2E test suite validates the complete pipeline against 3 fixture codebases (feature-organised, layer-organised, mixed). Current benchmark: 100% activation accuracy across all 3 patterns and all 3 activation levels (domain assignment, glob matching, MCP lookup).

Auto-activation, not search

The integration into Claude Code and Cursor uses glob-based rule activation, the native mechanism both tools already support.

Each domain gets a rule file with glob patterns in the frontmatter:

---
description: billing domain
globs:
  - src/billing/**
  - **/billing.*
  - **/billing-*
---

When Claude Code opens a file matching those globs, the domain context loads. No MCP call, no background process, zero runtime overhead.

An MCP server complements the rules with 4 on-demand tools: domain_lookup(file), domain_context(name), domain_files(name), and list_domains(). A SessionStart hook prints a domain summary at the start of every Claude Code session, so the AI has system-level awareness from the first prompt.

Agents as a team model

This is the bit I'm most keen on long-term.

At Vend and Xero, teams owned domains. The billing team owned billing, the integrations team owned integrations. Ownership meant knowing the interfaces, the coupling points, the tech debt, and where things were headed. That knowledge lived in people's heads and got passed on through code reviews, architecture chats, and tribal memory.

Domain-specific AI agents formalise that same ownership model. An email agent loads the email domain's interface contract, its coupling to other domains, its current scaling stage, and its tracked tech debt. A billing agent carries the same for billing. They work within their boundaries and flag when a change crosses a domain line.

You don't need this from day one. Early on, one agent covers multiple areas. As the product grows, agents split along the same lines engineering teams split: by business domain. The operator (that's you) resolves conflicts where agents disagree, the same way an engineering manager resolves cross-team dependencies.

The analogy is rough, but it captures how AI-assisted development scales past a single person staring at a single context window.