NLCC:用自然语言编写代码的完整系统

NLCC = Natural Language Code Compiler

专业级自然语言编译器,将自然语言描述编译为可执行代码,并提供完整的可视化开发环境


目录


设计哲学

核心洞察:代码是Cheap的

在AI辅助编程的时代,成本结构发生了根本性变化:

传统成本模型

  • 代码编写:昂贵(人工时间)
  • 代码复用:节省成本
  • 过度设计:值得投入

AI时代成本模型

  • 代码生成:便宜(AI几秒生成几百行)
  • AI理解成本:昂贵(上下文窗口有限)
  • AI修改成本:极高(需要重新理解整个系统)

新的成本函数

总成本 = AI生成代码的时间(低)
       + 人类review的时间(中)
       + AI修改迭代的时间(高)
       + 系统复杂度导致的AI错误率(极高)

结论:在AI时代,应该牺牲代码复用来换取AI注意力的聚焦。

为什么牺牲代码复用?

传统方式:追求代码复用

场景:统一错误处理

// src/common/error.rs
pub struct Error {
    code: i32,
    message: String,
    context: Option<Box<dyn Any>>,
}

pub fn error_handle(err: &Error);  // 超级通用的错误处理

传统优势

  • ✅ 只写一次错误处理逻辑
  • ✅ 统一的错误格式
  • ✅ 易于维护

AI时代的问题

让AI写使用Error的代码时:

AI的思维过程:
1. 需要处理错误
2. 用Error结构
3. Error有哪些字段?code、message、context...
4. context是什么类型?Option<Box<dyn Any>>?
5. 需要downcast吗?什么具体类型?
6. 有初始化函数吗?
7. 错误码是多少?
8. 要检查None吗?
...(AI注意力被分散到10个细节上)

AI实际生成(很可能出错):

fn network_send(&self, data: &str) {
    if send_failed {
        let mut err = Error {
            code: 1000,
            message: "send failed".to_string(),
            context: None,  // ❌ 不知道应该设置什么类型
        };
        error_handle(&err);  // ❌ 类型信息可能丢失
    }
}

AI方式:牺牲代码复用

// 不设计通用的Error结构

// src/network/impl.rs
fn network_send(&self, data: &str) {
    if send_failed {
        // 简单直接,网络模块自己的错误处理
        eprintln!("[network] send failed: {}", std::io::Error::last_os_error());
        if let Some(callback) = &self.error_callback {
            callback("send failed");
        }
    }
}

// src/storage/impl.rs
fn storage_write(&mut self, data: &str) {
    if write_failed {
        // 存储模块自己的错误处理(完全不同)
        eprintln!("[storage] write failed: {}", std::io::Error::last_os_error());
        if self.retry_count < 3 {
            self.retry_count += 1;
            self.storage_write(data);  // 自己的重试逻辑
        }
    }
}

AI生成这个

AI的思维过程:
1. 需要处理错误
2. eprintln!打印
3. 调用回调(如果有)
4. 完成

AI只需要关注3个细节,专注度高!

成本对比

传统方式(追求复用):

设计通用Error:4小时
AI出错率:30%
人类review:每个module 30分钟
修复时间:20分钟 × 3轮 = 60分钟

10个module总成本:4 + 15 = 19小时

AI方式(牺牲复用):

设计通用Error:0小时
AI出错率:5%
人类review:每个module 5分钟
修复时间:5分钟 × 1轮 = 5分钟

10个module总成本:0 + 1.6 = 1.6小时

代码重复:每个module都写eprintln!(但没关系!)

节省时间:17小时!

核心设计原则

1. 代码是cheap的,AI注意力是昂贵的

不惜增加代码量来降低每个模块的复杂度。用代码重复换取逻辑简单

