核心信念(智能体优先的操作原则)
这是争议的裁决依据。当"该不该这么做"出现分歧时,回到这份文件,而不是回到聊天记录。
通用原则(附录 F)
- 人类掌舵,智能体执行。人类不直接贡献代码行。
- 工程师的工作是设计环境、明确意图、构建反馈回路。
- 上下文是稀缺资源;给地图,不给说明书。
- 智能体在运行时看不到的东西,对它来说不存在。
- 强制不变量,不微观管理实现。
- 中央强制边界,本地允许自主表达。
- 纠错成本低,等待成本高。
- 技术债是高息贷款,小额高频偿还。
- 遇到卡点先问:"缺的是什么能力?如何让它既清晰可读又可强制执行?"
- 人类品味要持续被捕捉——写进文档,或直接编码进工具。
- 交互式决策必须落盘:确认过但不写进仓库的决策等于没做。
- 改造存量项目时,重构不改变业务行为;行为变更必须显式登记并单独提交。
重构红线(R1–R7)
| 编号 | 红线 | 说明 |
|---|---|---|
| R1 | 保留原有业务行为 | 重构的定义就是行为不变。 |
| R2 | 行为变更显式登记 | bug 修复与业务变更必须在问题清单中显式标注,并单独提交。 |
| R3 | 先护栏后动手 | 没有测试和门禁保护的模块,先补保护再重构。 |
| R4 | 不做范围外优化 | 发现的新问题登记进台账,不在本次提交里顺手处理。 |
| R5 | 不删无法判断的内容 | 存疑的文档/代码标注"待核实"+ 开 issue,不静默删除。 |
| R6 | 不引入不可内化的依赖 | 优先可组合、API 稳定、行为可推理的依赖。 |
| R7 | 不藏信息 | 关键决策必须落进仓库,不允许只存在于对话或人的记忆里。 |
CoreC 架构取舍
为什么用六边形 + init() 工厂注册
- 取舍:牺牲编译期依赖可见性(
all包空导入是隐式 wiring),换取插件可独立开发/测试/新增而不改核心。 - 裁决依据:IIoT 场景驱动/传输协议频繁增减(Modbus/OPC UA/S7/Profinet/IEC61850…),插件隔离的价值 > 依赖可见性的价值。
- 边界:新增插件只改
all包 + 新包本身,不碰engine/core。若需碰core接口,属架构变更,须人工评审。
为什么 config 用 tree-based env 替换而非字节级
- 取舍:多一次 parse/serialize 往返,换取 YAML 注入防护 + 类型保留。
- 裁决依据:配置文件可能含不可信来源(运维粘贴、CI 注入),字节级替换可构造恶意 YAML。tree-based 在叶子节点替换 + 重新 marshal,env 值经 YAML 编码器转义。
- 边界:
config.example.yaml对该机制的描述必须与此一致。
为什么 API fail-closed 而非 fail-open
- 取舍:空
api.secret时拒绝启动而非无认证运行,牺牲"零配置启动"便利性,换取安全默认。 - 裁决依据:CoreC 的 API 可写 PLC(控制指令下发),无认证的写 API = 任何人可操控物理设备。
- 边界:所有入站路径遵循同一原则,且已机械落地——MQTT 命令订阅配了
command-topic却缺command-secret时拒绝启动(transport/mqtt/mqtt_lifecycle.go),webhook 配了webhook-addr却缺webhook-secret时同样拒绝启动(transport/httppush/push.go);空 secret 在认证中间件内 fail-closed 拒绝(hub/route/middleware.go)。
命名与风格约定
- 包名:单数小写,无下划线(
modbus非modbus_driver)。 - 接口名:核心缝隙用领域名(
core.Driver非core.IDriver)。 - 文件名:
snake_case.go;测试文件*_test.go;bug 回归*_bug_test.go;修复验证*_fix_test.go。 - 错误处理:错误必须包裹上下文(
fmt.Errorf("read tag %s: %w", name, err)),禁止裸返回。 - 日志:结构化
slog,禁止fmt.Println(T6);密钥/secret 值禁止出现在日志中。 - goroutine:每个
go启动必须绑定 context 取消或 WaitGroup(T8);goleak 在主要包(engine、hub/route、driver/、transport/、rule)的 TestMain 中强制验证。 - channel:数据通道必须有 buffer + drop 策略;信号通道用
chan struct{}单写单关。 - 配置:可选字段用
omitempty;必填字段在validate()中校验并返回明确错误。
何时更新本文件
- 做出了非显而易见的架构取舍 → 记录取舍 + 裁决依据 + 边界
- 命名/风格出现争议且裁决了 → 记录约定
- 核心信念被违反且决定容忍 → 记录例外 + 原因 + 到期条件