From a5f38a95ee8fa9a778c51566a6a3c576fc6d5d0b Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Mon, 8 Jun 2026 13:21:26 +0800 Subject: [PATCH] docs: document v02 deploy yaml source --- AGENTS.md | 1 + deploy/README.md | 5 ++++- docs/reference/g14-gitops-cicd.md | 3 ++- docs/reference/spec-hwpod-harness.md | 4 ++-- tools/hwlab-cli/client.test.ts | 22 ++++++++++++++++++++++ tools/src/hwlab-caserun-lib.ts | 2 -- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ac714de4..7ca6a641 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,7 @@ HWLAB 是硬件实验室运行面和控制面项目。本文是 agent、指挥 - G14 是当前 HWLAB DEV/PROD 原生 k8s 与 GitOps 运行面真相;`hwlab-dev` 与 `hwlab-prod` 均由 G14 k3s、Tekton、`G14-gitops` 和 Argo CD 管理,详见 [docs/reference/g14-gitops-cicd.md](docs/reference/g14-gitops-cicd.md)。 - `v0.2` 是 G14 上的加法扩容线:固定分支 `v0.2`、固定开发 workspace `G14:/root/hwlab-v02`、固定 CI/CD source repo `G14:/root/hwlab-v02-cicd.git`、固定 namespace `hwlab-v02`、FRP 入口 `74.48.78.17:19666/19667`;创建和集成 `v0.2` 不得删除、重命名、复用或改义现有 `G14`/`G14-gitops` 分支、`hwlab-dev`/`hwlab-prod` namespace 或 17666/17667、18666/18667 入口。 +- `v0.2` 的人写 deploy/runtime 配置单一出处是 `deploy/deploy.yaml`;`deploy/deploy.json` 不再是 v0.2 兼容源。所有脚本、renderer、planner 和 CLI 必须通过 `scripts/src/structured-config.mjs` / `scripts/src/deploy-config.mjs` 这类格式无关读写层消费配置,禁止把 YAML parser import 或 ad hoc YAML 解析散落到业务脚本里。 - G14 GitOps render 若改变 Argo Application、AppProject、runtime path 或 DEV/PROD 拆分目录,必须同步应用 `deploy/gitops/g14/argocd/project.yaml`、`application-dev.yaml` 和 `application-prod.yaml`;只推 `G14-gitops` 分支不等于 Argo 已切到新 path。 - D601 HWLAB DEV、D601 `dev-cd-apply`、`ci-publish` 和旧 `main` JS 脚本式 CI/CD 已退出 G14 发布入口;G14 Tekton 只能通过 `scripts/g14-artifact-publish.mjs` 作为集群内 build/push helper,再由 GitOps/Argo CD rollout,新开发、发布、验收、文档和运行面实验不得把 D601 或 legacy 脚本 CD 当作当前 HWLAB runtime source-of-truth。 - G14 k3s 操作必须通过 UniDesk route `G14:k3s` 执行;不得用 D601 kubeconfig、Docker Desktop Kubernetes、master server 本地 check/build 或旧 JS CD 结果作为 G14 DEV/PROD 通过证据。 diff --git a/deploy/README.md b/deploy/README.md index 25dc64a3..0c743e0a 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,6 +1,6 @@ # Deploy Contract -`deploy.schema.json` defines the future `deploy/deploy.yaml` manifest shape. +`deploy.schema.json` defines the current `deploy/deploy.yaml` manifest shape. The MVP acceptance environment is DEV only. Public endpoint source fields live in `deploy/deploy.yaml`: frontend `http://74.48.78.17:16666` and API/edge @@ -12,6 +12,9 @@ for future compatibility, but PROD deployment is not part of MVP acceptance. - `deploy/deploy.yaml` is the DEV-only deploy manifest. - `deploy/deploy.yaml` is the single source for `health.path`, `publicEndpoints`, `frp.proxies`, and `k3s.serviceMappings`. +- Config parsing and writing must go through `scripts/src/structured-config.mjs` + and `scripts/src/deploy-config.mjs`; do not add direct YAML parser calls in + planners, renderers, smoke scripts, or CLIs. - `deploy/k8s/base` contains parseable k3s resource skeletons for the frozen HWLAB service IDs rendered from the manifest contract. - `deploy/k8s/dev` contains the DEV health contract and endpoint metadata. diff --git a/docs/reference/g14-gitops-cicd.md b/docs/reference/g14-gitops-cicd.md index 41ccec74..202d54ea 100644 --- a/docs/reference/g14-gitops-cicd.md +++ b/docs/reference/g14-gitops-cicd.md @@ -75,7 +75,8 @@ npm run g14:gitops:render -- --source-revision HWLAB 是 monorepo,G14 CI/CD 加速必须按组件输入判断构建和滚动;v0.2 env-reuse 的组件边界与环境配方直接来自 `deploy/deploy.yaml`,运行态镜像身份来自 per-service artifact catalog;`CI.json` 已删除,不再作为任何 planner 输入。 -- `scripts/g14-ci-plan.mjs` 是只读 planner,默认读取当前 workspace 的 `deploy/deploy.yaml`、`deploy/artifact-catalog.dev.json` 和 `deploy/deploy.yaml` 内的 lane service declarations/env recipe,输出 `affectedServices`、`reusedServices`、`componentCommitId`、`componentInputHash`、`dockerfileHash`、`baseImageDigest`、`buildArgsHash` 和原因;它不得修改 deploy、catalog 或 GitOps 文件。Tekton `prepare-source` 会先从 `G14-gitops` 注入上一轮发布态 catalog,source 分支里的 catalog 只作为 seed contract。 +- `deploy/deploy.yaml` 是当前 v0.2 人写 deploy/runtime 配置单一出处;`deploy/deploy.json` 不得作为 v0.2 兼容源恢复。配置读写由 `scripts/src/structured-config.mjs` 和 `scripts/src/deploy-config.mjs` 统一承载,只有该格式无关层直接处理 YAML/JSON 解析;planner、renderer、smoke、artifact helper 和 CLI 只调用读写 helper。 +- `scripts/g14-ci-plan.mjs` 是只读 planner,默认读取当前 workspace 的 `deploy/deploy.yaml`、`deploy/artifact-catalog.dev.json`,以及 `deploy/deploy.yaml` 内的 lane service declarations/env recipe,输出 `affectedServices`、`reusedServices`、`componentCommitId`、`componentInputHash`、`dockerfileHash`、`baseImageDigest`、`buildArgsHash` 和原因;它不得修改 deploy、catalog 或 GitOps 文件。Tekton `prepare-source` 会先从 `G14-gitops` 注入上一轮发布态 catalog,source 分支里的 catalog 只作为 seed contract。 - v0.2 服务清单来自显式 `--services` 或 `deploy.lanes.v02.envReuseServices`;旧 `deploy.services[]`、`deploy.k3s.serviceMappings[]` 和 `internal/protocol.SERVICE_IDS` 推导路径不再作为 planner 输入。 - v0.2 env-reuse 组件边界和环境镜像配方以 `deploy/deploy.yaml` 的 `lanes.v02.serviceDeclarations`、`lanes.v02.envRecipe` 和 `lanes.v02.bootConfig` 为单一配置点;新增服务或调整 `componentPaths`、`runtimeKind`、`entrypoint`、Bun 版本、系统包、launcher 路径和 HWPOD alias 时先改 deploy 配置与 schema/测试,不再把这些属性硬编码进 planner 或 artifact publish helper。 - `hwpod` 是 runner 内的稳定 HWPOD task 入口,由 `tools/hwpod-cli.ts`、`tools/hwpod-compiler-cli.ts`、`tools/hwpod-ctl.ts`、`tools/hwpod-node.ts` 和 `skills/hwpod-cli/`、`skills/hwpod-ctl/` 组成。修改这些路径时,G14/v0.2 CI 必须至少触发携带 `/usr/local/bin/hwpod` 的 runtime skills/env-reuse 重新装配或 rollout,不能全量复用旧 artifact 后只报告 PipelineRun 成功。 diff --git a/docs/reference/spec-hwpod-harness.md b/docs/reference/spec-hwpod-harness.md index e7c42dfc..6cfb4def 100644 --- a/docs/reference/spec-hwpod-harness.md +++ b/docs/reference/spec-hwpod-harness.md @@ -301,7 +301,7 @@ CaseRun 的 trace 处理必须遵循 [spec-v02-code-agent-trace.md](spec-v02-cod `hwlab-cli case aggregate --run-id --case-repo /root/hwlab-case-registry` 是已完成 CaseRun 的无服务二次整理入口。它只读取 case registry repo 里已有的 `runs///` 产物,不启动新的 CaseRun、不访问硬件、不触发 CI/CD、不追加自动评价或 pass/fail 判定;默认输出 `runs///aggregate.md`,并只把这个 markdown 文件 `git add`、`git commit`、`git push` 回 case registry repo。若 registry 里存在其他并行 dirty 产物,`case aggregate` 不得顺带提交它们。 -`aggregate.md` 是该 run 的主阅读入口,必须按固定顺序聚合运行环境信息、HWPOD 信息、Code Agent 信息、输入 Prompt、低噪声 Trace、final response 和最后 diff。Trace 正文优先使用 `agent-messages.json` 里的共享 Web/CLI renderer rows;普通 message row 直接加粗展示正文,不做折叠,只有工具调用 row 使用 `-
/` 列表项折叠,且 `` 本身就是折叠按钮,文案写成单行截短的 `已运行 `。工具调用展开体必须保留或恢复 `stdout:`、`stderr:`、`exitCode=` 等结构换行,不能把详情挤成一行。缺少 rows 时才嵌入已有 `agent-trace.md`。聚合文件可以列原始产物索引和 trace/result/inspect 命令作为审计线索,但不能把 `summary.md`、`result.json`、`final-response.md` 或原 trace 文件继续声明为对外主阅读路径。 +`aggregate.md` 是该 run 的主阅读入口,必须按固定顺序聚合运行环境信息、HWPOD 信息、Code Agent 信息、输入 Prompt、低噪声 Trace、final response 和最后 diff。Trace 正文优先使用共享 Web/CLI renderer rows;普通 message row 直接加粗展示正文,不做折叠,只有工具调用 row 使用 `-
/` 列表项折叠,且 `` 本身就是折叠按钮,文案写成单行截短的 `已运行 `。工具调用展开体和新生成的 `agent-trace.json` 必须保留完整 command/stdout/stderr/exitCode 正文和结构换行,不能把详情挤成一行,也不能在 full trace 产物里做 preview 截断;只允许 summary 截短。缺少 rows 时才嵌入已有 `agent-trace.md`。聚合文件可以列原始产物索引和 trace/result/inspect 命令作为审计线索,但不能把 `summary.md`、`result.json`、`final-response.md` 或原 trace 文件继续声明为对外主阅读路径。 验收已完成 case04 时,使用现有 registry 产物回放,不重新启动 CaseRun: @@ -328,6 +328,6 @@ hwlab-cli case aggregate d601-f103-v2-arm2d-integration \ 7. 长任务验收必须覆盖 `hwlab-cli case run start ` 立即返回,以及 `status/result/logs ` 在 worker 运行中能短查询到阶段、耗时、stdout/stderr byte count、trace/session/conversation/thread 信息和下一条轮询命令;不得把同步命令长时间无输出视为有效 CaseRun 操作体验。 8. `d601-f103-v2-compile` 的真实流程只覆盖当前编排链路和 compile-only smoke;操作员直接运行 `hwpod-cli build`、直接调用 Keil 或只检查 node 侧 job,不等同于 CaseRun 流程跑完。 9. agent-task CaseRun 的真实流程必须证明 `case run` 已创建或调用 Code Agent / AgentRun session,任务 prompt 已进入 agent 上下文,CaseRun 已采集隔离 subject worktree diff,并已继续执行编译、下载或 I/O smoke 等后续动作;当前版本只记录这些事实,不自动判断 agent 是否完成任务。 -10. 已完成 run 的 registry 聚合验收必须通过 `hwlab-cli case aggregate --run-id ` 输出单个 `aggregate.md`,并证明该文件包含运行环境、HWPOD、Code Agent、Prompt、低噪声 Trace、final response 和最后 diff;Trace 中 message 加粗直接展示,工具调用用 `-
` 缩进和单行截短的 `已运行 ` summary 折叠,展开后保留详情换行。该命令不得启动新 CaseRun,也不得提交当前聚合 markdown 以外的并行 registry dirty 文件。 +10. 已完成 run 的 registry 聚合验收必须通过 `hwlab-cli case aggregate --run-id ` 输出单个 `aggregate.md`,并证明该文件包含运行环境、HWPOD、Code Agent、Prompt、低噪声 Trace、final response 和最后 diff;Trace 中 message 加粗直接展示,工具调用用 `-
` 缩进和单行截短的 `已运行 ` summary 折叠,展开后保留完整详情换行。新归档的 `agent-trace.json` 也必须保存 full trace row body,不得把 tool detail 压缩为 preview。该命令不得启动新 CaseRun,也不得提交当前聚合 markdown 以外的并行 registry dirty 文件。 11. Windows subject worktree 文本编辑必须能在 CRLF 文件中通过 `workspace.apply-patch` 完成源码修改,返回 before/after SHA 与 diff 摘要,并保留原文件 CRLF;`workspace.apply-patch` 在 context 不匹配时必须返回可诊断 payload,而不是只给 `context not found`。 12. Keil `debug.download` 自动装配必须输出结构化 `cmd.run` argv 步骤;带空格的 `probeName` 在 plan 中必须是单独 argv 元素。`io.uart.read` 必须通过节点本地 `serial-monitor` 读取正在监控的 COM/baud;未监控或工具失败时必须返回包含 `ioProbe`/COM 口/baud/monitor status/启动建议的结构化 blocker details。 diff --git a/tools/hwlab-cli/client.test.ts b/tools/hwlab-cli/client.test.ts index ad8ddfa8..fccbf590 100644 --- a/tools/hwlab-cli/client.test.ts +++ b/tools/hwlab-cli/client.test.ts @@ -1743,6 +1743,28 @@ test("hwlab-cli Web trace render reports suppressed noise and command tool detai assert.match(text, /当前可见 HWPOD/u); }); +test("hwlab-cli Web trace render keeps full tool details with --full", async () => { + const longStdout = `first line\n${"X".repeat(1500)}\nlast line`; + const command = "/bin/sh -lc 'cat > /tmp/main_patch.txt << '\''PATCHMAIN'\''\n*** Begin Patch\n*** Update File: projects/01_baseline/User/main.c\n@@\n+d601_arm2d_demo_task();\n*** End Patch\nPATCHMAIN\nhwpod workspace apply-patch --spec .hwlab/hwpod-spec.yaml --reason demo'"; + const result = await runHwlabCli(["client", "agent", "trace", "trc_render_full", "--base-url", "http://web.test", "--cookie", "hwlab_session=session-a", "--render", "web", "--full"], { + fetchImpl: async () => new Response(JSON.stringify({ + status: "completed", + traceId: "trc_render_full", + events: [ + { traceId: "trc_render_full", seq: 1, label: "item/commandExecution:completed", type: "tool_call", toolName: "commandExecution", status: "completed", itemId: "call_full", command, exitCode: 0, stdoutSummary: longStdout, createdAt: "2026-06-01T13:00:02.000Z" } + ] + }), { status: 200 }) + }); + + assert.equal(result.exitCode, 0); + const row = result.payload.body.rows[0]; + assert.match(row.body, /cat > \/tmp\/main_patch\.txt << '+PATCHMAIN'+/u); + assert.match(row.body, /\n\*\*\* Begin Patch/u); + assert.match(row.body, /stdout:\nfirst line\nX{1500}\nlast line/u); + assert.match(row.body, /exitCode=0/u); + assert.doesNotMatch(row.body, /last line\.\.\./u); +}); + test("hwlab-cli Web trace render keeps AgentRun middle assistant message", async () => { const result = await runHwlabCli(["client", "agent", "trace", "trc_render_agentrun_middle", "--base-url", "http://web.test", "--cookie", "hwlab_session=session-a", "--render", "web"], { fetchImpl: async () => new Response(JSON.stringify({ diff --git a/tools/src/hwlab-caserun-lib.ts b/tools/src/hwlab-caserun-lib.ts index 24c73292..d0b3a537 100644 --- a/tools/src/hwlab-caserun-lib.ts +++ b/tools/src/hwlab-caserun-lib.ts @@ -2200,9 +2200,7 @@ async function archivedAgentTraceBody(run: PreparedCaseRun, evidence: any) { async function materializeFullAgentTraceWithExistingCli(context: CaseContext, run: PreparedCaseRun, evidence: any, initialTrace: any) { const body = initialTrace?.body && typeof initialTrace.body === "object" ? initialTrace.body : initialTrace; - const existingRows = arrayOfObjects(body?.rows ?? body?.renderedRows ?? body?.traceRows); const existingEvents = arrayOfObjects(body?.events ?? body?.trace?.events ?? body?.sourceEvents); - if (existingRows.length > 0) return initialTrace; if (existingEvents.length > 0) return initialTrace; if (!run.agent) return initialTrace; const traceId = text(body?.traceId ?? initialTrace?.traceId ?? evidence.agent?.traceId ?? run.agent?.traceId);