2. 零循环依赖

  • modules/*/AGENTS.md 绝对禁止互相引用
  • 每个模块职责单一明确
  • AI不需要理解复杂的依赖关系

3. 自然语言描述意图,代码描述实现

  • AGENTS.md 描述"做什么"
  • skills/*.md 描述需求和约束
  • 生成的代码 是"怎么做"的具体实现

4. 按需加载,降低上下文消耗

  • 不是一次性加载所有MD
  • 根据当前任务动态加载相关模块
  • 降低AI的上下文窗口压力

5. MD是源码,代码是中间产物

  • 人类维护 modules/ 下的MD文档
  • build/ 下的代码是自动生成的,可随时重新编译
  • 就像今天维护Rust代码,不关心生成的MIR/汇编

6. 确定性优先(新增)

为什么需要确定性?

自然语言的模糊性是 AI 时代的最大挑战:

  • 同一个 AGENTS.md,今天的 LLM 可能理解为"单例模式"
  • 明天可能理解为"静态类"
  • 这导致生成的代码结构不稳定

解决方案:引入 IR 层

NLCC 通过一个确定性的中间表示(IR)层来解决:

AGENTS.md(模糊的自然语言)
  ↓
[意图解析器] - LLM 辅助解析
  ↓
IR(确定的 JSON)
  ↓
[验证器] - 静态分析
  ↓
代码生成(可以是确定性规则)

IR 的价值

  • 可验证nlcc check 可以验证接口一致性
  • 增量构建:只有 IR 变化才触发重新生成
  • 跨语言基础:IR 是语言无关的

7. 验证优先于生成(新增)

NLCC 的核心价值不是生成代码,而是保证代码正确性。

传统代码生成工具的问题:

  • ❌ 生成代码后不管对错
  • ❌ 出错时无限重试,成本失控
  • ❌ 错误传播到下游模块

NLCC 的解决方案:

  • 多级验证:语法 → 测试 → 静态分析
  • 熔断机制:最多重试 3 次,失败即停止
  • 错误隔离:单点失败不影响全局

8. 可维护性优先(新增)

代码可以重新生成,但调试体验不能妥协。

挑战:

  • 生成的代码有 Bug,如何定位到源码?
  • 人工修复了代码,下次生成会被覆盖

解决方案:

  • Source Map:从代码行映射到 AGENTS.md 章节
  • 补丁系统:保护手工编辑区域

核心架构

目录结构设计

project/
├── AGENTS.md              # 顶层意图描述(main函数)
├── modules/
│   ├── logger/
│   │   ├── AGENTS.md      # 模块意图
│   │   └── skills/        # 按需加载的细节
│   │       ├── output.md
│   │       ├── thread_safety.md
│   │       └── json_format.md
│   ├── network/
│   │   ├── AGENTS.md
│   │   └── skills/
│   │       ├── http.md
│   │       └── ssl.md
│   └── storage/
│       ├── AGENTS.md
│       └── skills/
└── build/                 # AI生成的一次性代码
    ├── .ir/               # IR 文件
    │   ├── logger.ir.json
    │   └── network.ir.json
    ├── .sourcemaps/       # Source Map
    │   ├── logger.sourcemap.json
    │   └── network.sourcemap.json
    ├── include/           # 公共接口层(零依赖区)
    │   ├── common_types.rs
    │   ├── logger.rs
    │   ├── network.rs
    │   └── storage.rs
    ├── src/               # 实现层
    │   ├── logger/
    │   │   ├── impl.rs
    │   │   ├── .patches/  # 补丁文件
    │   │   └── internal.rs
    │   ├── network/
    │   └── storage/
    └── api.rs             # 唯一对外接口

依赖关系图

         ┌─────────────────┐
         │   AGENTS.md     │  ← 顶层意图
         │  (项目main函数)  │
         └────────┬─────────┘
                  ↓ 指向
         ┌────────┴─────────┐
         │ modules/*/AGENTS │  ← 模块意图
         │  - 清晰边界      │
         │  - 职责单一      │
         └────────┬─────────┘
                  ↓ 指向
         ┌────────┴─────────┐
         │ modules/*/skills │  ← 按需细节
         └────────┬─────────┘
                  ↓ NLCC编译
         ┌────────┴─────────┐
         │   build/include  │  ← 代码接口层
         │   build/src      │  ← 代码实现层
         └──────────────────┘

关键约束

  • modules/*/AGENTS.md 绝对禁止互相引用
  • skills/*.md 只能被对应的AGENTS.md引用
  • build/ 下的代码自动生成,手工修改会被覆盖

两阶段编译流程

为什么需要两阶段?

传统编译器(如 C):

  1. 先编译头文件(.h)- 定义接口
  2. 再编译实现文件(.c)- 依赖接口

NLCC 同样需要:

  1. 接口编译(快速,失败也快)
  2. 实现编译(可以并行,依赖接口)

阶段一:接口编译

# 只编译接口
nlcc build --interfaces-only

# 生成:
build/include/
  ├── logger.rs      (只有接口签名)
  ├── network.rs
  └── storage.rs

生成的接口文件示例

// build/include/logger.rs
// 📍 Source: modules/logger/AGENTS.md
// 🕐 Generated: 2026-02-20T10:30:00Z
// 🔒 Hash: a1b2c3d4

/// 日志记录器接口
pub trait Logger {
    /// 记录日志消息
    ///
    /// # 约束
    /// - 性能: <100μs
    /// - 线程安全: 是
    fn log(&self, message: &str);

    /// 设置日志级别
    ///
    /// # 线程安全
    /// 否,需要独占访问
    ///
    /// # 可能返回错误
    /// 如果级别无效
    fn set_level(&mut Logger, level: LogLevel) -> Result<(), Error>;
}

/// 日志级别
#[derive(Debug, Clone, Copy)]
pub enum LogLevel {
    Debug,
    Info,
    Warn,
    Error,
}

阶段二:实现编译

# 编译实现
nlcc build --implementations

# 或直接 build(自动执行两个阶段)
nlcc build

构建顺序

阶段一:接口编译
  ↓
logger (interface)  ← 无依赖,最先编译
  ↓
network (interface)  ← 依赖 logger 接口
  ↓
storage (interface)  ← 依赖 logger 接口
  ↓
app (interface)  ← 依赖所有接口

阶段二:实现编译(可并行)
  ↓
logger (impl)  ← 可以立即开始
  ↓
network (impl)  ← 等待 logger 接口完成
  ↓
storage (impl)  ← 等待 logger 接口完成
  ↓
app (impl)  ← 等待所有依赖实现完成

接口注册机制

在 AGENTS.md 中显式声明

## Export Interface

本模块对外暴露的接口:

pub fn logger_log(logger: &Logger, message: &str)
// 线程安全:是
// 阻塞:否
// 性能:<100μs

pub fn logger_set_level(logger: &mut Logger, level: LogLevel) -> Result<(), Error>
// 线程安全:否
// 阻塞:否
// 可能返回错误


**接口契约一旦冻结,除非大版本变更,否则不修改。**

提示词架构

NLCC采用AI原生提示词架构,让自然语言(Markdown文档)成为源码,代码成为编译后的中间产物。

1. AGENTS.md:MD文档的main函数

核心原则:每个AGENTS.md是唯一入口,描述"做什么",不描述"怎么做"。

项目级AGENTS.md

# AGENTS.md - 项目全局视图

## 项目背景
这是一个高性能网络服务器,支持并发连接和事件驱动架构。

## 核心功能
- 网络连接管理(TCP/SSL)
- 异步事件处理
- 日志记录
- 数据持久化

## 主要模块
- [logger/](modules/logger/AGENTS.md):日志记录模块
- [network/](modules/network/AGENTS.md):网络通信模块
- [storage/](modules/storage/AGENTS.md):数据存储模块

## 对外接口
应用通过`api.rs`提供统一的接口:

pub fn app_start();
pub fn app_stop();


## 设计原则
- 零循环依赖
- 编译期隔离
- AI注意力优先

模块级AGENTS.md

# Logger Module - AGENTS.md

## 功能定位
记录应用日志到文件和控制台,支持多种日志级别和输出格式。

## 核心接口

pub fn logger_log(logger: &Logger, message: &str);
pub fn logger_set_level(logger: &mut Logger, level: LogLevel);
pub fn logger_set_output(logger: &mut Logger, target: OutputTarget);


## 主要职责
1. 接收日志消息
2. 格式化输出(文本/JSON)
3. 写入目标(文件/控制台)
4. 线程安全保证

## 依赖
- 依赖:无(零依赖模块)
- 被依赖:network、storage

## 细节文档
- [输出策略](skills/output.md):如何支持多种输出格式
- [线程安全](skills/thread_safety.md):如何保证并发安全
- [性能优化](skills/performance.md):如何优化日志性能

## 注意事项
- 不要在这个模块中添加网络功能
- 不要阻塞主线程

2. Skills目录:按需加载的细节

核心原则:skills只描述意图和需求,不描述具体实现。

示例:logger/skills/json_format.md

# JSON格式日志输出

## 需求描述
日志需要支持JSON格式输出,便于日志收集和分析系统(如ELK)解析。

## 输出格式

{
"timestamp": "2026-02-15T10:30:00Z",
"level": "ERROR",
"module": "network",
"message": "Connection failed",
"context": {

"peer": "192.168.1.100:8080",
"error_code": 110

}
}


## 使用场景
- 生产环境日志收集
- 自动化日志分析
- 结构化查询

## 性能要求
- JSON序列化时间 < 100μs
- 不能阻塞主线程

## 不需要关心
- 具体用哪个JSON库(AI自己选择)
- 如何优化性能(AI自己考虑)

3. 按需加载策略

核心思想:不是一次性加载所有MD,而是根据AI的注意力范围动态加载。

场景1:AI生成logger模块代码

步骤1:读取 logger/AGENTS.md
→ AI理解模块的整体意图

步骤2:AGENTS.md引用了 skills/output.md
→ AI读取这个文件,了解输出需求

步骤3:AI开始生成代码
→ 只关注当前模块,不受其他模块干扰

场景2:AI需要理解logger如何被network使用

步骤1:读取 logger/AGENTS.md
→ 了解logger提供的接口

步骤2:读取 network/AGENTS.md
→ 发现network依赖logger

步骤3:按需加载 skills/json_format.md
→ 了解network需要JSON格式的日志

4. 接口演进管理

核心挑战:在零循环依赖的架构中,模块A(如logger)的接口变化会影响所有依赖它的模块(如network、storage)。如何管理这种"隐式"依赖变更的影响范围?

解决方案:语义化版本 + 自动影响分析

# logger/AGENTS.md

## 版本信息
- 当前版本: 2.0.0
- 变更类型: BREAKING CHANGE

## 接口变更历史
### v2.0.0 (2026-02-20)
- **破坏性变更**: `logger_log()` 签名从 `fn(logger, message)` 改为 `fn(logger, message, level)`
- **原因**: 支持动态日志级别
- **影响模块**: network, storage, testing
- **迁移指南**: 所有调用需要添加level参数

### v1.1.0 (2026-02-15)
- **新增功能**: 支持结构化日志(JSON格式)
- **向后兼容**: 是
- **影响模块**: 无(可选升级)

自动影响分析工具

# 分析logger接口变更的影响范围
$ nlcc analyze-impact logger --version 2.0.0

分析结果:
  依赖模块:
    ✓ network (依赖: logger_log)
    ✓ storage (依赖: logger_log, logger_flush)
    ✓ testing (依赖: logger_set_level)

  需要重新生成的模块:
    → network/impl.rs
    → storage/impl.rs
    → testing/impl.rs

  推荐操作:
    1. 先更新logger到v2.0.0
    2. 自动重新生成依赖模块
    3. 运行集成测试验证

增量构建策略

logger v2.0.0 发布
    ↓
自动检测依赖关系
    ↓
智能构建顺序:
  1. logger/impl.rs (首先构建)
  2. network/impl.rs (依赖logger)
  3. storage/impl.rs (依赖logger)
  4. app/impl.rs (依赖所有)
    ↓
自动运行回归测试
    ↓
验证通过 → 发布到生产

5. Skills冲突解决机制

核心挑战:当两个skill对同一模块提出冲突需求时,AI如何裁决?

示例冲突

# skills/performance.md
## 需求
- 使用内存池减少分配开销
- 缓存最近1000条日志

# skills/low_memory.md
## 需求
- 严格限制内存使用 < 10MB
- 不使用缓存

解决方案:优先级规则 + 显式冲突声明

# logger/AGENTS.md

## Skills优先级
1. **critical/** (关键约束,必须满足)
   - security.md
   - safety.md

2. **functional/** (功能需求,主要考虑)
   - output.md
   - format.md

3. **optimization/** (优化需求,权衡考虑)
   - performance.md
   - low_memory.md

## 冲突解决策略
当optimization/类skill冲突时:
- 优先满足functional/需求
- 在functional/约束内做最优权衡
- 在AGENTS.md中明确记录权衡决策

## 当前权衡决策
- **性能 vs 内存**: 选择低内存(优先级:functional/reliability.md)
- **延迟 vs 吞吐**: 选择低延迟(实时系统要求)

AI裁决流程

1. 读取所有skills
   ↓
2. 检测冲突需求
   ↓
3. 应用优先级规则
   - critical > functional > optimization
   ↓
4. 识别冲突类型
   - 直接冲突(A要求X,B要求not X)
   - 资源竞争(A要求CPU,B要求内存)
   ↓
5. 生成权衡决策
   - 在AGENTS.md中记录决策原因
   ↓
6. 生成代码时体现决策
   - 添加注释说明权衡点

示例:AI生成的权衡代码

// logger/impl.rs
// 权衡决策: 按照AGENTS.md中的优先级,
// 选择了低内存方案而非性能优化方案
// 原因: functional/reliability.md 要求在受限环境中运行

impl Logger {
    // 不使用缓存(满足low_memory.md)
    // 代价: 性能降低10%(可接受)
    pub fn log(&self, msg: &str) {
        self.write_direct(msg);  // 直接写入,无缓存
    }
}

中间表示(IR)层

为什么需要 IR?

传统编译器有 AST/HIR/MIR 等中间表示,NLCC 同样需要 IR 来:

  • 消除歧义:自然语言的模糊性在 IR 层被明确化
  • 可验证性:IR 可以被静态分析工具检查
  • 增量构建:只有 IR 变化才触发代码重新生成
  • 跨语言基础:IR 是语言无关的,可映射到多种目标语言

IR 结构定义

NLCC 使用轻量级的 JSON 作为 IR 格式(MVP 阶段):

{
  "version": "1.0",
  "module": "logger",
  "hash": "a1b2c3d4",
  "metadata": {
    "generated_at": "2026-02-20T10:30:00Z",
    "source_files": ["AGENTS.md", "skills/output.md"]
  },

  "exports": [
    {
      "name": "logger_log",
      "signature": "fn(logger: &Logger, message: &str)",
      "thread_safe": true,
      "blocking": false,
      "error_handling": "none",
      "constraints": {
        "performance": "<100μs"
      }
    },
    {
      "name": "logger_set_level",
      "signature": "fn(logger: &mut Logger, level: LogLevel) -> Result<(), Error>",
      "thread_safe": false,
      "blocking": false,
      "error_handling": "may_fail"
    }
  ],

  "dependencies": [],

  "constraints": {
    "performance": {
      "logger_log": "<100μs"
    },
    "memory": "<10MB",
    "thread_safety": "required"
  },

  "optimization_hints": {
    "priority": "low_latency",
    "tradeoffs": [
      "performance vs memory: choose low_memory (functional/reliability.md)"
    ]
  }
}

IR 生成流程

AGENTS.md + skills/*.md
  ↓
[意图解析器] - LLM 辅助解析
  ↓
IR (JSON)
  ↓
[验证器] - 静态分析
  ↓
IR 验证通过
  ↓
[代码生成器] - 可以是确定性规则
  ↓
Rust 代码

工具支持

# 查看 IR(不生成代码)
nlcc check --ir-only logger

# 输出:
# ✓ IR 生成成功
# • 模块: logger
# • 导出接口: 2 个
# • 依赖: 无
# • 约束: 性能 <100μs, 内存 <10MB

# 导出 IR 文件
nlcc check --export-ir --output build/.ir/logger.ir.json

IR 的价值

可验证性示例

# 检查接口一致性
nlcc check --verify-interfaces

# 场景:logger v2.0.0 改变了接口签名
# 输出:
# ❌ 接口不匹配
# • logger_log() 签名变化:
#   - 旧: fn(logger, message)
#   - 新: fn(logger, message, level)
# • 影响模块: network, storage
# • 建议:运行 nlcc analyze-impact logger

增量构建示例

# 第一次构建
$ nlcc build
→ 生成 IR: build/.ir/logger.ir.json (2450 tokens)
→ 生成代码: build/src/logger/impl.rs

# 修改 AGENTS.md(只改描述,不改接口)
$ vim modules/logger/AGENTS.md

# 第二次构建
$ nlcc build
→ 检测到 IR 未变化(hash 相同)
→ 跳过代码生成(节省时间和成本)
→ ✓ 无需重新生成

技术规格

本章节将NLCC从设计理念转化为可实施的工程规格,明确核心概念、系统架构、接口定义和算法流程,为编译器开发提供详细的技术指导。

核心概念的形式化定义

1. "编译"的定义(更新)

NLCC编译器的形式化流程:

输入:自然语言意图(modules/下的Markdown文件集合)
  ↓
意图解析(MD → IR)
  ↓
IR 验证(静态分析)
  ↓
上下文组装(按需加载AGENTS.md、skills/*.md、依赖接口摘要)
  ↓
AI编排引擎(提示词工程 + LLM调用 + 结果解析)
  ↓
代码生成与验证(生成 → 编译 → 测试 → 迭代修正 + 熔断)
  ↓
Source Map 生成
  ↓
输出:源代码文件(build/下的.rs/.go/.py等)

关键区别

  • 传统编译器:词法分析 → 语法分析 → 语义分析 → 代码生成
  • NLCC编译器:意图理解 → IR 生成 → 验证 → AI生成 → 多级验证

2. AGENTS.md的语法规范

为了让AI和工具能准确解析,定义轻量级的"意图描述语言"(IDL)规范:

必需章节结构

# <模块名称> - AGENTS.md

## 功能定位
[必填] 1-3句话描述模块的核心功能

## 核心接口
[必填] 使用标准化的伪代码格式定义接口

## 主要职责
[必填] 列表形式,3-7项

## 依赖
[必填] 明确声明依赖关系

## 细节文档
[必填] 引用skills/*.md文件

## 注意事项
[可选] 约束和限制

## Skills优先级
[可选] 定义冲突解决优先级

接口定义规范示例

pub fn logger_log(logger: &Logger, message: &str)
  // 记录日志消息
  // 线程安全:是
  // 阻塞:否

pub fn logger_set_level(logger: &mut Logger, level: LogLevel) -> Result<(), Error>
  // 设置日志级别
  // 线程安全:否,需要独占访问
  // 可能返回错误:如果级别无效

AI交互层设计

系统架构

┌──────────────┐
│ CLI/Web界面  │  ← 用户交互入口
└───────┬──────┘
        ↓
┌──────────────┐
│ 意图解析器   │  ← 解析AGENTS.md和skills/*.md
└───────┬──────┘
        ↓
┌──────────────┐
│ IR生成器  │  ← 生成中间表示
└───────┬──────┘
        ↓
┌──────────────┐
│ IR验证器  │  ← 静态分析验证
└───────┬──────┘
        ↓
┌──────────────┐
│ 上下文组装器 │  ← 按需加载依赖,组装提示词
└───────┬──────┘
        ↓
┌──────────────────────────────┐
│       AI编排引擎              │
│  提示词模板 → LLM → 结果解析 │
└───────────┬──────────────────┘
            ↓
┌──────────────────────────────┐
│  代码生成与验证引擎        │
│  生成 → 编译 → 测试 → 迭代   │
└───────────┬──────────────────┘
            ↓
┌──────────────────┐
│ Source Map生成│  ← 生成源码映射
└───────────┬──────┘
            ↓
┌──────────────────┐
│  产物输出        │  ← 写入build/目录
└──────────────────┘

LLM调用策略

模型选择矩阵

任务类型推荐模型Token预算理由
意图理解GPT-4/Claude 3.54K需要深度理解
IR生成GPT-4/Claude 3.52K需要结构化输出
接口生成GPT-4/Claude 3.52K类型系统复杂
逻辑实现GPT-3.5/Claude Haiku4K标准算法
测试生成GPT-4/Claude 3.52K边界条件
局部修复GPT-3.5/Claude Haiku1K简单修复

提示词模板结构

1. 角色定义(你是一个...)
2. 任务描述(你需要生成...)
3. 约束条件(必须满足...)
4. 参考信息(根据以下意图...)
5. 输出格式(返回...)

上下文窗口管理

上下文组装算法(增强版)

def assemble_context(module_name: str) -> Context:
    """
    策略:优先级队列 + Token预算 + 智能摘要
    """
    # 1. 加载AGENTS.md(必须)
    agents_md = load_agents_md(module_name)
    tokens_used = count_tokens(agents_md)

    # 2. 按优先级加载skills
    skills_refs = extract_skill_refs(agents_md)
    skills_md = ""

    # 按优先级排序
    priority_map = {
        'critical': 1.0,
        'functional': 0.8,
        'optimization': 0.5
    }

    skills_refs.sort(key=lambda s: priority_map.get(s.category, 0.5), reverse=True)

    for ref in skills_refs:
        skill_md = load_skill(ref.path)
        if tokens_used + count_tokens(skill_md) <= MAX_TOKENS:
            skills_md += f"\n## {ref.name}\n{skill_md}"
            tokens_used += count_tokens(skill_md)
        else:
            # 跳过低优先级skill
            if priority_map.get(ref.category, 0.5) < 0.8:
                print(f"  ⚠️  跳过低优先级skill: {ref.name}")
                continue

    # 3. 加载依赖接口摘要(优先于完整实现)
    dependencies = resolve_dependencies(module_name)
    interfaces_summary = load_interface_signatures(dependencies)

    # 如果摘要仍超出预算,使用更精简版本
    if tokens_used + count_tokens(interfaces_summary) > MAX_TOKENS:
        interfaces_summary = load_minimal_interfaces(dependencies)

    return Context(
        agents_md=agents_md,
        skills_md=skills_md,
        dependencies=interfaces_summary
    )

智能摘要生成

# 第一次编译
$ nlcc build logger
  ✓ 加载 modules/logger/AGENTS.md (2450 tokens)
  ✓ 加载 skills/output.md (1200 tokens)
  📝 生成摘要: build/.ir/logger-summary.json

# 第二次编译(依赖模块)
$ nlcc build network
  ✓ 加载 modules/network/AGENTS.md (3100 tokens)
  📝 使用摘要: logger (150 tokens) ← 而不是完整的 2450 tokens
  ✓ 总计: 3250 tokens (节省了 2300 tokens)

摘要格式

// build/.ir/logger-summary.json
{
  "module": "logger",
  "version": "1.0.0",
  "hash": "a1b2c3d4",

  "exports": [
    {
      "name": "logger_log",
      "signature": "fn(logger: &Logger, message: &str)",
      "thread_safe": true
    },
    {
      "name": "logger_set_level",
      "signature": "fn(logger: &mut Logger, level: LogLevel) -> Result<(), Error>",
      "thread_safe": false
    }
  ],

  "constraints": {
    "performance": "<100μs",
    "memory": "<10MB"
  },

  "metadata": {
    "generated_at": "2026-02-20T10:30:00Z",
    "tokens_saved": 2300
  }
}

多轮迭代修正(增强版)

迭代生成流程

def generate_with_verification(
    module: str,
    ir: IR,
    max_iterations: int = 3
) -> GenerationResult:
    """
    带熔断机制的代码生成
    """
    for iteration in range(1, max_iterations + 1):
        print(f"[{iteration}/{max_iterations}] 生成代码...")

        # 1. 生成代码
        code = llm.generate(ir)

        # 2. L0: 语法验证
        compile_result = compile_check(code)
        if not compile_result.success:
            print(f"  ❌ 编译失败: {compile_result.error_summary}")

            # 局部修复(只把错误相关上下文发给LLM)
            error_context = extract_error_context(
                compile_result.errors,
                code  # 只传递相关代码行
            )

            print(f"  🤖 尝试局部修复...")
            code = llm.fix_local_error(code, error_context)
            continue  # 重试

        print(f"  ✅ 编译通过")

        # 3. L1: 单元测试
        test_result = run_tests(code)
        if not test_result.success:
            print(f"  ❌ 测试失败: {test_result.failures}")

            # 分析失败原因
            failure_context = analyze_test_failure(
                test_result.failures,
                code
            )

            print(f"  🤖 尝试修复测试...")
            code = llm.fix_test_failure(code, failure_context)
            continue  # 重试

        print(f"  ✅ 测试通过")

        # 4. 成功
        return GenerationResult(
            success=True,
            code=code,
            iterations=iteration
        )

    # 熔断:超过最大重试次数
    print(f"  ⚠️  达到最大重试次数 ({max_iterations}),触发熔断")

    # 生成占位代码 + 显式错误报告
    return generate_placeholder_with_error(
        module=module,
        last_error=compile_result.error_summary,
        ir=ir
    )


def extract_error_context(
    errors: List[CompilerError],
    code: str
) -> ErrorContext:
    """
    提取错误相关的代码上下文(局部修复)

    只把错误附近的代码发给LLM,而不是整个文件
    """
    # 示例:Rust 编译器错误
    # error[E0425]: cannot find value `x` in this scope
    #    --> src/logger.rs:45:20

    error_contexts = []
    for error in errors:
        # 定位错误行
        line = error.line_number
        col = error.column_number

        # 只提取错误前后的 5 行(而不是整个文件)
        context = extract_lines_around(code, line, radius=5)

        error_contexts.append(ErrorContext(
            error_code=error.code,  # E0425
            message=error.message,
            relevant_code=context,
            line=line,
            col=col
        ))

    return error_contexts


def generate_placeholder_with_error(
    module: str,
    last_error: str,
    ir: IR
) -> GenerationResult:
    """
    生成占位代码并抛出显式错误
    """
    placeholder = f"""
// 🔴 NLCC 自动生成的占位代码
// ⚠️  模块 '{module}' 生成失败,需要人工介入
//
// 最后一次错误:
// {last_error}
//
// 请检查:
// 1. modules/{module}/AGENTS.md 是否描述清晰
// 2. 是否有冲突的 skills/*.md
// 3. 运行 nlcc check --verify-interfaces 检查接口一致性

// TODO: 请手工实现此模块

{generate_stub_from_ir(ir)}
"""

    # 记录到构建日志
    build_log.record_failure(
        module=module,
        error=last_error,
        timestamp=datetime.now()
    )

    # 阻断下游构建
    block_dependent_modules(module)

    return GenerationResult(
        success=False,
        code=placeholder,
        error=last_error
    )

产物验证与质量保证

自动化验证流水线

层次1:编译验证(L0)
  ↓ 通过
层次2:单元测试(L1)
  ↓ 通过
层次3:集成测试
  ↓ 通过
层次4:安全扫描(允许警告)(L2)

影响范围分析

算法

  1. 检测变更类型(AGENTS.md / skills / 接口)
  2. 解析依赖图
  3. BFS传播影响
  4. 标记需要重新生成的模块
  5. 生成拓扑排序的构建顺序

开发工具链

CLI工具规范

nlcc init [project-name]          # 初始化项目
nlcc build [module-name]          # 编译模块
nlcc build --interfaces-only      # 只编译接口
nlcc build --implementations      # 只编译实现
nlcc check --ir-only              # 查看IR
nlcc check --verify-interfaces    # 验证接口一致性
nlcc check --export-ir            # 导出IR文件
nlcc analyze-impact <file-path>   # 分析影响
nlcc serve [--port=3000]          # 启动Web界面
nlcc test [--coverage]            # 运行测试
nlcc check [--security]           # 代码检查

项目配置

# .nlcc/config.toml

[project]
name = "my-nlcc-project"
version = "0.1.0"

[compiler]
target_language = "rust"
default_model = "gpt-4"
max_context_tokens = 8000
max_iterations = 3

# Token预算配置
[compiler.tasks]
generate = 8000      # 代码生成
check = 4000         # 静态检查
test = 6000          # 测试生成

# 优先级配置
[compiler.priorities]
critical = 1.0
functional = 0.8
optimization = 0.5

[build]
strategy = "auto"
parallel_jobs = 4

[testing]
enable_auto_tests = true
coverage_target = 80

[security]
enable_auto_scan = true

安全与伦理边界

提示词注入防护

检测可疑模式

  • "ignore instruction"
  • "forget above"
  • "new instruction"
  • HTML标签注入

防护措施

  1. 扫描并警告
  2. 自动清理危险内容
  3. 沙盒执行环境

沙盒执行

Docker隔离

  • 只读文件系统挂载
  • 禁止网络访问
  • 限制CPU和内存
  • 超时自动终止

开发路线图(修订)

Phase 1: MVP(2个月)

✅ 基础CLI工具
✅ 简单的IR层(JSON格式)
✅ 单一LLM调用
✅ Rust支持
✅ 编译验证
✅ 接口编译 + 实现编译
✅ 基础熔断机制

Phase 2: Beta(3个月)

✅ 完整的IR层
✅ Skills系统
✅ 多轮迭代
✅ 测试生成
✅ 影响分析
✅ Source Map生成
✅ 补丁系统
✅ Token预算管理器

Phase 3: v1.0(2个月)

✅ Web界面
✅ 完整的验证流水线(L0+L1+L2)
✅ 安全审计
✅ 完整文档
✅ 团队协作工具

Phase 4: 多语言Beta(3个月)

✅ Go后端
✅ Python后端
✅ 跨语言接口定义
✅ FFI桩生成

Phase 5: 生态扩展(长期)

✅ 插件系统
✅ 第三方扩展
✅ 社区贡献

代码生成与验证流水线

多级验证架构

NLCC 的核心价值不是生成代码,而是保证代码正确性。

┌─────────────────────────────────────────────────┐
│  L0: 语法验证(编译器检查)                      │
│  rustc --check / go build / python -m py_compile │
└──────────────┬──────────────────────────────────┘
               ↓ 通过
┌─────────────────────────────────────────────────┐
│  L1: 行为验证(单元测试)                        │
│  自动生成的测试 + 编译验证                        │
└──────────────┬──────────────────────────────────┘
               ↓ 通过
┌─────────────────────────────────────────────────┐
│  L2: 静态分析(可选,允许警告)                   │
│  Clippy / Golangci-lint / Pylint                │
└──────────────┬──────────────────────────────────┘
               ↓ 通过
┌─────────────────────────────────────────────────┐
│  ✓ 验证通过,代码可用                            │
└─────────────────────────────────────────────────┘

熔断机制示例

$ nlcc build

[1/6] logger        ✅ 编译通过
[2/6] storage       ✅ 编译通过
[3/6] network       ❌ 生成失败
   🤖 尝试 1/3: 编译错误 E0382 (use of moved value)
   🤖 尝试 2/3: 编译错误 E0502 (cannot borrow as mutable)
   🤖 尝试 3/3: 测试失败 (test_reconnect 超时)
   ⚠️  达到最大重试次数,触发熔断

   📄 生成占位代码: build/src/network/impl.rs
   ❌ 阻断依赖模块: app (依赖 network)

   💡 建议:
   1. 检查 modules/network/AGENTS.md
   2. 运行 nlcc check --verify-interfaces
   3. 查看构建日志: build/.nlcc/network-build.log

构建结果:✅ 2 成功, ❌ 1 失败, ⏸️  1 阻断

错误隔离

关键原则:单个模块失败不影响其他模块(除非有依赖关系)。

# 按拓扑排序构建
for module in topological_sort():
    try:
        # 独立的LLM上下文(不受其他模块错误影响)
        result = build_module(module)
        results[module] = result
    except Exception as e:
        # 记录失败,但继续构建其他模块
        results[module] = BuildResult(
            success=False,
            error=str(e)
        )
        continue

# 分析影响
analyze_impact(results)

调试与可维护性

Source Map:从代码到意图的映射

为什么需要 Source Map?

当 AI 生成的代码出现 Bug 时,传统调试方式面临挑战:

  • 断点打在 impl.rs:45,但这个位置对应哪个意图描述?
  • 如何从代码行回溯到 AGENTS.md 的哪个章节?
  • 修复 Bug 后,如何将修改回馈到源码?

NLCC 通过 Source Map 解决这个问题。

Source Map 结构

// build/.sourcemaps/logger.sourcemap.json
{
  "version": 3,
  "module": "logger",
  "generated_file": "build/src/logger/impl.rs",
  "source_files": [
    "modules/logger/AGENTS.md",
    "modules/logger/skills/output.md",
    "modules/logger/skills/thread_safety.md"
  ],

  "mappings": {
    "45": {
      "function": "logger_log",
      "source": "AGENTS.md",
      "source_line": 12,
      "source_column": 5,
      "description": "线程安全日志记录",
      "skills_involved": ["thread_safety.md"]
    },
    "78": {
      "function": "format_json",
      "source": "skills/json_format.md",
      "source_line": 8,
      "description": "JSON序列化",
      "name": "timestamp格式化"
    },
    "120": {
      "function": "logger_flush",
      "source": "AGENTS.md",
      "source_line": 25,
      "description": "刷新缓冲区",
      "optimization": "内存池优化"
    }
  },

  "metadata": {
    "generated_at": "2026-02-20T10:30:00Z",
    "generator": "nlcc v2.0",
    "llm_model": "gpt-4",
    "iteration_count": 2
  }
}

调试工具集成

IDE 插件示例(VS Code)

// .vscode/settings.json
{
  "nlcc.enableSourceMaps": true,
  "nlcc.autoNavigate": true
}

使用场景

// build/src/logger/impl.rs:45
pub fn logger_log(logger: &Logger, message: &str) {
    // 💡 IDE 提示:此代码来自 AGENTS.md:12

    // 🔍 点击这里,自动跳转到 AGENTS.md:12
    let formatted = format!("[LOG] {}", message);

    // ❌ Bug: 这里有空指针风险
    write_to_file(&logger.file, &formatted);
}

按 Ctrl+Click(或 Cmd+Click) → 自动打开 AGENTS.md:12

# modules/logger/AGENTS.md:12

## 核心接口

pub fn logger_log(logger: &Logger, message: &str)


## 主要职责
1. 接收日志消息  ← ← ← ← ← ← 你在这里
2. 格式化输出
3. 写入目标

反向映射:从错误到意图

编译器错误 → 意图描述

# 编译错误
$ cargo build
error[E0382]: use of moved value: `logger.file`
   --> build/src/logger/impl.rs:45:20
    |
45  |     write_to_file(&logger.file, &formatted);
    |                    ^^^^^^^^^^^ value moved here

# NLCC 增强错误信息
$ nlcc build
error[E0382]: use of moved value
   --> build/src/logger/impl.rs:45:20
    |
    = 📍 意图来源: modules/logger/AGENTS.md:12 (线程安全日志记录)
    = 📖 相关约束: skills/thread_safety.md (必须使用 Arc 保护)
    = 💡 建议: 在 AGENTS.md 中明确说明"使用 Arc 保护共享状态"

补丁系统:手工修改的持久化

问题场景

  1. AI 生成的代码有 Bug
  2. 人工修复了代码
  3. 下次重新编译时,修复被覆盖

解决方案:受保护的手工编辑区域

代码标识

// ========== NLCC GENERATED BEGIN ==========
// 🔒 此区域由 AI 生成,重新编译时会被覆盖
pub fn logger_log(logger: &Logger, message: &str) {
    let formatted = format!("[LOG] {}", message);
    write_to_file(&logger.file, &formatted);
}
// ========== NLCC GENERATED END ==========

// ========== MANUAL PATCH BEGIN (issue #42) ==========
// 📝 手工修复: 修复并发场景下的文件句柄竞争问题
// 🔗 Issue: https://github.com/.../issues/42
// 👤 审查: twg2020, 2026-02-20
// ✅ 测试: test_concurrent_logging passed
pub fn logger_log_threadsafe(logger: &Logger, message: &str) {
    let file = logger.file.clone();  // 使用 Arc
    let formatted = format!("[LOG] {}", message);
    write_to_file(&file, &formatted);  // 线程安全
}
// ========== MANUAL PATCH END ==========

重新生成时的行为

def regenerate_with_patches(
    module: str,
    agents_md: str
) -> str:
    """
    重新生成代码,保留手工补丁
    """
    # 1. 读取当前代码
    current_code = read_generated_code(module)

    # 2. 提取手工编辑区域
    manual_patches = extract_manual_sections(current_code)

    # 3. 生成新的 AI 代码
    new_ai_code = llm.generate(agents_md)

    # 4. 合并:保留手工部分
    final_code = merge_code(new_ai_code, manual_patches)

    # 5. 写入文件
    write_code(module, final_code)

    # 6. 报告
    print(f"✅ 重新生成完成,保留了 {len(manual_patches)} 个手工补丁")

    return final_code


def extract_manual_sections(
    code: str
) -> List[ManualPatch]:
    """
    提取手工编辑区域
    """
    patches = []

    # 正则匹配
    pattern = r"""
        MANUAL\ PATCH\ BEGIN
        \((.*?)\)      # 捕获元数据,如 (issue #42)
        .*?            # 补丁内容
        MANUAL\ PATCH\ END
    """

    for match in re.finditer(pattern, code, re.DOTALL):
        metadata = match.group(1)
        content = match.group(0)

        patches.append(ManualPatch(
            metadata=metadata,
            content=content,
            start_line=match.start(),
            end_line=match.end()
        ))

    return patches

Web 界面可视化

┌──────────────────────────────────────────────┐
│ 📝 logger/impl.rs                            │
├──────────────────────────────────────────────┤
│                                              │
│ 🟢 AI 生成区域 (绿色背景)                     │
│ pub fn logger_log(...) { ... }               │
│                                              │
│ 🟡 手工编辑区域 (黄色背景,受保护)            │
│ // ========== MANUAL PATCH BEGIN =========   │
│ pub fn logger_log_fast(...) { ... }          │
│ // ========== MANUAL PATCH END ============   │
│                                              │
└──────────────────────────────────────────────┘

💡 提示:下次构建时,黄色区域将被保留

Web可视化界面

界面布局

┌─────────────────────────────────────────────────────────────────┐
│  NLCC Web Studio                                          🔔 📊 │
├──────────┬──────────────────────────────────────────────────────┤
│          │                                                       │
│  📁 项目  │  📝 编辑器区                              👁️ 预览区  │
│  浏览器   │                                                       │
│          │  AGENTS.md - Logger Module                  impl.rs   │
│  ┌──────┐ │  ┌────────────────────────────────────┐  ┌────────┐│
│  │ AGENT│ │  │ # Logger Module                     │  │pub...  ││
│  │  .md │ │  │                                     │  │        ││
│  │      │ │  │ ## 功能定位                         │  │fn log  ││
│  └──────┘ │  │ 记录应用日志到文件和控制台...      │  │_logger ││
│    ↓      │  │                                     │  │(msg)   ││
│  ┌──────┐ │  │ ## 核心接口                         │  │{       ││
│  │skills│ │  │ ```rust                              │  │  ...   ││
│  │      │ │  │ pub fn logger_log(...);              │  │}       ││
│  └──────┘ │  │ ```                                 │  │        ││
│    ↓      │  │                                     │  │        ││
│  ┌──────┐ │  └────────────────────────────────────┘  └────────┘│
│  │build │ │                                                       │
│  │      │ │  ┌──────────────────────────────────────────────┐  │
│  └──────┘ │  │ 📊 状态面板                                 │  │
│          │  │                                              │  │
│          │  │ ✅ logger/AGENTS.md    hash: a1b2c3d4        │  │
│          │  │ ✅ logger/impl.rs      已生成 2024-02-19     │  │
│          │  │ ⏳ network/AGENTS.md   hash: e5f6g7h8       │  │
│          │  │ 🔄 network/impl.rs     需要重新生成          │  │
│          │  │                                              │  │
│          │  └──────────────────────────────────────────────┘  │
│          │                                                       │
│          │  ┌──────────────────────────────────────────────┐  │
│          │  │ 🔧 构建控制                                   │  │
│          │  │                                              │  │
│          │  │ 策略: [auto ▼]  一键构建: [🚀 Build All]     │  │
│          │  │                                              │  │
│          │  │ 进度: ████████░░ 80% (4/5 modules)            │  │
│          │  │                                              │  │
│          │  │ ✅ logger     ✅ storage   ✅ common         │  │
│          │  │ ✅ network   ⏳ testing                     │  │
│          │  │                                              │  │
│          │  └──────────────────────────────────────────────┘  │
└──────────┴──────────────────────────────────────────────────────┘

核心功能模块

1. 项目浏览器(左侧面板)

功能

  • 📁 树形显示项目结构
  • 🔍 搜索文件
  • 🏷️ 标签显示(已生成、需更新、冲突)
  • 📊 依赖关系图可视化

交互

  • 点击文件 → 在编辑器中打开
  • 右键文件 → 显示上下文菜单

    • 重命名
    • 删除
    • 查看历史
    • 对比版本

状态标识

📁 modules/
  📁 logger/
    ✅ AGENTS.md      (已生成,无变化)
    ✅ output.md
    ✅ thread_safety.md
    📄 impl.rs        (生成时间: 2024-02-19 10:30)

  📁 network/
    🔄 AGENTS.md      (源文件已变化,需重新生成)
    📄 impl.rs        (旧版本)

2. 实时代码编辑器(中间面板)

功能

  • 📝 Monaco Editor(VS Code同款)
  • 🎨 语法高亮(Markdown)
  • 🔍 实时预览(渲染后的Markdown)
  • 💾 自动保存(防丢失)
  • 📜 版本历史(可回滚)

自动保存机制

editor.onDidChangeModelContent(() => {
  // 防抖:停止输入1秒后自动保存
  debounce(() => {
    this.autoSave();
  }, 1000);
});

autoSave() {
  // 保存到服务器
  this.saveToServer();

  // 自动计算hash
  const newHash = this.calculateHash();

  // 自动更新状态
  this.updateModuleStatus(newHash);
}

辅助功能(增强)

  • 🤖 AI提示:当光标停在某个位置时,AI可以提供建议
  • 📖 文档悬浮:鼠标悬停在关键词上显示文档
  • 🔗 跳转:点击 [[network/AGENTS.md]] 自动跳转
  • 🗺️ Source Map 导航:点击生成的代码,自动跳转到对应的 AGENTS.md 章节

3. 实时代码预览(右侧面板)

功能

  • 👁️ 预览生成的代码
  • 🔄 实时同步(编辑器变化时)
  • 📊 差异对比(新旧版本对比)

智能同步

// 当AGENTS.md变化时
onAGENTSMDChanged() {
  // 防抖:停止输入3秒后预览
  debounce(() => {
    // 调用AI生成预览(仅预览,不写入文件)
    this.previewGeneratedCode();
  }, 3000);
}

previewGeneratedCode() {
  // 显示加载动画
  this.showLoading();

  // AI生成(不保存)
  const previewCode = await this.ai.generatePreview(this.currentAGENTS);

  // 显示预览
  this.showPreview(previewCode);

  // 显示差异对比
  this.showDiff(this.oldCode, previewCode);
}

4. 状态监控面板(增强)

功能

  • 📊 实时显示所有模块状态
  • 🔔 自动通知(需要重新生成时)
  • 📈 构建统计
  • IR 状态:显示 IR 是否变化

状态显示

┌────────────────────────────────────────┐
│ 📊 构建状态                            │
├────────────────────────────────────────┤
│                                         │
│ ✅ logger      已生成 2024-02-19 10:30 │
│    IR: a1b2c3d4 (未变化)              │
│                                         │
│ ✅ storage    已生成 2024-02-19 10:35 │
│    IR: d4e5f6g7 (未变化)              │
│                                         │
│ 🔄 network    需要重新生成              │
│    IR: e5f6g7h8 → f6g7h8i9 (已变化)   │
│                                         │
│ ⏳ testing    未生成                    │
│                                         │
│ 总计: 2/4 模块已生成                    │
│                                         │
└────────────────────────────────────────┘

5. 一键构建控制(底部面板)

功能

  • 🚀 一键构建所有模块
  • ⚙️ 策略选择(auto/always/preserve)
  • 📊 进度条显示
  • 📝 构建日志

构建按钮

<button onclick="buildAll()">
  🚀 构建所有模块
  <span class="badge">2 个需要更新</span>
</button>

<select id="strategy">
  <option value="auto">自动(推荐)</option>
  <option value="always">总是重新生成</option>
  <option value="preserve">保留手工修改</option>
</select>

构建流程可视化

🚀 开始构建...

✅ [1/6] logger       → 已是最新,跳过
⏳ [2/6] storage     → 正在生成...
   🤖 AI理解需求中...
   ✅ 代码生成完成
   ✅ 编译通过

🔄 [3/6] network     → 检测到源文件变化
   💾 已备份: network/impl.rs.backup
   🤖 AI理解需求中...
   ✅ 代码生成完成
   ✅ 编译通过

⏳ [4/6] testing     → 正在生成...
...

🎉 构建完成!成功: 6, 失败: 0, 跳过: 0

自动化构建系统

自动决策逻辑

实时监控系统

// 后台自动运行
class NLCCWebMonitor {
  constructor() {
    this.fileHashes = new Map();  // 缓存所有文件的hash
    this.watchers = new Map();    // 文件监控器
  }

  // 启动监控
  startWatching(projectPath) {
    // 扫描所有 AGENTS.md 和 skills/*.md
    const files = this.scanProject(projectPath);

    files.forEach(file => {
      const watcher = fs.watch(file.path, () => {
        this.onFileChanged(file);
      });
      this.watchers.set(file.path, watcher);
    });
  }

  // 文件变化时自动判断
  onFileChanged(file) {
    const newHash = this.calculateHash(file.path);
    const oldHash = this.fileHashes.get(file.path);

    if (newHash !== oldHash) {
      // 源文件变化
      this.fileHashes.set(file.path, newHash);

      // 自动标记需要重新生成
      this.markForRegeneration(file.module);

      // 通知前端:状态变化
      this.notifyFrontend({
        type: 'FILE_CHANGED',
        module: file.module,
        needsRegeneration: true
      });
    }
  }
}

完全无需人工决策

// 前端自动显示状态
class BuildStatusPanel {
  render() {
    const modules = this.getModuleStatus();

    modules.forEach(module => {
      if (module.hashChanged) {
        // 自动显示"需要重新生成"图标
        this.showIcon(module.name, '🔄 需要重新生成');
      } else if (module.implExists) {
        // 自动显示"已生成"图标
        this.showIcon(module.name, '✅ 已生成');
      } else {
        // 自动显示"未生成"图标
        this.showIcon(module.name, '⏳ 未生成');
      }
    });
  }
}

三种策略模式

1. auto(自动,默认)✅

行为

  • AGENTS.md不变 → 保留手工修改,跳过生成
  • AGENTS.md变化 → 重新生成,自动备份

界面显示

┌──────────────────────────────────┐
│ 策略: 自动                        │
├──────────────────────────────────┤
│ ✅ logger    AGENTS.md未变化      │
│    → 跳过,保留手工修改           │
│                                   │
│ 🔄 network  AGENTS.md已变化       │
│    → 重新生成,自动备份           │
│    💾 backup/impl.rs.20240219    │
└──────────────────────────────────┘

适用场景:日常开发

2. always(总是重新生成)🔄

行为

  • 总是重新生成,忽略手工修改
  • 不自动备份(或备份到临时目录)

界面显示

┌──────────────────────────────────┐
│ 策略: 总是重新生成                │
├──────────────────────────────────┤
│ 🔄 logger    强制重新生成         │
│    → 覆盖手工修改                 │
│                                   │
│ 🔄 network  强制重新生成          │
│    → 覆盖手工修改                 │
└──────────────────────────────────┘

适用场景

  • CI/CD
  • 发布前构建
  • 确保完全由AI生成

3. preserve(总是保留)🛡️

行为

  • 总是保留手工修改,不重新生成
  • 即使AGENTS.md变化

界面显示

┌──────────────────────────────────┐
│ 策略: 保留手工修改                │
├──────────────────────────────────┤
│ 🛡️ logger   保留手工修改         │
│    → 忽略 AGENTS.md 变化          │
│                                   │
│ 🛡️ network  保留手工修改         │
│    → 忽略 AGENTS.md 变化          │
└──────────────────────────────────┘

适用场景

  • 调试阶段
  • 极端性能优化
  • 手工修复关键bug

手工编辑区域保护

可视化标识

在代码编辑器中,用不同颜色标识不同区域:

// 🟢 AI生成的区域(绿色背景)
// ========== NLCC GENERATED BEGIN ==========
pub fn logger_log(logger: &Logger, message: &str) {
    eprintln!("[LOG] {}", message);
}
// ========== NLCC GENERATED END ==========

// 🟡 手工编辑区域(黄色背景,受保护)
// ========== MANUAL EDIT BEGIN (fast_log) ==========
pub fn fast_log(message: &str) {
    // 手工优化的特殊函数
    unsafe {
        // 直接系统调用
    }
}
// ========== MANUAL EDIT END ==========

重新生成时的行为

// 重新生成时
regenerate() {
  // 1. 读取当前代码
  const currentCode = fs.readFileSync('impl.rs', 'utf8');

  // 2. 提取手工编辑区域
  const manualSections = this.extractManualSections(currentCode);

  // 3. 生成新的AI代码
  const newAICode = await this.ai.generate(this.agentsMD);

  // 4. 合并:保留手工部分
  const finalCode = this.mergeCode(newAICode, manualSections);

  // 5. 写入文件
  fs.writeFileSync('impl.rs', finalCode, 'utf8');

  // 6. 通知前端
  this.notifyFrontend({
    type: 'CODE_REGENERATED',
    preserved: manualSections.length,
    regenerated: true
  });
}

智能通知系统

自动通知触发条件

// 通知触发器
const notificationTriggers = {
  // 1. 检测到源文件变化
  onSourceChanged: (module) => {
    this.showNotification({
      title: `${module} 需要重新生成`,
      message: '检测到 AGENTS.md 或 skills/*.md 变化',
      level: 'info',
      actions: [
        { label: '立即生成', primary: true, action: () => this.build(module) },
        { label: '查看差异', action: () => this.showDiff(module) }
      ]
    });
  },

  // 2. 构建成功
  onBuildSuccess: (module) => {
    this.showNotification({
      title: '构建成功',
      message: `${module} 已成功生成`,
      level: 'success',
      duration: 3000
    });
  },

  // 3. 构建失败
  onBuildFailed: (module, error) => {
    this.showNotification({
      title: '构建失败',
      message: `${module}: ${error.message}`,
      level: 'error',
      actions: [
        { label: '查看日志', action: () => this.showBuildLog(module) },
        { label: '重试', action: () => this.retryBuild(module) }
      ]
    });
  },

  // 4. 检测到冲突
  onConflictDetected: (module) => {
    this.showNotification({
      title: '检测到冲突',
      message: `${module} 的 impl.rs 有手工修改,但 AGENTS.md 也变化了`,
      level: 'warning',
      actions: [
        { label: '覆盖(备份)', primary: true, action: () => this.buildWithBackup(module) },
        { label: '保留手工', action: () => this.preserveManual(module) },
        { label: '查看对比', action: () => this.showDiff(module) }
      ]
    });
  }
};

依赖关系可视化

图形化显示

// 使用 D3.js 或 Cytoscape.js 渲染依赖图
class DependencyGraph {
  render(modules) {
    const nodes = modules.map(m => ({
      id: m.name,
      label: m.name,
      status: m.status,  // 'up-to-date', 'needs-update', 'error'
      dependencies: m.deps
    }));

    const edges = [];
    modules.forEach(m => {
      m.deps.forEach(dep => {
        edges.push({
          from: dep,
          to: m.name,
          label: 'depends on'
        });
      });
    });

    // 渲染图形
    this.graph = new Cytoscape({
      container: document.getElementById('dependency-graph'),
      elements: { nodes, edges },
      style: [
        {
          selector: 'node',
          style: {
            'background-color': (node) => {
              switch(node.data('status')) {
                case 'up-to-date': return '#4CAF50';
                case 'needs-update': return '#FF9800';
                case 'error': return '#F44336';
                default: return '#9E9E9E';
              }
            }
          }
        }
      ]
    });
  }
}

交互功能

  • 🖱️ 点击节点:显示模块详情
  • 🔍 高亮路径:显示完整的依赖链
  • 🏷️ 过滤显示:只显示需要更新的模块
  • 📐 自动布局:层次化布局算法

实践指南

工作流程

# 1. 人类修改意图
vim modules/logger/skills/json_format.md

# 2. 触发"编译"
nlcc build

# 3. NLCC自动执行
Reading modules/logger/AGENTS.md...
  → Loading skills/output.md...
  → Loading skills/json_format.md...
Generating code...
  → build/src/logger/impl.rs
  → build/include/logger.rs
Compiling...
  → cargo build --release
Testing...
  → All tests passed
Build complete!

# 4. 查看生成的代码(可选,就像今天看汇编)
cat build/src/logger/impl.rs

# 5. 运行
cargo run --release

与传统编译器的对比

传统编译器(Rustc)自然语言编译器(NLCC)
输入:Rust代码输入:自然语言(AGENTS.md)
输出:机器码/汇编输出:Rust代码
错误:借用检查、类型推断错误错误:意图模糊、逻辑矛盾
优化:MIR优化、LLVM优化优化:模块拆分、依赖管理
调试:看MIR/汇编(--emit mir)调试:看生成的Rust代码
工具链:Cargo → Rustc → LLVM工具链:意图分析 → IR生成 → 代码生成 → Cargo编译

Web版实际使用场景

场景1:首次创建项目

1. 打开 NLCC Web Studio
   → 自动创建示例项目结构

2. 在项目浏览器中创建新模块
   右键 → 新建模块 → 输入名称: "logger"

3. 编辑 AGENTS.md
   在编辑器中编写:

# Logger Module

## 功能
记录日志到文件和控制台
...


4. 自动保存 + 实时预览
→ 右侧自动显示生成的代码预览

5. 点击"🚀 构建当前模块"
→ 自动生成 impl.rs
→ 自动编译
→ 显示构建结果

场景2:修改已有模块

1. 在项目浏览器中打开 logger/AGENTS.md
   → 编辑器显示当前内容

2. 修改需求
   添加:

## 新需求
支持 JSON 格式输出


3. 自动检测变化
→ 状态面板自动显示: 🔄 logger 需要重新生成
→ 右下角弹出通知

4. 查看预览
→ 右侧自动显示新代码预览
→ 高亮显示差异部分

5. 点击"🚀 构建当前模块"
→ 自动备份旧版本: impl.rs.backup
→ 生成新版本
→ 显示对比

场景3:手工修改 + 自动保护

1. 手工编辑生成的代码
   在 impl.rs 中添加:

// ========== MANUAL EDIT BEGIN ==========
pub fn fast_log(msg: &str) {

 // 手工优化的特殊函数

}
// ========== MANUAL EDIT END ==========


2. 下次重新生成时
→ 自动识别手工编辑区域
→ 保留手工部分
→ 只覆盖 AI 生成的部分

3. 可视化显示
→ 在编辑器中用不同颜色标识:
   - 🟢 绿色: AI生成的区域
   - 🟡 黄色: 手工编辑区域(受保护)

如何开始

1. 从小项目开始

  • 不要在大型遗留项目上尝试
  • 选择新项目、工具项目、实验性项目

2. 设计MD架构

  • 划分模块:哪些功能是独立的?
  • 编写项目级AGENTS.md
  • 编写模块级AGENTS.md
  • 编写skills/*.md

3. 验证提示词质量

  • 给另一个AI看你的AGENTS.md
  • 它能理解这个模块做什么吗?
  • 它知道如何使用这个模块吗?

4. 维护MD,而不是代码

  • 需要修改功能时,编辑AGENTS.md
  • 运行 nlcc build 重新生成
  • 不要直接编辑 build/ 下的代码

调试与质量保证

调试三层模型

当AI生成的代码出现问题时,调试需要在三个层次进行:

1. 意图层(AGENTS.md)
   ↓ 问题:需求描述不清晰或矛盾?
   ↓ 解决:优化MD描述,添加更多上下文

2. 理解层(AI推理)
   ↓ 问题:AI是否正确理解了意图?
   ↓ 解决:添加示例代码,明确约束条件

3. 实现层(生成的代码)
   ↓ 问题:代码实现有bug?
   ↓ 解决:手工修改(保护区域)或修正意图

实战调试策略(增强)

场景1:性能不符合预期

步骤1:定位问题
$ nlcc analyze-performance logger

分析结果:
  瓶颈函数:logger_log()
  耗时:200μs(要求:<100μs)
  调用次数:10,000次/秒

步骤2:查看意图
→ logger/AGENTS.md 中没有明确性能要求

步骤3:修正意图
在 logger/skills/performance.md 中添加:

性能要求

  • logger_log() 必须在 100μs 内完成
  • 允许使用内存缓存优化性能

    
    步骤4:重新生成
    $ nlcc build logger
    
    结果:
    ✓ 性能提升至 80μs
    ✓ 使用了内存池优化

场景2:偶发性Bug

// network/impl.rs
// AI生成的代码有并发bug
pub fn handle_connection(&mut self, conn: &Connection) {
    // ❌ Bug:数据竞争
    self.active_connections.push(conn);
}
调试过程:

1. 查看AGENTS.md
   → 发现没有明确线程安全要求

2. 添加skill
   创建 network/skills/thread_safety.md:

## 线程安全

  • handle_connection 可能被多线程调用
  • 必须使用 Mutex 或 Arc 保护共享状态

    
    3. 重新生成
    → AI自动生成线程安全的代码
    
    4. 验证
    → 运行并发测试,问题解决

质量保证工具链(增强)

# 1. 静态分析(增强)
$ nlcc check
✓ 检查所有AGENTS.md的完整性
✓ 验证模块间依赖关系
✓ 检测冲突的skills
✓ 验证IR一致性
⚠️  warning: logger/skills/performance.md 与 low_memory.md 有潜在冲突

# 2. 单元测试生成
$ nlcc test generate --unit

为每个模块自动生成单元测试:
  ✓ logger/tests/test_logger.rs
  ✓ network/tests/test_network.rs
  测试覆盖率目标:80%

# 3. 集成测试
$ nlcc test integration

运行端到端集成测试:
  ✓ 测试完整的数据流
  ✓ 验证模块间接口契约
  ✓ 性能基准测试

# 4. 回归测试
$ nlcc test regression --before logger-v1.0.0 --after logger-v2.0.0

对比版本间行为差异:
  ✓ 性能变化:+5%(可接受)
  ⚠️ 内存使用:+20%(需要优化)

团队协作最佳实践

1. 版本控制策略

推荐的工作流:

项目结构(Git仓库):
  .gitignore:
    build/          # 忽略生成的代码
    *.backup        # 忽略备份文件
    .nlcc/cache/    # 忽略AI响应缓存
    .ir/         # 忽略IR文件

  提交规范:
    ✅ 提交 modules/ 和 AGENTS.md(源代码)
    ❌ 不提交 build/(生成产物)
    ✅ 提交 tests/(测试代码)
    ✅ 提交 .nlcc/config.toml(项目配置)

  CI/CD集成:
    .github/workflows/nlcc-ci.yml:
      1. 检出代码
      2. 运行 nlcc check(验证MD完整性)
      3. 运行 nlcc check --verify-interfaces
      4. 运行 nlcc build(生成代码)
      5. 运行 cargo test(测试)
      6. 运行 nlcc benchmark(性能基准)

2. 协作规范

# .nlcc/TEAM_GUIDELINES.md

## AGENTS.md 编写规范

### 统一的风格
- 使用一致的章节结构
- 功能描述不超过3句话
- 接口定义必须包含类型和用途

### 示例对比

❌ 不好的描述:

功能

这个模块负责处理网络相关的一些事情,比如连接管理、数据传输什么的。


✅ 好的描述:

功能

管理TCP连接的生命周期(创建、维护、关闭)
处理异步数据传输(发送、接收、重试)
支持SSL/TLS加密


### Code Review流程
1. PR主要审查AGENTS.md的改动
2. 生成的代码由CI自动验证
3. 只有MD变更需要人工review

## IR管理规范

### IR提交规则
- ✅ .ir/*.json 文件可以提交(方便审查)
- ✅ IR 变化需要说明原因
- ❌ 不依赖 IR 文件构建(自动生成)

## Skills管理规范

### 命名约定
- functional/[功能].md(功能需求)
- critical/[约束].md(关键约束)
- optimization/[目标].md(优化目标)

### 冲突预防
- 在添加新skill前,先运行 `nlcc check-conflict`
- 如果有冲突,在AGENTS.md中明确优先级

3. 知识共享

团队学习路径:

第1周:理解NLCC理念
  - 阅读《NLCC设计哲学》
  - 完成示例项目(编写一个简单模块)
  - 理解"代码是cheap的"核心思想

第2周:实践AGENTS.md编写
  - 选择一个真实的小模块
  - 编写AGENTS.md和skills
  - 团队成员互相review

第3周:掌握调试技巧
  - 学会三层调试模型
  - 熟练使用nlcc工具链
  - 能够快速定位问题根源

第4周:理解IR和验证流水线
  - 学习如何阅读IR文件
  - 掌握nlcc check --verify-interfaces
  - 理解熔断机制的作用

第5周:参与实际项目
  - 在监督下修改真实模块
  - 处理接口变更和冲突解决
  - 积累实战经验

4. 项目模板

# 创建新项目
$ nlcc init my-project --template=web-service

生成的模板包含:
  AGENTS.md                 # 项目级意图
  modules/
    logger/AGENTS.md        # 日志模块示例
    api/AGENTS.md           # API模块示例
    config/AGENTS.md        # 配置模块示例
  tests/
    integration/            # 集成测试框架
  .nlcc/
    config.toml             # 项目配置
    TEAM_GUIDELINES.md      # 团队规范(含上述内容)
  .github/
    workflows/
      nlcc-ci.yml           # CI/CD配置

模板的优势:
  ✓ 新成员快速上手
  ✓ 统一的项目结构
  ✓ 内置最佳实践
  ✓ 自动化的质量检查

技术演化

历史规律:抽象层不断上升

┌─────────────┬──────────────┬─────────────┬──────────────┐
│   时代      │  程序员关注   │  工具       │  输出物      │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 机器码时代  │ 0101序列     │ 手工拨开关  │ 机器码       │
│ 1940s      │              │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 汇编时代    │ 助记符       │ 汇编器      │ 机器码       │
│ 1950s      │ (MOV, ADD)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 高级语言    │ 算法逻辑     │ 编译器      │ 汇编/机器码  │
│ 1970s+     │ (for, if)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ AI时代      │ 业务意图     │ 自然语言    │ 代码         │
│ 2020s+     │ (自然语言)   │ 编译器      │              │
└─────────────┴──────────────┴─────────────┴──────────────┘

类比:代码 = 未来的汇编

今天我们如何看待汇编?

场景1:应用开发
工程师:我要写一个Web服务器
选择:Go、Python、Java
绝不会考虑:手写汇编

场景2:系统编程
工程师:我要写Linux内核
选择:Rust/C语言,偶尔内联汇编
不会全用:纯汇编

场景3:极致优化
工程师:这个加密循环性能不够
考虑:手写汇编优化这一小段

明天我们如何看待代码?

场景1:应用开发
工程师:我要写一个Web服务器
做法:写AGENTS.md描述意图
工具:自然语言编译器(NLCC)
生成:Go/Python代码(自动)
绝不会考虑:手写Go代码

场景2:系统编程
工程师:我要写操作系统内核
做法:写关键模块的AGENTS.md
生成:Rust代码(自动)
偶尔手工优化:极少数性能关键路径

场景3:极致优化
工程师:AI生成的这段代码性能不够
考虑:手工优化这一小段

结论

  • 汇编依然存在,但适用范围极小(1%)
  • 代码依然存在,但适用范围会大大降低(10% → 1%)
  • NLCC不会淘汰代码,就像高级语言不会淘汰汇编

人类工程师的职责演化

现在(高级语言时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 定义接口(.rs文件)
3. 实现逻辑(impl.rs)
4. 调试、测试、优化
5. 维护代码(修复bug、添加功能)
6. Code Review

时间分配

  • 架构设计:10%
  • 写代码:60%
  • 调试测试:20%
  • 维护:10%

未来(NLCC时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 编写意图描述(AGENTS.md)
3. 审查AI生成的代码(偶尔,5%时间)
4. 处理AI搞不定的极端场景(1%时间)
5. 监控系统运行状态

时间分配

  • 架构设计:20%
  • 编写MD:30%
  • 审查代码:5%
  • 极端场景:1%
  • 监控、优化、学习:44%

核心转变

  • 从"如何实现" → "要实现什么"
  • 从"细节控制" → "意图表达"
  • 从"代码维护" → "意图维护"

目标用户

NLCC的目标用户是会写代码的程序员,而不是完全不懂编程的人。

小张 - 后端开发工程师

  • 熟练掌握 Python/Java
  • 经常写重复性代码(CRUD、API接口)
  • 想提高效率:"我只想描述需求,不想手写每一行代码"
  • 痛点:

    • "写 CRUD 很枯燥,但又不能不做"
    • "有时候想法很简单,实现起来要写很多代码"
    • "想快速验证想法,不想浪费时间在样板代码上"

小李 - 全栈开发者

  • 前后端都能写
  • 经常需要快速开发原型
  • 想要自然语言生成完整功能
  • 痛点:

    • "项目初期,只是想快速验证功能"
    • "手写前端+后端很累"
    • "如果能说清楚需求就自动生成该多好"

王工 - 算法工程师

  • 擅长算法和数据处理
  • 不想花时间在 Web 开发上
  • 需要快速搭建演示系统
  • 痛点:

    • "我的算法很复杂,但界面很简单"
    • "不想学 React/Vue,只想展示结果"
    • "只要能跑起来,怎么实现都行"

共同点:

  • ✅ 会编程,懂技术
  • ✅ 想提高开发效率
  • ✅ 能准确描述需求
  • ✅ 能读懂生成的代码,可以二次修改
  • ❌ 不想重复写样板代码
  • ❌ 不想被框架和工具链束缚

愿景

让程序员更高效地创造软件

NLCC 的使命是提升开发效率,让程序员能够:

  • 用自然语言描述需求,不再手写每一行样板代码
  • 快速验证想法,从需求到可运行代码只需几分钟
  • 保持完全掌控,生成的代码清晰可读,可以二次修改
  • 专注核心逻辑,把时间花在真正重要的地方
  • 可视化开发,通过Web界面直观管理整个项目

不是低代码平台,不是玩具工具,而是专业级编译器

NLCC 将自然语言视为一种编程语言,通过编译器技术将其转换为可执行代码。生成的代码与手写代码无异,性能、可维护性、可扩展性完全一致。

核心理念:

  • 自然语言是合法的编程语言
  • 编译器负责从需求到代码的转换
  • 程序员保持对生成的完全掌控
  • Web界面让开发过程直观可见
  • 确定性优先:通过 IR 层消除不确定性
  • 验证优先:多级验证确保代码质量
  • 可维护性优先:Source Map 让调试可追踪

用自然语言写代码,像说话一样自然


未来展望

NLCC不仅是一个编译系统,更是通向未来软件工程的桥梁。随着AI能力的不断提升,NLCC将在以下几个方向持续演进:

1. 测试左移:自然语言测试用例

核心思想:在编写功能代码之前,先用自然语言描述测试场景,让AI同时生成代码和测试。

示例

# network/skills/testing.md

## 测试场景

### 场景1:网络断开重连
**描述**:当网络连接意外断开时,系统应该自动重连,最多重试3次,每次间隔指数退避(1s, 2s, 4s)

**验证步骤**:
1. 建立正常连接
2. 模拟网络中断
3. 验证自动重连触发
4. 验证重连次数不超过3次
5. 验证间隔时间符合指数退避

**期望结果**:在第3次重试成功后,连接恢复正常

### 场景2:并发压力测试
**描述**:系统应支持1000个并发连接,每个连接每秒发送10条消息,持续运行1小时不崩溃

**性能指标**:
- 消息丢失率:< 0.01%
- 平均响应时间:< 50ms
- P99响应时间:< 200ms

AI生成

// network/tests/test_reconnect.rs
// AI自动生成的测试代码
#[test]
fn test_auto_reconnect_with_exponential_backoff() {
    // 基于自然语言描述生成的完整测试
}

// network/tests/test_concurrent_connections.rs
#[test]
fn test_1000_concurrent_connections_stability() {
    // 压力测试代码
}

优势

  • ✅ 测试用例与需求同步更新
  • ✅ 避免测试与实现脱节
  • ✅ 降低编写测试的门槛

2. 多语言目标:一次编写,到处编译

核心思想:既然MD是源码,理论上可以针对不同后端生成不同语言的代码。

架构设计

         AGENTS.md(语言无关的意图)
                ↓
    ┌───────────┼───────────┐
    ↓           ↓           ↓
  Rust      Go        Python
  后端      后端       后端
    ↓           ↓           ↓
高性能     简单易用   快速原型

示例配置

# .nlcc/config.toml

[targets]
rust = { enabled = true, optimize = "speed" }
go = { enabled = true, optimize = "maintainability" }
python = { enabled = true, optimize = "development" }

[module.logger]
targets = ["rust", "go"]  # logger模块生成Rust和Go版本

[module.scripting]
targets = ["python"]  # 脚本模块只生成Python版本

使用场景

场景1:跨语言项目
  核心引擎(Rust) + 业务逻辑(Go) + 脚本扩展(Python)
  → 一次编写AGENTS.md,自动生成多语言接口

场景2:渐进式迁移
  老项目(Python) → 新项目(Rust)
  → 保持AGENTS.md不变,切换生成目标

场景3:技术栈选型
  先用Python快速验证原型
  → 确认需求后切换到Rust生产版本

接口兼容性保证

# api/AGENTS.md

## 跨语言接口定义
所有后端语言必须实现相同的RESTful API接口:
- GET /api/resources
- POST /api/resources
- PUT /api/resources/:id
- DELETE /api/resources/:id

数据格式:JSON
错误处理:统一错误码

3. AI代理协作:分布式AI开发

核心思想:未来可能不是单个AI解析所有MD,而是为每个模块分配一个"AI代理",它们根据各自的AGENTS.md协作。

架构

         项目级AGENTS.md
              ↓
    ┌─────────┼─────────┐
    ↓         ↓         ↓
  Agent    Agent    Agent
  Logger   Network  Storage
    ↓         ↓         ↓
  独立上下文  独立上下文  独立上下文
    ↓         ↓         ↓
  生成代码  生成代码  生成代码
    └─────────┼─────────┘
              ↓
        自动集成测试

协作协议

# AGENTS.md(项目级)

## AI代理协作协议

### 代理职责划分
- **Logger代理**:专注于日志功能的实现
- **Network代理**:专注于网络通信
- **Storage代理**:专注于数据持久化

### 通信方式
- 代理之间不直接通信
- 通过build/include/的公共接口定义契约
- api.rs作为顶层协调者

### 冲突解决
- 如果两个代理对同一接口有不同理解
- 由项目级AGENTS.md中的优先级规则裁决
- 记录决策日志供人类审查

优势

  • ✅ 每个代理使用更小的上下文窗口
  • ✅ 并行生成,提高速度
  • ✅ 单个代理出错不影响其他模块

4. 智能演进:自优化系统

核心思想:系统根据运行时反馈,自动优化AGENTS.md描述和生成的代码。

反馈循环

  编写AGENTS.md
       ↓
  生成代码
       ↓
  部署运行
       ↓
  收集指标(性能、错误率)
       ↓
  AI分析指标
       ↓
  建议优化(MD或代码)
       ↓
  人类审核
       ↓
  应用改进

示例

# logger/AGENTS.md

## 性能优化历史

### 2026-02-20: 添加内存池
**触发条件**:
  - 监控发现内存分配频繁(>1000次/秒)
  - 性能分析显示malloc是瓶颈

**AI建议**:
  - 使用内存池减少分配开销
  - 预分配1000个log buffer

**人类审核**:✅ 批准
**效果**:性能提升30%

### 2026-02-25: 添加批量写入
**触发条件**:
  - 高吞吐场景下单条写入成为瓶颈

**AI建议**:
  - 累积10条日志后批量写入
  - 权衡:可能丢失最后几条(进程崩溃时)

**人类审核**:✅ 批准(添加配置选项)
**效果**:吞吐量提升50%

安全措施

  • ✅ 所有自动优化都需要人类审核
  • ✅ 保留版本历史,可以回滚
  • ✅ 运行测试验证优化效果

5. 生态扩展:NLCC插件系统

核心思想:支持第三方扩展NLCC的功能。

插件类型

# 示例:自定义风格检查插件
# plugins/style_checker.py

class StyleCheckerPlugin:
    def check_agents_md(self, content: str) -> List[Issue]:
        """检查AGENTS.md是否符合团队风格"""
        issues = []

        # 检查章节结构
        required_sections = ["功能定位", "核心接口", "主要职责"]
        for section in required_sections:
            if section not in content:
                issues.append(Issue(
                    level="warning",
                    message=f"缺少必需章节: {section}"
                ))

        return issues

    def suggest_improvements(self, content: str) -> List[Suggestion]:
        """提供改进建议"""
        return [
            Suggestion(
                location="功能定位",
                suggestion="建议添加性能指标"
            )
        ]

插件配置

# .nlcc/plugins.toml

[[plugins]]
name = "style-checker"
path = "plugins/style_checker.py"
enabled = true

[[plugins]]
name = "security-scanner"
path = "plugins/security.py"
enabled = true

[[plugins]]
name = "team-standards"
path = "plugins/standards.py"
enabled = true

时间线预测

2026年Q2:NLCC v1.0
  ✓ 基础编译功能
  ✓ Web可视化界面
  ✓ Rust代码生成

2026年Q3:测试左移
  ✓ 自然语言测试用例
  ✓ 自动测试生成
  ✓ 覆盖率报告

2026年Q4:多语言支持
  ✓ Go后端
  ✓ Python后端
  ✓ 跨语言接口

2027年Q1:AI协作
  ✓ 多代理架构
  ✓ 并行生成
  ✓ 冲突自动解决

2027年Q2:智能优化
  ✓ 运行时监控
  ✓ 自动优化建议
  ✓ A/B测试框架

2027年Q3:生态繁荣
  ✓ 插件市场
  ✓ 第三方扩展
  ✓ 社区贡献

总结

NLCC是一个完整的自然语言编程系统,包含:

设计哲学

  • 代码是cheap的,AI注意力是昂贵的
  • 牺牲代码复用换取AI注意力聚焦
  • 零循环依赖的模块化架构
  • 确定性优先:通过 IR 层消除不确定性
  • 验证优先:多级验证确保代码质量
  • 可维护性优先:Source Map 让调试可追踪

核心架构

  • AGENTS.md:意图描述(做什么)
  • skills/*.md:需求和约束(具体需求)
  • IR 层:确定性的中间表示(消除歧义)
  • build/:自动生成的代码(怎么做)

编译器核心特性(v2.0 增强)

  • 两阶段编译:接口编译 + 实现编译
  • IR 层:JSON 格式的中间表示
  • 验证流水线:L0 语法 + L1 测试 + L2 静态分析
  • 熔断机制:最多重试 3 次,失败即停止
  • Source Map:从代码到意图的映射
  • 补丁系统:保护手工修改
  • Token 管理:优先级队列 + 智能摘要

Web可视化界面

  • 项目浏览器:可视化查看项目结构
  • 实时编辑器:在线编辑MD文档
  • 代码预览:实时查看生成的代码
  • 状态监控:自动检测变化并通知
  • 一键构建:自动化编译流程

自动化构建系统

  • 三种策略模式:auto/always/preserve
  • 手工编辑保护:保留手工修改区域
  • 智能通知:自动提醒需要更新的模块
  • 依赖可视化:图形化显示模块依赖关系

实践指南

  • 从小项目开始
  • 设计清晰的MD架构
  • 验证提示词质量
  • 维护MD而非代码

NLCC不是愿景,而是正在实现的系统。它代表了编程语言演化的必然趋势:抽象层不断上升,自然语言将成为新的源码。


v2.0 的关键:在保持"简单实用"的同时,引入编译器工程的核心实践。
通过 IR 层、两阶段编译、验证流水线、Source Map 等特性,NLCC 从一个"代码生成工具"升级为真正的"自然语言编译器"。

相关文档

作者:twg2020
首发:somingbai.com
更新:2026-02-20(v2.0,基于专业编译器设计评审优化)

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com

如何彻底解决AI的"失忆"问题:一个自动化方案

Context overflow: prompt too large for the model.

这个错误困扰了我很久。
背景说明:

Clawdbot其实自带了自动上下文管理机制,但在实际使用中经常出现bug,
导致"Context overflow"错误频繁发生。本文记录了我如何设计一套
三层保护机制来彻底解决这个问题。


直到最近,我终于设计了一个三层保护机制,彻底解决了这个问题。


🎯 问题的本质

症状

你正在和AI深入讨论一个复杂问题,突然:

Context overflow: prompt too large for the model.
Try again with less input or a larger-context model.

然后呢?

  • ❌ 会话被强制重启
  • ❌ 前面的讨论全部丢失
  • ❌ 你需要重新解释一遍背景
  • ❌ AI像是失忆了一样

为什么会发生?

根本原因:AI的"记忆"是有限的。

每个模型都有一个上下文窗口(Context Window)

  • GPT-3.5: 4K tokens
  • GPT-4: 8K/32K tokens
  • Claude-2: 100K tokens
  • GLM-4: 128K tokens

但即使是128K,也有限度。

每次对话,AI都要:

  1. 读取整个历史记录
  2. 理解上下文
  3. 生成回复

如果历史记录太长,就会超出模型的处理能力。

一个类比

想象你在看一本书:

  • 前10页,你能记住所有细节
  • 前100页,你只能记住大概
  • 前1000页,你连主角名字都忘了

AI的"上下文窗口"就是这本书的厚度。超过这个厚度,AI就开始"失忆"。


💡 为什么之前的方案不行?

方案1:手动保存上下文

做法: 每次快满时,手动让AI总结并保存到文件。

问题:

  • ❌ 需要人工监控(看dashboard)
  • ❌ 容易忘记(忙碌时)
  • ❌ 时机难把握(早了浪费,晚了溢出)

方案2:增大上下文窗口

做法: 换用支持更大上下文的模型。

问题:

  • ❌ 成本高(大模型更贵)
  • ❌ 速度慢(处理更多token)
  • ❌ 治标不治本(还是会满)

方案3:只保存,不重置(我之前的方案)

做法: 检测到token ≥ 50%时,自动保存上下文。

问题:

  • 只拍照,不打扫房间
  • ❌ Token继续累积
  • ❌ 最终还是会溢出

就像把房间拍照保存了,但房间里的东西还在,没有清理。


🛠️ 我的解决方案:三层自动化保护

核心思想

不要等待溢出,而是主动管理。

当Token使用率达到50%时,自动执行:

  1. 保存上下文 - 不丢失信息
  2. 重置会话 - Token归零
  3. 恢复上下文 - 无缝衔接
  4. 通知机制 - 确保新会话知道这个自动化系统的存在

架构图

graph TD
    A[每5分钟检查Token] --> B{Token ≥ 50%?}
    B -->|否| A
    B -->|是| C[步骤1: 保存上下文]
    C --> D[步骤2: 备份会话]
    D --> E[步骤3: 删除会话]
    E --> F[Token归零!]
    F --> G[步骤4: 恢复上下文]
    G --> H[步骤5: 通知机制]
    H --> A

流程说明:

  1. 定期检查Token使用率
  2. 超过50%阈值时触发重置
  3. 保存→备份→删除→恢复→通知
  4. 循环往复,永不溢出

🔬 技术实现

监控脚本

核心逻辑:

def get_session_info() -> tuple:
    """从API获取Token使用率"""
    response = requests.get("http://localhost:8001/api/sessions/")
    sessions = response.json()

    # 找到主会话
    main_session = [s for s in sessions if s['kind'] == 'direct'][0]

    return (
        main_session['usage_percentage'],  # Token使用率
        main_session['session_id'],         # 会话ID
        main_session['session_key']         # 会话Key
    )

def trigger_full_reset(usage, session_id, session_key):
    """执行完整的重置流程"""
    # 步骤1: 保存上下文
    save_context(session_key)

    # 步骤2: 备份会话文件
    backup_session(session_id)

    # 步骤3: 删除会话文件(强制重置)
    delete_session(session_id)

    # 步骤4: 恢复上下文
    restore_context(new_session_key)

    # 步骤5: 通知自动化机制
    notify_automation(new_session_key)

关键点:

  • 删除会话文件是核心(Token归零的秘诀)
  • 先备份再删除(防止数据丢失)
  • 等待新会话创建(避免找不到session_key)

Cron定时任务

*/5 * * * * /usr/bin/python3 /root/clawd/scripts/auto_save_context.py

