# Token Context 归因

> Canonical path：`specs/daemon/token-context-attribution.md`
> 范围：记录 AgentTeam 在每个 runtime input boundary 装配的 semantic block，并按累计贡献识别 AgentTeam 可控优化机会。
> 状态：已实现 materialized attribution，并为提供可信 invocation identity 与 root-Context 归属的 runtime 实现 exposure correlation。上位规范为 [AgentTeam Token 消耗诊断](./token-optimization.md)。
> 相关规范：[Prompt Compiler Architecture](./prompt-compiler-architecture.md)。

## 1. 记录边界

当前实现为已实际进入或可能进入 runtime 的 Context materialization 生成一个
`InputBoundary`：

- thread start/resume；
- wake/live delivery；
- active-turn steer；
- deferred、compaction 和 output-truncation continuation；
- final visible reply check；
- execution start/continuation；
- attachment 和 reference Context。

每个 boundary 使用 typed event ID，并绑定 launch-level Run。当前不持久化通用
turn/request correlation。

以下内容不能重复计量：

-同一 delivery 的 retry；
- renderer mirror；
- inspect operation；
- cumulative snapshot；
-未真正交付给 runtime 的 compile attempt。

## 2. Semantic Block

每条 block attribution 只包含：

- registered abstract `blockId`；
- `PromptBlock.Type`；
- layer 和 slot；
- origin 和 control；
- model-visible lifetime；
- compiler estimate；
- event/run correlation。

`PromptBlock.Type` 沿用 Prompt Compiler 的四种 canonical 类型：

- `instruction`；
- `turn_context`；
- `notice`；
- `reference`。

不得新增同名 `catalog` 或 `payload` 类型；相应语义由 block ID、origin、layer/slot 表达。

Registry 为每个 block 定义：

- code-controlled display name；
- origin/control；
- lifetime：`boundary_only`、`session_persistent`、`until_replaced` 或 `unknown`；
- optional per-injection target estimate；
- one suggested action；
- required validation。

Block ID 不得包含 app/user value、source path 或 source identifier。Unknown/path-like ID 统一为 `unattributed.prompt_surface`，不能成为优化机会。

## 3. Origin 与 Control

Origin：

- `agentteam_policy`；
- `agentteam_generated`；
- `workspace_configuration`；
- `user_task_payload`；
- `unknown`。

Control：

- `direct`；
- `assembly`；
- `none`；
- `unknown`。

合法关系：

| Origin | Control | 优化资格 |
| --- | --- | --- |
| `agentteam_policy` | `direct` | 可调整内容与注入。 |
| `agentteam_generated` | `direct` 或 `assembly` | 可调整生成、选择和生命周期。 |
| `workspace_configuration` | `assembly` | 仅允许无损装配优化。 |
| `user_task_payload` | `assembly` 或 `none` | 进入 ledger，不进入通用压缩榜单。 |
| `unknown` | `unknown` | 只诊断。 |

Execution protocol/framing 与 delegated task payload 必须是不同 block；混合 block 不能标记为 `direct`。

## 4. Estimate 与累计

Compiler estimate：

```text
ceil(Unicode runes / 4)
```

它只用于相对归因，不是 provider tokenizer 或 billing truth。

每个 block aggregate 计算：

```text
meanTokensWhenInjected
injectionCount
injectionCoverage
cumulativeMaterializedEstimate
  = sum(estimate over deduplicated InputBoundaries)

cumulativeExposureEstimate
  = sum(estimate over correlated model invocations where block is active)

cumulativeControllableExposureEstimate
  = exposure estimate of eligible direct/assembly material

cumulativeTargetExposureEstimate
  = target estimate evaluated over the same active invocation set

cumulativeAddressableExposureEstimate
  = max(
      cumulativeControllableExposureEstimate
      - cumulativeTargetExposureEstimate,
      0
    )
```

`boundary_only` 只贡献当前 boundary；`session_persistent` 从 materialization 起贡献同
Session 后续 invocation；`until_replaced` 在 typed replacement 或成功 compaction
前持续贡献。

当前实现只在 runtime 同时提供以下证据时记录 exposure：

- stable unique model invocation ID；
- usage 属于当前 Process 的 root Context，而不是 runtime-native child/subagent；
- Process 已持有从实际 launch/delivery boundary 演进得到的完整 active-block set。

