遥测、调试与提示词轨迹

traceId 从会话一路传到回合、工具调用和模型请求头;OpenTelemetry 默认关闭,配了 OTLP 端点才加载;错误与端点怎样脱敏;日志的格式、位置与 7 天保留;模型输入输出的本地录制与 prompt-trajectory;debug 包的抓包代理与时间线界面。

作者 David更新于 40 篇(共 47 篇)

Agent CLI 的可观测性分三层:本地的结构化日志、本地的模型输入输出录制(model-io),以及可选的 OpenTelemetry 导出。前两层默认就开着,数据只落在本机;第三层默认关闭。给开发者用的还有两件工具:apps/zcode-cli/packages/debug(读日志与会话库、带网络抓包的时间线界面)和 apps/zcode-cli/tools/prompt-trajectory(把请求还原成可复现的轨迹)。桌面端另有模型轨迹面板、会话调试快照和自己的 ARMS 前端监控,这里只点到。

代码分布:apps/zcode-cli/packages/telemetry 是 OpenTelemetry 的实现,10 个文件、3874 行;日志在 apps/zcode-cli/packages/adapters/src/logging;model-io 在 apps/zcode-cli/packages/adapters/src/model/runner-debug.ts;core 侧的入口是 RuntimeTelemetryFacade,它只调用 contracts 里定义的遥测端口(apps/zcode-cli/packages/core/src/telemetry/runtime-telemetry.ts:34)。

怎么用:数据在哪、默认开不开

位置默认调整
结构化日志~/.zcode/cli/log/zcode-<本地日期>.jsonl开;生产 info 起,开发态 debug 起;保留 7 天ZCODE_LOG_DIR 换目录,ZCODE_LOG_CONSOLE=1 同时写 stderr
模型输入输出~/.zcode/cli/rollout/model-io-<会话>.jsonl,开发态在 debug/开,测试环境除外;生产最多 3 个会话文件、单文件 64 MiB桌面设置“完整保留模型 I/O”取消压缩与限额
用量事实会话库的 model_usageturn_usagetool_usage 三张表开,保留 30 天无开关
OpenTelemetry发往 OTEL_EXPORTER_OTLP_* 指定的端点关,没配端点连 SDK 都不加载配端点即开;ZCODE_MODEL_TELEMETRY_ENABLED=0 强制关
进程资源样本以协议通知发给桌面 Host协议模式下每 60 秒一次无开关

出处依次是:日志目录与级别 apps/zcode-cli/packages/adapters/src/logging/index.ts:173logging/index.ts:222logging/index.ts:226,保留天数 apps/zcode-cli/packages/adapters/src/logging/retention.ts:6;model-io 的目录与上限 apps/zcode-cli/packages/bootstrap/src/app/paths.ts:13apps/zcode-cli/packages/adapters/src/model/runner-debug.ts:35;用量保留见SQLite 会话库;遥测开关 apps/zcode-cli/packages/telemetry/src/bootstrap.ts:124;采样周期 packages/shared/src/processResourceTelemetry.ts:29ZCODE_RUNTIME_ENV 未设置时按生产处理(packages/shared/src/runtimeEnv.ts:120)。NOTICE 对 model-io 的说明(NOTICE.md:62):

共享 Agent 的模型输入输出日志在开发和生产运行中默认写入本地,测试环境除外。日志可能含提示词、代码、上下文、工具参数和模型回复;请求头及部分图像、视频数据有脱敏处理,但不能认为所有用户文本均已脱敏。

traceId:一条任务链一根

CLI 的 AGENTS.md 把 traceId 定成硬约定(apps/zcode-cli/AGENTS.md:74):

traceId 默认对应一次顶层 session 的完整任务链,session 内创建的子 session、subagent、重试任务、后台队列任务和异步 I/O 都应归属到同一个 traceId

下一条接着规定 sessionIdturnIdmessageIdtoolCallIdspanIdparentSpanId 都是 traceId 之下的结构化子标识(apps/zcode-cli/AGENTS.md:75)。落到代码里,贯穿全程的是一个很小的结构(apps/zcode-cli/packages/contracts/src/tracing/tracer.ts:14):

export interface TraceContext {
  traceId: TraceId;
  queryId?: QueryId;
  spanId?: string;
  parentSpanId?: string;
  parentId?: string;
  sessionId?: SessionId;
  turnId?: TurnId;
  attributes?: Record<string, string | number | boolean>;
}

