开源 · Apache 2.0 · Java 17+

代码即日志。
别再写日志语句了。

NarrativeTrace 把运行中的代码变成可读的叙事:给调试者看的执行追踪、给写代码的 AI 代理用的无值结构化追踪,以及一条在行为漂移时让构建失败的基线。

implementation("ai.narrativetrace:narrativetrace-core:0.1.0")

build/narrativetrace/customer_places_order.md
# Customer places order- OrderService.placeOrder("C-42", qty: 5) — 4.2ms  - Customers.verifyGoodStanding("C-42") → true  - PricingService.calculate(5) → 49.95  - PaymentService.charge(card: [REDACTED])    → PaymentConfirmation(txId="T-9")  - OrderRepository.save(Order{…})    → Order{id=ORD-1001, total=49.95} // 这一切没有写过一行日志语句。
0行日志出现在你的业务逻辑里
~10 ns追踪关闭时每次调用的开销
15–30%AI 代理阅读你的代码时少用的 token
0个核心运行时依赖

前后对比

删掉日志,留下故事。

一个典型的服务类里,三分之一是日志语句——而它们仍然漏掉了你真正需要的那一条。 NarrativeTrace 自动捕获方法名、参数、返回值和调用结构。你已经写好的代码,就是叙事。

之前 — 到处都是日志

public Order placeOrder(String customerId, int qty) {
    log.info("Placing order for {} qty {}", customerId, qty);
    customers.verifyGoodStanding(customerId);
    log.debug("Customer in good standing");
    var price = pricing.calculate(qty);
    log.info("Calculated price: {}", price);
    var order = repository.save(new Order(customerId, price));
    log.info("Order saved: {}", order.getId());
    return order;
}

之后 — 代码即日志

public Order placeOrder(String customerId, int qty) {
    customers.verifyGoodStanding(customerId);
    var price = pricing.calculate(qty);
    return repository.save(new Order(customerId, price));
}

// 零行日志。
// NarrativeTrace 自动捕获叙事。

生成的追踪 — Markdown、JSON、散文、时序图,以及给 AI 的无值 .nt

叙事追踪
- OrderService.placeOrder("C-42", 5)
  - Customers.verifyGoodStanding("C-42") → true
  - PricingService.calculate(5) → 49.95
  - OrderRepository.save(Order{…}) → Order{id=ORD-1001, total=49.95}

同一条追踪的散文版 — 用于 bug 报告、业务沟通和 LLM 上下文

new ProseRenderer().render(trace)
The order service places an order for customer id "C-42", quantity 5:
  Customers verify good standing for customer id "C-42", returning true.
  The pricing service calculates for quantity 5, returning 49.95.
  The order repository saves the order Order{…}, returning Order{id=ORD-1001, total=49.95}.
  Returns Order{id=ORD-1001, total=49.95}.

散文的可读性,恰好等于你命名的质量。DataProcessor.process(a, b) 会渲染成 The data processor processes a: 0, b: 0:准确,却毫无用处。这正是清晰度评分存在的理由:它根据运行时叙事给每个名字打分,让代码学会讲自己的故事。 清晰度诊断 →

叙事审批测试 0.2.0 · 下一版本

测试能抓住错误的值。
叙事能抓住错误的行为。

每次运行之后,NarrativeTrace 都会把每个场景的调用结构与上一次绿色运行比较,用一行话说明变了什么。 打开审批模式,未经审批的变化(多了一次调用、少了一次调用、结果不同)会以一份可读的 diff 让构建失败,直到有人审批为止。测试是绿的,行为却变了。现在你知道了。

./gradlew test — 每次运行,无需配置
NarrativeTrace — Suite complete
  5 scenarios recorded
  Clarity: 100% high | 0% moderate | 0% low
  Reports: build/narrativetrace
  Since last green: 4 scenarios unchanged · 1 changed:
    "Customer places order" (−1 call Customers.verifyGoodStanding)
approval.set(true) — 重构必须经过审批
Narrative changed against the approved baseline
  src/test/narratives/OrderServiceTest/customer_places_order.approved.nt

  - OrderService.placeOrder(customerId, qty) → value