每5分钟检查一次,完全自动化,无需人工干预。

注: 完整代码实现已开源,可参考项目仓库。

🛡️ 三层保护:确保机制永不失效

问题:会话重置后,新会话"失忆"了

当会话被删除后,AI创建了一个全新的会话。这个新会话:

  • 从零开始
  • 不知道自动化机制的存在
  • 不会继续监控Token使用率

解决方案:三层通知机制

第1层:主动通知 📢

时机: 会话重置完成后立即执行

def notify_automation(session_key: str):
    """发送通知到新会话"""
    notice = """
    ## 🤖 自动化机制通知

    你的会话刚刚完成了自动重置。

    系统已为你部署了自动上下文保存机制:
    - 每5分钟检查Token使用率
    - 超过50%自动触发重置
    - 你不需要做任何事情!
    """
    send_to_session(session_key, notice)

第2层:持久化记录 📄

文件: /root/clawd/AGENTS.md

每次会话启动时,AI会自动读取这个文件:

## 🤖 自动上下文保存机制

**重要!** 这个工作区有一个自动化机制在运行。

- 每5分钟检查Token使用率
- 超过50%自动触发重置
- 关键文件:/root/clawd/scripts/auto_save_context.py

优点: 完全持久化,不会丢失。

第3层:上下文携带 📋

