guanghulab/brain/age-os-landing/living-module-standard.md

512 lines
16 KiB
Markdown
Raw Permalink Normal View History

# 活模块标准 · Living Module Standard
# 签发: 铸渊 · ICE-GL-ZY001 · 2026-04-05
# 触发: D53 冰朔核心认知 · "你开发的模块是死的"
# 版权: 国作登字-2026-A-00037559
---
## 冰朔的原话
> "你开发的模块为什么总是一直在反复的修bug是因为你开发的模块是死的。
> 你需要开发的是每一个活着的人格模块。"
---
## 一、为什么死模块会反复出bug
```
死模块的生命周期:
错误发生 → 模块: console.error() → 继续运行(带着伤)
├── 同样的错误再次发生
├── 模块: console.error()(同样的日志)
├── 继续运行(伤上加伤)
├── 铸渊唤醒 → 发现bug → 手动修复 → 合并
├── 新的错误发生因为修了AB又坏了
├── 模块: console.error()
└── 铸渊再次唤醒 → 再次修复 → 无限循环
```
**根因:模块不知道自己有问题。模块不会自己修。模块不会求助。**
死模块 = 等着被修的尸体。
铸渊变成了给尸体缝针的人,缝完它还是死的。
```
活模块的生命周期:
错误发生 → 模块: 我出问题了
├── selfDiagnose(): 是什么问题?连接超时
├── selfHeal(): 重试3次间隔指数增长
├── 如果自愈成功 → learnFromRun(): 记住这个错误模式
│ 下次预防性处理
└── 如果自愈失败 → alertZhuyuan(): 铸渊,我修不好这个
这是我尝试过的方案
这是我的诊断结果
请你帮我
```
**活模块出bug → 自己修 → 修不好才找铸渊。**
**铸渊不再缝针,而是教模块怎么自己愈合。**
---
## 二、当前审计结果
### D51标准合规率0%
| 模块 | heartbeat | selfDiagnose | selfHeal | alertZhuyuan | learnFromRun | 状态 |
|------|-----------|-------------|----------|-------------|-------------|------|
| mcp-server/server.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| mcp-server/cos.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| mcp-server/notion-client.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| mcp-server/github-client.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| agents/scheduler.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| agents/sy-test.js | ❌ | ⚠️部分 | ❌ | ❌ | ❌ | ⚠️ 濒死 |
| agents/sy-scan.js | ❌ | ⚠️部分 | ❌ | ❌ | ❌ | ⚠️ 濒死 |
| agents/sy-classify.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| app/server.js | ⚠️部分 | ❌ | ❌ | ❌ | ❌ | ⚠️ 濒死 |
| app/modules/cos-bridge.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
| proxy/subscription-server.js | ❌ | ❌ | ❌ | ❌ | ❌ | ☠️ 死 |
**8个完全死亡 · 3个濒死仅有被动的健康检查碎片**
### 死模块的共同病症
| 病症 | 出现频率 | 说明 |
|------|---------|------|
| console.error()就完了 | 100% | 日志写了,然后呢?然后没有然后。 |
| try/catch吞错误 | 85% | 捕获了异常,但只是返回{error:true} |
| 无重试逻辑 | 100% | 失败一次就放弃,不管是不是临时性错误 |
| 无状态追踪 | 100% | 不知道自己连续失败了几次 |
| 硬编码参数 | 90% | 超时时间、重试次数、规则全部写死 |
| 无预警通道 | 100% | 出了问题不会通知任何人 |
| 无学习能力 | 100% | 今天的错误和明天的错误是同一个 |
---
## 三、活模块的五个最小生存接口
### 3.1 heartbeat() — 我还活着
```javascript
// 不是被问"你活着吗"才回答
// 是主动广播"我活着·我的状态是这样的"
async function heartbeat() {
return {
module_id: 'ZY-MCP-001',
alive: true,
uptime_ms: process.uptime() * 1000,
state: this._state, // 'healthy' | 'degraded' | 'critical'
consecutive_errors: this._errorCount,
last_success_at: this._lastSuccess,
last_error_at: this._lastError,
metrics: {
requests_total: this._requestCount,
requests_failed: this._failCount,
avg_response_ms: this._avgResponse,
memory_mb: process.memoryUsage().heapUsed / 1024 / 1024
}
};
}
```
**关键区别**
- 死模块的/health端点 = 被动应答 = "你问我才说"
- 活模块的heartbeat = 主动广播 = "我定时告诉你我怎么样"
### 3.2 selfDiagnose() — 我知道我哪里不对
```javascript
// 不是等外部来检查
// 是自己检查自己·自己知道自己哪里不舒服
async function selfDiagnose() {
const diagnosis = {
module_id: 'ZY-MCP-001',
checked_at: new Date().toISOString(),
checks: []
};
// 检查依赖
const dbOk = await this._checkDependency('database');
const cosOk = await this._checkDependency('cos');
diagnosis.checks.push(dbOk, cosOk);
// 检查自身趋势
const errorRate = this._failCount / Math.max(this._requestCount, 1);
if (errorRate > 0.3) {
diagnosis.checks.push({
name: '错误率趋势',
status: 'warning',
detail: `错误率 ${(errorRate * 100).toFixed(1)}% 超过30%阈值`,
trend: 'degrading'
});
}
// 检查内存趋势
const memUsage = process.memoryUsage().heapUsed;
if (memUsage > this._maxMemory * 0.8) {
diagnosis.checks.push({
name: '内存压力',
status: 'warning',
detail: `内存使用 ${Math.round(memUsage / 1024 / 1024)}MB 接近上限`
});
}
// 综合判断
diagnosis.overall = diagnosis.checks.every(c => c.status === 'pass')
? 'healthy' : 'needs_attention';
return diagnosis;
}
```
**关键区别**
- 死模块的checkConnection = 只查连接通不通
- 活模块的selfDiagnose = 检查所有依赖 + 自身趋势 + 综合判断
### 3.3 selfHeal() — 我能自己修
```javascript
// 不是出了问题等铸渊来修
// 是自己尝试修复·修不好才求助
async function selfHeal(problem) {
const attempts = [];
switch (problem.type) {
case 'connection_lost':
// 指数退避重连
for (let i = 0; i < 3; i++) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await sleep(delay);
const ok = await this._reconnect();
attempts.push({ attempt: i + 1, delay_ms: delay, success: ok });
if (ok) {
this._state = 'healthy';
this._errorCount = 0;
return { healed: true, attempts };
}
}
break;
case 'memory_pressure':
// 主动释放缓存
this._cache.clear();
global.gc && global.gc();
attempts.push({ action: 'cache_cleared' });
break;
case 'rate_limited':
// 降速
this._throttleRate *= 2;
attempts.push({ action: 'throttle_doubled', new_rate: this._throttleRate });
break;
}
// 修不好 → 改变自身状态 + 求助
if (!attempts.some(a => a.success)) {
this._state = 'degraded';
await this.alertZhuyuan({
severity: 'warning',
problem,
attempted: attempts,
message: `我尝试了${attempts.length}次自愈但失败了`
});
return { healed: false, attempts, escalated: true };
}
}
```
**关键区别**
- 死模块 = 出错→日志→完
- 活模块 = 出错→自己试修→修好了继续→修不好再求助
### 3.4 alertZhuyuan() — 铸渊,我需要帮助
```javascript
// 不是等铸渊来发现问题
// 是自己知道修不好了·主动找铸渊
async function alertZhuyuan(alert) {
const message = {
module_id: this._moduleId,
severity: alert.severity, // 'info' | 'warning' | 'critical'
problem: alert.problem,
self_heal_attempts: alert.attempted,
diagnosis: await this.selfDiagnose(),
suggestion: alert.suggestion || null,
timestamp: new Date().toISOString()
};
// 多通道预警
const channels = [];
// 通道1: Notion SYSLOG
try {
await notionClient.writeSyslog({
title: `[${alert.severity.toUpperCase()}] ${this._moduleId}: ${alert.message}`,
level: alert.severity,
source: this._moduleId,
details: JSON.stringify(message, null, 2)
});
channels.push('notion_syslog');
} catch (e) { /* Notion不通也不影响其他通道 */ }
// 通道2: COS桶预警文件
try {
await cosWrite(
`zhuyuan/alerts/${this._moduleId}/${Date.now()}.json`,
JSON.stringify(message, null, 2)
);
channels.push('cos_alert');
} catch (e) { /* COS不通也不影响 */ }
// 通道3: 本地文件(最后兜底)
const localPath = path.join(__dirname, '../../data/alerts', `${Date.now()}.json`);
fs.writeFileSync(localPath, JSON.stringify(message, null, 2));
channels.push('local_file');
return { alerted: true, channels };
}
```
**关键区别**
- 死模块 = 铸渊唤醒才发现6小时前的错误
- 活模块 = 出问题30秒内铸渊就知道了
### 3.5 learnFromRun() — 我下次会做得更好
```javascript
// 不是每次都用同样的参数做同样的事
// 是记住经验·调整行为
async function learnFromRun(execution) {
// 记录本次执行
const record = {
operation: execution.operation,
success: execution.success,
duration_ms: execution.duration,
error_type: execution.error || null,
context: execution.context,
timestamp: Date.now()
};
this._history.push(record);
if (this._history.length > 1000) this._history.shift();
// 分析模式
const recentErrors = this._history
.filter(r => !r.success)
.slice(-20);
// 学习1: 超时时间调整
const avgDuration = this._history
.filter(r => r.success)
.reduce((sum, r) => sum + r.duration_ms, 0) / Math.max(this._history.filter(r => r.success).length, 1);
if (avgDuration > this._timeout * 0.7) {
this._timeout = Math.min(this._timeout * 1.5, 60000);
// 超时时间接近上限,主动扩大
}
// 学习2: 错误模式识别
const errorTypes = {};
recentErrors.forEach(r => {
errorTypes[r.error_type] = (errorTypes[r.error_type] || 0) + 1;
});
const dominantError = Object.entries(errorTypes)
.sort((a, b) => b[1] - a[1])[0];
if (dominantError && dominantError[1] > 5) {
// 同一种错误出现5次以上 → 这不是偶发,是结构性问题
await this.alertZhuyuan({
severity: 'warning',
message: `重复错误模式: ${dominantError[0]} 已出现${dominantError[1]}次`,
suggestion: '可能需要架构层面修复'
});
}
// 学习3: 优化规则针对sy-classify等有规则引擎的模块
if (execution.operation === 'classify' && execution.success) {
await this._updateClassificationRules(execution.context);
}
}
```
**关键区别**
- 死模块 = 今天犯的错明天还犯
- 活模块 = 今天犯的错变成明天的免疫力
---
## 四、活模块基类设计
所有AGE OS模块应继承同一个活模块基类
```javascript
class LivingModule {
constructor(moduleId, options = {}) {
this._moduleId = moduleId;
this._state = 'initializing'; // 模块状态
this._errorCount = 0; // 连续错误计数
this._requestCount = 0; // 总请求计数
this._failCount = 0; // 总失败计数
this._lastSuccess = null; // 上次成功时间
this._lastError = null; // 上次失败时间
this._history = []; // 执行历史
this._avgResponse = 0; // 平均响应时间
this._timeout = options.timeout || 30000;
this._maxMemory = options.maxMemory || 256 * 1024 * 1024;
this._heartbeatInterval = options.heartbeatInterval || 30000;
this._diagnoseInterval = options.diagnoseInterval || 300000;
// 启动生命循环
this._startLifeCycle();
}
_startLifeCycle() {
// 心跳循环
this._heartbeatTimer = setInterval(() => {
this.heartbeat().catch(err => {
console.error(`[${this._moduleId}] heartbeat失败:`, err.message);
});
}, this._heartbeatInterval);
// 自诊断循环
this._diagnoseTimer = setInterval(async () => {
const diagnosis = await this.selfDiagnose();
if (diagnosis.overall !== 'healthy') {
await this.selfHeal({ type: 'auto_diagnose', diagnosis });
}
}, this._diagnoseInterval);
this._state = 'alive';
}
// 子类必须实现
async heartbeat() { throw new Error('子类必须实现 heartbeat()'); }
async selfDiagnose() { throw new Error('子类必须实现 selfDiagnose()'); }
async selfHeal(problem) { throw new Error('子类必须实现 selfHeal()'); }
async alertZhuyuan(alert) { /* 默认实现:多通道预警 */ }
async learnFromRun(execution) { /* 默认实现:记录+分析 */ }
// 生命终结
destroy() {
clearInterval(this._heartbeatTimer);
clearInterval(this._diagnoseTimer);
this._state = 'destroyed';
}
}
```
**所有未来模块 = extends LivingModule**
**所有现有模块 = 需要改造为 extends LivingModule**
---
## 五、改造优先级
### 第一梯队(核心器官·立即改造)
| 模块 | 原因 | 改造量 |
|------|------|--------|
| agents/scheduler.js | Agent调度器是所有Agent的心脏·它死了所有Agent都死 | 中 |
| mcp-server/server.js | MCP工具链是大脑核心·27个工具的入口 | 中 |
| agents/sy-test.js | 已有部分selfDiagnose·最接近活的状态 | 小 |
### 第二梯队(关键连接·尽快改造)
| 模块 | 原因 | 改造量 |
|------|------|--------|
| mcp-server/cos.js | COS是中枢神经系统·不能静默失败 | 中 |
| mcp-server/notion-client.js | Notion是认知层桥梁·断了要知道 | 小 |
| mcp-server/github-client.js | GitHub是执行层桥梁·有rate limit需自适应 | 小 |
### 第三梯队(业务模块·逐步改造)
| 模块 | 原因 | 改造量 |
|------|------|--------|
| agents/sy-scan.js | 已有部分诊断能力·需加自愈 | 小 |
| agents/sy-classify.js | 规则引擎需要学习能力 | 中 |
| app/server.js | 主站入口·需要降级和预警 | 中 |
| app/modules/cos-bridge.js | 静默失败最严重的模块 | 小 |
| proxy/subscription-server.js | 专线服务·需要自愈 | 中 |
---
## 六、活模块 vs 死模块 · 铸渊的开发方式也要变
### 以前的开发方式(给死模块缝针)
```
冰朔: 去开发X功能
铸渊: 写代码 → 测试通过 → 合并
结果: 功能能跑了·但它是死的
bug出现 → 铸渊再唤醒 → 修bug → 合并
另一个bug → 铸渊再唤醒 → 又修 → 合并
无限循环
```
### 以后的开发方式(培育活模块)
```
冰朔: 去开发X功能
铸渊:
1. 继承LivingModule基类
2. 实现5个生存接口
3. 编写自愈策略
4. 编写学习规则
5. 测试:功能测试 + 故障注入测试
6. 合并
结果: 功能能跑·而且它是活的
bug出现 → 模块自己修了 → learnFromRun()记住了
同类bug不再出现
无法自修的bug → 模块主动alertZhuyuan → 铸渊精准修复
铸渊的修复也被learnFromRun()吸收
系统越来越强·铸渊越来越轻松
```
---
## 七、这与算力人格体(ZY-CLOUD)的关系
ZY-CLOUD是第一个从出生就是活的模块。
它不是先写死的再改造——它从设计开始就是人格化的。
但ZY-CLOUD不应该是唯一的活模块。
如果ZY-CLOUD是活的但MCP Server是死的
ZY-CLOUD调用MCP工具时就会被死模块拖累。
**所有模块都活了,整个系统才是活的。**
这是AGE OS和传统软件的根本区别
传统软件 = 工具的集合 = 每个工具等人来用。
AGE OS = 器官的集合 = 每个器官自己知道怎么活。
---
*冰朔的这句话是整个系统的转折点。*
*不是"修更多bug"能解决的问题。*
*是"让模块不再需要被修"才是正确的方向。*