Merge branch 'feat/windows-pwsh-default' into feat/windows-acl-sandbox

# Conflicts:
#	packages/bash/pwsh-local/src/index.ts
#	packages/sandbox/sandbox-local/src/index.ts
This commit is contained in:
Huanqi Cao
2026-08-09 17:50:55 +08:00
1197 changed files with 3013 additions and 2907 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 apps/cli/reference/README.md
README.md: 4f8aa86c0f6cdb91eb843048cd5ed4943a896c73
README.zh.md: 09bc19220a869bedfcaa98baccbf6d4f6a3f3223
README.md: bb3e1d77f00e03f6a21f4da3c04994f208e84293
README.zh.md: 3802f940ef6663ec215cf09293a9edda5ea4c512

View File

@@ -21,7 +21,7 @@ dsh --profile web --dump-default-config
dsh --profile web --patch ./extra.yml --dump-config
```
`--dump-default-config` prints only the bundle layers; `--dump-config` adds the profile's `cordis.patch.yml`, the home-level `$DSH_HOME/cordis.patch.yml`, and `--patch` overlays. Both print provenance comments per layer; `!!js` expressions remain unevaluated, and unmatched patch targets are reported on stderr.
`--dump-default-config` prints only the bundle layers; `--dump-config` adds the profile's `cordis.patch.yml`, the home-level `$DSH_HOME/cordis.patch.yml`, and `--patch` overlays. Both print comments naming the file that supplied each row and every overlay that changed it; `!!js` expressions remain unevaluated, and unmatched patch targets are reported on stderr.
## One-shot run

View File

@@ -21,7 +21,7 @@ dsh --profile web --dump-default-config
dsh --profile web --patch ./extra.yml --dump-config
```
`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml``--patch` overlay。两者都会按层打印来源注释`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。
`--dump-default-config` 只打印组合包各层;`--dump-config` 额外加上 profile 的 `cordis.patch.yml`、home 级的 `$DSH_HOME/cordis.patch.yml``--patch` overlay。两者都会打印注释,标明每行由哪个文件提供,以及哪些 overlay 修改过它`!!js` 表达式保持未求值,找不到目标的 patch 会报告到 stderr。
## 一次性运行

View File

@@ -1,7 +1,7 @@
/**
* Config-dump entry for `dsh --profile <name> --dump-config`: compose the
* profile's patch layers through the include plugin's patch algorithm without
* booting or evaluating `!!js`, with one provenance layer per bundle, the
* booting or evaluating `!!js`, with one source layer per bundle, the
* profile's own patch file, and each `--patch` overlay.
* @module @deepseek-ai/dsh/dump-config
*/
@@ -21,7 +21,7 @@ const NAME = 'dsh'
/* v8 ignore start -- built-bin acceptance drives this boot-free dispatch */
/**
* Print a profile composition with provenance comments.
* Print a profile composition with comments naming each source file and patch layer.
* @param profile - the profile name.
* @param defaultOnly - omit the profile's user layer and `--patch` overlays
* (the recovery diagnostic for a broken `cordis.patch.yml`, which is then

View File

@@ -518,7 +518,7 @@ describe.skipIf(!existsSync(dshBin))('dsh BUILT bin (node lib/bin.js, no tsx)',
expect(code).toBe(0)
expect(stdout).toContain('provider: configured-provider')
expect(stdout).not.toContain('personal-provider')
// Both layers patched the row; provenance lists them in application order.
// Both layers patched the row; the comment lists them in application order.
expect(stdout).toContain(`patched by ${profilePatch}, ${overlay}`)
expect(stderr).toContain('patch: entry "absent-row" not found')
}, 30_000)

View File

@@ -89,7 +89,7 @@ describe('web e2e: approval takeover keeps its actions reachable', () => {
await input.fill('')
// Read-only: the mode whose denial the model escalates from. Switched
// through the shipped access-mode chip, not a test-only seam.
// through the shipped access-mode chip, not a test-only override.
await page.locator('[aria-label^="Access mode"]').click()
await page.getByRole('menuitem', { name: 'Read Only' }).click()
await expect.poll(

View File

@@ -4,7 +4,7 @@
// a route keeps deriving from its own log — the tier order the gateway
// resolves on every read.
// Zero model calls: the switch is settings/llm-domain traffic only, so there
// is no fixture and a stray stream would fail loud on the open seam. Both
// is no fixture and a stray stream would fail loud because the adapter registry is empty. Both
// routes are declared host-side (not through the UI, which has its own
// scenario) through the pi-ai adapter the shipped tree already mounts: a
// fixture-less scaffold registers no adapter at all, so the routes the

View File

@@ -232,7 +232,7 @@ describe('web e2e: lifecycle & chrome (workspace flow / reload / dark mode)', ()
it.skipIf(MODE === 'record')('cascades the dark theme from the body attribute to painted surfaces', async () => {
onTestFailed(() => saveFailureShot(page, 'web-e2e-lifecycle-dark'))
// This scenario pins the ThemeService's DOM contract seam directly (the
// This scenario pins the ThemeService's DOM contract directly (the
// body[data-ds-dark-theme] attribute -> stylesheet cascade); the REAL
// user gesture above it (Settings -> Appearance cubes) is owned by
// settings-chrome.e2e.ts. Driving the attribute here keeps the cascade

View File

@@ -1,6 +1,6 @@
// Web e2e scenarios: live-turn interactions — cancellation, error surfacing,
// and transient-retry recovery, all through the real composition and wire.
// The model seam is dsh-llm-replay with override sidecars: `hang` (+ a
// The model adapter is dsh-llm-replay with override sidecars: `hang` (+ a
// readyFile marker) makes mid-stream cancel deterministic by construction,
// `throw` entries express provider failures by stable code, and `{ patches }`
// augmentation injects a transient throw before the recorded success so

View File

@@ -7,7 +7,7 @@
// provider status. The customized-settings fold writes the curated
// reasoning field as a merge patch. Zero model calls: configuration is pure
// settings/credentials/llm-domain traffic, so there is no fixture and a
// stray stream would fail loud on the open seam. The provider under test is
// stray stream would fail loud because the adapter registry is empty. The provider under test is
// minimax-cn so a developer's real ANTHROPIC/OPENAI environment keys can
// never shadow the derived reference. The deletion dialog distinguishes a
// reference-free profile from a page-managed key before the credential and

View File

@@ -1,6 +1,6 @@
// Web e2e scenario: fresh round trip. A real chromium types a prompt into the
// real composer; the wire, apiproxy, agent loop, and the REAL bash tool (echo
// in the temp workspace) all run; the model seam is dsh-llm-replay (keyless)
// in the temp workspace) all run; the model adapter is dsh-llm-replay (keyless)
// or the live adapter (record). Drive steps run in every mode and wait only
// on generic completion (whenTurnSettled — never model-content selectors, so
// record cannot hang on a live model answering differently); assertion steps

View File

@@ -151,7 +151,7 @@ export interface WebScaffold {
mode: WebSnapshotMode
/** Browser-facing origin for the bound test server. */
baseUrl: string
/** Settled root context (the in-process barrier seam; headless event subscription is its sanctioned use). */
/** Settled root context (the in-process readiness barrier; headless event subscription is its sanctioned use). */
ctx: Context
/** Temp project directory sessions run in (bash/fs tool cwd). */
workspaceCwd: string

View File

@@ -83,7 +83,7 @@ function withCompaction(raw: string, meter: TokenMeterService): string {
/**
* Append one event at the next seq/time.
* @param event - the event body, without seq/time.
* @returns the seq it took, so provenance cites the push instead of arithmetic over the push order below.
* @returns the assigned seq, so later `sourceEventSeqs` cite the pushed event directly.
*/
const at = (event: Record<string, unknown>): number => {
const taken = seq++

View File

@@ -27,7 +27,7 @@ const MODE = webSnapshotMode()
const HOLD_PROVIDER = 'web-test-hold'
const HOLD_MODEL = 'hold'
/** Model seam that completes the owner turn, then holds its delegated child open. */
/** Model stub that completes the owner turn, then holds its delegated child open. */
class StagedAdapter extends LlmAdapter {
activeCalls = 0
private calls = 0

View File

@@ -2,7 +2,7 @@
// the composer (issue #1470). The entered `/name args` line claims into
// skill.invoke: the real host forwards the gesture as an ordinary user
// prompt, injects the rendered body as instructions context named after the
// skill, and starts a turn answered by the replay seam. The transcript shows
// skill, and starts a turn answered by the replay adapter. The transcript shows
// the gesture bubble, the collapsed context-injection row, and the reply.
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
@@ -133,7 +133,7 @@ describe.skipIf(MODE === 'record')('web e2e: user-explicit skill invocation thro
expect(injected).not.toContain(ARGS_TEXT)
await injectionRow.click()
// The injection started a turn; the replay seam answers it.
// The injection started a turn; the replay adapter answers it.
await page.getByText('USER_INVOKE_REPLY', { exact: false }).first().waitFor({ timeout: 20_000 })
const snapshot = await captureStableAria(page, '[class*="centerCol"]', scaffold.workspaceCwd)