Merge remote-tracking branch 'origin/codex/goal-session' into codex/commands

# Conflicts:
#	packages/examples/stdio-demo/README.md
#	packages/ui/tui/README.md
This commit is contained in:
Tianyi Cui
2026-07-19 22:40:13 +08:00
255 changed files with 1757 additions and 507 deletions

View File

@@ -5,10 +5,10 @@ import { defineAcpSnapshotSuite, type Scenario, type SnapshotSuiteOptions } from
/**
* The acp-agent example's snapshot suite: the scenario table for
* `dsh-acp-snapshot`'s suite factory, which owns every compare/guard mechanic
* (golden + re-persisted-log diffs, record/refresh write-back, the pinned-header
* (expected-output + re-persisted-log diffs, record/refresh write-back, the pinned-header
* uniformity guard, the fixture guards). Fixtures live under `snapshots/<name>/`;
* `pnpm run test:snapshot:record` re-records model transcripts against the real
* API; `pnpm run test:snapshot:refresh` rewrites current replay goldens keyless.
* API; `pnpm run test:snapshot:refresh` rewrites current replay expected outputs keyless.
* See the package README (packages/support/acp-snapshot) and the snapshot RFC,
* docs/rfc/implemented/testing/2026-06-19-acp-snapshot-tests.md.
*/
@@ -137,7 +137,7 @@ const SCENARIOS: Scenario[] = [
// The mid-turn seams fire during a real model turn, so each is recorded with its hook active
// (the model's reaction to a deny/block/force-continue is part of the captured transcript).
// SessionStart/SubagentStart are excluded because detached injection races log
// order; SubagentStop writes no transcript, so a golden could not prove it ran.
// order; SubagentStop writes no transcript, so an expected output could not prove it ran.
// Unit tests cover those points; the hook-snapshot-matrix RFC owns the rationale.
{ name: 'hook-cc-promptsubmit-context', hasModelTurn: true, recorded: true },
{ name: 'hook-cc-pretool-deny', hasModelTurn: true, recorded: true },

View File

@@ -13,7 +13,7 @@ import { describe, expect, it } from 'vitest'
const snapshotsDir = join(dirname(fileURLToPath(import.meta.url)), 'snapshots')
const scenarioDir = join(snapshotsDir, 'advanced-toolchain')
const sessionFixture = join(scenarioDir, 'session.jsonl')
const streamGolden = join(scenarioDir, 'stream-json.golden.jsonl')
const streamExpected = join(scenarioDir, 'stream-json.expected.jsonl')
const configPath = fileURLToPath(new URL('../advanced.cordis.snapshot.yml', import.meta.url))
const binScript = fileURLToPath(new URL('../../../packages/examples/cli-demo/src/bin.ts', import.meta.url))
const tsconfigPath = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url))
@@ -134,7 +134,7 @@ describe('headless stream-json snapshots', () => {
expect(result.stderr).toBe('')
const normalized = normalizeHeadlessStream(result.stdout, runCwd)
if (refreshing) await writeFile(streamGolden, normalized)
expect(normalized).toBe(await readFile(streamGolden, 'utf8'))
if (refreshing) await writeFile(streamExpected, normalized)
expect(normalized).toBe(await readFile(streamExpected, 'utf8'))
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
})

View File

@@ -20,4 +20,4 @@ Run `pnpm run demo:code-mode tui` for the sibling Code Mode overlay.
## Snapshot tests
`tests/snapshots/<scenario>/session.jsonl` supplies recorded user prompts and model chunks; sibling child logs drive subagents and workflows. The keyless suite executes those scripts through the real loop and tool implementations, then compares readable terminal cell/style goldens. Use `pnpm run test:snapshot:refresh` for presentation-only changes and `pnpm run test:snapshot:record` with a DeepSeek key when a recorded model journey changes. The implemented [TUI snapshot RFC](../../docs/rfc/implemented/testing/2026-07-18-tui-terminal-state-snapshots.md) owns the scenario matrix and the split between recorded journeys, transient package snapshots, and PTY coverage.
`tests/snapshots/<scenario>/session.jsonl` supplies recorded user prompts and model chunks; sibling child logs drive subagents and workflows. The keyless suite executes those scripts through the real loop and tool implementations, then compares readable expected terminal cell/style output. Use `pnpm run test:snapshot:refresh` for presentation-only changes and `pnpm run test:snapshot:record` with a DeepSeek key when a recorded model journey changes. The implemented [TUI snapshot RFC](../../docs/rfc/implemented/testing/2026-07-18-tui-terminal-state-snapshots.md) owns the scenario matrix and the split between recorded journeys, transient package snapshots, and PTY coverage.

View File

@@ -298,7 +298,7 @@ describe('TUI recorded-session terminal snapshots', () => {
it(scenario.name, async () => {
observedScenarios.add(scenario.name)
const result = await runScenario(scenario)
const terminalFile = join(scenarioDir(scenario), 'terminal.golden.txt')
const terminalFile = join(scenarioDir(scenario), 'terminal.expected.txt')
if (MODE === 'record' || MODE === 'refresh') {
await mkdir(scenarioDir(scenario), { recursive: true })
await writeFile(terminalFile, result.terminal)
@@ -319,7 +319,7 @@ afterAll(async () => {
for (const scenario of SCENARIOS) {
const expected = [
'session.jsonl',
'terminal.golden.txt',
'terminal.expected.txt',
...scenario.seedWorkspace === true ? ['workspace'] : [],
...Array.from({ length: scenario.childSessions ?? 0 }, (_, index) => `session.${index + 1}.jsonl`),
].sort()