Merge remote-tracking branch 'origin/master' into xtr/react-loop-simplification
# Conflicts: # .agents/notes/implemented/architecture/2026-07-19-package-owned-invariant-service.i18n.yaml # examples/acp-agent/tests/snapshots/fs-glob-sampling/session.jsonl # packages/ui/tui/README.i18n.yaml # packages/ui/tui/src/components/dialogs.ts # packages/ui/tui/tests/tui.spec.ts
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { mkdir, writeFile } from 'node:fs/promises'
|
||||
import { mkdir, utimes, writeFile } from 'node:fs/promises'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { homedir } from 'node:os'
|
||||
import { expect, it } from 'vitest'
|
||||
@@ -47,7 +47,6 @@ const SUBAGENT_DURABILITY_FAILURE_CONFIG = fileURLToPath(
|
||||
const LSP_CONFIG = fileURLToPath(new URL('./lsp.cordis.yml', import.meta.url))
|
||||
const WEB_CONFIG = fileURLToPath(new URL('../web.cordis.yml', import.meta.url))
|
||||
const FS_SEARCH_CONFIG = fileURLToPath(new URL('./fs-search.cordis.yml', import.meta.url))
|
||||
const FS_SEARCH_BIN = fileURLToPath(new URL('./fixtures/fs-search-bin', import.meta.url))
|
||||
const SNAPSHOTS_DIR = join(dirname(fileURLToPath(import.meta.url)), 'snapshots')
|
||||
const PACKED_CHUNKS_SOURCE = 'hook-cc-pretool-deny'
|
||||
|
||||
@@ -60,6 +59,33 @@ async function prepareDelimiterPathWorkspace(cwd: string): Promise<void> {
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed the over-cap glob fixture: eight files under `tree/` with fixed mtimes,
|
||||
* so the packaged ripgrep's `--sort=modified` order is deterministic — three
|
||||
* files under `archive/`, one each under `docs/`, `src/`, and `test/`, plus
|
||||
* two flat files (six top-level entries). Scoping the search to `tree/` keeps
|
||||
* the harness's own session artifacts out of the listing.
|
||||
*/
|
||||
async function prepareFsSearchWorkspace(cwd: string): Promise<void> {
|
||||
const tree = join(cwd, 'tree')
|
||||
const files: Array<[relative: string, mtime: Date]> = [
|
||||
[join('archive', 'a.ts'), new Date(2000, 0, 1, 0, 0, 0, 1)],
|
||||
[join('archive', 'b.ts'), new Date(2000, 0, 1, 0, 0, 0, 2)],
|
||||
[join('archive', 'c.ts'), new Date(2000, 0, 1, 0, 0, 0, 3)],
|
||||
[join('docs', 'guide.md'), new Date(2000, 0, 1, 0, 0, 0, 4)],
|
||||
[join('src', 'index.ts'), new Date(2000, 0, 1, 0, 0, 0, 5)],
|
||||
[join('test', 'spec.ts'), new Date(2000, 0, 1, 0, 0, 0, 6)],
|
||||
['top.txt', new Date(2000, 0, 1, 0, 0, 0, 7)],
|
||||
['notes.md', new Date(2000, 0, 1, 0, 0, 0, 8)],
|
||||
]
|
||||
for (const [relative, mtime] of files) {
|
||||
const target = join(tree, relative)
|
||||
await mkdir(dirname(target), { recursive: true })
|
||||
await writeFile(target, 'fixture\n')
|
||||
await utimes(target, mtime, mtime)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Migrate backend-oriented scenarios to the headless stream-json suite;
|
||||
// this ACP suite should eventually retain only automation-protocol contracts.
|
||||
|
||||
@@ -153,18 +179,28 @@ const SCENARIOS: Scenario[] = [
|
||||
hasModelTurn: true,
|
||||
recorded: true,
|
||||
},
|
||||
// The real Loader/app/bash path executes a deterministic rg stand-in at the
|
||||
// external-process seam, pinning over-cap glob sampling without depending on
|
||||
// a host-installed ripgrep binary.
|
||||
// The real Loader/app/subprocess path executes the PACKAGED ripgrep binary
|
||||
// against a prepared workspace whose fixed mtimes pin the
|
||||
// `--sort=modified` order, pinning over-cap glob sampling without depending
|
||||
// on a host-installed ripgrep binary or a PATH stand-in. POSIX-only because
|
||||
// the displayed paths carry `/` separators the session-log comparison
|
||||
// cannot normalize. Recorded (not authored): the assistant turn is a real
|
||||
// model transcript; re-record with `test:snapshot:record -t fs-glob-sampling`
|
||||
// and then `migrate:packed-session-fixtures`, which canonicalizes the live
|
||||
// log's eager-drain-packed rows into the maximal-run layout replay produces.
|
||||
// The recorded fixture's `request/header` config and `request/context` are
|
||||
// normalized to the replay-produced minimal shape (the live adapter logs
|
||||
// model capabilities like maxTokens/reasoningEffort that llm-replay has no
|
||||
// data for), and its tool-result paths are canonicalized to `/` separators.
|
||||
{
|
||||
name: 'fs-glob-sampling',
|
||||
hasModelTurn: true,
|
||||
recorded: false,
|
||||
recorded: true,
|
||||
posixOnly: true,
|
||||
pinsHeader: true,
|
||||
headerClass: 'fs-search',
|
||||
configPath: FS_SEARCH_CONFIG,
|
||||
env: { PATH: `${FS_SEARCH_BIN}:${process.env.PATH ?? ''}` },
|
||||
posixOnly: true,
|
||||
prepareWorkspace: prepareFsSearchWorkspace,
|
||||
},
|
||||
{ name: 'fs-read', hasModelTurn: true, recorded: true },
|
||||
{ name: 'fs-write', hasModelTurn: true, recorded: true },
|
||||
|
||||
Reference in New Issue
Block a user