它靠 AsyncLocalStorage 在异步调用间隐式传递(tracer.ts:166),各层只用 createChildTraceContext 派生:traceId 原样继承,spanId 新生成,旧的变成 parentSpanIdtracer.ts:212)。

层级何时生成出处
traceId创建应用时随根上下文生成,是一个 UUID;协议模式优先沿用客户端带来的 traceIdapps/zcode-cli/packages/bootstrap/src/app/create-app.ts:153apps/zcode-cli/packages/contracts/src/interfaces/shared.ts:43apps/zcode-cli/packages/bootstrap/src/zcode-protocol/server-types.ts:274
sessionIdsess_ 加 UUID;会话行的 trace_id 列记下所属 traceId,分叉出的子会话沿用父会话的shared.ts:31apps/zcode-cli/packages/core/src/runtime/methods/session-fork.ts:159
turnIdqueryId每回合派生一次子上下文apps/zcode-cli/packages/core/src/runtime/methods/turn.ts:111
模型请求每一步再派生,请求头带上 x-zcode-trace-idx-request-idx-session-idx-query-idx-zcode-session-typeapps/zcode-cli/packages/core/src/runtime/methods/turn-model-step.ts:158apps/zcode-cli/packages/adapters/src/model/runner-attribution.ts:36
toolCallId每次工具调用派生,工具 ID 和工具名作为属性apps/zcode-cli/packages/core/src/tool/executor/call-runner.ts:110
spanId随每次派生生成,取 UUID 的前 16 位tracer.ts:100

这组字段最终出现在三个地方:每一行结构化日志的顶层字段(apps/zcode-cli/packages/adapters/src/logging/serialize.ts:72),会话库里会话与用量表的 trace_id 列,以及发往模型服务的请求头。最后这一项 NOTICE 也写到了:模型请求“可带认证信息、客户端环境及会话/请求/追踪标识”(NOTICE.md:36)。

图表加载中…

图里最后一条虚线要单独说明:OpenTelemetry 的 trace 与上面的 traceId 不是一回事。agent_turn span 默认从空上下文起一条新 trace,会话 ID、回合 ID 只作为属性挂在上面(apps/zcode-cli/packages/telemetry/src/agent-trace-runtime.ts:151apps/zcode-cli/packages/telemetry/src/agent-trace-support.ts:311)。前台子 Agent 以 child 方式挂进父回合的 trace,后台子 Agent 与工作流子会话则各起一条,再用 spawned_by 链接回来(apps/zcode-cli/packages/core/src/runtime/methods/subagent.ts:295apps/zcode-cli/packages/bootstrap/src/app/workflow-facade.ts:298)。

OpenTelemetry:默认关,配了端点才开

开关的判断在 CLI 异步启动的边界(bootstrap.ts:120):

export async function prepareModelTelemetryEnv(
  env: EnvRecord,
  options: PrepareModelTelemetryOptions = {},
): Promise<EnvRecord> {
  if (!resolveOtlpTraceEndpoint(env) || isExplicitlyDisabled(env.ZCODE_MODEL_TELEMETRY_ENABLED)) {
    return env;
  }
  const existingInstallationId = normalizeTelemetryDeviceMid(env.ZCODE_TELEMETRY_DEVICE_MID);
  const installationId =
    existingInstallationId ?? (await resolveStandaloneDeviceMid(env.ZCODE_HOME?.trim()));
  const preparedEnv = installationId ? { ...env, ZCODE_TELEMETRY_DEVICE_MID: installationId } : env;

  if (!preparingOwner && !preparedOwner) {
    preparingOwner = createPreparedOwner(preparedEnv, options);
  }
  preparedOwner = await preparingOwner;
  return preparedEnv;
}

端点只认环境变量:trace 取 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,没有就取 OTEL_EXPORTER_OTLP_ENDPOINT 再拼 /v1/traces;指标同理,两者都没有时沿用 trace 端点,注释说 ARMS 的自定义接入点对两者共用一个 URL(bootstrap.ts:75bootstrap.ts:98)。请求头来自 OTEL_EXPORTER_OTLP_TRACES_HEADERSOTEL_EXPORTER_OTLP_HEADERS,服务名缺省 zcode-cli-agentbootstrap.ts:173)。ZCODE_MODEL_TELEMETRY_ENABLED0falseoffdisabled 时强制关闭(bootstrap.ts:414)。没有端点时直接返回,createModelTelemetry 交出的是空实现(bootstrap.ts:44),OTel SDK 也只在确认启用后才动态加载(bootstrap.ts:176)。

