DSH / Atlas
2026-07-13implementedfeature

Session query relationship tracing

会话查询关系追踪

Session relationships are encoded across immutable headers, positional surface operations, and logged arrays of cited source-event seqs. A consumer reconstructing those relationships directly would need to duplicate corpus precedence, surface folding, malformed-log handling, deterministic lineage ordering, and cloning. Positional replacement and cited-source relationships mean different things, so collapsing them int

English

Problem

Session relationships are encoded across immutable headers, positional surface operations, and logged arrays of cited source-event seqs. A consumer reconstructing those relationships directly would need to duplicate corpus precedence, surface folding, malformed-log handling, deterministic lineage ordering, and cloning. Positional replacement and cited-source relationships mean different things, so collapsing them into one generic edge type would also lose meaning.

Decision

ctx.sessionQuery exposes traceSession(sessionId) and traceEvent({ sessionId, seq }) alongside its exact reads. Both are one-shot views over the existing live-preferred corpus: session tracing consumes one complete corpus listing, while event tracing consumes one loaded logical log and one canonical surface fold. The service retains no lineage, reverse-index, or replacement state after a call.

SessionLineageTrace returns the target, known parents in immediate-to-outward order, and recursive descendant trees whose siblings sort by creation time and then session id. complete: true carries the known root; complete: false carries the first unresolved parent id. A cycle connected to the target fails with SESSION_QUERY_INVALID_LINEAGE.

SessionEventTrace keeps positional replacements separate from cited source-event relationships. replacedBy is the immediate positional replacer, replacementChain follows replacers to the final node, and replacedEventSeqs lists the actual surface nodes directly removed by the target. sourceEventSeqs preserves direct logged source order, while derivedEventSeqs lists later direct reverse references in log order. The query does not follow cited source events transitively.

Validation boundary

Event tracing checks target existence before surface analysis. Both event listing and tracing then use dsh-session's one-pass surface fold, which accepts or rejects the loaded log as a whole: event seqs are zero-based and contiguous, surface markers obey event-type eligibility, only surface event types may cite source-event seqs, present arrays are nonempty and duplicate-free, every source is an earlier seq, and every positional replacement names and cites all surface nodes it removes. Every contract failure uses SESSION_QUERY_INVALID_SURFACE; there is no weaker classification-only surface standard.

All returned records and arrays are detached. A known live event trace never consults persistence; persisted event traces preserve the exact-read list/load consistency check. Session lineage is necessarily a cross-corpus operation and therefore preserves cross-corpus persistence failure semantics.

Alternatives considered

  • Expose standalone tracing helpers — rejected because the source-precedence and detachment boundary belongs to ctx.sessionQuery; public helpers would invite callers to bypass it.
  • Combine replacement and cited-source edges — rejected because a positional replacement can shadow surface nodes while also citing non-surface construction inputs, and consumers need to distinguish those meanings.
  • Return all transitively cited source events — rejected because it obscures logged direct evidence, increases result size, and lets one malformed distant edge alter otherwise local output.
  • Best-effort traces over malformed source-event lists — rejected because a structurally plausible partial result would look authoritative. Exact inspection fails loudly when the canonical relationship contract is broken.

Consequences

Consumers receive deterministic relationship views without a cache or second corpus. Event tracing performs whole-log validation and allocation on each call, while lineage tracing lists the complete logical corpus on each call. Those costs keep the source of truth explicit and are separate from the content-bearing full-text-search and filtering API.

The feature has unit and service-level coverage but no snapshot or end-to-end fixture because it introduces no model-facing consumer, transcript change, or cross-process protocol.

中文

问题

会话关系分散编码在不可变 header、位置式表面操作和已记录的来源事件 seq 引用数组中。消费方如果直接重建这些关系,就必须重复实现语料优先级、表面折叠、格式错误日志的处理、确定性的谱系顺序和克隆。位置替换关系与来源事件引用关系表示不同含义,因此把两者合并为一种通用边类型也会丢失含义。

决策

ctx.sessionQuery 除精确读取外,还公开 traceSession(sessionId)traceEvent({ sessionId, seq })。两者都是基于现有「实时数据优先」语料的一次性视图:会话追踪读取一次完整语料列表,事件追踪读取一份逻辑日志并执行一次规范表面折叠。服务在调用结束后不会保留谱系、反向索引或替换状态。

SessionLineageTrace 返回目标、按从直接父级到外层父级排序的已知父级,以及递归的后代树;同级节点先按创建时间排序,再按 session id 排序。complete: true 会携带已知根节点;complete: false 会携带第一个无法解析的父级 id。与目标相连的环会以 SESSION_QUERY_INVALID_LINEAGE 失败。

SessionEventTrace 将位置替换与来源事件引用关系分开保留。replacedBy 是直接的位置替换者,replacementChain 沿替换者追踪至最终节点,replacedEventSeqs 则列出目标直接移除的真实表面节点。sourceEventSeqs 保留日志中直接来源的顺序,而 derivedEventSeqs 按日志顺序列出后续的直接反向引用。查询不会沿被引用的来源事件继续向上追踪。

校验边界

事件追踪会在分析表面之前检查目标是否存在。随后,事件列表与追踪都会使用 dsh-session 的单遍表面折叠,对加载的日志整体进行接受或拒绝:事件 seq 从零开始且连续;表面标记符合事件类型的适用范围;只有表面事件类型可以引用来源事件 seq;存在的数组必须非空且没有重复项;每个来源必须是更早的 seq;每次位置替换必须指明并引用它所移除的全部表面节点。任何约定违例都使用 SESSION_QUERY_INVALID_SURFACE;系统不存在只用于分类、要求更弱的表面标准。

所有返回的记录与数组都与内部状态分离。已知的实时事件追踪绝不查询持久化;来自持久化数据的事件追踪保留精确读取所要求的列表/加载一致性检查。会话谱系必然属于跨语料操作,因此也保留跨语料的持久化失败语义。

考虑过的替代方案

  • 公开独立的追踪辅助函数:不予采纳,因为源优先级与状态分离边界属于 ctx.sessionQuery;公开辅助函数会诱使调用方绕过该边界。
  • 合并替换边与来源事件引用边:不予采纳,因为位置替换可以遮蔽表面节点,同时引用不在表面上的构造输入,而消费方需要区分这两种含义。
  • 返回所有传递引用的来源事件:不予采纳,因为这会掩盖日志中直接记录的证据、增大结果,并让一条遥远的格式错误边改变原本局部的输出。
  • 对格式错误的来源事件列表返回尽力而为的追踪结果:不予采纳,因为结构上看似合理的局部结果会显得具有权威性。当规范的关系约定损坏时,精确检查会明确报错。

后果

消费方无需缓存或引入第二份语料,即可获得确定性的关系视图。事件追踪每次调用都会执行全日志校验和分配,而谱系追踪每次调用都会列出完整的逻辑语料。这些成本让真源保持明确,并且与承载内容的全文搜索及过滤 API 相互独立。

该功能具备单元测试和服务层测试覆盖,但没有快照或端到端 fixture(测试前置数据),因为它没有引入面向模型的消费方、transcript(文本记录)变更或跨进程协议。