docs: replace vague provenance prose with recorded facts

This commit is contained in:
Turtle
2026-08-09 15:35:02 +08:00
parent 8c124f84b6
commit 9704749b01
380 changed files with 946 additions and 874 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-06-20-core-data-structures-catalog.md
2026-06-20-core-data-structures-catalog.md: 9a3f80df592f28adc365d5e64cc15516d92b47b5
2026-06-20-core-data-structures-catalog.zh.md: a1184cb25823c10949713271434628c3650678dd
2026-06-20-core-data-structures-catalog.md: fd2b8ef8c7a43d9835cfbc39fc296465d7f5aba5
2026-06-20-core-data-structures-catalog.zh.md: 6aafdd70384c89ce39113227d11db93f53107442

View File

@@ -35,7 +35,7 @@ The durability requirement was specific: the doc shows the **literal** current t
- Complete type declarations and their JSDoc are pasted verbatim into a dedicated ` ```ts type-equiv ` fence. A concise ` ```ts public-api ` fence carries the source-equivalent ambient projection for a class whose implementation bodies do not belong in the catalog. `doc-typecheck` recognizes both and skips them (the bare declarations are not standalone-compilable), and **excludes them from the opt-out ratio** — they are a separately-checked category, not unchecked sketches.
- A new `scripts/verify-type-equiv.ts` extracts each block via the TypeScript parser and asserts that its declaration structure and every JSDoc comment match the declared symbol, ignoring only formatting whitespace and non-JSDoc comments. Ordinary blocks retain the complete declaration. A `public-api` projection retains a class's public fields, constructor, accessors, and methods with their original JSDoc while removing implementation bodies and private or protected members. This is chosen over a compiled `_Check` assertion because source names and documentation identity, not assignability, are the properties the catalog preserves.
- Provenance lives in a central `scripts/type-equiv.manifest.json` (`{ doc, symbol, source }` entries), **not** in directive comments in the prose. The script enforces a **1:1 correspondence** between each primary type-equiv block and one manifest entry, so a block can never be silently unchecked and an entry can never rot. A paired `.zh.md` block reuses the unsuffixed sibling's entry only when the complete tracked fence sequence matches in order, kind, and byte-exact body; otherwise the gate checks it independently, finds no manifest entry, and fails.
- Each type block's document, symbol, and source file are recorded in `scripts/type-equiv.manifest.json` (`{ doc, symbol, source }` entries), **not** in directive comments in the prose. The script enforces a **1:1 correspondence** between each primary type-equiv block and one manifest entry, so a block can never be silently unchecked and an entry can never rot. A paired `.zh.md` block reuses the unsuffixed sibling's entry only when the complete tracked fence sequence matches in order, kind, and byte-exact body; otherwise the gate checks it independently, finds no manifest entry, and fails.
- Wired into `doc-sync`, so relevant documentation changes run it locally and CI runs it with the other documentation checks.
### Maintenance is the author's job, with a gate backstop
@@ -46,7 +46,7 @@ The durability requirement was specific: the doc shows the **literal** current t
- **A flat dump of all cross-package vocabulary** — the `BashExecRequest` test case killed it: if seam vocabulary is "core", the catalog helps no one; the tiered spine-vs-seam structure won.
- **A compiled `_Check` assignability assertion** instead of the source match — rejected because assignability does not preserve names or JSDoc: a renamed field with the same type or a changed contract comment would pass.
- **Provenance as directive comments in the prose** — rejected for the central manifest, whose enforced 1:1 correspondence means a block can never be silently unchecked and an entry can never rot.
- **Put each type block's source in a directive comment** — rejected for the central manifest, whose enforced 1:1 correspondence means a block can never be silently unchecked and an entry can never rot.
## Verification lesson

View File