开源代码里没有内置任何 OTLP 端点。桌面端拉起 Agent 时,只把自己继承到的 OTEL_* 转给它,没有端点就一个遥测变量都不传(packages/services/src/zcode-agent/agentTelemetryEnv.ts:13);桌面自己的 ARMS 前端监控与数仓事件端点同样“由运行时环境变量提供,未配置即停用,构建产物不内嵌”(packages/shared/src/env.ts:52env.ts:56)。NOTICE 第二节的十七类对外请求里没有单列这条遥测链路,最接近的是上面引过的“追踪标识”随模型请求发出。

启用后的参数(apps/zcode-cli/packages/telemetry/src/otlp-exporter.ts:31otlp-exporter.ts:56):

协议OTLP,protobuf over HTTP,gzip 压缩
超时3000 毫秒
trace 采样父级优先,顶层按 traceId 抽 10%
span 批处理每批 100 条,队列 2000 条,每 5000 毫秒一批
指标每 300000 毫秒导出一次,DELTA 时间性
同时存活的 span 写入器最多 5000 个,超出就丢弃并计数(agent-trace-runtime.ts:115

span 一共八种:agent_turnagent_steptool_executioncommand_executioncontext_compactiondetached_operationmodel_callmodel_attempt,每种各有一个时长直方图,另有调用尝试次数、按类型的 Token 增量、首个事件、首段内容、首段文字的延迟、流停顿次数等指标(apps/zcode-cli/packages/telemetry/src/agent-metrics.ts:57)。属性记 ID、枚举、计数、耗时和清洗过的错误信息,不记提示词、回复或工具参数正文;模型 span 上的服务地址是脱敏后的 origin 加路由(apps/zcode-cli/packages/telemetry/src/provider-endpoint.ts:47)。

身份方面有三点:安装 ID 存在 ~/.zcode/v2/telemetry-state.json,只有遥测启用时才会生成(bootstrap.ts:226);桌面端传给 Agent 的用户身份是账号 ID 的 sha256,注释说 Trace 可以按用户关联,但不会上传账号、邮箱或登录名(agentTelemetryEnv.ts:27);每次启动的实例 ID 与安装 ID 只进 trace 的资源属性,不进指标,免得指标序列基数无限膨胀(otlp-exporter.ts:240)。另外,OTEL_*ZCODE_TELEMETRY_* 这些变量会先被捕获进进程私有区,再从所有子进程环境里剔除,Bash、MCP 与工具子进程拿不到 OTLP 端点和鉴权头(packages/shared/src/runtimeEnv.ts:74apps/zcode-cli/packages/bootstrap/src/telemetry-bootstrap.ts:9)。

脱敏

遥测、日志、model-io 各有各的脱敏规则,强度不同:

数据规则出处
span 属性ID 只收 [A-Za-z0-9._:-] 且不超过 128 字符,枚举转小写,不合格就整项丢弃agent-trace-support.ts:22
指标标签每种指标一份白名单,高基数的执行 ID 与业务内容只进 traceagent-metrics.ts:39agent-metrics.ts:195
错误信息先截到 4096 字符再清洗,结果最多 2048 字符;同一个异常沿调用链冒泡时,只在最先认领它的 span 上记正文apps/zcode-cli/packages/telemetry/src/error-sanitizer.ts:54error-sanitizer.ts:39
服务端点去掉用户名、密码、查询串,路径里的邮箱、UUID、长数字、长十六进制、疑似令牌分段替换成占位符provider-endpoint.ts:47
日志键名含 api key、authorization、cookie、credential、password、secret、token 的值替换为 [Redacted],只看键名不看内容serialize.ts:15
model-io请求与响应头里的鉴权、密钥、令牌、Cookie 一类改成 [redacted],图片与视频的 base64 只留一句说明apps/zcode-cli/packages/adapters/src/model/runner-network-headers.ts:3apps/zcode-cli/packages/adapters/src/model/runner-debug-redaction.ts:35

错误信息的清洗规则最细(error-sanitizer.ts:58):

  const sanitized = value
    .slice(0, 4_096)
    .replace(/\bhttps?:\/\/[^\s"'<>]+/giu, sanitizeUrl)
    .replace(
      /(\bauthorization\b["']?\s*[:=])\s*(?:(?:Bearer|Basic)\s+)?[^\s,"'};]+/giu,
      "$1 {redacted}",
    )
    // ...
    .replace(/\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]+/giu, "$1 {redacted}")
    .replace(/\b(?:sk|rk|pk)-[A-Za-z0-9_-]{12,}\b/giu, "{secret}")
    .replace(/\bgh[pousr]_[A-Za-z0-9]{20,}\b/gu, "{secret}")
    .replace(/\bAKIA[A-Z0-9]{16}\b/gu, "{secret}")
    .replace(/\bAIza[0-9A-Za-z_-]{30,}\b/gu, "{secret}")
    .replace(/\b[A-Za-z0-9]{4,32}@[0-9a-f]{12,}\b/giu, "{secret}")
    .replace(/\b[^/@\s]+@[^/@\s]+\.[^/@\s]+\b/gu, "{email}")

后面还会把 /Users/.../home/...、临时目录和 Windows 盘符路径折成 {path}。相比之下,日志的脱敏只按键名判断,写进消息正文或其他字段的内容原样落盘;AGENTS.md 要求需要高敏信息时“必须显式进入受控 debug 路径”(apps/zcode-cli/AGENTS.md:82)。从代码看,按子串匹配键名还有个副作用:totalTokenstokenCountthresholdTokens 这类计数字段的键名也含 token,写进文件时同样变成 [Redacted]serialize.ts:17,这类字段见 apps/zcode-cli/packages/core/src/runtime/methods/microcompact.ts:67)。

日志

createNodeLoggerFactory 每写一条就同步追加一行 JSON,写失败直接吞掉,“Logging must never break the agent execution path”(logging/index.ts:134)。文件按本地日期命名为 zcode-YYYY-MM-DD.jsonllogging/index.ts:248)。每行固定的顶层字段是 timestampleveleventmodulemessagetraceIdspanIdparentSpanIdsessionIdturnIdtoolCallIddurationMsstatus,其余上下文进 context,错误进 errorserialize.ts:72);status 只允许 startedwaitingcompletedfailedcancelled 五种(serialize.ts:101)。最低级别在开发态是 debug,生产与测试是 infologging/index.ts:226);仓库根的 AGENTS.md 第 79 行规定 debug 留给协议原始数据、流式分块这类高频诊断,“生产环境不落盘”。

