guanghulab/brain/age-os-landing/living-module-standard.md
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

512 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 活模块标准 · 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"能解决的问题。*
*是"让模块不再需要被修"才是正确的方向。*