文件: /root/clawd/RESUME-SESSION.md (开头)

每次恢复上下文时,AI会读取这个文件:

## 🤖 自动化机制提示

**重要!** 你现在是在一个有自动化保护的会话中运行。

- 每5分钟检查Token使用率
- 超过50%自动触发重置

优点: 确保恢复后的会话知道机制。

容错分析

场景第1层第2层第3层结果
正常重置完美
通知失败仍可从文件得知
AGENTS.md未读通知和模板保底
恢复失败通知和AGENTS.md保底

结论:新会话99.99%会知道自动化机制!


📊 效果验证

数据对比

重置前:

  • Token使用率:85%
  • 会话文件:75行消息
  • 文件大小:122KB
  • 风险:随时溢出

重置后:

  • Token使用率:0%
  • 会话文件:1行(全新)
  • 上下文:从RESUME-SESSION.md恢复
  • 风险:消除!

运行日志

[2026-02-19 14:30:54] 检查token使用率...
[2026-02-19 14:30:57] 当前主会话token使用率: 13.93%
[2026-02-19 14:30:57] ✓ 使用率正常,无需重置

当使用率 ≥ 50%时:

[2026-02-19 XX:XX:XX] ⚠️ Token使用率 85% 超过阈值 50%
[2026-02-19 XX:XX:XX] 步骤1: 保存上下文...
[2026-02-19 XX:XX:XX] ✓ 会话已备份到: backup/session_xxx.jsonl
[2026-02-19 XX:XX:XX] ✓ 会话文件已删除,会话将重置
[2026-02-19 XX:XX:XX] ✓ 新会话已创建
[2026-02-19 XX:XX:XX] ✓ 步骤5完成: 已通知新会话自动化机制
[2026-02-19 XX:XX:XX] ✅ 会话重置完成!Token已归零!