保留策略:每个进程启动 60 秒后清理一次,删掉 7 天之前的日志文件,只动文件名严格匹配日期格式的,结果本身记一条 debug 日志(retention.ts:6retention.ts:7retention.ts:132);应用和协议入口各调度一次,同一个工厂只会调度一次(logging/index.ts:207)。启动过程由 StartupTimer 记账,每个阶段一条 info,带本段耗时与累计耗时(apps/zcode-cli/packages/bootstrap/src/startup-logging.ts:26),比如会话库迁移的开始与结束。

模型请求录制:model-io

每次模型请求(流式与非流式都算)结束后,适配层把请求与响应写进 model-io,一行一条 type: "model_io" 记录:请求体、请求头、消息、工具名、采样参数,响应的正文、推理文本、工具调用、用量,以及 sessionIdtraceIdturnIdquerySourcerunner-debug.ts:109)。目录由 bootstrap 算好后交给模型适配器(apps/zcode-cli/packages/bootstrap/src/model-factory.ts:29);AgentRuntime 也收了一份 modelIoDirapps/zcode-cli/packages/core/src/runtime/agent-runtime.ts:270),但 core 里没有任何代码读它。容量限制写在文件开头(runner-debug.ts:34):

// 生产环境 rollout 目录最多保留的 model-io 会话文件数。超出删最旧。
const MAX_ROLLOUT_FILES = 3;
// 生产环境单个 session 的 model-io 文件硬上限。诊断日志不能因为无限增长影响 agent 主流程。
const MAX_ROLLOUT_SESSION_BYTES = 64 * 1024 * 1024;
// 开发态保留更多上下文,但仍避免单个 debug 文件无限膨胀。
const MAX_DEBUG_SESSION_BYTES = 256 * 1024 * 1024;
// 缓存缺失或文件超限后写 baseline 时,仅保留最近上下文,避免长 session 重启后再次写出巨型记录。
const MAX_ROLLOUT_BASELINE_MESSAGES = 64;
const MAX_DEBUG_BASELINE_MESSAGES = 256;

