fix(ci): restore acp snapshot transcripts and windows coverage gate ordering

- The base-mounted projection cache's write-behind forces session-log
  flushes at cache-chosen times, splitting packed chunk rows and collapsing
  the persistence window the keyless acp transcripts pin. ACP exposes no
  session-listing surface, so the automation profile disables the base row,
  restoring the pre-base behavior the fixtures were recorded against.
- The windows coverage lane runs suites that read built lib/ output (the
  webworker-packer image tests) and raced the build gate's tsdown writes
  against a partial tree; every coverage gate now waits for the build gate.
This commit is contained in:
_Kerman 2026-08-24 16:17:19 +08:00
parent 334dd53c92
commit 5fe36b513e
6 changed files with 23 additions and 11 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 packages/bundle/acp-app/README.md
README.md: d00458d3e23cfd9ff8984454aace991d3c2f8dd9
README.zh.md: e32eac45d407af25c474b6df483dc587dd4a5038
README.md: 491d5b211fb8d010ba41485465093360eae7b598
README.zh.md: ee26b13c0e66dbb8ed14f5c620ee1089f7120570

View file

@ -4,7 +4,7 @@ English | [中文](README.zh.md)
The automation-only ACP stdio application as a `dsh` profile bundle over [`dsh-base`](../base/README.md). It inherits the base's disabled module-HMR policy; its patch sets the coding-agent persona and default model route, mounts an app-owned zero-option command provider, and starts [`dsh-acp`](../../acp/acp/README.md) only after that provider accepts the invocation. `dsh --profile acp --help` therefore writes help and exits without claiming stdin or stdout.
The startup provider binds stdin EOF to the launcher's bounded successful shutdown. ACP connection close, SIGINT, and SIGTERM drain the bridge-owned agents and the root profile tree before exit. Stdout is reserved for newline-delimited ACP JSON-RPC frames. The bundle disables model-generated session titles because ACP exposes no title surface; deterministic fallback titles remain durable without an auxiliary model request. A deployment selects a different complete composition through profile bundles and patch files, not another app bin.
The startup provider binds stdin EOF to the launcher's bounded successful shutdown. ACP connection close, SIGINT, and SIGTERM drain the bridge-owned agents and the root profile tree before exit. Stdout is reserved for newline-delimited ACP JSON-RPC frames. The bundle disables model-generated session titles because ACP exposes no title surface; deterministic fallback titles remain durable without an auxiliary model request. It also keeps the base projection cache disabled: ACP exposes no session-listing surface, and the cache's write-behind would force session-log flushes at cache-chosen times, changing the durable JSONL batching this profile's keyless transcripts pin. A deployment selects a different complete composition through profile bundles and patch files, not another app bin.
The shipped row creates sessions with `deepseek-official` and `deepseek-v4-flash`; a later patch can replace that row's complete config. The base profile owns adapters, tools, persistence, policy, settings, credentials, and the per-session workspace supplied by the ACP client.

View file

@ -4,7 +4,7 @@
以 [`dsh-base`](../base/README.zh.md) 为基础的 automation-only ACP stdio 应用 `dsh` profile 组合包。它继承 base 默认禁用模块 HMR(热模块替换)的策略;其 patch 设置 coding agent(编程智能体)persona 与默认模型路由、挂载应用自有的零选项命令提供方,并且只在该提供方接受调用后启动 [`dsh-acp`](../../acp/acp/README.zh.md)。因此,`dsh --profile acp --help` 会写出 help 并退出,不会占用 stdin 或 stdout。
启动提供方把 stdin EOF 绑定到启动器的有界成功关闭。ACP 连接关闭、SIGINT 与 SIGTERM 会在退出前排空 bridge 自有 agent 以及根 profile 树。Stdout 仅保留给换行分隔的 ACP JSON-RPC frame。ACP 不提供 title 表层,因此本组合包禁用模型生成的 session title;确定性的 fallback title 仍会持久化,但不发起辅助模型请求。部署方通过 profile 组合包与 patch 文件选择另一套完整组合,而不是使用另一个 app bin。
启动提供方把 stdin EOF 绑定到启动器的有界成功关闭。ACP 连接关闭、SIGINT 与 SIGTERM 会在退出前排空 bridge 自有 agent 以及根 profile 树。Stdout 仅保留给换行分隔的 ACP JSON-RPC frame。ACP 不提供 title 表层,因此本组合包禁用模型生成的 session title;确定性的 fallback title 仍会持久化,但不发起辅助模型请求。本组合包同样禁用 base 的投影缓存:ACP 不提供 session 列表表层,而缓存的写回会在缓存选定的时机强制 session 日志 flush,从而改变本 profile 免密钥转录所固定的持久 JSONL 批处理格式。部署方通过 profile 组合包与 patch 文件选择另一套完整组合,而不是使用另一个 app bin。
随附配置项使用 `deepseek-official` 与 `deepseek-v4-flash` 创建 session;后续 patch 可以替换该配置项的完整 config。base profile 负责适配器、工具、持久化、策略、settings 与 credentials;ACP client 为每个 session 提供工作区。

View file

@ -8,6 +8,14 @@
- id: session-title-llm
disabled: true
# The base projection cache serves session-listing columns for web surfaces.
# ACP exposes no listing surface, and the cache's write-behind would force
# session-log flushes at cache-chosen times — changing the durable JSONL
# batching this profile's keyless transcripts pin — so the automation profile
# disables the base row.
- id: session-projection-cache
disabled: true
- insert:
- id: acp-app-startup
name: '@deepseek-ai/dsh-acp-app'

View file

@ -167,6 +167,7 @@ describe('gate graph validation', () => {
const byId = new Map(complete.map(subject => [subject.id, subject]))
expect(byId.get('coverage')?.allowFailure).not.toBe(true)
expect(byId.get('coverage')?.needs).toContain('build')
expect(byId.get('coverage-exempt-heavy')?.allowFailure).not.toBe(true)
expect(byId.get('coverage-exempt-heavy')?.needs).toContain('build')
expect(byId.get('coverage-exempt-heavy')?.after).toContain('coverage')

View file

@ -471,13 +471,16 @@ function ciWindowsBlockingGates(): Gate[] {
}
function ciWindowsCompleteGates(): Gate[] {
const coverage = coverageGates().map(gate => gate.id === 'coverage-exempt-heavy'
? {
...gate,
needs: [...new Set(['build', ...(gate.needs ?? [])])],
after: [...new Set(['coverage', ...(gate.after ?? [])])],
}
: gate)
// Coverage executes suites that read built `lib/` output (the
// webworker-packer image tests), so every coverage gate waits for the
// build gate instead of racing its tsdown writes against a partial tree.
const coverage = coverageGates().map(gate => ({
...gate,
needs: [...new Set(['build', ...(gate.needs ?? [])])],
...gate.id === 'coverage-exempt-heavy'
? { after: [...new Set(['coverage', ...(gate.after ?? [])])] }
: {},
}))
const observational = ciWindowsObservationalGates()
// The required production site replaces the observational MPA build; both
// VitePress modes write the same output directory and cannot overlap.