Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts: # apps/cli/README.md # apps/cli/src/web.ts # apps/web/tests/smoke-fixture.e2e.ts # docs/architecture.i18n.yaml # docs/module-graph.md # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl # packages/client/connection/src/client/api.ts # packages/client/connection/src/client/fixture.ts # packages/client/runtime/README.md # packages/client/runtime/src/client/index.ts # packages/client/runtime/src/client/sessions/conversation.ts # packages/client/runtime/src/client/sessions/service.ts # packages/client/runtime/src/client/sessions/session.ts # packages/client/ui-conversation/src/client/apply.ts # packages/client/ui-conversation/src/client/contract/slots.ts # packages/client/ui-conversation/src/client/index.ts # packages/client/ui-conversation/src/client/service.ts # packages/client/ui-conversation/src/client/skeleton/ConversationRoot.tsx # packages/client/ui-conversation/src/client/skeleton/EmptyState.tsx # packages/client/ui-conversation/src/client/skeleton/InputBar.tsx # packages/client/ui-conversation/src/client/stores.ts # packages/client/ui-conversation/tests/apply-inject.spec.tsx # packages/client/ui-conversation/tests/service-orchestration.spec.ts # packages/client/ui-conversation/tests/skeleton-branches.spec.tsx # packages/client/ui-conversation/tests/skeleton.spec.tsx # packages/cordis/tool-cordis/src/api-catalog.ts # packages/host/apiproxy/package.json # packages/host/apiproxy/src/api-proxy.ts # packages/host/apiproxy/src/api/sessions.schema.ts # packages/host/runtime/package.json # packages/host/runtime/src/boot.ts # packages/host/runtime/tests/host-runtime.spec.ts # packages/host/runtime/tsconfig.json # packages/host/webserver/README.md # packages/host/webserver/src/index.ts # packages/host/webserver/tests/webserver.spec.ts # packages/llm/llm-pi-ai/tests/convert.spec.ts # packages/ui/acp/src/codec.ts # packages/ui/acp/tests/codec.spec.ts # pnpm-lock.yaml
This commit is contained in:
@@ -23,7 +23,7 @@ The optional `./invariant` companion rejects a forged durable `sandbox/mode` eve
|
||||
|
||||
## The per-session store
|
||||
|
||||
A runtime switch (an ACP `session/set_config_option`, a test scenario) is one log-only `sandbox/mode` event on the session it applies to. `effective = explicit grant ?? fold(events) ?? deployment default`, so an override survives restart by replay and two sessions never see each other's state. Workspace identity does not need another event: the immutable `SessionHeader.cwd` recorded at creation is the root for every call in that session. The event is log-only (the `approval/*` precedent): the model learns the mode from the enforcing tools' denial markers, never from the event.
|
||||
A runtime switch is one log-only `sandbox/mode` event on the session it applies to. `effective = explicit grant ?? fold(events) ?? deployment default`, so an override survives restart by replay and two sessions never see each other's state. Workspace identity does not need another event: the immutable `SessionHeader.cwd` recorded at creation is the root for every call in that session. The event is log-only (the `approval/*` precedent): the model learns the mode from the enforcing tools' denial markers, never from the event.
|
||||
|
||||
## Model Experience
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Per-session sandbox-mode override: the session log as the store. A runtime
|
||||
* switch (an ACP `session/set_config_option`, a test scenario) is recorded as
|
||||
* one `sandbox/mode` event on the session it applies to;
|
||||
* switch (a UI policy control or test scenario) is recorded as one
|
||||
* `sandbox/mode` event on the session it applies to;
|
||||
* `effective = fold(events) ?? the deployment default`, so an override
|
||||
* survives restart by replay, two sessions can never see each other's state,
|
||||
* and there is no external config store. The event is log-only (the
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('SandboxPolicyService', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('resolves a symlink-sensitive session cwd with filesystem semantics', async () => {
|
||||
it.skipIf(process.platform === 'win32')('resolves a symlink-sensitive session cwd with POSIX component semantics', async () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'dsh-policy-cwd-'))
|
||||
try {
|
||||
const lexical = join(root, 'lexical')
|
||||
@@ -78,7 +78,7 @@ describe('SandboxPolicyService', () => {
|
||||
mkdirSync(lexical)
|
||||
mkdirSync(child, { recursive: true })
|
||||
const link = join(lexical, 'link')
|
||||
symlinkSync(child, link, process.platform === 'win32' ? 'junction' : 'dir')
|
||||
symlinkSync(child, link, 'dir')
|
||||
const cwd = `${link}${sep}..`
|
||||
const ctx = await mounted({ mode: 'workspace-write', workspaceRoot: '/fallback' })
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { canonicalPath, writableRoots } from '@deepseek-ai/dsh-sandbox'
|
||||
describe('canonicalPath', () => {
|
||||
it('resolves symlinks (an existing path realpaths)', () => {
|
||||
const dir = mkdtempSync(join(tmpdir(), 'dsh-roots-'))
|
||||
expect(canonicalPath(dir)).toBe(realpathSync(dir))
|
||||
expect(canonicalPath(dir)).toBe(realpathSync.native(dir))
|
||||
})
|
||||
|
||||
it('returns the spelling as-is when the path cannot be resolved (conservative — matches nothing until it exists)', () => {
|
||||
@@ -30,9 +30,9 @@ describe('writableRoots', () => {
|
||||
it('workspace-write grants the workspace root plus the platform temp areas, canonical and deduplicated', () => {
|
||||
const ws = mkdtempSync(join(tmpdir(), 'dsh-ws-'))
|
||||
const roots = writableRoots({ mode: 'workspace-write', workspaceRoot: ws })
|
||||
expect(roots).toContain(realpathSync(ws))
|
||||
expect(roots).toContain(realpathSync.native(ws))
|
||||
expect(roots).toContain(canonicalPath('/tmp'))
|
||||
expect(roots).toContain(realpathSync(tmpdir()))
|
||||
expect(roots).toContain(realpathSync.native(tmpdir()))
|
||||
// Deduplicated after canonicalization (/tmp and os.tmpdir() may coincide).
|
||||
expect(new Set(roots).size).toBe(roots.length)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user