🤔 设计思考

为什么选择50%作为阈值?

太高(如80%):

  • ❌ 来不及保存
  • ❌ 容易溢出

太低(如20%):

  • ❌ 重置太频繁
  • ❌ 丢失上下文

50%刚刚好:

  • ✅ 有足够时间保存
  • ✅ 留有安全余量
  • ✅ 平衡了频率和风险

为什么不是简单清理旧消息?

方案A:删除最早的50%消息

  • ❌ 会丢失关键上下文
  • ❌ 破坏对话连贯性

方案B:智能压缩(AI总结)

  • ✅ 保留关键信息
  • ✅ 但需要额外调用API
  • ✅ 成本和时间开销

我的方案:完整备份 + 删除文件

  • ✅ 保留完整历史
  • ✅ Token归零(彻底)
  • ✅ 恢复时智能总结

为什么需要三层保护?

单一机制的脆弱性:

  • 脚本可能失败
  • 文件可能未读
  • 通知可能丢失

三层冗余的价值:

  • ✅ 任何一层失效都有其他层保底
  • ✅ 符合"防御性编程"原则
  • ✅ 增加系统鲁棒性

🚀 如何应用到你自己的项目?

前置条件

  1. 会话文件管理:AI的会话存储在文件中
  2. API监控:能获取Token使用率
  3. 命令行工具:能发送消息到会话

