针对AI代码助手悄声破坏架构边界的问题,作者做了个开源CI门禁:YAML定义架构约束规则,AST+Semgrep解释器匹配,违规则退出1。
Enforce your team's architectural contracts on every pull request — deterministically, at zero scan token cost, with instant AI remediation.
$ npx archsentry scan --config archsentry.yml --path src --explain
❌ ArchSentry found 1 violation(s) (1 error, 0 warnings):
• [error] no-direct-sql src/controllers/user.controller.ts:7
All database writes must go through the repository layer.
> await db.query("INSERT INTO users (email, name) VALUES ($1, $2)", [payload.email, payload.name]);
💡 Remediation: All database writes must go through the repository layer. Move this call
behind the appropriate service or repository layer so the access path is centralized
and reviewable, rather than issued directly from `src/controllers/user.controller.ts`.
$ echo $?
1
AI coding assistants (Cursor, Copilot, Claude Code) generate thousands of lines of code per day. While standard linters catch syntax errors and SAST tools detect known CVE vulnerabilities, neither addresses a subtler problem: architectural drift — when code gradually violates team-level design rules, layer boundaries, and structural contracts that no linter explicitly enforces.
The problem isn't bad code. It's code that's individually reasonable but collectively corrosive — a direct SQL query here, a service-layer bypass there, a side-effect buried in a "utils" file. Over months, the architecture becomes a suggestion rather than a contract.
Traditional linters operate on single files. They can't track cross-layer dependencies, enforce access patterns between bounded contexts, or understand that UserController shouldn't talk to db directly while UserRepository should.
SAST scanners are great at finding known vulnerability patterns but operate in a binary world: vulnerable or safe. They have no concept of architectural intent.
AI code review tools have started to address this, but they suffer from token costs, latency, and inconsistent results. One PR gets a thorough review; the next gets a rubber-stamp because the model is overloaded.
ArchSentry is a deterministic architectural enforcement tool that runs locally, in CI, or as a pre-commit hook. It lets you define your team's architectural contracts in a simple YAML file and enforces them automatically on every code change.
Unlike AI-based tools, ArchSentry doesn't require LLM API calls to check your architecture. The scanning engine is a custom-built Semgrep-compatible rule evaluator that runs at near-zero cost.
You define your architecture in archsentry.yml:
layers:
- name: controllers
pattern: "src/controllers/**/*.ts"
- name: services
pattern: "src/services/**/*.ts"
- name: repositories
pattern: "src/repositories/**/*.ts"
- name: models
pattern: "src/models/**/*.ts"
rules:
- name: no-direct-sql
message: "All database writes must go through the repository layer"
severity: error
pattern: |
await $DB.query(...)
inside: |
src/controllers/**/*
- name: controller-to-repository
message: "Controllers must only call services, not repositories directly"
severity: error
from: controllers
to: repositories
Then run the scanner:
$ npx archsentry scan --config archsentry.yml --path src --explain
❌ ArchSentry found 1 violation(s) (1 error, 0 warnings):
• [error] no-direct-sql src/controllers/user.controller.ts:7
All database writes must go through the repository layer.
> await db.query("INSERT INTO users (email, name) VALUES ($1, $2)", [payload.email, payload.name]);
💡 Remediation: All database writes must go through the repository layer. Move this call
behind the appropriate service or repository layer so the access path is centralized
and reviewable, rather than issued directly from `src/controllers/user.controller.ts`.
The --explain flag shows the exact line and suggests a fix — without requiring any AI call during the detection phase.
name: Architecture Check
on: [pull_request]
jobs:
archsentry:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g archsentry
- run: npx archsentry scan --config archsentry.yml --path src
# .pre-commit-config.yaml
repos:
- repo: https://github.com/archsentry/archsentry-precommit
rev: v1.0.0
hooks:
- id: archsentry
args: ['--config', 'archsentry.yml', '--path', 'src']
| Feature | ArchSentry | Traditional SAST | AI Code Review |
|---|---|---|---|
| Token cost | $0 | $0 | $0.01-0.50/PR |
| Latency | <1s | 1-5s | 10-60s |
| Deterministic | ✅ | ✅ | ❌ |
| Architectural rules | ✅ | ❌ | ✅ |
| CI-native | ✅ | ✅ | ✅ |
| Self-hosted | ✅ | ✅ | ❌ |
npm install -g archsentry
# Initialize in your project
npx archsentry init
# Edit archsentry.yml with your architecture
npx archsentry scan --path src --explain
The archsentry init command creates a sensible default configuration based on your project structure, which you can then customize.
AI coding assistants are powerful collaborators, but they don't know your architecture. They generate code that looks correct in isolation but erodes your design over time. ArchSentry provides the guardrails that keep AI-assisted code aligned with your team's architectural intent — without the token costs and latency of AI-based scanning.
The architectural contract is now code, not convention. Enforce it.