@@ -35,7 +35,7 @@ Status: implemented
- 完整的类型声明及其 JSDoc 会逐字粘贴到专用的 ` ```ts type-equiv ` 围栏中。简洁的 ` ```ts public-api ` 围栏承载类的源码等价环境声明投影,用于实现体不应进入目录的类。`doc-typecheck` 会识别并跳过这两种围栏(裸声明无法独立编译),并且**将它们排除在 opt-out 比例之外**——它们是单独受检的类别,而不是未经检查的草图。
- 新增的 `scripts/verify-type-equiv.ts` 通过 TypeScript 解析器提取每个块,并断言其声明结构和每条 JSDoc 注释都与所声明的符号匹配,只忽略格式空白和非 JSDoc 注释。普通块保留完整声明。`public-api` 投影保留类的公共字段、构造函数、访问器和方法及其原始 JSDoc,同时移除实现体以及私有或受保护成员。之所以选择它而非编译式 `_Check` 断言,是因为目录所保留的是源码名称与文档一致性,而不是可赋值性。
- 来源信息存放在集中的 `scripts/type-equiv.manifest.json`(`{ doc, symbol, source }` 条目)中,**而非**行文中的指令注释。脚本在每个主 type-equiv 块与一条 manifest(元数据清单)条目之间强制执行 **1:1 对应**,因此一个块永远不会被静默漏检,一条条目也永远不会腐烂。只有当配对 `.zh.md` 块的完整受跟踪围栏序列在顺序、类型和按字节精确的正文上均与无后缀兄弟文件匹配时,才会复用后者的条目;否则门禁会独立检查该块,发现没有 manifest 条目后失败。
- 每个类型块的文档、symbol 和源文件都记录在集中的 `scripts/type-equiv.manifest.json`(`{ doc, symbol, source }` 条目)中,**而非**行文中的指令注释。脚本在每个主 type-equiv 块与一条 manifest(元数据清单)条目之间强制执行 **1:1 对应**,因此一个块永远不会被静默漏检,一条条目也永远不会腐烂。只有当配对 `.zh.md` 块的完整受跟踪围栏序列在顺序、类型和按字节精确的正文上均与无后缀兄弟文件匹配时,才会复用后者的条目;否则门禁会独立检查该块,发现没有 manifest 条目后失败。
- 接入 `doc-sync`,因此相关文档变更会在本地运行它,CI 也会与其他文档检查一起运行它。
### 维护是作者的职责,门禁作为兜底
@@ -46,7 +46,7 @@ Status: implemented
- **平铺罗列所有跨包词汇**:`BashExecRequest` 测试案例否决了它。如果 seam 词汇算「核心」,目录对谁都没帮助;分层的主干与 seam 结构胜出。
- **用编译式 `_Check` 可赋值性断言**代替源码匹配:否决。可赋值性不会保留名称或 JSDoc;同类型字段改名或约定注释变化仍会通过。
- **来源信息作为行文中的指令注释**:否决,改用集中 manifest;其强制的 1:1 对应确保一个块永远不会被静默漏检,一条条目也永远不会腐烂。
- **将每个类型块的源文件写进指令注释**:否决,改用集中 manifest;其强制的 1:1 对应确保一个块永远不会被静默漏检,一条条目也永远不会腐烂。
## 验证教训

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-27-worktree-local-lefthook.md
2026-07-27-worktree-local-lefthook.md: 75dfd47087356c34005ec4673e174e451a72c660
2026-07-27-worktree-local-lefthook.zh.md: 42d4d89e375dfd7b28298d89e82c5e9e74908062
2026-07-27-worktree-local-lefthook.md: 5a10c5d3769bbe5ad1fd0407982bb34c8763e2ae
2026-07-27-worktree-local-lefthook.zh.md: e7e96f2317368621a348f4a851672bbec1b7e857

View File

@@ -12,7 +12,7 @@ Lefthook-generated hooks prefer an absolute binary path captured from the instal
## Decision
Hook installation is worktree-scoped. With `CI=true` or `GITHUB_ACTIONS=true`, the installer returns before Git discovery or mutation because automated jobs do not consume contributor hooks. Otherwise, it requires Git 2.26 or newer for configuration-scope provenance, upgrades a format-0 repository to format 1, enables `extensions.worktreeConfig`, and assigns the current worktree an absolute `core.hooksPath` at `$GIT_DIR/dsh-hooks`.
Hook installation is worktree-scoped. With `CI=true` or `GITHUB_ACTIONS=true`, the installer returns before Git discovery or mutation because automated jobs do not consume contributor hooks. Otherwise, it requires Git 2.26 or newer so `git config --show-scope` can report which scope supplied a value, upgrades a format-0 repository to format 1, enables `extensions.worktreeConfig`, and assigns the current worktree an absolute `core.hooksPath` at `$GIT_DIR/dsh-hooks`.
Before upgrading format 0, the installer refuses direct common-config `extensions.*`; it also refuses direct `core.worktree` or `core.bare=true` and non-empty dormant worktree configs that enabling the extension would activate. The migration removes direct `core.bare=false` because false is Git's default. The common repository config and every existing `config.worktree` must be regular files. These checks disable include expansion because Git's repository-format parser also ignores included targets. A repository-scoped lock serializes migration and hook writes; its process ID, random token, file identity, and exact contents must still match at release. Dead or invalid locks require manual recovery rather than automatic breaking.

View File