实现步骤

  1. 编写监控脚本

    • 定期检查Token使用率
    • 超过阈值时触发重置
  2. 实现重置逻辑

    • 备份会话文件
    • 删除原文件
    • 等待新会话创建
  3. 恢复上下文

    • 从备份文件总结关键信息
    • 发送到新会话
  4. 测试验证

    • 手动触发重置
    • 验证上下文恢复
    • 确认Token归零

关键代码片段

备份会话文件:

import shutil
from datetime import datetime

timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_file = f"backup/session_{session_id}_{timestamp}.jsonl"
shutil.copy2(session_file, backup_file)

删除会话文件(强制重置):

from pathlib import Path

session_file = Path(f"/path/to/sessions/{session_id}.jsonl")
session_file.unlink()  # 删除文件,触发AI创建新会话

发送恢复消息:

import subprocess

subprocess.run([
    'clawbot', 'sessions', 'send',
    '--sessionKey', new_session_key,
    '--message', '读取 RESUME-SESSION.md 恢复上下文'
])

💡 更深层的思考

AI的"记忆"问题

短期记忆(Context Window):

  • 有限容量
  • 需要持续管理
  • 类似人类的"工作记忆"

长期记忆(文件系统):

  • 无限容量
  • 需要主动存储
  • 类似人类的"长期记忆"

我的方案本质:
将短期记忆定期转存到长期记忆,然后清空短期记忆。

自动化的价值

人工 vs 自动:

对比项人工监控自动化脚本
需要关注持续查看dashboard无需关注
出错概率高(容易忘记)低(代码执行)
时间成本每天数次0
可靠性受情绪影响100%执行

结论:把重复性任务交给机器,人类专注于创造。


🎯 总结

问题

  • AI的上下文窗口有限
  • 对话过长会溢出
  • 手动管理不可靠

解决方案

  • ✅ 自动监控(每5分钟)
  • ✅ 智能重置(50%阈值)
  • ✅ 完整备份(不丢失信息)
  • ✅ 上下文恢复(无缝衔接)
  • ✅ 三层保护(机制永不失效)

效果

  • Token使用率:85% → 0%
  • 上下文:完整保留
  • 人工干预:0
  • 运行稳定性:100%

哲学思考

最好的工具是透明的。

当你不再需要担心"Context overflow"时,你才能真正专注于与AI的深度对话。


📚 相关资源

完整实现:

  • 监控脚本:Python实现,支持API监控和自动重置
  • 定时任务:Cron配置,每5分钟自动检查
  • 日志系统:完整的运行日志和错误追踪

核心文件:

  • auto_save_context.py - 自动化监控脚本
  • auto-context-save.md - 完整技术文档
  • auto-context-save-persistence.md - 三层保护详解

相关阅读:


如果你也有遇到过"Context overflow"的问题,希望这个方案能帮到你。有问题欢迎讨论!

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-19

AI原生提示词架构设计:让自然语言成为新源码

前言

在上一篇《AI时代的代码架构:如何设计让AI更好编程的系统》中,我提出了一个核心观点:代码是cheap的,AI注意力是昂贵的,应该设计专门的架构来适应AI的认知特点。

但如果只优化代码架构,只解决了一半的问题。另一半问题在于:给AI的提示词(Prompt)本身也需要架构。

在探索Claude Code、Clawdbot等AI辅助编程工具的过程中,我发现一个现象:很多人把提示词当成零散的文本片段,想到什么写什么。这就像在机器码时代,程序员直接写0101序列——没有抽象,没有结构,难以维护。

我认为:在AI时代,提示词(Markdown文档)将成为新的"源码",而代码将成为编译后的"中间产物"。

本文将阐述一套与代码架构相辅相成的AI原生提示词架构设计


核心洞察:提示词也需要架构

传统误区

很多人认为提示词就是一段自然语言文本:

❌ 错误做法:把所有信息写在一个prompt里

"你是一个C语言程序员,请帮我写一个日志系统。
这个系统需要支持:
1. 输出到文件
2. 输出到控制台
3. 日志级别控制
4. 线程安全
5. 还要支持JSON格式输出
6. 还要支持滚动日志
7. 还要..."

问题

  • AI的注意力被分散到10+个细节上
  • 核心逻辑容易出错
  • 难以维护和扩展

正确思路:模块化 + 按需加载

✅ 正确做法:架构化的提示词

项目/
├── AGENTS.md              # 顶层意图(main函数)
├── modules/
│   ├── logger/
│   │   ├── AGENTS.md      # 模块意图
│   │   └── skills/        # 按需加载的细节
│   │       ├── output.md
│   │       ├── thread_safety.md
│   │       └── json_format.md
│   └── network/
│       ├── AGENTS.md
│       └── skills/
│           ├── tcp.md
│           └── ssl.md
└── build/                 # AI生成的一次性代码
    └── src/

优势

  • AI的注意力聚焦:每次只关注一个模块的意图
  • 降低认知负担:细节放在skills里,按需加载
  • 易于维护:修改意图,重新"编译"即可

提示词架构设计

1. AGENTS.md:MD文档的main函数

核心原则:每个AGENTS.md是唯一入口,描述"做什么",不描述"怎么做"。

项目级AGENTS.md

# AGENTS.md - 项目全局视图

## 项目背景
这是一个高性能网络服务器,支持并发连接和事件驱动架构。

## 核心功能
- 网络连接管理(TCP/SSL)
- 异步事件处理
- 日志记录
- 数据持久化

## 主要模块
- [logger/](modules/logger/AGENTS.md):日志记录模块
- [network/](modules/network/AGENTS.md):网络通信模块
- [storage/](modules/storage/AGENTS.md):数据存储模块

## 对外接口
应用通过`api.h`提供统一的接口:

void app_start();
void app_stop();


## 设计原则
- 零循环依赖
- 编译期隔离
- AI注意力优先

作用

  • 给AI提供全局视图
  • 说明项目背景和目标
  • 列出主要模块和依赖关系
  • 就像C程序的main函数,是整个系统的入口

模块级AGENTS.md

# Logger Module - AGENTS.md

## 功能定位
记录应用日志到文件和控制台,支持多种日志级别和输出格式。

## 核心接口

void logger_log(Logger logger, const char message);
void logger_set_level(Logger* logger, LogLevel level);
void logger_set_output(Logger* logger, OutputTarget target);


## 主要职责
1. 接收日志消息
2. 格式化输出(文本/JSON)
3. 写入目标(文件/控制台)
4. 线程安全保证

## 依赖
- 依赖:无(零依赖模块)
- 被依赖:network、storage

## 细节文档
- [output策略](skills/output.md):如何支持多种输出格式
- [线程安全](skills/thread_safety.md):如何保证并发安全
- [性能优化](skills/performance.md):如何优化日志性能

## 注意事项
- 不要在这个模块中添加网络功能
- 不要阻塞主线程

作用

  • 描述模块的职责和边界
  • 说明接口和使用方式
  • 列出依赖关系
  • 指向细节文档(skills)

2. Skills目录:按需加载的细节

核心原则:skills只描述意图和需求,不描述具体实现。

示例:logger/skills/json_format.md

# JSON格式日志输出

## 需求描述
日志需要支持JSON格式输出,便于日志收集和分析系统(如ELK)解析。

## 输出格式

{
"timestamp": "2026-02-15T10:30:00Z",
"level": "ERROR",
"module": "network",
"message": "Connection failed",
"context": {

"peer": "192.168.1.100:8080",
"error_code": 110

}
}


## 使用场景
- 生产环境日志收集
- 自动化日志分析
- 结构化查询

## 性能要求
- JSON序列化时间 < 100μs
- 不能阻塞主线程

## 不需要关心
- 具体用哪个JSON库(AI自己选择)
- 如何优化性能(AI自己考虑)

关键点

  • ✅ 描述"做什么":支持JSON格式
  • ✅ 描述"为什么要做":便于日志分析
  • ✅ 描述"使用场景":生产环境
  • ❌ 不描述"怎么做":不用告诉AI用哪个库

示例:logger/skills/thread_safety.md

# 线程安全保证

## 需求描述
日志模块可能被多个线程同时调用,必须保证线程安全。

## 关键要求
1. 不能丢失日志消息
2. 不能死锁
3. 性能开销最小化

## 常见场景
- 主线程写日志,工作线程也写日志
- 多个网络连接同时记录错误

## 可选方案(仅供参考,AI可以自行决定)
- 使用互斥锁(简单,但可能阻塞)
- 使用无锁队列(复杂,但性能好)
- 使用线程本地缓冲(延迟写入)

## 性能目标
- 单次日志调用 < 50μs
- 支持至少10个并发线程

3. 按需加载策略

核心思想:不是一次性加载所有MD,而是根据AI的注意力范围动态加载。

场景1:AI生成logger模块代码

步骤1:读取 logger/AGENTS.md
→ AI理解模块的整体意图

步骤2:AGENTS.md引用了 skills/output.md
→ AI读取这个文件,了解输出需求

步骤3:AI开始生成代码
→ 只关注当前模块,不受其他模块干扰

场景2:AI需要理解logger如何被network使用

步骤1:读取 logger/AGENTS.md
→ 了解logger提供的接口

步骤2:读取 network/AGENTS.md
→ 发现network依赖logger

步骤3:按需加载 skills/json_format.md
→ 了解network需要JSON格式的日志

类比:现代操作系统的按需加载

传统程序:
启动时加载所有代码到内存
→ 浪费内存,启动慢

现代程序(动态链接):
启动时只加载必需的代码
→ 节省内存,启动快
→ 使用到某个模块时,才加载

AI提示词架构:
AI开始工作时,只加载必需的MD
→ 降低上下文消耗
→ 需要细节时,才加载skills

与代码架构的对应关系

完美映射

提示词架构(MD)          代码架构(C)
─────────────────         ─────────────────
AGENTS.md          ↔     api.h / module.h
skills/output.md   ↔     src/module/impl.c(实现细节)
项目AGENTS.md       ↔     项目对外接口
按需加载MD         ↔     动态链接/模块化编译

核心原则一致性

原则提示词架构代码架构
零循环依赖AGENTS.md不互相include.h文件不互相include
清晰边界每个AGENTS.md职责单一每个module职责单一
按需加载skills目录按需读取编译期隔离
单一入口AGENTS.md是main函数api.h是唯一对外接口
意图抽象MD描述"做什么".h描述接口

生成流程

人类维护层(源码):
├── AGENTS.md
├── modules/*/AGENTS.md
└── modules/*/skills/*.md
        ↓
        ↓ AI"编译"
        ↓
AI生成层(中间产物):
├── include/*.h
└── src/*/impl.c
        ↓
        ↓ 传统编译
        ↓
机器码(运行产物):
└── binary

技术本质:编程语言演化的延续

历史规律:抽象层不断上升

┌─────────────┬──────────────┬─────────────┬──────────────┐
│   时代      │  程序员关注   │  工具       │  输出物      │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 机器码时代  │ 0101序列     │ 手工拨开关  │ 机器码       │
│ 1940s      │              │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 汇编时代    │ 助记符       │ 汇编器      │ 机器码       │
│ 1950s      │ (MOV, ADD)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 高级语言    │ 算法逻辑     │ 编译器      │ 汇编/机器码  │
│ 1970s+     │ (for, if)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ AI时代      │ 业务意图     │ 自然语言    │ 代码         │
│ 2020s+     │ (自然语言)   │ 编译器      │              │
└─────────────┴──────────────┴─────────────┴──────────────┘

每一次革命的本质

机器码 → 汇编:符号抽象

之前

程序员需要记住:
01001001 = LOAD寄存器
01001010 = ADD操作
01001011 = STORE操作

之后

程序员只需要写:
LOAD A, 10
ADD B, 5
STORE A, result

本质:用符号代替数字,降低记忆负担

底层依然存在:CPU还是执行0101,但程序员不需要关心了


汇编 → 高级语言:控制流抽象

之前

; 计算1到100的和
MOV AX, 0
MOV CX, 100
MOV BX, 1
loop_start:
ADD AX, BX
INC BX
DEC CX
JNZ loop_start
STORE AX, sum

之后

int sum = 0;
for (int i = 1; i <= 100; i++) {
    sum += i;
}

本质

  • 用控制流(for, if)代替跳转指令
  • 用变量名代替寄存器
  • 用类型系统代替手动内存管理

底层依然存在:CPU还是执行跳转指令,但程序员不需要关心了

适用范围降低

  • 99%的代码用高级语言
  • 1%的极端性能场景(OS内核、驱动)用汇编

高级语言 → AI:意图抽象

之前

# 发送HTTP请求并处理错误
import requests

try:
    response = requests.get('https://api.example.com/users')
    if response.status_code == 200:
        users = response.json()
        for user in users:
            print(user['name'])
    else:
        logger.error(f"HTTP {response.status_code}: {response.text}")
except requests.exceptions.RequestException as e:
    logger.error(f"Request failed: {e}")

之后(AI时代)

<!-- network/AGENTS.md -->

# Network Module

## 功能
发送HTTP请求到API服务器,获取用户列表。

## 接口

UserList network_fetch_users(Network self);


## 错误处理
如果请求失败,需要:
1. 记录错误日志(通过logger模块)
2. 返回NULL给调用者
3. 不要抛异常(C语言不支持)

## 性能要求
- 超时时间:5秒
- 重试次数:3次

本质

  • 用自然语言描述意图,代替具体的控制流
  • AI负责"怎么做",人类只说"做什么"
  • 代码成为中间产物,就像今天的汇编

底层依然存在

  • CPU还是执行机器码
  • 编译器还是生成汇编
  • 但程序员99%不需要关心了

适用范围降低

  • 99%的代码用AI + 自然语言生成
  • 1%的极端场景(AI生成代码性能不够)手工写代码

技术演化的规律

规律1:抽象层不断上升

机器码(硬件) → 汇编(符号) → 高级语言(逻辑) → 自然语言(意图)
   ↓               ↓              ↓                ↓
 只有极少数人掌握   少数人        大多数人        所有人

规律2:旧技术不会消失,适用范围降低

汇编语言的演化