一个会话一个文件,生产态在新会话建文件时按修改时间淘汰最旧的(runner-debug.ts:497)。同一会话里,后一次请求只记相对上一次新增的消息,标成 delta,避免完整历史在文件里一遍遍重复(runner-debug.ts:742);失败的请求保留完整消息,方便排查 400 一类错误(runner-debug.ts:703)。文件超过上限时整个重写成一条只带最近上下文的基线记录,而不是继续追加(runner-debug.ts:523)。记忆抽取这种后台请求不写进来,免得占掉槽位、又在下一次抽取时被自己读到(apps/zcode-cli/packages/core/src/runtime/helpers/project-memory-agent.ts:48)。

桌面设置里的“完整保留模型 I/O”(packages/ui/src/i18n/locales/zh-CN.ts:1823)会让写入跳过轮转、限额和压缩,但仍过脱敏(runner-debug.ts:487);这个偏好经协议下发,同时改掉已有会话和以后新建会话的行为(apps/zcode-cli/packages/bootstrap/src/zcode-protocol/model-io-preferences.ts:8)。桌面端的模型轨迹面板 ModelTrajectoryPanepackages/ui/src/ModelTrajectoryPane.tsx:39)就是读这些文件:Host 从文件尾部最多读 32 MiB,按 sessionId 精确匹配,默认只取最近 200 次调用(packages/services/src/zcode-agent/modelTrajectoryFileTail.ts:7packages/services/src/zcode-agent/modelTrajectory.ts:20)。资源管理器把 cli/debugcli/rollout 归为“模型轨迹”,标成可以放心清理(packages/services/src/storage/domain/storageCatalog.ts:92storageCatalog.ts:30)。

prompt-trajectory:把请求还原成轨迹

tools/prompt-trajectory 放在 pnpm workspace 里,但不进生产 CLI 和单文件打包(apps/zcode-cli/tools/prompt-trajectory/README.md:5)。README 给的命令(prompt-trajectory/README.md:11):

pnpm --filter @zcode/bootstrap^... build
pnpm --filter @zcode/bootstrap build

pnpm --filter @zcode/prompt-trajectory record -- \
  --fixture /path/to/recording.json \
  --out /tmp/zcode-prompt-trajectory/basic-live

pnpm --filter @zcode/prompt-trajectory record:prompt -- \
  --prompt "Say hello in one short sentence."

pnpm --filter @zcode/prompt-trajectory derive -- \
  --out /tmp/zcode-prompt-trajectory/basic-live

pnpm --filter @zcode/prompt-trajectory model-io -- \
  --input ~/.zcode/cli/debug/model-io-<session>.jsonl \
  --out /tmp/zcode-prompt-trajectory/model-io-session
  • recordrecord:prompt 真正跑一遍 Agent:在 127.0.0.1 的随机端口起一个代理,把模型 provider 的 baseURL 换成它,上游请求照常转发,同时把整条对话记进 trajectory.jsonl,流式增量先拼成一条完整的助手消息再写(apps/zcode-cli/tools/prompt-trajectory/src/openai-provider-proxy.ts:38prompt-trajectory/README.md:32)。不给 --model 等参数时沿用 CLI 自己的模型配置(prompt-trajectory/README.md:41),所以会产生真实的模型调用与费用。
  • derivetrajectory.jsonl 推出每一步完整的请求体快照,OpenAI 与 Anthropic 两种形状各一份(prompt-trajectory/README.md:56)。
  • model-io 把一份真实的 model-io 文件展开 delta,默认只留 querySourcemain_turn 的主对话,排除标题生成之类的旁路调用,转成可复用的 Anthropic 轨迹(apps/zcode-cli/tools/prompt-trajectory/src/model-io.ts:11)。

NOTICE 专门提醒过这类工具:配成真实上游的录制代理会转发请求,“不能因名称含测试/录制就认为完全离线”(NOTICE.md:51)。

debug 包:抓包代理与时间线

README 开头一句(apps/zcode-cli/packages/debug/README.md:3):

Development-only trace and context viewer for ZCode.

它是一个 Hono 服务加一个 React 前端,只读三类本地数据:~/.zcode/cli/log 下的结构化日志、会话库(以只读方式打开,apps/zcode-cli/packages/debug/server/sources.ts:75)、界面里选定的会话事件 JSONL,不回写 Agent 的库(debug/README.md:11)。另外默认起一个基于 http-mitm-proxy 的本地抓包代理。