@@ -12,7 +12,7 @@ Lefthook 生成的钩子会优先使用安装时从对应 worktree 记录的绝
## 决策
钩子安装以 worktree 为作用域。当 `CI=true` 或 `GITHUB_ACTIONS=true` 时,安装程序会在探测 Git 或做出任何变更之前返回,因为自动化任务不会使用贡献者钩子。否则,为了获取配置作用域的来源信息,安装程序要求 Git 2.26 或更高版本;它会将格式版本为 0 的仓库升级到格式版本 1,启用 `extensions.worktreeConfig`,并将当前 worktree 的 `core.hooksPath` 设为指向 `$GIT_DIR/dsh-hooks` 的绝对路径。
钩子安装以 worktree 为作用域。当 `CI=true` 或 `GITHUB_ACTIONS=true` 时,安装程序会在探测 Git 或做出任何变更之前返回,因为自动化任务不会使用贡献者钩子。否则,安装程序要求 Git 2.26 或更高版本,使 `git config --show-scope` 可以报告由哪个作用域提供配置值;它会将格式版本为 0 的仓库升级到格式版本 1,启用 `extensions.worktreeConfig`,并将当前 worktree 的 `core.hooksPath` 设为指向 `$GIT_DIR/dsh-hooks` 的绝对路径。
升级格式 0 之前,安装程序会拒绝共用配置中直接设置的 `extensions.*`;它还会拒绝直接设置的 `core.worktree` 或 `core.bare=true`,以及启用扩展后将被激活的非空且尚未生效的 worktree 配置。迁移会移除直接设置的 `core.bare=false`,因为 false 是 Git 的默认值。共用仓库配置和每个已有的 `config.worktree` 都必须是常规文件。这些检查会禁用 include 展开,因为 Git 的仓库格式解析器也会忽略 include 目标。仓库级锁会串行化迁移和钩子写入;释放时,锁的进程 ID、随机令牌、文件身份和完整内容必须仍然匹配。所属进程已结束或内容无效的锁必须手动恢复,不会被自动破坏。

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-06-in-repository-landlock-release.md
2026-08-06-in-repository-landlock-release.md: 3ae9e9c3c50a1d0202a345e419cb2b7079e29ffa
2026-08-06-in-repository-landlock-release.zh.md: ffebe45c537ee192ef855296b3334937485e2a89
2026-08-06-in-repository-landlock-release.md: 1540cebbf5a3dffa20003c70ffcec426aeca104b
2026-08-06-in-repository-landlock-release.zh.md: eaa576f0b39630eb07286906c1f537a0498ad646

View File

@@ -8,7 +8,7 @@ English | [中文](2026-08-06-in-repository-landlock-release.zh.md)
The `@deepseek-ai/node-addon-landlock-run` source already lives beside its DeepSeek Harness consumers under `native/landlock-run`, but it previously kept a separate pnpm workspace and lockfile and depended on a standalone repository for npm publication. Harness packages consumed a fixed registry version, so one pull request could change the launcher contract and its consumer without testing those changes together. The source repository's native workflow could rehearse the package, but it did not publish the artifact it tested.
The mirror also duplicated release coordination: export the source, update another lockfile, run another release workflow, publish the native family, then return to this repository to bump registry dependencies. That split made source-to-binary provenance, rollback, and security-fix coordination harder without changing what npm users actually needed.
The mirror also duplicated release coordination: export the source, update another lockfile, run another release workflow, publish the native family, then return to this repository to bump registry dependencies. That split made it harder to match each binary to its source commit, roll back releases, and coordinate security fixes without changing what npm users actually needed.
The existing unscoped npm names are owned by the standalone publisher account rather than the `@deepseek-ai` organization. Moving only the workflow would therefore leave publication dependent on a personal credential outside the repository's release ownership.
@@ -37,7 +37,7 @@ Launcher protocol, TypeScript entry code, native source, harness consumption, an
npm consumers install `@deepseek-ai/node-addon-landlock-run`; the old unscoped package names are not silently redirected. A supported Linux host downloads the scoped entry package and its matching architecture package; the other architecture package is skipped. An unsupported host receives no platform binary and follows the existing deterministic fail-closed probe path.
The implementation touches more files than a dependency-line edit because the repository must also own workspace constraints, TypeScript build order, cleanup, CI triggers, release tags, lockfile generation, packed-install provenance, release documentation, and generated notices. The behavioral boundary stays narrow: it changes only the Landlock package family and its three direct workspace consumers, not the version or publication state of other DeepSeek Harness packages.
The implementation touches more files than a dependency-line edit because the repository must also own workspace constraints, TypeScript build order, cleanup, CI triggers, release tags, lockfile generation, comparison of installed binaries with workspace builds, release documentation, and generated notices. The behavioral boundary stays narrow: it changes only the Landlock package family and its three direct workspace consumers, not the version or publication state of other DeepSeek Harness packages.
The first scoped release must use an `@deepseek-ai` organization token through the `npm-publish` environment's `NPM_TOKEN`, because npm cannot configure trusted publishing until a package exists. After bootstrap, all three packages must authorize this repository's release workflow before the fallback token can be removed. npm still publishes packages sequentially and offers no cross-package transaction, so a failed publish can leave a partial version. Because npm rejects an already-published name and version, an operator must inspect the registry and publish only the missing tarballs rather than rerunning the workflow unchanged. Linux x64 and arm64 runners remain the authoritative binary and real-kernel checks; a macOS checkout can verify the entry package and unsupported-platform behavior but cannot replace those jobs.