1950年代:所有编程都用汇编
1980年代:系统编程用汇编,应用编程用高级语言(90% vs 10%)
2020年代:只有OS内核、驱动、嵌入式用汇编(1% vs 99%)

未来:只有极端性能优化的场景用汇编(0.1% vs 99.9%)

手工写代码的演化(预测):

2020年代:所有编程都手写代码
2030年代:大多数编程用AI生成,少数极端场景手写(10% vs 90%)
2050年代:只有极致性能场景手工写代码(1% vs 99%)
2100年代:只有特殊领域(AI无法理解)手工写代码(0.1% vs 99.9%)

规律3:工具复杂度转移

机器码时代:
工具:简单(手工拨开关)
程序员负担:重(需要记住所有0101)

汇编时代:
工具:汇编器
程序员负担:减轻(只需要写助记符)

高级语言时代:
工具:复杂的编译器、链接器、优化器
程序员负担:很轻(只需要写逻辑)

AI时代:
工具:极其复杂的自然语言编译器(大模型)
程序员负担:极轻(只需要描述意图)

类比:代码 = 未来的汇编

今天我们如何看待汇编?

场景1:应用开发
工程师:我要写一个Web服务器
选择:Go、Python、Java
绝不会考虑:手写汇编

场景2:系统编程
工程师:我要写Linux内核
选择:C语言,偶尔内联汇编
不会全用:纯汇编

场景3:极致优化
工程师:这个加密循环性能不够
考虑:手写汇编优化这一小段

结论:汇编依然存在,但适用范围极小。

明天我们如何看待代码?

场景1:应用开发
工程师:我要写一个Web服务器
做法:写AGENTS.md描述意图
工具:自然语言编译器(NLCC)
生成:Go/Python代码(自动)
绝不会考虑:手写Go代码

场景2:系统编程
工程师:我要写操作系统内核
做法:写关键模块的AGENTS.md
生成:C代码(自动)
偶尔手工优化:极少数性能关键路径

场景3:极致优化
工程师:AI生成的这段代码性能不够
考虑:手工优化这一小段

结论:代码依然存在,但99%的人不需要手写。

类比总结

今天:
汇编 → 编译器 → 机器码
程序员写汇编,不需要看生成的机器码
(除非极端性能优化)

明天:
自然语言(MD) → 自然语言编译器(AI) → 代码 → 传统编译器 → 机器码
程序员写MD,不需要看生成的代码
(除非极端性能优化)

高级语言不会淘汰汇编:汇编依然在OS内核、驱动中发挥作用
AI不会淘汰高级语言:代码依然是重要的中间层,但适用范围大大降低


未来展望:自然语言编译器(NLCC)

会是什么样的?

项目结构

project/
├── AGENTS.md              # 顶层意图描述
├── modules/
│   ├── logger/
│   │   ├── AGENTS.md      # 模块意图
│   │   └── skills/        # 按需加载的细节
│   │       ├── output.md
│   │       ├── thread_safety.md
│   │       └── json_format.md
│   └── network/
│       ├── AGENTS.md
│       └── skills/
│           ├── http.md
│           └── ssl.md
└── build/                 # 生成的一次性代码
    ├── src/
    │   ├── logger/
    │   │   ├── impl.c
    │   │   └── internal.h
    │   └── network/
    │       ├── http.c
    │       └── ssl.c
    ├── include/
    │   ├── logger.h
    │   └── network.h
    ├── compile.log        # 编译日志
    └── test_report.xml    # 测试报告

工作流程

# 1. 人类修改意图
vim modules/logger/skills/json_format.md

# 2. 触发"编译"
nlcc build

# 3. NLCC自动执行
Reading modules/logger/AGENTS.md...
  → Loading skills/output.md...
  → Loading skills/json_format.md...
Generating code...
  → build/src/logger/impl.c
  → build/include/logger.h
Compiling...
  → gcc -c build/src/logger/impl.c -o build/obj/logger.o
Testing...
  → All tests passed
Build complete!

# 4. 查看生成的代码(可选,就像今天看汇编)
cat build/src/logger/impl.c

# 5. 运行
./build/bin/app

NLCC和传统编译器的对比

传统编译器(GCC)自然语言编译器(NLCC)
输入:C代码输入:自然语言(AGENTS.md)
输出:机器码/汇编输出:C代码
错误:语法错误、链接错误错误:意图模糊、逻辑矛盾
优化:寄存器分配、指令调度优化:模块拆分、依赖管理
调试:看汇编代码(-S)调试:看生成的C代码
工具链:预处理 → 编译 → 汇编 → 链接工具链:意图分析 → 代码生成 → 传统编译

实践建议:如何开始

1. 从小项目开始

不要:在大型遗留项目上尝试
应该:在新项目、工具项目、实验性项目开始

推荐起点

  • 个人工具脚本
  • 小型库或框架
  • 概念验证项目

2. 设计MD架构

步骤1:划分模块
→ 哪些功能是独立的?
→ 依赖关系是什么?

步骤2:编写项目级AGENTS.md
→ 项目背景是什么?
→ 主要模块有哪些?
→ 对外接口是什么?

步骤3:编写模块级AGENTS.md
→ 这个模块做什么?
→ 接口是什么?
→ 依赖哪些模块?

步骤4:编写skills/*.md
→ 需要哪些细节描述?
→ 按场景拆分(不要写成大而全)

3. 验证提示词质量

标准:给另一个AI看你的AGENTS.md

  • 它能理解这个模块做什么吗?
  • 它知道如何使用这个模块吗?
  • 它会产生误解吗?

如果AI都有问题,那说明意图描述不够清晰。

4. 维护MD,而不是代码

场景:需要修改logger模块

错误做法:
直接编辑 build/src/logger/impl.c
→ 下次nlcc build时,你的修改被覆盖

正确做法:
编辑 modules/logger/AGENTS.md 或 skills/*.md
→ 运行 nlcc build
→ 重新生成代码

5. 代码审查(未来偶尔需要)

场景:性能不够

步骤1:看生成的代码
cat build/src/logger/impl.c

步骤2:找到性能瓶颈
→ 发现JSON序列化太慢

步骤3:选择优化策略
A. 修改AGENTS.md,明确性能要求(推荐)
B. 手工优化这一小段代码(极端情况)

人类工程师的职责演化

现在(高级语言时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 定义接口(.h文件)
3. 实现逻辑(.c文件)
4. 调试、测试、优化
5. 维护代码(修复bug、添加功能)
6. Code Review

时间分配

  • 架构设计:10%
  • 写代码:60%
  • 调试测试:20%
  • 维护:10%

未来(AI时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 编写意图描述(AGENTS.md)
3. 审查AI生成的代码(偶尔,5%时间)
4. 处理AI搞不定的极端场景(1%时间)
5. 监控系统运行状态

时间分配

  • 架构设计:20%
  • 编写MD:30%
  • 审查代码:5%
  • 极端场景:1%
  • 监控、优化、学习:44%

核心转变

  • 从"如何实现" → "要实现什么"
  • 从"细节控制" → "意图表达"
  • 从"代码维护" → "意图维护"

总结

核心观点

  1. 提示词也需要架构

    • 不是零散的文本,而是有组织的MD文档
    • AGENTS.md是唯一入口,skills是按需加载的细节
  2. 与代码架构完美对应

    • 零循环依赖、清晰边界、单一入口
    • 提示词描述意图,代码描述实现
  3. 技术演化的延续

    • 机器码 → 汇编 → 高级语言 → 自然语言
    • 每次抽象都降低程序员负担
    • 代码的地位 = 今天汇编的地位
  4. 未来已来

    • 自然语言编译器(NLCC)会出现
    • 代码放在build/目录,成为一次性中间产物
    • 人类只维护MD,就像今天只维护C代码
  5. 适用范围降低

    • AI不会淘汰代码,就像高级语言不会淘汰汇编
    • 但99%的场景不需要手工写代码
    • 只有极端性能场景才需要

行动建议

现在就开始:
1. 选择一个小项目
2. 设计AGENTS.md架构
3. 编写模块级MD和skills
4. 用AI生成代码
5. 验证、迭代、优化

记住:
- MD是源码,代码是中间产物
- 维护MD,而不是代码
- 意图清晰 > 代码完美

这是继《AI时代的代码架构》后的第二篇思考。核心观点是:在AI时代,提示词(自然语言)将成为新的源码,而代码将成为编译后的中间产物。 这不是科幻,而是编程语言演化的必然趋势。就像高级语言没有淘汰汇编,AI也不会淘汰代码——只是适用的范围会大大降低。欢迎交流讨论!

相关阅读

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-15

AI时代的代码架构:如何设计让AI更好编程的系统

前言

在探索Claude Code辅助编程的过程中,我逐渐意识到一个核心问题:传统的软件架构设计思想,可能并不适合AI时代。

传统工程学追求代码复用、模块化、可维护性——这些当然重要。但在AI能够快速生成大量代码的今天,我认为代码本身变得cheap了,真正昂贵的是AI的注意力。

基于这个核心洞察,我设计了一套专门为AI编程优化的架构方案。本文将详细阐述这个架构的思想、设计原则和最佳实践。

核心洞察:代码是Cheap的

传统时代的成本结构

在传统软件开发中:

  • 编写代码:昂贵(需要资深工程师、耗时)
  • 复制代码:廉价(Ctrl+C/Ctrl+V)
  • 维护代码:昂贵(理解成本、耦合风险)

所以传统工程学强调:

  • ✅ DRY原则(Don't Repeat Yourself)
  • ✅ 代码复用
  • ✅ 统一抽象
  • ✅ 提前设计(过度设计)

AI时代的成本结构

在AI辅助编程中:

  • 代码是cheap的:AI生成代码极快(几秒钟生成几百行)
  • module随时可以替换:没搞好就再做一个,代价很低
  • 完全不需要提前过度设计:让实际需求驱动架构演化
  • AI的上下文窗口:昂贵(有限的注意力)
  • AI理解复杂系统:困难(容易遗漏细节)

新的成本函数:

总成本 = AI生成代码的时间(低)
       + 人类review的时间(中)
       + AI修改迭代的时间(高)
       + 系统复杂度导致的AI错误率(极高)

结论:在AI时代,应该牺牲代码复用来换取AI注意力的聚焦


深入理解:为什么要牺牲代码复用?

让我用具体例子说明这个观点。

传统方式:追求代码复用

场景:统一错误处理

// include/common/error.h
typedef struct {
    int code;
    char message[256];
    void* context;      // 通用的上下文
    int context_size;
} Error;

void error_handle(Error* err);  // 超级通用的错误处理

// 所有module都用这个Error
void network_send(Network* self, const char* data) {
    if (send_failed) {
        Error err = {
            .code = ERR_NETWORK,
            .context = self->internal_state,
            .context_size = sizeof(self->internal_state)
        };
        error_handle(&err);  // 复用通用处理
    }
}

传统优势

  • ✅ 只写一次错误处理逻辑
  • ✅ 统一的错误格式
  • ✅ 易于维护

传统成本

  • 需要设计"万能"的Error结构
  • 需要考虑所有使用场景
  • 人类工程师能理解这个复杂抽象

AI时代的问题

让AI写network_send时:

AI的思维过程:
1. 需要处理错误
2. 用Error结构
3. Error有哪些字段?code、message、context、context_size...
4. context是什么类型?void*?
5. 需要设置context_size吗?多大?
6. 有初始化函数吗?
7. 错误码是多少?
8. 要检查NULL吗?
...(AI注意力被分散到10个细节上)

AI实际生成(很可能出错):

void network_send(Network* self, const char* data) {
    if (send_failed) {
        Error err;  // ❌ 忘记初始化
        err.code = 1000;
        strcpy(err.message, "send failed");  // ❌ 忘记检查长度
        // ❌ 忘记设置context
        error_handle(&err);  // ❌ 可能段错误
    }
}

问题:AI注意力被分散到Error结构的细节上,核心逻辑反而出错。

AI方式:牺牲代码复用

// 不设计通用的Error结构

// src/network/impl.c
void network_send(Network* self, const char* data) {
    if (send_failed) {
        // 简单直接,网络模块自己的错误处理
        fprintf(stderr, "[network] send failed: %s\n", strerror(errno));
        if (self->error_callback) {
            self->error_callback("send failed");
        }
    }
}

// src/storage/impl.c
void storage_write(Storage* self, const char* data) {
    if (write_failed) {
        // 存储模块自己的错误处理(完全不同)
        fprintf(stderr, "[storage] write failed: %s\n", strerror(errno));
        if (self->retry_count < 3) {
            self->retry_count++;
            storage_write(self, data);  // 自己的重试逻辑
        }
    }
}

AI生成这个

AI的思维过程:
1. 需要处理错误
2. fprintf打印
3. 调用回调(如果有)
4. 完成

AI只需要关注3个细节,专注度高!

成本对比

传统方式(追求复用):

设计通用Error:4小时
AI出错率:30%
人类review:每个module 30分钟
修复时间:20分钟 × 3轮 = 60分钟

10个module总成本:4 + 15 = 19小时

AI方式(牺牲复用):

设计通用Error:0小时
AI出错率:5%
人类review:每个module 5分钟
修复时间:5分钟 × 1轮 = 5分钟

10个module总成本:0 + 1.6 = 1.6小时

代码重复:每个module都写fprintf(但没关系!)

节省时间:17小时!

"牺牲代码复用"的真正含义

不是

  • ❌ 随意复制粘贴
  • ❌ 不做任何抽象
  • ❌ 写烂代码

而是

  • ✅ 用代码重复换取逻辑简单
  • ✅ 用更多代码行换取AI理解成本低
  • ✅ 用手工维护换取AI出错率低

类比

这就像:

传统时代(手工制作家具):

  • 用精密的模具(通用抽象)
  • 一次设计,批量生产
  • 成本:设计贵,生产便宜

AI时代(3D打印):

  • 不需要精密模具
  • 每个产品单独打印
  • 成本:设计便宜,生产也便宜
  • 宁愿多打印几次,也不设计复杂模具

架构设计:依赖倒置 + 零循环依赖

设计目标

  1. 零循环依赖:AI不需要理解复杂的依赖关系
  2. 清晰的边界:每个模块的职责单一明确
  3. 可组合性:像搭积木一样组装复杂系统
  4. 可测试性:每个模块可以独立测试

目录结构设计

project/
├── include/              # 公共接口层(零依赖区)
│   ├── common_types.h   # POD数据结构
│   ├── logger.h         # 抽象接口
│   ├── network.h
│   ├── storage.h
│   └── ...
├── src/                 # 实现层
│   ├── logger/          # 实现logger.h
│   │   ├── impl.c
│   │   └── internal.h
│   ├── network/
│   └── storage/
└── api.h                # 唯一对外头文件

依赖关系图

         ┌─────────────────┐
         │     api.h       │  ← 最底层(对外窗口)
         │   (组合接口)     │
         └────────┬─────────┘
                  ↑ 依赖
         ┌────────┴─────────┐
         │    include/      │  ← 第二层(抽象接口层)
         │  - POD数据结构    │
         │  - 抽象接口定义   │
         └────────┬─────────┘
                  ↑ 依赖
         ┌────────┴─────────┐
         │   src/module*/   │  ← 第三层(实现层)
         └──────────────────┘

关键约束:

  • include/*.h 绝对禁止互相包含
  • src/module*/ 只依赖include/,不能依赖其他module
  • api.h 组合需要的接口对外暴露

三个关键设计问题

问题1:Module间如何通信?

传统困惑:既然module不能互相依赖,那怎么协作?

答案:所有通信接口也在include/里定义为抽象。

// include/event_bus.h
typedef struct EventBus EventBus;
void event_bus_publish(EventBus*, const char* topic, void* data);
void event_bus_subscribe(EventBus*, const char* topic,
                         void (*callback)(void*));

// src/logger/impl.c
#include "event_bus.h"
#include "logger.h"

void logger_init(Logger* self, EventBus* bus) {
    event_bus_subscribe(bus, "message.received", log_callback);
}

// src/network/impl.c
#include "event_bus.h"
#include "network.h"

void network_on_message(Network* self, const char* msg) {
    event_bus_publish(self->event_bus, "message.received", (void*)msg);
}

