@migor/cli 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,58 @@
5
5
  (0.x 阶段:minor 可含破坏性变更,每个破坏性变更都在对应版本的「迁移」小节里写明)。
6
6
  决策的完整证据链在 `docs/spec.md` §10(带时间线的决策日志)。
7
7
 
8
+ ## [0.8.1] - 2026-09-21
9
+
10
+ ### 变更
11
+
12
+ > 本版主题(窗口 `0.8.0 → 0.8.1`,含 #107–#110):**出站链路传播** —— spec §9.2 那条
13
+ > 「出站传播仍开放」的项收口。**无破坏性变更**:只新增一个公开函数;既有 API、trace 形状、
14
+ > OTLP 导出值与 id 生成本身全部逐字不变(id 投影只是从 `integrations/otlp.ts` 的私有函数
15
+ > **上移到** `core/trace.ts` 成为单一真源,取值一字未改)。
16
+
17
+ ### 新增
18
+
19
+ - **`currentTraceparent(): string | undefined`**(出站链路传播):给出**当前调用期** span 的
20
+ W3C `traceparent`(`00-<32位trace>-<16位span>-00`),自己带在出站请求上(`fetch` 头 / gRPC
21
+ metadata)。下游若也是 agentia(或任何认 `traceparent` 的服务),就能把「谁触发了这次调用」
22
+ 关联到**具体 span**,而不是只到 run 粒度:
23
+
24
+ ```ts
25
+ import { currentTraceparent } from '@migor/agentia';
26
+
27
+ const tp = currentTraceparent();
28
+ await fetch(url, { headers: { ...(tp ? { traceparent: tp } : {}) } });
29
+ ```
30
+
31
+ 粒度:普通工具与 `@Prompt` **不建 span**,取到的是发起它们的那次 `llm.turn`;`@Skill` /
32
+ `@SubAgent` 方法体内取到的是自己的 `capability` span(内层覆盖外层)。入站那一半
33
+ (`traceparent` 头 → run 根 `links`)已随 0.6.2 落地,本版把出站补上,跨服务关联从此双向。
34
+
35
+ ### 已知边界(同时写进 `usage-guide` §7)
36
+
37
+ - **只给读取器,不替你做注入** —— 框架不创建出站请求,注入那一行是宿主的(与「webhook 用
38
+ sink + 你自己的 `fetch`」同一条既有决策)。
39
+ - `run` 根 span 由 `runAgent` 打开 ⇒ 更早的 `contextInit` / 记忆水合取到 `undefined` —— 那时
40
+ 确实还没有 span 可指,不编造。
41
+ - flags 位恒 `00`:本框架不采样(每次 run 全量记账),不替下游声明「已采样」。
42
+ - id 宽度:内部 id 是 UUID,出站与 OTLP 共用**同一份**投影(trace 去横线 32-hex、span 截
43
+ 16-hex)⇒ 下游收到的 span id 与 collector 里那个**是同一个数**(各写一份会让同一次调用在
44
+ 两个系统里出现两个 span id)。
45
+
46
+ ### 仓库自身(不面向使用者)
47
+
48
+ - 第七 / 第八轮复审散件沉淀进 `docs/guards.md` 附录 B,并立「多 agent 同仓作业」三条纪律
49
+ (结论钉 commit / 门禁跑隔离导出树 / 不碰别人的未提交改动)。
50
+ - 出处链更正:spec §10 的「132 条直接用例」→ **127**(逐文件计数,独立复核不可复现 132),
51
+ 全仓口径改引「+140 条(`tests/` 增量)」;覆盖率棘轮分支 85→88 / 函数 92→95。
52
+ - 新增两条守卫并入册:id 投影**单源**(OTLP 与出站必须同一个数)、出站**调用期作用域**
53
+ (并行不串 / 内层不外泄),两条都做过承重性反向验证。
54
+ - 发布面清单的 lock 项改为**按包名锚定**:裸 `"version"` 计数会被**恰好同版本号的第三方
55
+ 依赖**撞网(本次真发生:`@grpc/proto-loader` 恰好 @0.8.1 ⇒ 闸门报「4 处应为 0.8.1,实际
56
+ 命中 5 处」,读起来像漏项)。夹具同步加了同版本诱饵,断言它既不被替换、也不进网。
57
+
58
+ **迁移**:无。既有代码不需要任何改动;要开始用出站传播,就在出站请求上加一行 `traceparent`。
59
+
8
60
  ## [0.8.0] - 2026-09-21
9
61
 
10
62
  ### 变更
@@ -727,7 +779,8 @@
727
779
  首个公开发布:`@migor/agentia` + `@migor/cli`(scope `@migor/*`),两包版本同步。
728
780
  框架本体单包;CLI 独立成包(workspaces)。
729
781
 
730
- [Unreleased]: https://github.com/retrychx/agentia/compare/v0.8.0...HEAD
782
+ [Unreleased]: https://github.com/retrychx/agentia/compare/v0.8.1...HEAD
783
+ [0.8.1]: https://github.com/retrychx/agentia/releases/tag/v0.8.1
731
784
  [0.8.0]: https://github.com/retrychx/agentia/releases/tag/v0.8.0
732
785
  [0.7.2]: https://github.com/retrychx/agentia/releases/tag/v0.7.2
733
786
  [0.7.1]: https://github.com/retrychx/agentia/releases/tag/v0.7.1
package/dist/AGENTS.md CHANGED
@@ -678,8 +678,34 @@ runner.submit(msg.value, {
678
678
  换宿主这条缝不变:gRPC 宿主把 metadata 的 `traceparent` 翻进 `options.traceContext`,
679
679
  见 §6.2「gRPC 宿主」。
680
680
 
681
- > **只做入站**:框架**不生成**出站 `traceparent`(运行中没有「当前 span」这个概念,硬造一个会是假的
682
- > spanId,比不做更糟)。要从 run 往外传,用结果里的 `runId`(== `traceId`)拼你自己的头,见 §7 已知边界。
681
+ **出站(反过来:你调别人)**:在 run 内用 `currentTraceparent()` 取当前 span 的 W3C 头,
682
+ 自己带在出站请求上 —— 下游若也是 agentia(或任何认 `traceparent` 的服务),接到的就是一条指向
683
+ **具体 span**(回合 / 能力调用)的 link,而不是只到 run 粒度:
684
+
685
+ ```ts
686
+ import { currentTraceparent } from '@migor/agentia';
687
+
688
+ @Tool({ description: '把工单交给订单服务' })
689
+ async placeOrder(input: { sku: string }) {
690
+ const tp = currentTraceparent(); // 不在 run 内 → undefined(那时不该编一个)
691
+ const res = await fetch(orderSvc, {
692
+ method: 'POST',
693
+ headers: { 'content-type': 'application/json', ...(tp ? { traceparent: tp } : {}) },
694
+ body: JSON.stringify(input),
695
+ });
696
+ return res.json();
697
+ }
698
+ ```
699
+
700
+ - **粒度**:普通工具与 `@Prompt` **不建 span**,它们的「当前 span」就是发起它们的那次 `llm.turn`;
701
+ `@Skill` / `@SubAgent` 的方法体内则是它自己的 `capability` span。内层覆盖外层。
702
+ - **不自动注入**:框架不创建出站请求,注入那一行是你自己的(同上 `fetch`;gRPC 宿主塞进 metadata)。
703
+ - 与入站同一个格式、同一份 id 投影:`currentTraceparent()` 的输出喂回 `parseTraceparent()` 逐字还原,
704
+ 下游 OTLP 里看到的 span id 与本地 collector 里的是**同一个数**(见 §7 已知边界)。
705
+
706
+ > **出站的边界(如实)**:`run` 根 span 由 `runAgent` 打开,所以比它更早的环节 ——
707
+ > `contextInit`、记忆水合(`MemoryStore.load`)—— `currentTraceparent()` 返回 `undefined`:
708
+ > 那时确实还没有 span 可指。flags 位恒 `00`(本框架**不采样**,不替下游声明「已采样」)。
683
709
 
684
710
  #### 指标(从 trace 派生)
685
711
 
@@ -1250,7 +1276,7 @@ const callable = {
1250
1276
  | `agentia harvest` 的产物是轨迹骨架 | trace **不记 assistant 文本**(llm.turn 只记 usage/事件),故 harvest 用例脚本里的 text 块是占位、预填 `expect` 是从原 trace 抄录的实际轨迹 —— 脚手架不是成品,人工核对后再进 CI(见 §6「线上 trace 回流」) |
1251
1277
  | 分叉重放不是续跑 | `forkMessages` 与 `traceToMessages` / harvest **同源有损**:trace 不记 assistant 文本与 run 原始输入(重放里 assistant 是标注占位、首尾 user 是合成),也不记 blackboard(分叉种子经 `RunInvocationOptions.blackboard` 自带);它产出喂回 `app.run` 的 messages、起的是**新 run**,不是接着原 run 的循环位置跑 |
1252
1278
  | 评分来自 run 之外 | `Score` 走 run 根 `score` **事件**而非 span 字段(评分通常在 run 跑完后才产生);`attachScore` 找不到根 span 时静默忽略,多次调用即多条事件(不同维度各记各的) |
1253
- | 链路关联只做**入站** | `traceContext` / `traceparent` 头只把**上游**接进来(run 根的 `links`);框架**不生成**出站 `traceparent` —— 运行中没有「当前 span」可导出,硬造会给出假 spanId。要从 run 往外传,用 `result.trace.traceId`(== `runId`)自行拼头。另:link 只落在 run 根(子 span 不散),且**一进程内**不跨进程自动传播 —— 队列场景要自己把 `traceContext` 传下去(HTTP 头带走,或随 `TaskRecord.spec.options` 落库) |
1279
+ | 链路关联:入站自动、**出站只给读取器** | `traceContext` / `traceparent` 头把**上游**接进来(run 根的 `links`);出站方向给 `currentTraceparent()`(当前 span 的 W3C 串,回合 / 能力调用粒度),但框架**不替你做注入** —— 它不创建出站请求,那一行由宿主的 `fetch` / metadata 自己写。两个边界:① `run` 根 span 由 `runAgent` 打开 ⇒ 更早的 `contextInit` / 记忆水合取到 `undefined`(那时确实没有 span);② flags 恒 `00`(本框架不采样)。id 宽度经**同一份投影**压到 16 位(与 OTLP 导出共用,单一真源)—— 故下游收到的 span id 与 collector 里的是同一个数。另:link 只落在 run 根(子 span 不散),且**一进程内**不跨进程自动传播 —— 队列场景要自己把 `traceContext` 传下去(HTTP 头带走,或随 `TaskRecord.spec.options` 落库) |
1254
1280
  | 配额不是框架子系统 | 只给缝(middleware + TraceSink + BudgetGuard),计数放哪(内存 / Redis / DB)与超限怎么办都是你的策略 |
1255
1281
  | 人工审批两种形态 | 进程内闸门用 `middleware`(`await` 决策再放行);跨进程耐久审批用 `@Tool({ approval: 'required' })` + `POST /tasks/:id/approve`(挂起/恢复,见 §6.6「人工审批」) |
1256
1282
  | 审批超时是**惰性**判定 | `approvalTimeoutMs` 不起定时器:`approve` / `poll` / `resumePending` 读到过期挂起任务时才自动全拒并重派 —— 没人读的任务不会自己超时(要定期扫就调 `resumePending()`) |
@@ -9,10 +9,10 @@
9
9
  "typecheck": "tsc --noEmit -p tsconfig.json"
10
10
  },
11
11
  "dependencies": {
12
- "@migor/agentia": "^0.8.0"
12
+ "@migor/agentia": "^0.8.1"
13
13
  },
14
14
  "devDependencies": {
15
- "@migor/cli": "^0.8.0",
15
+ "@migor/cli": "^0.8.1",
16
16
  "tsx": "^4.19.0",
17
17
  "typescript": "^7.0.2",
18
18
  "@types/node": "^22.0.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@migor/cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Agentia 框架命令行工具:create 脚手架 + g 能力生成 + dev 本地可观测面板(trace inspector)",
5
5
  "type": "module",
6
6
  "bin": {