View File

@@ -8,7 +8,7 @@ Status: implemented
`@deepseek-ai/node-addon-landlock-run` 源码已经与其 DeepSeek Harness 消费方一同位于 `native/landlock-run` 下,但此前仍保留独立的 pnpm workspace 和锁文件,并依赖一个独立仓库发布到 npm。Harness 包使用 npm 注册表中的固定版本,因此同一个 PR(Pull Request)可以同时修改启动器约定及其消费方,却无法一起测试这些改动。源码仓库的原生工作流可以演练打包流程,但不会发布它实际测试过的产物。
发布镜像还造成重复的发布协调工作:导出源码、更新另一份锁文件、运行另一套发布工作流、发布原生包家族,然后回到本仓库更新注册表依赖。npm 用户的实际需求并未改变,这种拆分却增加了从源码到二进制的溯源、回滚和安全修复协调难度。
发布镜像还造成重复的发布协调工作:导出源码、更新另一份锁文件、运行另一套发布工作流、发布原生包家族,然后回到本仓库更新注册表依赖。npm 用户的实际需求并未改变,这种拆分却让每个二进制更难对应到其源提交,也让发布回滚和安全修复协调更困难。
现有的非 scoped npm 包名归独立发布账号所有,而不属于 `@deepseek-ai` 组织。因此,仅迁移工作流仍会让发布依赖仓库发布归属之外的个人凭证。
@@ -37,7 +37,7 @@ Status: implemented
npm 消费方改为安装 `@deepseek-ai/node-addon-landlock-run`;原先的非 scoped 包名不会被静默重定向。受支持的 Linux 主机会下载 scoped 入口包及与其架构匹配的包,并跳过另一架构的包。不受支持的主机不会收到平台二进制文件,并继续沿用现有的确定性失败闭合探测路径。
实现涉及的文件比只修改一行依赖更多,因为仓库还必须负责 workspace 约束、TypeScript 构建顺序、清理、CI 触发条件、发布 tag、锁文件生成、打包安装来源证明、发布文档和生成的第三方声明。行为边界仍然很窄:此次改动只影响 Landlock 包家族及其 3 个直接 workspace 消费方,不改变其他 DeepSeek Harness 包的版本或发布状态。
实现涉及的文件比只修改一行依赖更多,因为仓库还必须负责 workspace 约束、TypeScript 构建顺序、清理、CI 触发条件、发布 tag、锁文件生成、将已安装二进制与 workspace 构建进行比较、发布文档和生成的第三方声明。行为边界仍然很窄:此次改动只影响 Landlock 包家族及其 3 个直接 workspace 消费方,不改变其他 DeepSeek Harness 包的版本或发布状态。
第一次发布 scoped 包时,必须通过 `npm-publish` 环境的 `NPM_TOKEN` 使用 `@deepseek-ai` 组织 token,因为 npm 只有在包已经存在后才能配置 trusted publishing。完成 bootstrap 后,必须让 3 个包都授权本仓库的发布工作流,才能移除后备 token。npm 仍会按顺序发布各个包,且不提供跨包事务,因此发布失败可能留下只完成了一部分的版本。由于 npm 会拒绝已经发布的同名同版本包,操作人员必须检查注册表并只发布缺失的 tarball,而不能原样重新运行工作流。Linux x64 和 arm64 runner 仍提供权威的二进制构建与真实内核检查;macOS checkout 可以验证入口包和不受支持平台上的行为,但不能取代这些作业。

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-08-browser-gif-evidence-chain.md
2026-08-08-browser-gif-evidence-chain.md: 93dfad76b3c4d0934120a164ab22dd4b898e2e01
2026-08-08-browser-gif-evidence-chain.zh.md: 8aafc842e55775bade8885a792ce7b92dfc8df4e
2026-08-08-browser-gif-evidence-chain.md: b1ee54aa21949c50d69be3384a35547b752e6858
2026-08-08-browser-gif-evidence-chain.zh.md: 43fa0139b198c91363ccf30327a62c0b894557a0

View File

