Seismograph
"An earthquake's damage isn't determined at the epicenter. It's determined by the geology between the epicenter and everything else — the fault lines, the soil composition, the depth of the bedrock. Code changes work the same way."
What It Does
Before you make a change, Seismograph maps the propagation path — every function, module, test, type, config, and downstream system that will feel the tremor. Not just "what calls this function" (your IDE does that), but:
- - What assumptions about this code exist elsewhere?
- What tests validate the current behavior you're about to change?
- What documentation promises the behavior you're about to break?
- What downstream systems depend on the output shape you're about to modify?
- What side effects of this code have become relied upon, even though they weren't intended?
The Seismic Model
Earthquake Anatomy → Change Anatomy
| Seismic Concept | Code Equivalent |
|---|
| Epicenter | The line(s) of code you're modifying |
| Fault line |
Interface boundaries, type contracts, API surfaces |
|
P-waves (first, compression) | Direct callers/importers — feel the change immediately |
|
S-waves (second, shear) | Indirect dependents — feel it through intermediaries |
|
Surface waves (slowest, most destructive) | Side-effect dependents — feel it through emergent behavior |
|
Seismic velocity | How fast the change propagates (tight coupling = faster) |
|
Liquefaction | Loosely-defined interfaces that collapse under unexpected change |
|
Aftershocks | Secondary bugs caused by fixing the primary change's breakage |
|
Magnitude | Scope of the change × coupling density × downstream reach |
|
Intensity (varies by location) | Impact varies by distance and intervening architecture |
Wave Analysis
P-Waves: Direct Impact
Propagation: Immediate callers, importers, and direct consumers.
Speed: Instant. These break at compile/import time.
Damage: Usually low — these are caught by static analysis.
CODEBLOCK0
S-Waves: Indirect Impact
Propagation: Second-order dependents. Things that use things that use the changed code.
Speed: Slower. These break at runtime or during integration testing.
Damage: Medium — often caught by integration tests, if they exist.
CODEBLOCK1
Surface Waves: Side-Effect Impact
Propagation: Code that depends on the
behavior of the changed code without explicitly calling it. Event listeners, database triggers, log parsers, monitoring alerts, cached values, file watchers.
Speed: Slowest. These break in production, days or weeks later.
Damage: Highest — invisible until they cause an incident.
CODEBLOCK2
Magnitude Scale
| Magnitude | Description | Typical Impact |
|---|
| 1.0 - 2.0 | Micro. Internal refactor, no interface change. | Self-contained. No propagation. |
| 2.0 - 3.0 |
Minor. Implementation detail change, interface preserved. | P-waves only. Tests may need updates. |
|
3.0 - 4.0 | Moderate. Interface change, same semantics. | P and S-waves. Direct consumers affected. |
|
4.0 - 5.0 | Significant. Semantic change to public interface. | All wave types. Integration tests break. |
|
5.0 - 6.0 | Major. Behavioral change affecting downstream systems. | Cross-service impact. Deployment coordination needed. |
|
6.0 - 7.0 | Severe. Schema/contract breaking change. | Data migration required. Multi-team coordination. |
|
7.0+ | Catastrophic. Architectural assumption change. | System-wide impact. Staged rollout mandatory. |
Geological Survey: Pre-Change Analysis
CODEBLOCK3
Output Format
CODEBLOCK4
When to Invoke
- - Before any change to a public interface, API, or shared type
- Before renaming anything that crosses a module boundary
- Before modifying database schemas or wire formats
- Before removing any function, field, or parameter
- When someone says "this should be a simple change" (it never is)
- During PR review to assess whether the change accounts for its full impact
Why It Matters
The #1 source of production incidents isn't bad code — it's changes that propagated further than anyone expected. A "simple rename" that broke a webhook. A "minor optimization" that changed a timing guarantee. A "cleanup refactor" that removed a field a downstream system needed.
Seismograph doesn't prevent changes. It prevents surprises. Because the question is never "should we make this change?" — it's "do we understand what this change will touch?"
Zero external dependencies. Zero API calls. Pure static and historical analysis.
地震仪
地震的破坏力并非由震中决定,而是由震中与周边区域之间的地质条件——断层线、土壤成分、基岩深度所决定。代码变更也是如此。
功能概述
在进行变更之前,地震仪会绘制传播路径——每一个会感受到震动的函数、模块、测试、类型、配置和下游系统。不仅仅是什么调用了这个函数(你的IDE就能做到),还包括:
- - 其他地方存在哪些关于这段代码的假设?
- 哪些测试验证了你即将更改的当前行为?
- 哪些文档承诺了你即将破坏的行为?
- 哪些下游系统依赖于你即将修改的输出结构?
- 这段代码的哪些副作用已被依赖,即使它们并非有意为之?
地震模型
地震解剖 → 变更解剖
接口边界、类型契约、API表面 |
|
P波(初至,压缩波) | 直接调用者/导入者——立即感受到变更 |
|
S波(次至,剪切波) | 间接依赖者——通过中介感受到变更 |
|
面波(最慢,最具破坏性) | 副作用依赖者——通过涌现行为感受到变更 |
|
地震波速 | 变更传播的速度(紧耦合 = 更快) |
|
液化 | 定义松散的接口在意外变更下崩溃 |
|
余震 | 修复主要变更破坏后引发的二次错误 |
|
震级 | 变更范围 × 耦合密度 × 下游影响范围 |
|
烈度(因位置而异) | 影响因距离和中间架构而不同 |
波分析
P波:直接影响
传播: 直接调用者、导入者和直接消费者。
速度: 即时。这些在编译/导入时就会破坏。
损害: 通常较低——静态分析即可捕获。
分析:
├── 每个导入变更模块的文件
├── 每个调用变更函数的函数
├── 每个扩展或实现变更类型的类型
├── 每个直接测试变更行为的测试
└── 预估:受影响文件数,可能影响的代码行数
S波:间接影响
传播: 二阶依赖者。使用那些使用了变更代码的代码。
速度: 较慢。这些在运行时或集成测试期间破坏。
损害: 中等——如果存在集成测试,通常能被捕获。
分析:
├── 传递性导入者(A使用B,B使用变更)
├── 消费变更函数输出的函数
├── 读取变更代码写入数据的系统
├── 由变更逻辑解析的配置
└── 预估:传播深度,最薄弱的中介
面波:副作用影响
传播: 依赖变更代码
行为但不显式调用它的代码。事件监听器、数据库触发器、日志解析器、监控告警、缓存值、文件监视器。
速度: 最慢。这些在生产环境中破坏,可能在数天或数周后。
损害: 最高——在引发事故之前不可见。
分析:
├── 响应变更代码发出事件的事件订阅者
├── 对变更行为进行模式匹配的监控/告警规则
├── 从变更代码输出计算出的缓存值
├── 由变更代码查询触发的数据库触发器
├── 期望变更代码日志格式的日志解析器/聚合器
├── 学习(而非约定)了输出形状的下游服务
└── 预估:面波损害概率,检测难度
震级标度
| 震级 | 描述 | 典型影响 |
|---|
| 1.0 - 2.0 | 微级。内部重构,无接口变更。 | 自包含。无传播。 |
| 2.0 - 3.0 |
轻微。实现细节变更,接口保留。 | 仅P波。测试可能需要更新。 |
|
3.0 - 4.0 | 中等。接口变更,语义相同。 | P波和S波。直接影响消费者。 |
|
4.0 - 5.0 | 显著。公共接口的语义变更。 | 所有波类型。集成测试破坏。 |
|
5.0 - 6.0 | 重大。影响下游系统的行为变更。 | 跨服务影响。需要部署协调。 |
|
6.0 - 7.0 | 严重。模式/契约破坏性变更。 | 需要数据迁移。多团队协调。 |
|
7.0+ | 灾难性。架构假设变更。 | 全系统影响。必须分阶段发布。 |
地质调查:变更前分析
阶段1:震中映射
├── 识别正在变更的确切代码行
├── 分类变更类型:
│ ├── 重命名(最低风险)
│ ├── 签名变更(中等风险)
│ ├── 行为变更(高风险)
│ ├── 删除(最高风险)
│ └── 新增(通常安全,除非重载现有名称)
└── 确定震级基线
阶段2:波传播
├── P波分析:
│ ├── 静态依赖图遍历
│ ├── 类型系统影响(编译时什么会破坏?)
│ └── 直接测试影响(哪些测试会失败?)
├── S波分析:
│ ├── 传递性依赖遍历(2-3跳)
│ ├── 数据流追踪(输出在哪里被消费?)
│ └── 集成测试影响
└── 面波分析:
├── 事件/消息订阅者
├── 数据库触发器和视图
├── 监控和告警规则
├── 缓存失效影响
└── 日志格式依赖
阶段3:断层线评估
├── 对于每条波路径,评估中间架构:
│ ├── 强边界(类型化接口、契约)→ 波衰减
│ ├── 弱边界(鸭子类型、约定)→ 波放大
│ ├── 无边界(直接耦合)→ 波通过
│ └── 断层线(已知脆弱点)→ 波放大
└── 调整每个受影响位置的烈度
阶段4:余震预测
├── 如果修复主要破坏,会发生哪些二次破坏?
├── 哪些修复是安全的(局部化)vs 级联的(引发更多波)?
├── 预估总变更集:原始变更 + 所有必要的适配
└── 总变更集是否超出原始意图的合理范围?
阶段5:地震仪报告
├── 震级和烈度图
├── 受影响位置的优先级列表
├── 推荐的变更策略(直接、分阶段、功能开关后)
├── 余震预测
└── 推荐:执行 / 分阶段发布 / 重新考虑
输出格式
╔══════════════════════════════════════════════════════════════╗
║ 地震仪分析报告 ║
║ 提议:重命名 User.email → User.emailAddress ║
║ 震级:4.7(显著) ║
╠══════════════════════════════════════════════════════════════╣
║ ║
║ 震中:src/models/user.ts:24 ║
║ ║
║ P波(直接影响): ║
║ ├── 14个文件导入User并访问.email ║
║ ├── 8个测试断言.email ║
║ ├── 2个API序列化器包含email键 ║
║ └── 编译时破坏:是(TypeScript将捕获) ║
║ ║
║ S波(间接影响): ║
║ ├── 3个服务消费包含email字段的User API响应 ║
║ ├── 1个webhook负载包含email(外部消费者) ║
║ ├── 1个CSV导出使用email作为列标题 ║
║ └── 运行时破坏:可能(在下游服务中) ║
║ ║
║ 面波(副作用影响): ║
║ ├── Elasticsearch索引映射email字段 → 搜索破坏 ║
║ ├── 监控告警匹配日志输出中的email ║
║ ├── 2个Zapier集成引用email字段 ║
║ └── 检测难度:高(数周后才能发现) ║
║ ║