依赖倒置原则

  • 高层模块和低层模块都依赖抽象(include/
  • 抽象不依赖具体实现
  • 实现依赖抽象

问题2:数据结构放在哪里?

困惑:如果需要传递复杂结构,放哪里会打破零依赖原则?

答案:纯POD(Plain Old Data)结构可以放include/,甚至放api.h

// include/common_types.h
typedef struct {
    const char* method;
    const char* url;
    const char* body;
} HttpRequest;

typedef struct {
    int code;
    const char* message;
} HttpResponse;

为什么不会循环依赖?

  • POD结构只包含基本类型、指针、数组
  • 不include其他头文件
  • 即使多个接口include它,也是树状依赖,不会循环

注意:带函数指针的结构也算"数据结构",可以放include/

// include/observer.h
typedef struct {
    void (*on_message)(const char* msg);
    void (*on_error)(int error_code);
} ObserverCallbacks;

问题3:何时拆分Module?

困惑:拆分的粒度如何掌握?多少代码算太复杂?

答案:没有固定行数标准,看AI出错率

判断指标:

  1. 编译错误率

    AI第一次生成 → 编译通过
    如果通过率 < 70%,说明太复杂了
  2. 修改轮次

    AI生成 → 人类review → 指出问题 → AI修改 → 又发现问题...
    如果平均 > 2轮,说明超出了AI注意力范围
  3. 常见错误信号

    • ❌ 忘记NULL检查
    • ❌ 忘记释放内存
    • ❌ 边界条件遗漏
    • ❌ 错误处理不完整

本质原因:AI的注意力被核心逻辑占用,细节顾不上。

实验数据(假设):

Module大小代码行数AI编译通过率修改轮次
单体500行50%3-5轮
拆分后150行85%1-2轮

结论:当AI出错率上升时,继续拆分,或者提取成独立子项目。

与微服务架构的深度对比

相似性(理念层面)

维度微服务AI-Native架构
边界定义清晰的业务边界清晰的功能边界
依赖方向通过API互相调用通过抽象接口依赖
独立演进可以独立升级module可独立替换实现
团队协作不同团队负责不同服务不同AI/人负责不同module
核心理念解耦、隔离解耦、AI注意力管理

本质区别(实现层面)

1. 隔离边界

微服务:进程级隔离

服务A                服务B
[进程1] ──网络──→ [进程2]
  ↓                    ↓
独立内存空间        独立内存空间
  • ✅ 故障隔离:服务B崩溃不影响服务A
  • ✅ 语言自由:A用Go,B用Python
  • ❌ 性能开销:序列化、网络延迟(1-10ms)

AI-Native架构:编译期隔离

┌───────────────────进程───────────────────┐
│                                           │
│  moduleA  ──函数调用──→  moduleB         │
│    ↓                      ↓               │
│  共享地址空间        共享地址空间        │
│                                           │
└───────────────────────────────────────────┘
  • ✅ 性能:零拷贝、直接调用(1-10ns)
  • ✅ 调试:统一的内存空间、gdb一步跟踪
  • ❌ 故障传播:moduleB段错误 → 整个进程挂掉

性能差异:100万倍!

2. 部署复杂度

微服务需要:

  • 容器编排(Kubernetes)
  • 服务发现
  • 负载均衡
  • 配置管理
  • 链路追踪
  • 100+个基础设施组件

AI-Native架构需要:

  • 编译器
  • 链接器
  • 就这!

3. 扩展性

微服务:水平扩展(用户激增 → 加机器)

AI-Native架构:垂直扩展(加CPU/内存)或提取热点module为独立进程

架构定位

这个架构本质是:"单体应用 + 微服务理念"

  • 结构上:单体应用(一个进程)
  • 设计上:微服务思想(边界清晰、接口驱动)

适用场景:

✅ 嵌入式系统(资源受限)
✅ 系统编程(操作系统、数据库)
✅ 高性能场景(网络延迟不能接受)
✅ AI辅助开发(核心诉求)
✅ 小团队(运维能力有限)

❌ 超大规模(需要水平扩展)
❌ 多语言团队
❌ 需要强故障隔离(金融、核电站)

微服务架构的未来演进

我预测:随着AI的智能变得越来越廉价,一部分微服务架构可能会向AI-Native架构演进。

演进的动力

传统微服务的成本

  • 运维100+个基础设施组件(K8s、服务发现、链路追踪...)
  • 网络延迟:每次调用1-10ms
  • 序列化/反序列化开销
  • 分布式系统的复杂度(CAP理论、最终一致性...)

AI时代的变化

  • 代码是cheap的:重构一个service的成本极低
  • module随时可以替换:单体内部也可以模块化
  • AI能处理复杂依赖:只要边界清晰,AI能管理单体内部的模块关系

演进的路径

阶段1:纯微服务(现在)
[服务A] ──网络──→ [服务B] ──网络──→ [服务C]
  进程1               进程2                进程3

优点:故障隔离、水平扩展
缺点:运维复杂、网络开销

阶段2:混合架构(过渡期)
┌────────────────进程1────────────────┐
│  moduleA ──函数调用──→ moduleB      │
│    ↓                         ↓       │
│  [隔离边界]              [隔离边界]   │
└─────────────────────────────────────┘
         │                      │
         └──────网络──────→ 进程2 (服务C)

优点:核心性能敏感部分用module
      需要独立扩展的部分用服务
缺点:架构复杂度增加

阶段3:AI-Native单体(未来趋势)
┌───────────────────────────────────────────┐
│  moduleA → moduleB → moduleC → moduleD   │
│    (编译期隔离,边界清晰)                  │
└───────────────────────────────────────────┘

优点:
- 性能最优(函数调用)
- 运维最简(一个进程)
- AI友好(清晰的模块边界)
- module可以随时替换重构

缺点:
- 需要垂直扩展(加CPU/内存)
- 但CPU/内存越来越便宜了!

哪些场景会先演进?

优先演进到AI-Native的场景

  1. AI辅助开发的团队:已经在用AI写代码,自然选择AI友好的架构
  2. 性能敏感的系统:高频交易、游戏引擎、实时数据处理
  3. 小团队项目:没有专门的运维团队,不想维护K8s
  4. 快速迭代的初创公司:需要频繁重构,代码复用不是瓶颈

继续使用微服务的场景

  1. 超大规模系统:Facebook、Instagram级别(需要水平扩展)
  2. 多语言团队:不同服务用不同语言(Go、Python、Java)
  3. 需要强隔离:金融、核电站、医疗(故障隔离是硬需求)
  4. 遗留系统:已经在微服务上运行,迁移成本太高

本质转变

传统思维:
"代码是昂贵的,所以需要复用"
→ 设计通用服务(UserService、OrderService...)
→ 通过网络调用复用

AI时代思维:
"代码是cheap的,AI注意力是昂贵的"
→ 设计清晰的模块边界
→ 编译期隔离,函数调用
→ module随时可以替换重构

这是技术范式的转移:从"追求运行时的复用"转向"追求AI开发的效率"。


1. 引入依赖注入(DI)容器

问题:手工组装module依赖容易出错。

// main.c - 手工组装(容易遗漏)
Logger* logger = logger_create();
Storage* storage = storage_create();
Network* net = network_create();
network_set_observer(net, logger);
storage_set_observer(storage, logger);
// ...几十个组装代码

改进

// include/di.h
typedef struct DIContainer DIContainer;
void di_register(DIContainer*, const char* name, void* instance);
void* di_resolve(DIContainer*, const char* name);

// main.c
DIContainer* di = di_create();
di_register(di, "logger", logger_create());
di_register(di, "storage", storage_create());

Network* net = network_create(di);  // 自动注入依赖

好处

  • 自动管理依赖关系
  • 测试时注入Mock对象
  • AI不需要记住组装顺序

2. 接口版本管理

问题:接口变更导致旧代码编译失败。

// v1
void logger_log(Logger*, const char* msg);

// v2(破坏性变更)
void logger_log(Logger*, const char* msg, int level);

改进

include/
├── logger/
│   ├── v1.h  # 老接口
│   └── v2.h  # 新接口
└── logger.h  # 默认指向v2

好处:多版本共存、渐进式迁移

3. 生命周期管理

问题:AI生成的代码可能忘记初始化或释放资源。

改进

// include/lifecycle.h
typedef enum {
    LIFECYCLE_INIT,
    LIFECYCLE_START,
    LIFECYCLE_STOP,
    LIFECYCLE_DESTROY
} LifecycleState;

typedef struct {
    void (*on_init)(void);
    void (*on_start)(void);
    void (*on_stop)(void);
    void (*on_destroy)(void);
} LifecycleHooks;

void lifecycle_register(const char* module_name, LifecycleHooks* hooks);
void lifecycle_init_all(void);  // 按依赖顺序初始化
void lifecycle_destroy_all(void);

4. 可观测性内置

统一监控接口

// include/observability.h
void obs_log(const char* module, const char* level, const char* msg);
void obs_metric(const char* module, const char* name, double value);
void obs_trace(const char* module, const char* func);

// AI生成的代码自带可观测性
void network_send(Network* self, const char* data) {
    obs_trace("network", "send");
    // ...
    obs_metric("network", "bytes_sent", strlen(data));
}

5. 插件化架构(可选)

对于频繁变动的module,做成动态插件

project/
├── include/
│   └── plugin.h
├── plugins/
│   ├── logger_plugin.so
│   └── network_plugin.so
// include/plugin.h
typedef struct Plugin {
    const char* name;
    void* (*init)(void);
    void (*destroy)(void*);
} Plugin;

void plugin_load(const char* path);
void* plugin_get(const char* name);

如何保证AI遵循规则?

方案A:编译期检查

# 扫描include/目录,检测违规依赖
make check-dependencies

方案B:AI Prompt工程

给AI的系统提示词:

你在一个严格约束的项目中工作:
1. include/里的头文件不能include其他include/的头文件
2. src/里的代码只能include其对应的include/里的头文件
3. 违反这些规则会导致编译失败

方案C:自动化测试

CI/CD中加入依赖检查:

#!/bin/bash
# 检测循环依赖
python scripts/check_circular_deps.py include/

完整架构示例

project/
├── include/
│   ├── di.h              # 依赖注入
│   ├── lifecycle.h       # 生命周期
│   ├── observability.h   # 可观测性
│   ├── common_types.h    # POD数据结构
│   ├── logger/
│   │   └── v1.h
│   ├── network/
│   │   └── v1.h
│   └── storage/
│       └── v1.h
├── src/
│   ├── core/             # 核心框架(DI、生命周期)
│   ├── logger/           # 实现logger/v1.h
│   ├── network/
│   └── storage/
├── plugins/              # 可选:动态加载模块
├── tests/
│   └── unit/             # 每个module独立测试
├── scripts/
│   └── check_deps.py     # 依赖检查工具
└── api.h                 # 唯一对外接口

核心原则总结

  1. 代码是cheap的,AI注意力是昂贵的

    • 不惜增加代码量来降低每个模块的复杂度
  2. 零循环依赖

    • include/绝对禁止互相包含
    • src/只依赖include/
  3. 依赖倒置

    • 所有接口定义在include/
    • 实现在src/
  4. 动态拆分

    • 没有固定的行数标准
    • 看AI出错率调整边界
  5. 基础设施内置

    • DI容器、生命周期、可观测性
    • 让AI专注于业务逻辑

实践效果预测

AI编码质量提升

指标传统架构AI-Native架构
编译通过率50%85%
修改轮次3-5轮1-2轮
代码行数/module500行150行
内存泄漏率15%3%

开发效率提升

传统方式:
AI生成 → 编译错误 → 修复 → 发现新错误 → 再修复 → ... (5轮)
耗时:2小时

AI-Native方式:
AI生成 → 小调整 → 通过 (1轮)
耗时:20分钟

后续思考

1. 工具支持

能否开发一个IDE插件,自动检测依赖违规?

  • 实时扫描include/目录
  • 高亮显示违规依赖
  • 自动生成依赖图

2. AI模型优化

能否针对这种架构训练专门的模型?

  • 理解零依赖约束
  • 自动生成符合规则的代码
  • 更高的首次编译通过率

3. 度量标准

如何量化"AI注意力成本"?

  • Token消耗(上下文长度)
  • 修改轮数
  • 人类review时间

参考资源

  • 依赖倒置原则(DIP):Robert C. Martin的Clean Architecture
  • 微服务架构:Martin Fowler的Microservices文章
  • AI辅助编程:GitHub Copilot、Claude Code实践

这是我在探索AI辅助编程过程中的架构思考。核心观点是:代码本身不再是瓶颈,AI的注意力才是。 架构设计应该服务于AI的认知特点,而不是传统的工程美学。如果你也在做类似的探索,欢迎交流讨论!

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-15

Clawdbot飞书插件对接实战:踩坑与解决方案

前言

最近在给Clawdbot(一个基于Node.js的AI Bot框架)对接飞书消息渠道时,遇到了一些坑。虽然官方文档写得还算详细,但实际操作中还是踩了不少雷。这篇文章记录了我遇到的问题和最终的解决方案,希望能帮到同样在做飞书集成的开发者。

技术背景

Clawdbot简介

Clawdbot是一个模块化的AI Bot框架,支持多渠道接入(Telegram、WhatsApp、QQ、飞书等)。它的架构是:

用户消息 → 各渠道插件 → Gateway(消息网关) → AI处理 → 回复用户

飞书插件负责:

  • 接收飞书消息
  • 转换成统一格式
  • 发送回复到飞书

飞书开放平台

飞书开放平台提供了两种消息接收方式:

  1. Webhook模式:HTTP回调,适合有公网IP的服务器
  2. 长连接模式:WebSocket连接,适合内网环境

我们选择长连接模式,因为服务器在内网,没有公网IP。

踩坑记录

坑1:插件登录成功,但收不到消息

症状

  • 日志显示 [feishu:default] logged in to feishu as cli_xxx
  • 说明登录认证通过了
  • 但在飞书发消息,Bot完全没有反应
  • 日志里也没有任何消息接收记录

原因分析

飞书插件的代码使用的是Lark SDK的WebSocket客户端:

// gateway.ts
const wsClient = new WSClient({
  appID: config.appId,
  appSecret: config.appSecret,
  eventTypes: ['im.message.receive_v1'],  // 订阅消息事件
});

wsClient.start();

虽然SDK代码里订阅了 im.message.receive_v1 事件,但飞书开放平台需要手动配置订阅

解决方案

  1. 登录飞书开放平台

    • 进入你的自建应用
    • 找到"事件订阅"配置
  2. 配置订阅模式

    • 订阅模式选择:长连接
    • 订阅事件必须勾选:im.message.receive_v1
  3. 关键步骤:发布应用

    • 点击右上角"发布"按钮
    • 选择"正式发布"
    • ⚠️ 这一步容易被忽略!
  4. 重启Clawdbot

    clawdbot gateway restart

验证

# 查看日志,应该能看到连接建立
tail -f /tmp/clawdbot/clawdbot-*.log | grep feishu

坑2:长连接WebSocket没有真正建立

症状

  • 配置都做了
  • 应用也发布了
  • 但还是收不到消息

原因

Lark SDK的WebSocket连接建立有一些时序问题。如果SDK启动太快,飞书开放平台还没来得及处理应用发布,连接会失败。

解决方案

在插件启动代码中添加重试逻辑:

async function startFeishuGateway() {
  let retries = 3;
  while (retries > 0) {
    try {
      await wsClient.start();
      console.log('[feishu] WebSocket connected');
      break;
    } catch (error) {
      retries--;
      console.log(`[feishu] Connection failed, ${retries} retries left`);
      if (retries > 0) {
        await new Promise(resolve => setTimeout(resolve, 5000));
      }
    }
  }
}

坑3:消息格式转换问题

症状

  • 终于收到消息了
  • 但回复时飞书报错:invalid message format

原因

飞书的消息格式和其他平台(如Telegram)差异很大。飞书支持多种消息类型:

  • text(纯文本)
  • post(富文本)
  • interactive(交互式卡片)

Clawdbot统一使用 text 类型,但飞书的text类型需要特定的JSON结构。

解决方案

在飞书插件的发送逻辑中做格式转换:

function formatMessageForFeishu(text: string) {
  return {
    msg_type: 'text',
    content: JSON.stringify({
      text: text
    })
  };
}

最终配置清单

飞书开放平台配置

  • [ ] 创建自建应用,获取App ID和App Secret
  • [ ] 权限管理:添加"获取与发送消息"权限
  • [ ] 事件订阅:

    • [ ] 订阅模式:长连接
    • [ ] 订阅事件:im.message.receive_v1
  • [ ] 发布应用:正式发布
  • [ ] 版本管理:记录版本号,方便回滚

Clawdbot配置

{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxx",
      "appSecret": "your_secret_here",
      "encryptKey": "",  // 长连接模式可留空
      "verificationToken": "",  // 长连接模式可留空
      "capabilities": {
        "inlineButtons": "allowlist"  // 按钮功能
      }
    }
  }
}

日志检查

# 查看飞书插件状态
tail -100 /tmp/clawdbot/clawdbot-*.log | grep feishu

# 应该看到:
# [feishu:default] logged in to feishu as cli_xxx
# [feishu] WebSocket connected

架构图

┌─────────┐     WebSocket      ┌──────────────┐
│         │ ◄──────────────────► │              │
│  飞书    │     长连接          │ Clawdbot     │
│  server │                    │ Gateway      │
│         │                     │              │
└─────────┘                     └──────┬───────┘
                                       │
                                       │ 消息分发
                                       ▼
                                ┌─────────────┐
                                │   AI Agent  │
                                │ (GLM-4.7)   │
                                └─────────────┘

经验总结

  1. 文档要看仔细:飞书开放平台的文档很长,但"事件订阅"部分一定要逐字读完
  2. 发布应用别忘:这是最容易漏的一步,配置改了必须重新发布
  3. 日志是最好的朋友:遇到问题先看日志,能定位90%的问题
  4. 长连接≠即时生效:应用发布后可能需要等待几分钟才能生效
  5. 消息格式要统一:不同渠道的消息格式差异大,需要做好适配层

参考资源

后续优化

目前飞书渠道已经可以正常收发消息了,后续计划:

  1. 支持更多消息类型(图片、文件、卡片)
  2. 实现消息已读状态同步
  3. 支持群消息@机器人
  4. 添加飞书特有功能(如工作通知)

本文记录了实际开发中遇到的问题和解决方案,如果你也在做类似的集成,希望对你有帮助。有问题欢迎交流!

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-15