@@ -8,15 +8,15 @@ English | [中文](2026-08-08-browser-gif-evidence-chain.zh.md)
A browser-demo storyboard can contain individually truthful screenshots without proving one truthful execution. Reusing global application state can admit old settings or sessions, capture automation can accidentally combine frames from separate model runs, and a chat transcript can show a successful fallback without exposing the tool rejection that caused it. Fuzzy accessible-name matching can also accept prompt echoes or descendant text instead of the intended result.
Headless production recording has two further boundaries. A product default may open a native operating-system surface that automation cannot drive, while replacing that surface with a mock or test hook would change the provenance. After publication, a successful git push does not prove that a private-repository GIF is fetchable or that GitHub recognizes the pull-request Markdown as an image.
Headless production recording has two further boundaries. A product default may open a native operating-system surface that automation cannot drive, while replacing that surface with a mock or test hook would mean the GIF no longer shows the production path. After publication, a successful git push does not prove that a private-repository GIF is fetchable or that GitHub recognizes the pull-request Markdown as an image.
## Decision
The [`record-browser-gif`](../../../skills/record-browser-gif/SKILL.md) workflow treats one storyboard as one evidence chain pinned to an exact pull-request head. Before building, it requires a clean worktree and records that commit SHA. Each run uses fresh `DSH_HOME`, `DSH_AGENTS_HOME`, workspace, session, and isolated browser state, and every published frame comes from the same server and model-backed scenario run. When a fresh browser context is unavailable, the exact origin's cookies and site storage are cleared before navigation. Existing user browser state is used only when requested or required, is declared in the provenance, and does not substantiate fresh client state. A failed capture run is discarded and repeated from fresh roots rather than combined with another run.
The [`record-browser-gif`](../../../skills/record-browser-gif/SKILL.md) workflow treats one storyboard as one evidence chain pinned to an exact pull-request head. Before building, it requires a clean worktree and records that commit SHA. Each run uses fresh `DSH_HOME`, `DSH_AGENTS_HOME`, workspace, session, and isolated browser state, and every published frame comes from the same server and model-backed scenario run. When a fresh browser context is unavailable, the exact origin's cookies and site storage are cleared before navigation. Existing user browser state is used only when requested or required, is stated next to the GIF, and does not substantiate fresh client state. A failed capture run is discarded and repeated from fresh roots rather than combined with another run.
Browser automation waits for unique, exact semantic states. When the claim concerns a tool call, rejection, or recovery, the storyboard includes a detail or trajectory frame that identifies the tool, shows its status or stable error code, and shows the downstream result. The final encoded GIF remains the verification subject; when a viewer cannot animate it, representative frames are decoded from that GIF instead of treating source screenshots as equivalent evidence.
The available browser-control workflow remains preferred. When it is unavailable, the recorder uses the repository-declared Playwright dependency in an isolated headless browser rather than installing another driver or opening the user's browser. A native production surface may be replaced only through normal application configuration with an official browser-operable production backend, and that override is stated in the provenance. Fixtures, mock transports, synthetic events, and test-only hooks do not substantiate a real-production claim.
The available browser-control workflow remains preferred. When it is unavailable, the recorder uses the repository-declared Playwright dependency in an isolated headless browser rather than installing another driver or opening the user's browser. A native production surface may be replaced only through normal application configuration with an official browser-operable production backend, and that override is stated next to the GIF. Fixtures, mock transports, synthetic events, and test-only hooks do not substantiate a real-production claim.
Publication verifies the boundary again. The assets branch contains media only, the staged and published bytes match the verified artifact, and a private-repository asset is checked through authenticated API or raw requests for its path, byte size, checksum, response status, and media type. This proves the repository-member review path only; the [documentation-site image decision](2026-08-06-doc-site-carries-its-images.md) owns why a public site cannot depend on a private raw URL. Immediately before the pull-request body changes, the live head must still equal the recorded head. After the edit, the live head is checked again and must remain at that recorded value; GitHub's Markdown renderer separately must produce the expected image.
@@ -34,4 +34,4 @@ Publication verifies the boundary again. The assets branch contains media only,
GUI evidence now establishes one causal execution rather than a collage of plausible states, and reviewers can inspect both a structured tool failure and the completed result. Publication detects stale pull-request heads, corrupted or misplaced media, and invalid image Markdown before the body is treated as finished.
The workflow spends additional scratch state, may repeat a real model round after a capture failure, and usually adds a detail frame plus authenticated publication checks. Headless recordings can use fewer production backends than an interactive desktop, and every such selection remains part of the stated provenance.
The workflow spends additional scratch state, may repeat a real model round after a capture failure, and usually adds a detail frame plus authenticated publication checks. Headless recordings can use fewer production backends than an interactive desktop, and every selected backend is stated next to the GIF.

View File

