From 0545a962e5e8834d4601edc65a87879584bdc71d Mon Sep 17 00:00:00 2001 From: eetoc Date: Fri, 17 Jul 2026 21:07:23 +0800 Subject: [PATCH 1/2] fix(docs): exclude v1 migration fields from schema coverage --- Taskfile.yml | 2 ++ docs/pages/agent-compose-yaml-manual.md | 3 ++- docs/pages/zh-CN/agent-compose-yaml-manual.md | 3 ++- tools/genpages/check-pages.mjs | 8 +++---- tools/genpages/package.json | 4 ++-- tools/genpages/schema-coverage.mjs | 15 +++++++++++++ tools/genpages/schema-coverage.test.mjs | 21 +++++++++++++++++++ 7 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 tools/genpages/schema-coverage.mjs create mode 100644 tools/genpages/schema-coverage.test.mjs diff --git a/Taskfile.yml b/Taskfile.yml index cbd2c56e..cc39d2a7 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -81,6 +81,8 @@ tasks: - '../../pkg/compose/spec.go' - 'check-pages.mjs' - 'render-pages.mjs' + - 'schema-coverage.mjs' + - 'schema-coverage.test.mjs' - 'package.json' - 'package-lock.json' generates: diff --git a/docs/pages/agent-compose-yaml-manual.md b/docs/pages/agent-compose-yaml-manual.md index 3d754cae..a0f1c41c 100644 --- a/docs/pages/agent-compose-yaml-manual.md +++ b/docs/pages/agent-compose-yaml-manual.md @@ -261,6 +261,7 @@ Each `workspaces.` accepts: | `provider` | string | Required | `local` or `git`. | | `url` | string | Required for `git` | Git clone URL. It is forbidden for `local`. | | `branch` | string | Optional for `git` | Branch to check out. It is forbidden for `local`. | +| `commit` | string | Optional for `git` | Commit to check out. It is forbidden for `local`. | | `path` | string | Provider-specific | For `local`, a required path relative to the compose directory that cannot escape the project root. For `git`, a clone target/subpath that defaults to `.` and cannot escape the workspace root. | A local workspace is copied into an isolated snapshot for each project run. Agent changes to that snapshot do not modify the source directory. @@ -686,7 +687,7 @@ workspace: path: . ``` -If `name` is combined with any of `provider`, `url`, `branch`, or `path`, the object is treated as an inline workspace rather than an inherited project workspace with overrides. To reuse a project entry, set only `name`. +If `name` is combined with any of `provider`, `url`, `branch`, `commit`, or `path`, the object is treated as an inline workspace rather than an inherited project workspace with overrides. To reuse a project entry, set only `name`. ### `scheduler` diff --git a/docs/pages/zh-CN/agent-compose-yaml-manual.md b/docs/pages/zh-CN/agent-compose-yaml-manual.md index 052442f1..08faac06 100644 --- a/docs/pages/zh-CN/agent-compose-yaml-manual.md +++ b/docs/pages/zh-CN/agent-compose-yaml-manual.md @@ -260,6 +260,7 @@ workspace: | `provider` | string | 必填 | `local` 或 `git`。 | | `url` | string | `git` 必填 | Git clone URL;`local` 不允许设置。 | | `branch` | string | `git` 可选 | 要检出的分支;`local` 不允许设置。 | +| `commit` | string | `git` 可选 | 要检出的提交;`local` 不允许设置。 | | `path` | string | 必填/可选 | `local` 时是配置文件目录下的相对源目录且不可逃逸;`git` 时是仓库内 clone target/subpath,默认 `.`。 | 本地 Workspace 在每次项目 run 创建时被复制为隔离快照,Agent 对快照的修改不会写回源目录。 @@ -691,7 +692,7 @@ workspace: path: . ``` -若 `name` 与 `provider`/`url`/`branch`/`path` 同时出现,该对象按内联 Workspace 处理,而不是从顶层继承后局部覆盖。需要复用时只写 `name`。 +若 `name` 与 `provider`/`url`/`branch`/`commit`/`path` 同时出现,该对象按内联 Workspace 处理,而不是从顶层继承后局部覆盖。需要复用时只写 `name`。 ### `scheduler` diff --git a/tools/genpages/check-pages.mjs b/tools/genpages/check-pages.mjs index 5f977d87..679e545a 100644 --- a/tools/genpages/check-pages.mjs +++ b/tools/genpages/check-pages.mjs @@ -2,6 +2,8 @@ import { readFile, readdir, stat } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import { documentedYAMLSchemaFields } from "./schema-coverage.mjs"; + const scriptDir = path.dirname(fileURLToPath(import.meta.url)); const repositoryRoot = path.resolve(scriptDir, "../.."); const pagesDir = path.join(repositoryRoot, "docs", "pages"); @@ -62,11 +64,7 @@ async function checkEnglishManuals() { async function checkYAMLSchemaCoverage() { const schema = await readFile(schemaPath, "utf8"); - const fields = new Set( - [...schema.matchAll(/yaml:"([^",]+)/g)] - .map((match) => match[1]) - .filter((field) => field !== "-"), - ); + const fields = documentedYAMLSchemaFields(schema); for (const relativePath of [ "agent-compose-yaml-manual.md", diff --git a/tools/genpages/package.json b/tools/genpages/package.json index cb70d91d..3485741f 100644 --- a/tools/genpages/package.json +++ b/tools/genpages/package.json @@ -3,8 +3,8 @@ "private": true, "type": "module", "scripts": { - "build": "node render-pages.mjs && node check-pages.mjs", - "test": "node render-pages.mjs && node check-pages.mjs" + "build": "node --test && node render-pages.mjs && node check-pages.mjs", + "test": "node --test" }, "dependencies": { "marked": "15.0.12" diff --git a/tools/genpages/schema-coverage.mjs b/tools/genpages/schema-coverage.mjs new file mode 100644 index 00000000..1dd59e9f --- /dev/null +++ b/tools/genpages/schema-coverage.mjs @@ -0,0 +1,15 @@ +// These fields preserve v1 presentation metadata during migration. They are +// intentionally absent from the v2 authoring manual and will leave with the +// compatibility path. +const v1MigrationCompatibilityFields = new Set([ + "description", + "display_name", +]); + +export function documentedYAMLSchemaFields(schema) { + return new Set( + [...schema.matchAll(/yaml:"([^",]+)/g)] + .map((match) => match[1]) + .filter((field) => field !== "-" && !v1MigrationCompatibilityFields.has(field)), + ); +} diff --git a/tools/genpages/schema-coverage.test.mjs b/tools/genpages/schema-coverage.test.mjs new file mode 100644 index 00000000..0b8fa076 --- /dev/null +++ b/tools/genpages/schema-coverage.test.mjs @@ -0,0 +1,21 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { documentedYAMLSchemaFields } from "./schema-coverage.mjs"; + +test("excludes temporary v1 migration fields from documentation coverage", () => { + const schema = ` +type example struct { + Name string \`yaml:"name,omitempty"\` + DisplayName string \`yaml:"display_name,omitempty"\` + Description string \`yaml:"description,omitempty"\` + Commit string \`yaml:"commit,omitempty"\` + Internal string \`yaml:"-"\` +} +`; + + assert.deepEqual( + [...documentedYAMLSchemaFields(schema)].sort(), + ["commit", "name"], + ); +}); From 4236b665afb629efe3da4dd5add47881c143d66b Mon Sep 17 00:00:00 2001 From: eetoc Date: Fri, 17 Jul 2026 21:12:03 +0800 Subject: [PATCH 2/2] fix(docs): exclude workspace commit from schema coverage --- docs/pages/agent-compose-yaml-manual.md | 3 +-- docs/pages/zh-CN/agent-compose-yaml-manual.md | 3 +-- tools/genpages/schema-coverage.mjs | 23 +++++++++++++------ tools/genpages/schema-coverage.test.mjs | 9 +++++++- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/pages/agent-compose-yaml-manual.md b/docs/pages/agent-compose-yaml-manual.md index a0f1c41c..3d754cae 100644 --- a/docs/pages/agent-compose-yaml-manual.md +++ b/docs/pages/agent-compose-yaml-manual.md @@ -261,7 +261,6 @@ Each `workspaces.` accepts: | `provider` | string | Required | `local` or `git`. | | `url` | string | Required for `git` | Git clone URL. It is forbidden for `local`. | | `branch` | string | Optional for `git` | Branch to check out. It is forbidden for `local`. | -| `commit` | string | Optional for `git` | Commit to check out. It is forbidden for `local`. | | `path` | string | Provider-specific | For `local`, a required path relative to the compose directory that cannot escape the project root. For `git`, a clone target/subpath that defaults to `.` and cannot escape the workspace root. | A local workspace is copied into an isolated snapshot for each project run. Agent changes to that snapshot do not modify the source directory. @@ -687,7 +686,7 @@ workspace: path: . ``` -If `name` is combined with any of `provider`, `url`, `branch`, `commit`, or `path`, the object is treated as an inline workspace rather than an inherited project workspace with overrides. To reuse a project entry, set only `name`. +If `name` is combined with any of `provider`, `url`, `branch`, or `path`, the object is treated as an inline workspace rather than an inherited project workspace with overrides. To reuse a project entry, set only `name`. ### `scheduler` diff --git a/docs/pages/zh-CN/agent-compose-yaml-manual.md b/docs/pages/zh-CN/agent-compose-yaml-manual.md index 08faac06..052442f1 100644 --- a/docs/pages/zh-CN/agent-compose-yaml-manual.md +++ b/docs/pages/zh-CN/agent-compose-yaml-manual.md @@ -260,7 +260,6 @@ workspace: | `provider` | string | 必填 | `local` 或 `git`。 | | `url` | string | `git` 必填 | Git clone URL;`local` 不允许设置。 | | `branch` | string | `git` 可选 | 要检出的分支;`local` 不允许设置。 | -| `commit` | string | `git` 可选 | 要检出的提交;`local` 不允许设置。 | | `path` | string | 必填/可选 | `local` 时是配置文件目录下的相对源目录且不可逃逸;`git` 时是仓库内 clone target/subpath,默认 `.`。 | 本地 Workspace 在每次项目 run 创建时被复制为隔离快照,Agent 对快照的修改不会写回源目录。 @@ -692,7 +691,7 @@ workspace: path: . ``` -若 `name` 与 `provider`/`url`/`branch`/`commit`/`path` 同时出现,该对象按内联 Workspace 处理,而不是从顶层继承后局部覆盖。需要复用时只写 `name`。 +若 `name` 与 `provider`/`url`/`branch`/`path` 同时出现,该对象按内联 Workspace 处理,而不是从顶层继承后局部覆盖。需要复用时只写 `name`。 ### `scheduler` diff --git a/tools/genpages/schema-coverage.mjs b/tools/genpages/schema-coverage.mjs index 1dd59e9f..958f3157 100644 --- a/tools/genpages/schema-coverage.mjs +++ b/tools/genpages/schema-coverage.mjs @@ -2,14 +2,23 @@ // intentionally absent from the v2 authoring manual and will leave with the // compatibility path. const v1MigrationCompatibilityFields = new Set([ - "description", - "display_name", + "AgentSpec.description", + "AgentSpec.display_name", + "SchedulerSpec.description", + "SchedulerSpec.display_name", + "WorkspaceSpec.commit", ]); export function documentedYAMLSchemaFields(schema) { - return new Set( - [...schema.matchAll(/yaml:"([^",]+)/g)] - .map((match) => match[1]) - .filter((field) => field !== "-" && !v1MigrationCompatibilityFields.has(field)), - ); + const fields = new Set(); + for (const definition of schema.matchAll(/type\s+(\w+)\s+struct\s*\{([\s\S]*?)\n\}/g)) { + const [, typeName, body] = definition; + for (const tag of body.matchAll(/yaml:"([^",]+)/g)) { + const field = tag[1]; + if (field !== "-" && !v1MigrationCompatibilityFields.has(`${typeName}.${field}`)) { + fields.add(field); + } + } + } + return fields; } diff --git a/tools/genpages/schema-coverage.test.mjs b/tools/genpages/schema-coverage.test.mjs index 0b8fa076..65f69526 100644 --- a/tools/genpages/schema-coverage.test.mjs +++ b/tools/genpages/schema-coverage.test.mjs @@ -5,13 +5,20 @@ import { documentedYAMLSchemaFields } from "./schema-coverage.mjs"; test("excludes temporary v1 migration fields from documentation coverage", () => { const schema = ` -type example struct { +type AgentSpec struct { Name string \`yaml:"name,omitempty"\` DisplayName string \`yaml:"display_name,omitempty"\` Description string \`yaml:"description,omitempty"\` +} + +type WorkspaceSpec struct { Commit string \`yaml:"commit,omitempty"\` Internal string \`yaml:"-"\` } + +type ReleaseSpec struct { + Commit string \`yaml:"commit,omitempty"\` +} `; assert.deepEqual(