Go→TS 通知契约

INV-WS-12:wescode 的 Go 后端到 TypeScript 前端通知方法的闭合契约。


问题背景

两个功能曾"悄悄什么都不做"地上线:

原因:_dispatchNotification 使用 if-else 链且没有 default,新增 Method 忘了接线时运行时静默丢弃。


三层保证

1. Go 侧:封闭集合

internal/notify/method.go 定义 notify.Method(带未导出字段的 struct):

// 字面量构造不出来——方法名只能来自这个文件
var ChatStream = Method{name: "chat/stream"}
var CodeintelIndexComplete = Method{name: "codeintel/index-complete"}
// ...

2. 生成 TS 类型

notify/tsgen.go 从 Go AST 生成 wescodeNotifications.ts:

3. TS 侧:assertNever

_dispatchNotification 使用 switch + default: assertNever(method):


三项测试

测试断言
TestGeneratedTypeScriptIsCurrent生成物与 method.go 逐字相等
TestMethodsWalkIsNotVacuousAST walk 非空(避免恒真)
TestEveryMethodHasASender每个 Method 在 backend/ 真有发送方

事件载荷

fireToWindow / fireToBackend 的事件名与 payload 由类型系统约束:


添加新通知

  1. 在 internal/notify/method.go 添加 var XxxYyy = Method{name: "xxx/yyy"}
  2. 在 Go 代码中使用 Notify(notify.XxxYyy, payload)
  3. 运行 make notify-contract(排在 vet 之前)
  4. 在 _dispatchNotification 的 switch 添加 case

忽略通知

如果通知冗余(如 engine/health 由独立 watchdog 轮询),仍需显式写 case 并注明原因。


相关文档