@@ -8,15 +8,15 @@ Status: implemented
浏览器演示的分镜可以由每张都真实的截图组成,却无法证明这些截图来自同一次真实执行。复用应用全局状态可能引入旧设置或旧会话;录制自动化可能误将不同模型运行的画面合并;聊天 transcript(文本记录)可能显示降级处理成功,却没有揭示触发降级的工具拒绝。按无障碍名称进行模糊匹配,还可能误把提示词回显或后代文本当成预期结果。
无头模式下的生产环境录制还有两道边界。产品默认配置可能打开自动化无法操控的原生操作系统界面,而用 mock 或测试钩子替换该界面会改变证据来源。发布之后,git 推送成功也不能证明私有仓库中的 GIF 可以获取,或 GitHub 能将 PR(Pull Request)的 Markdown 识别为图片。
无头模式下的生产环境录制还有两道边界。产品默认配置可能打开自动化无法操控的原生操作系统界面,而用 mock 或测试钩子替换该界面,就意味着 GIF 不再展示生产路径。发布之后,git 推送成功也不能证明私有仓库中的 GIF 可以获取,或 GitHub 能将 PR(Pull Request)的 Markdown 识别为图片。
## 决策
[`record-browser-gif`](../../../skills/record-browser-gif/SKILL.md) 工作流将一套分镜视为一条证据链,并将其固定到精确的 PR head。构建之前,工作流要求工作树干净并记录其 commit SHA。每次运行都使用全新的 `DSH_HOME`、`DSH_AGENTS_HOME`、工作区、会话和隔离浏览器状态,所有发布帧均来自同一个服务器及同一次由模型驱动的场景执行。无法创建全新浏览器 context 时,应在导航之前清除该 origin 的 cookie 和站点存储。只有用户提出要求或确有必要时才能使用用户已有的浏览器状态;必须在证据来源中声明,并不得以此证明客户端状态全新。录制失败时,丢弃该次运行并从全新的状态根目录重新执行,不与另一次运行合并。
[`record-browser-gif`](../../../skills/record-browser-gif/SKILL.md) 工作流将一套分镜视为一条证据链,并将其固定到精确的 PR head。构建之前,工作流要求工作树干净并记录其 commit SHA。每次运行都使用全新的 `DSH_HOME`、`DSH_AGENTS_HOME`、工作区、会话和隔离浏览器状态,所有发布帧均来自同一个服务器及同一次由模型驱动的场景执行。无法创建全新浏览器 context 时,应在导航之前清除该 origin 的 cookie 和站点存储。只有用户提出要求或确有必要时才能使用用户已有的浏览器状态;必须在 GIF 旁说明,并不得以此证明客户端状态全新。录制失败时,丢弃该次运行并从全新的状态根目录重新执行,不与另一次运行合并。
浏览器自动化会等待唯一且精确的语义状态。如果需要证明工具调用、拒绝或恢复,分镜就必须包含详情帧或轨迹帧:标明工具、显示其状态或稳定错误码,并展示后续结果。最终编码出的 GIF 始终是验证对象;如果查看器无法播放动画,应从该 GIF 中解码出代表性帧,而不能将源截图视为等效证据。
仍应优先使用已有的浏览器控制工作流。如果该工作流不可用,录制程序应在隔离的无头浏览器中使用仓库已声明的 Playwright 依赖,而不是安装其他驱动或打开用户的浏览器。只有通过正常应用配置选用官方且可由浏览器操作的生产后端,才能替换原生生产界面,并且必须在证据来源说明中注明这一覆盖。fixture(测试前置数据)、mock 传输层、合成事件和测试专用钩子均不能支撑真实生产实现的主张。
仍应优先使用已有的浏览器控制工作流。如果该工作流不可用,录制程序应在隔离的无头浏览器中使用仓库已声明的 Playwright 依赖,而不是安装其他驱动或打开用户的浏览器。只有通过正常应用配置选用官方且可由浏览器操作的生产后端,才能替换原生生产界面,并且必须在 GIF 旁注明这一覆盖。fixture(测试前置数据)、mock 传输层、合成事件和测试专用钩子均不能支撑真实生产实现的主张。
发布环节会再次验证边界。资产分支只包含媒体文件,暂存和发布的字节必须与已验证产物一致;对于私有仓库中的资产,应通过经身份验证的 API 或原始内容请求,检查其路径、字节大小、校验和、响应状态和媒体类型。这只能证明仓库成员的评审访问路径;[文档站点图片决策](2026-08-06-doc-site-carries-its-images.md)解释了公共站点为何不能依赖私有的原始内容 URL。修改 PR 正文之前,必须再次确认在线 head 仍与录制时的 head 相同。编辑后还要再次检查在线 head,且它必须保持为该记录值;GitHub 的 Markdown 渲染器则须单独生成预期图片。
@@ -34,4 +34,4 @@ Status: implemented
GUI 证据现在能证明一次具有因果关系的执行,而不是将若干可信状态拼成集合;评审者既可以检查结构化的工具失败,也可以检查最终完成的结果。在 PR 正文被视为完成之前,发布验证可以发现陈旧的 PR head、损坏或位置错误的媒体文件,以及无效的图片 Markdown。
该工作流会占用额外的临时状态;录制失败后,可能需要重新执行一次由真实模型驱动的场景;通常还会增加一张详情帧和经身份验证的发布检查。相比交互式桌面,无头录制可使用的生产后端更少;每次选择这类后端时,都必须将其写入证据来源说明。
该工作流会占用额外的临时状态;录制失败后,可能需要重新执行一次由真实模型驱动的场景;通常还会增加一张详情帧和经身份验证的发布检查。相比交互式桌面,无头录制可使用的生产后端更少;每个选中的后端都会写在 GIF 旁。

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-08-unified-github-label-taxonomy.md
2026-08-08-unified-github-label-taxonomy.md: fddda6c99053e55d3e31a2f6e5c55add09772117
2026-08-08-unified-github-label-taxonomy.zh.md: 75333e3823d6e96ef41b1359a81d53f4bd872f87
2026-08-08-unified-github-label-taxonomy.md: 44508b4f0e2dc4de97950b0738829c0b362cc506
2026-08-08-unified-github-label-taxonomy.zh.md: b1e3629fd93dcbff6e253058b4c465dc9bb5fd63