OpenCode 的 `step-finish` part ID 满足该契约。Kimi ACP 仅报告会话当前 Context
占用量和窗口大小，不提供可信 provider invocation identity 或单次调用 token 分类；
因此 Kimi invocation exposure 保持 `unsupported`，不能用 turn、update 或 prompt
数量近似。Codex 与 Claude 同样缺少可信 provider invocation ID。

OpenCode 与 Codex driver 在成功 compaction 后给第一个 root invocation
usage 标记 `ContextCompacted`；Process 在记录该 invocation exposure 前先移除
`compactable` block。这样在 compaction 后完成的 invocation 不会错误携带已淘汰
reference。

Codex 只接受当前 launch、当前 root thread 上 exact
`threadId + turnId + contextCompaction item.id` 的 started/completed 配对作为
boundary。Boundary latch 只能由后续第一条同一 root thread usage 消费；foreign
subagent usage、缺失 identity、冲突 item pair、旧 launch notification 或其他
thread usage 均不能消费。Codex 当前仍缺少可信 provider invocation ID，因此这项
标记会正确推进 active-block lifetime，但不会把 runtime turn 或 usage notification
序号冒充 model invocation identity。

有 target 且 exposure 可用时机会使用 `addressable_exposure_target`；无 target 但
exposure 可用时使用 `exposure_contribution`；exposure 不可用时才退回
`materialized_contribution`。这些 estimator 名称必须反映真实证据口径。

Lifetime 或 invocation correlation 不完整时，materialized estimate 仍可用，exposure estimate 为 unavailable/limited，不能退化为 materialized estimate。
没有 code-controlled target 的 block 只报告 `materialized_contribution`，其
`addressableEstimate` 必须缺失，不能把全部物化贡献冒充可删除空间。只有 target
存在且 scope/lifetime 与 estimate 一致时，才报告 `addressable_exposure_target`。

报告同时输出互斥 Context partition：

```text
compiledMaterialized
  = agentteamOwned
    + workspaceConfiguration
    + userTaskPayload
    + unknown
```

`controllableMaterialized` 是优化资格视图，可能与 Workspace assembly 相交，不得与
上述 partition 分项相加。

Opportunity 按 `cumulativeAddressableExposureEstimate` 降序排列；exposure 不可用时，退回按 cumulative materialized estimate 排序并明确标记 estimator，之后按 injection count 和 stable block ID 排序。

## 5. Ledger 与 Top-N

完整 block ledger 是 comparison 和总量计算的数据源，包含 selected scope 内所有 observed registered block aggregate。

Top-N opportunity 是独立派生 view，通常最多十二项。Block 跌出 Top-N 不得在 comparison 中变成零。

达到完整 ledger hard bound 时：

- report 为 `limited`；
-不可声称 block comparison 完整；
-不得静默只比较 Top-N。

## 6. 隐私和资源

不得记录：

- Prompt 或 payload 正文；
- source path、file、line、symbol、source map；
- tool/retrieval/transcript content；
- secret；
- portable Agent/Run ref，以及 raw Agent/Session/launch/turn/request ID。

Raw attribution 最多保留七天。Query sample、report ledger 和 portable artifact
都有硬限制；query 对每个 metric family 只选择一次，禁止 per-Agent/per-block
full-store agentteam。第一版复用已有 Desktop metrics TSDB，不建立第二套存储。

Attribution failure 不得影响 Prompt compilation 或 delivery。

Attribution 属于默认关闭的详细诊断采集。Human `agentteam token analyze` 会在关闭时
自动开启当前 daemon lifetime 的采集（`--stop` 除外），`agentteam token ui` 可以直接开关，
`agentteam token analyze --stop` 在分析后关闭；Agent caller 只能读取。开启不会补录
之前未采集的 delivery boundary；存活 Process 会补记其无正文 launch ledger。

## 7. 验证要求

- 所有支持的 InputBoundary 被记录且 retry/mirror 不重复；
- `PromptBlock.Type` 与 Prompt Compiler 一致；
- origin/control 关系合法；
- execution framing 与 task payload 分离；
-累计 estimate 公式正确；
- 无 target 时 addressable 缺失；Context partition 互斥且求和等于 compiled；
- exposure supported/limited/unsupported 必须按 invocation coverage 明确标记，不能使用 injection count 伪造；
- runtime-native child/subagent usage 不得套用 root Context；
- runtime replay 的相同 invocation/block identity 必须去重；
-完整 ledger 与 Top-N 独立；
- unknown block 和 privacy boundary；
- bounded one-pass aggregation。