-   - Customers.verifyGoodStanding(customerId) → value
    - PricingService.calculate(qty) → value
    - PaymentService.charge(card) → value
    - OrderRepository.save(order) → value

  审阅 .received.nt,然后执行:./gradlew approveNarratives

每次运行后一行话

无需任何设置。每个测试本来就会写出的 .nt 文件就是上一次绿色运行的基线;测试失败时打印的是 自那以后变了什么——通常就是通往 bug 的最短路径——而不是整条追踪。

审批的是行为,不只是代码

为每个场景提交一份基线。任何改变结构的重构——你的,或者你的代理的——都会失败,直到有人审阅 diff 并运行 approveNarratives。代码 diff 是实现细节;叙事 diff 才是评审。

天生不含值

基线只包含名字和结构:没有测试夹具数据、没有 PII、没有注入面。它们不会因测试数据变动而失效, 可以安全提交到仓库,也可以安全地交给 AI 代理作为权威规格。

审批测试是如何工作的

面向 AI 辅助开发

你的 AI 代理能读代码。
现在它还能看代码运行。

Vibe coding 一直很顺,直到出了问题——没有人,无论是人还是代理,知道运行时到底发生了什么。 NarrativeTrace 给编码代理提供事实:真实的调用树,而不是靠静态阅读拼凑出来的猜测。

运行时的事实,而非猜测

只靠源码调试的代理会推断行为——而且推断错。一条叙事追踪展示了什么运行了、按什么顺序、带着什么参数和结果。 把它贴进任何代理的上下文,或者直接附上你的 CI 已经生成的每个测试的追踪文件。

每个上下文窗口装下更多逻辑

日志语句是噪音 token。去掉它们之后,代理阅读一个服务类的成本降低 15–30%——而追踪的每一行都是信号, 因为它是从名字生成的,不是从散文生成的。

一条无法毒害代理的追踪 0.2.0

每个测试还会写出一个 .nt 结构化追踪:调用树,去掉了所有运行时的值。零提示注入面、零 PII、 只用一小部分 token——可以安全地贴给代理,或提交到仓库。安全来自构造,而不是过滤。

分离是如何实现的

MCP 服务器 Pro 即将推出

Claude Code、Cursor 和 Copilot 将通过 Model Context Protocol 直接查询追踪、运行时依赖图和清晰度数据——只读, 输出级别分层,默认只给结构。

预览 MCP 设计

这个网站对代理同样友好:把你的助手指向 llms.txtllms-full.txt,它就能替你接入 NarrativeTrace。

面向遗留系统现代化

迁移那个没人懂的系统 — 而且有凭有据。

AI 代理让重写变得便宜;昂贵的是验证。给遗留系统套上追踪,你就得到了它真实的运行时行为——在改动之前, 以及改动之后的等价性证明。

给你真正拥有的架构拍一张 X 光

把 Java Agent 挂到一个未经修改的应用上——参考示例是一个部署在 WildFly 上、不带任何依赖的 EJB WAR, 只用一个 -javaagent 参数就完成追踪——或者直接跑你已有的 JUnit 4 套件。不改源码,不做文档考古。

零代码 Agent

证明行为没有改变

在动手之前,先把每个场景的行为固定在一份无值基线里——免费。然后比较移植或 AI 重写前后的整套追踪, 每一处差异都按风险分类 Pro。等价性不再是一种感觉,而是一份报告。

迁移差异

暴露隐藏的耦合 Pro

从真实执行中聚合出来的运行时依赖图:实线表示总是被调用的依赖,虚线表示带频率的条件依赖。 循环依赖和“上帝服务”无处可藏。

依赖图

找出最难读的代码

如果追踪读不通,说明代码在撒谎。清晰度评分根据运行时叙事给命名打分,并解释每一个分数:每个元素一条说明、 重命名建议、缩写展开(chk → check)。让你的重构——或你的代理的重构——先从最糟的角落开始。免费。

清晰度诊断

领域语言 0.2.0 · 下一版本

从真实运行中采集你的通用语言。

名字就是追踪。NarrativeTrace 把它们变成一份由团队维护、在 CI 中强制执行的活术语表——并把同一次运行 渲染成你的团队语言的散文。数据本身从不被触碰。