View File

@@ -45,7 +45,7 @@ The area set is intentionally extensible. When no existing description honestly
### Issues and migrations
Issues use native Issue Type instead of `kind/*`; their `area/*` labels remain optional. `source/*` labels record Issue provenance and do not apply to pull requests. Priority, GitHub defaults, and workflow triggers remain independent operational metadata.
Issues use native Issue Type instead of `kind/*`; their `area/*` labels remain optional. `source/*` labels record how an Issue was created and do not apply to pull requests. Priority, GitHub defaults, and workflow triggers remain independent operational metadata.
Label migrations preserve meaning before removing aliases: add the canonical replacement, verify the labelable, then remove the obsolete assignment. A label is deleted only after no pull request or Issue still uses it, and unrelated labels are never replaced as a set.
@@ -69,4 +69,4 @@ Label migrations preserve meaning before removing aliases: add the canonical rep
## Consequences
Reviewers and automation can query intent, semantic scope, provenance, priority, and operational triggers independently. Maintainers must read the change and the live label descriptions instead of inferring classification from title prefixes or paths. The live catalog, this rationale, and policy enforcement must move together when a kind or a non-obvious area boundary changes, and taxonomy migrations carry an explicit historical backfill and verification cost.
Reviewers and automation can query intent, semantic scope, how an Issue was created, priority, and operational triggers independently. Maintainers must read the change and the live label descriptions instead of inferring classification from title prefixes or paths. The live catalog, this rationale, and policy enforcement must move together when a kind or a non-obvious area boundary changes, and taxonomy migrations carry an explicit historical backfill and verification cost.

View File

@@ -45,7 +45,7 @@ Issue 已有原生 Issue Type 和独立的来源分类体系。在这两类对
### Issue 与迁移
Issue 使用原生 Issue Type,而不是 `kind/*`;其 `area/*` 标签仍然可选。`source/*` 标签记录 Issue 来源,不适用于 PR。优先级、GitHub 默认标签和工作流触发器仍是相互独立的管理元数据。
Issue 使用原生 Issue Type,而不是 `kind/*`;其 `area/*` 标签仍然可选。`source/*` 标签记录 Issue 的创建方式,不适用于 PR。优先级、GitHub 默认标签和工作流触发器仍是相互独立的管理元数据。
迁移标签时,须先保留语义,再移除别名:先添加规范替代标签,核验可加标签对象,再移除废弃的标签关系。只有在所有 PR 和 Issue 都不再使用某个标签后才能将其删除,且绝不整组替换无关标签。
@@ -69,4 +69,4 @@ Issue 使用原生 Issue Type,而不是 `kind/*`;其 `area/*` 标签仍然
## 后果
评审人和自动化流程可以分别查询意图、语义范围、来源、优先级和工作流触发条件。维护者必须阅读变更内容和现行标签说明,而不能根据标题前缀或路径推断分类。当某种类型或某条非显然的领域边界发生变化时,现行标签清单、本记录中的决策依据和政策执行必须同步更新;分类体系迁移还会产生明确的历史回填和验证成本。
评审人和自动化流程可以分别查询意图、语义范围、Issue 的创建方式、优先级和工作流触发条件。维护者必须阅读变更内容和现行标签说明,而不能根据标题前缀或路径推断分类。当某种类型或某条非显然的领域边界发生变化时,现行标签清单、本记录中的决策依据和政策执行必须同步更新;分类体系迁移还会产生明确的历史回填和验证成本。

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-09-concrete-prose-names-actors-and-recorded-facts.md
2026-08-09-concrete-prose-names-actors-and-recorded-facts.md: efb6e9bcc6f1c817bb0be07ccd31bafc4b2ac3fb
2026-08-09-concrete-prose-names-actors-and-recorded-facts.zh.md: 41b0ce82631536c53ea45d60c1405a8387885d0f

View File