图表加载中…

用法是 pnpm --filter debug devdebug/README.md:8),API 在 127.0.0.1:4174apps/zcode-cli/packages/debug/scripts/dev.ts:7),代理在 4184(apps/zcode-cli/packages/debug/server/network-capture.ts:30)。README 写的是“API/UI: http://127.0.0.1:4174”(debug/README.md:21),这只对构建后 start 的方式成立,那时同一端口也托管前端(apps/zcode-cli/packages/debug/server/index.ts:180);dev 模式下界面由 Vite 在 127.0.0.1:5174 提供,/api 再转到 4174(apps/zcode-cli/packages/debug/vite.config.ts:8)。

要让某个 CLI 走代理,按网络面板给的两个变量启动它:ZCODE_HTTP_PROXY 指向代理,ZCODE_AGENT_CA_CERT 指向代理自签的 CA(network-capture.ts:127)。CA 与私钥生成在包内的 certs/network-ca/ 下,已被 git 忽略(apps/zcode-cli/packages/debug/certs/README.md:3);Agent 只在受控的子进程边界把它们换成标准的代理与证书变量(debug/README.md:25,机制见执行边界:子进程、环境与网络)。代理只记方法、地址、状态码、请求与响应头、正文字节数,不存正文(network-capture.ts:230);authorizationcookiex-api-key 等头改成 [redacted]network-capture.ts:34);靠 x-zcode-trace-idx-trace-idtraceparent 请求头把请求归到 trace 下(network-capture.ts:33),默认保留最近 300 条(network-capture.ts:31)。只想看日志与数据库时,用 ZCODE_DEBUG_NETWORK_CAPTURE=0 关掉代理(network-capture.ts:307)。

界面按 traceId 列出任务链,点进一条,服务端把日志、事件、数据库里的消息与 part 拼成时间线,按事件配对推出回合、模型、工具、权限、子 Agent 几条泳道的 span,再附上上下文快照、上下文用量拆解与缓存报告(apps/zcode-cli/packages/debug/server/analyzer.ts:64)。上下文快照来自日志里带全文的 context.built 一类事件(见系统提示词、上下文与提醒);代理不存正文,要看完整的模型请求体,还得回到上面的 model-io。

进程资源采样与其他

  • 资源样本。协议模式的 Agent 每 60 秒采一次 CPU 占用、常驻内存与堆用量、运行时长和物理内存,用协议通知发给桌面 Host(apps/zcode-cli/packages/bootstrap/src/process-resource-sampler.ts:100apps/zcode-cli/packages/bootstrap/src/zcode-protocol/resource-sampler.ts:26)。进程标识是一个 8 字节随机数,注释说不用 pid 是“隐私红线要求”(process-resource-sampler.ts:18)。同一节拍还顺带淘汰驻留会话,并按“变化或心跳”门控写一条本地内存诊断日志(resource-sampler.ts:21resource-sampler.ts:32)。MCP 子进程的启动、崩溃与资源事件也走协议通知(apps/zcode-cli/packages/bootstrap/src/zcode-protocol-entrypoint.ts:321);桌面端再经 ARMS 的 sendCustom 上报(packages/desktop/src/main/desktopResourceTelemetry.ts:157),而 ARMS 只在运行时给了端点时才初始化(packages/desktop/src/main/appARMSBootstrap.ts:268)。
  • 会话调试快照。协议方法 session/debug 返回某个会话最近 200 轮的用量与缓存命中、最近 100 条网络状态(packages/shared/src/session-debug.ts:3packages/shared/src/zcode-protocol/index.ts:3571),请求头用的是已脱敏的那份,并限制条数与长度(apps/zcode-cli/packages/bootstrap/src/zcode-protocol/session-debug.ts:24)。
  • scripts/shadow-replay.mjs 不是遥测。它是交付前的对账工具:把真实会话库复制一份,全部历史会话过一遍冷恢复与产品投影,统计崩溃和静默丢失(apps/zcode-cli/scripts/shadow-replay.mjs:1),与会话库的关系见SQLite 会话库

下一篇:命令行入口、无头模式与打包——main.ts 怎样守住 stdout,全部子命令与全局选项,-p 无头模式的输出格式,以及单文件可执行怎么打出来。

本页目录