同一次运行 · 同一份术语表
订单服务 为顾客编号 "C-42" 下单,数量 2:
  顾客服务 按顾客编号 "C-42" 查找顾客,返回 顾客[编号=C-42, 等级=GOLD]。
  库存服务 为商品编号 "SKU-KB" 预留 2 件,返回 预留记录[商品编号=SKU-KB, 数量=2]。
  支付服务 向顾客编号 "C-42" 扣款,金额 179.98,返回 支付确认[交易编号=TXN-1]。
  返回 订单结果[订单编号=ORD-1, 总扣款=179.98]。

采集术语表

glossaryScan 从编译后的类和测试运行中,为每个仓库生成一份 glossary.json,按限界上下文划分。 定义、翻译和已弃用的同义词由你来维护;采集永远不会覆盖它们。

在 CI 中强制执行

使用了已弃用同义词的方法会在运行输出中被标记—— openAccountWithOverdraft → use openOverdraftAccount——而且 clarityCheck 可以因此让构建失败。词汇漂移是构建错误,而不是代码评审里的一句评论。

用你的语言写成的散文

整次运行读起来就是一段段句子——服务、动作、参数——用中文或西班牙语。类型名和字段名来自同一份术语表; 数据本身保持逐字节一致。简体中文和西班牙语率先发布;更多语言即将到来。

术语表与翻译后的追踪

工作原理

三步得到你的第一条叙事

1

添加两个依赖

dependencies {
  implementation(
    "ai.narrativetrace:narrativetrace-core:0.1.0")
  implementation(
    "ai.narrativetrace:narrativetrace-proxy:0.1.0")
}
2

包装一个服务 — 或自动包装

var context = new ThreadLocalNarrativeContext();
var service = NarrativeTraceProxy.trace(
    orderService, OrderService.class, context);

// 或者在 Spring 中:
@EnableNarrativeTrace(
    basePackages = "com.example.app")
3

读故事

service.placeOrder("C-42", 5);

System.out.println(
  new IndentedTextRenderer()
      .render(context.captureTrace()));

// JUnit 5/4:每个测试都会写出
// 自己的追踪文件。

版本

给人用的免费。AI 规模化与合规付费。

边界很简单:作为开发者阅读追踪永远免费,Apache 2.0。跨运行分析、规模化的 AI 集成、团队审批流程和合规级审计是付费的。

开源版 现已可用

一位开发者需要的一切,核心零运行时依赖。

  • 自动追踪:代理、Java Agent、Spring、Servlet
  • 全部五个捕获级别,可在运行时切换
  • @Narrated@OnError@NotTraced 注解 + 脱敏
  • JUnit 5 和 JUnit 4 的逐测试追踪文件:Markdown、JSON、散文、时序图
  • 清晰度评分、clarityCheck 门禁与 SLF4J 桥接
  • 审批测试与无值 .nt 追踪 — 0.2.0
  • 领域术语表、翻译后的追踪、OpenTelemetry、Micronaut — 0.2.0
开始使用

Platform 即将推出

托管后端,汇集每个服务、每个环境、每次运行的叙事。

  • 托管的 OTLP 追踪接入
  • 多租户存储与搜索
  • 团队仪表盘与保留策略
  • 组织级清晰度与审计报告
加入候补名单

完整对比见 Pro 概览。 开源构件发布在 Maven Central 的 ai.narrativetrace 之下。

集成

与你现有的技术栈无缝对接

Spring Boot 0.1.0
JUnit 5 0.1.0
JUnit 4 0.1.0
Java Agent 0.1.0
SLF4J 0.1.0
Micrometer 0.1.0
Servlet 0.1.0
Clarity CLI 0.1.0
Gradle 插件 0.2.0
Jakarta EE / WildFly 0.2.0
Micronaut 0.2.0
OpenTelemetry 0.2.0

不止 Java

一套架构,每个运行时

叙事捕获、双消费者输出和清晰度诊断——同一套设计,移植到各个平台。.NET 移植版已经能生成同样的无值 .nt 构件,所以审批基线可以在平台之间通用。

Java现已可用
.NET开发中
TypeScript开发中
Swift开发中
Python已规划

让你的代码开口说话。

五分钟得到你的第一条叙事。这个库的诞生过程中没有写过一行日志语句。