@@ -0,0 +1,33 @@
# Agent Note: Concrete prose names actors and recorded facts
Status: implemented
English | [中文](2026-08-09-concrete-prose-names-actors-and-recorded-facts.zh.md)
## Problem
Repository prose used abstract category labels where readers needed different concrete facts. The same label could mean earlier event seqs cited by a replacement, the provider and model that produced a message, the caller that supplied context, the file that supplied a configuration row, or the CI job that built a binary. Readers had to inspect code before they could tell which fact the sentence promised.
Replacing one broad label with another would preserve that ambiguity. Renaming types, fields, and protocol members during an editorial cleanup would instead change contracts that the wording problem did not require changing.
## Decision
Maintained prose names the exact actor, action, source, event, field, file, or process needed by the local contract. It states what was recorded and who or what recorded it. Writers apply a spoken-language check and replace words they would not use while explaining the same point to a colleague.
The rule applies to Markdown, READMEs, active Agent Notes, JSDoc and comments, prompts, diagnostics, and user-visible strings. An audit judges each sentence separately; it does not replace a term across the repository with one preferred synonym. The edited sentence preserves actor, action, conditions, order, modality, exceptions, ownership, failure behavior, and consequences.
Exact code identifiers, public APIs, durable fields, protocol members, type names, headings with external references, and filenames stay unchanged unless a coordinated contract rename is independently required. Surrounding prose explains their fields or behavior directly. Generated documents and catalogs update from their owning source.
This decision complements the [documentation tiers and budgets](2026-07-04-doc-tiers-and-budgets.md) decision, which continues to own placement, document form, and word budgets.
## Alternatives considered
**Ban a fixed list of words.** Rejected because a word may be an exact identifier or the clearest term in another contract. Sentence-level review catches ambiguity without rejecting valid names.
**Replace every abstract label with “source,” “origin,” or “metadata.”** Rejected because another broad label still leaves readers to infer whether the sentence means a file, caller, event seq, provider/model pair, commit, or build job.
**Rename every matching identifier with the prose.** Rejected because editorial clarity does not justify unrelated API, protocol, durable-format, type, or file migrations. Those changes require their own consumer audit and decision.
## Consequences
Documentation and diagnostics may use a few more words, but each statement tells readers which value or process matters without requiring source inspection. Repository-wide prose audits require semantic classification and cannot use blind replacement. Bilingual counterparts preserve the same concrete fact, and generated copies are refreshed only after their owning source changes.

View File

@@ -0,0 +1,33 @@
# Agent Note: 具体表述说明执行者和记录的事实
Status: implemented
[English](2026-08-09-concrete-prose-names-actors-and-recorded-facts.md) | 中文
## 问题
仓库行文使用了抽象的类别名称,但读者需要知道的具体事实各不相同。同一个名称可能指替换操作引用的早期事件 seq、生成消息的提供方和模型、提供上下文的调用方、提供某行配置的文件,或构建某个二进制文件的 CI 任务。读者必须查看代码,才能知道句子承诺的是哪项事实。
用另一个宽泛名称替换原名称,仍会保留这种歧义。在行文整理中重命名类型、字段和协议成员,反而会改变与行文问题无关的约定。
## 决策
仓库维护的行文直接写明当地约定需要的执行者、动作、来源、事件、字段、文件或进程。句子说明记录了什么,以及由谁或什么记录。写作者还要检查自己是否会在向同事解释同一个问题时使用这些词;如果不会,就替换它们。
该规则适用于 Markdown、README、活跃 Agent Note、JSDoc 与注释、提示词、诊断信息和用户可见字符串。审查会分别判断每个句子,不会在整个仓库中用一个偏好的近义词统一替换某个术语。编辑后的句子保留执行者、动作、条件、顺序、情态、例外、归属、失败行为和后果。
除非另一项独立需求明确要求协调重命名约定,否则确切的代码标识符、公开 API、持久字段、协议成员、类型名、带有外部引用的标题和文件名均保持不变。它们周围的行文直接说明其字段或行为。生成的文档和目录在维护它们的源文件修改后更新。
该决策补充了[文档层级与字数预算](2026-07-04-doc-tiers-and-budgets.md)决策;后者继续规定内容位置、文档形式和字数预算。
## 曾考虑的替代方案
**禁止一份固定词表中的所有词。** 不予采纳:某个词可能是确切的标识符,也可能是另一项约定中最清楚的用词。逐句审查可以找出歧义,且不会拒绝有效名称。
**将每个抽象名称都替换为“来源”、“起源”或“元数据”。** 不予采纳:另一个宽泛名称仍会让读者自行推测句子指的是文件、调用方、事件 seq、提供方/模型组合、commit 还是构建任务。
**在修改行文时重命名所有匹配的标识符。** 不予采纳:让行文更清楚,不能作为进行无关 API、协议、持久格式、类型或文件迁移的理由。这些改动需要各自的消费方审查和决策。
## 后果
文档和诊断信息可能会多用几个词,但每条说明都会告诉读者哪个值或哪个执行过程有关,无需查看源码。全仓库行文审查必须根据句子的具体含义分类,不能盲目替换。双语对侧文件保留相同的具体事实,只有在维护这些副本的源文件更改后才会刷新它们。