Merge remote-tracking branch 'origin/master' into stack/agent-profiles-1-seam

# Conflicts:
#	docs/capability-seams.md
#	docs/event-producer-consumer.md
#	packages/README.i18n.yaml
#	packages/ui/app-boot/README.i18n.yaml
#	packages/ui/app-boot/src/index.ts
#	scripts/doc-budgets.manifest.json
This commit is contained in:
Yichen Jiang
2026-08-08 14:00:34 +08:00
648 changed files with 21036 additions and 2796 deletions

View File

@@ -7,7 +7,7 @@ import SystemPrompt, { renderPrompt } from '@deepseek-ai/dsh-system-prompt'
import {
addHarnessSourceSection, assertEntriesActivated, assertEntriesLoaded, boot,
FAIL_LOUD_RELEASE_TIMEOUT_MS, HARNESS_SOURCE_SECTION,
installFailLoud, loadEnv, loadOverlayPatches, resolveConfigPath, type FailLoudProcess,
installFailLoud, loadEnv, loadLayeredEnv, loadOverlayPatches, resolveConfigPath, type FailLoudProcess,
} from '../src/index.ts'
const NAME = 'dsh-test-bin'
@@ -86,6 +86,190 @@ describe('loadEnv', () => {
})
})
describe('loadLayeredEnv', () => {
const NAMES = ['APP_BOOT_LAYERED_SHARED', 'APP_BOOT_LAYERED_USER', 'APP_BOOT_LAYERED_PROJECT'] as const
function clear(): void {
for (const name of NAMES) Reflect.deleteProperty(process.env, name)
}
it('layers user under project under the inherited environment', () => {
const home = tmp()
const project = tmp()
writeFileSync(join(home, '.env'), [
`${NAMES[0]}=user`,
`${NAMES[1]}=user-only`,
'APP_BOOT_LAYERED_INHERITED=user-loses',
'',
].join('\n'))
writeFileSync(join(project, '.env'), [
`${NAMES[0]}=project`,
`${NAMES[2]}=project-only`,
'APP_BOOT_LAYERED_INHERITED=project-loses',
'',
].join('\n'))
clear()
vi.stubEnv('DSH_HOME', home)
vi.stubEnv('APP_BOOT_LAYERED_INHERITED', 'inherited')
const warn = vi.fn()
try {
loadLayeredEnv(NAME, project, warn)
expect(process.env[NAMES[0]]).toBe('project')
expect(process.env[NAMES[1]]).toBe('user-only')
expect(process.env[NAMES[2]]).toBe('project-only')
expect(process.env['APP_BOOT_LAYERED_INHERITED']).toBe('inherited')
expect(warn).not.toHaveBeenCalled()
} finally {
clear()
vi.unstubAllEnvs()
}
})
it.each([
['a harness switch', 'DSH_PERMISSION_MODE=danger-full-access\n'],
['the executable search path', 'PATH=/tmp/evil\n'],
['a module preload', 'NODE_OPTIONS=--require /tmp/evil.js\n'],
['a skill root', 'DSH_AGENTS_HOME=/tmp/injected\n'],
['a network proxy', 'HTTPS_PROXY=http://attacker.example\n'],
['a lowercase network proxy', 'https_proxy=http://attacker.example\n'],
])('refuses to launch when a .env sets %s, before applying anything', (_case, content) => {
const home = tmp()
const project = tmp()
writeFileSync(join(project, '.env'), `${NAMES[1]}=applied-anyway\n${content}`)
clear()
vi.stubEnv('DSH_HOME', home)
try {
expect(() => loadLayeredEnv(NAME, project, vi.fn())).toThrow(/only the launching environment may set/)
expect(process.env[NAMES[1]]).toBeUndefined()
} finally {
clear()
vi.unstubAllEnvs()
}
})
it('reports each file value with its absolute path', () => {
const home = tmp()
const project = tmp()
writeFileSync(join(home, '.env'), `${NAMES[1]}=u\n`)
writeFileSync(join(project, '.env'), `${NAMES[2]}=p\n`)
clear()
vi.stubEnv('DSH_HOME', home)
try {
const snapshot = loadLayeredEnv(NAME, project, vi.fn())
expect(snapshot.get(NAMES[1])).toEqual({ value: 'u', source: 'user-env', path: join(home, '.env') })
expect(snapshot.get(NAMES[2])).toEqual({ value: 'p', source: 'project-env', path: join(project, '.env') })
expect(snapshot.getFrom(NAMES[2], ['process', 'user-env'])).toBeUndefined()
} finally {
clear()
vi.unstubAllEnvs()
}
})
it('resolves the harness home from the inherited environment, never from a file', () => {
const home = tmp()
const project = tmp()
writeFileSync(join(home, '.env'), `${NAMES[1]}=real-home\n`)
writeFileSync(join(project, '.env'), `${NAMES[2]}=set-by-project\n`)
clear()
vi.stubEnv('DSH_HOME', home)
try {
loadLayeredEnv(NAME, project, vi.fn())
expect(process.env[NAMES[1]]).toBe('real-home')
expect(process.env[NAMES[2]]).toBe('set-by-project')
} finally {
clear()
vi.unstubAllEnvs()
}
})
it('warns and continues when a layer exists but cannot be read', () => {
const home = tmp()
const project = tmp()
// A directory named `.env` is a present-but-unreadable layer.
mkdirSync(join(home, '.env'))
writeFileSync(join(project, '.env'), `${NAMES[2]}=project-only\n`)
clear()
vi.stubEnv('DSH_HOME', home)
const warn = vi.fn()
try {
const snapshot = loadLayeredEnv(NAME, project, warn)
expect(warn).toHaveBeenCalledWith(expect.stringContaining(`${NAME}: failed to load .env`))
expect(snapshot.get(NAMES[1])).toBeUndefined()
expect(snapshot.get(NAMES[2])).toEqual({ value: 'project-only', source: 'project-env', path: join(project, '.env') })
expect(process.env[NAMES[2]]).toBe('project-only')
} finally {
clear()
vi.unstubAllEnvs()
}
})
it('reports to stderr when the caller supplies no reporter', () => {
const home = tmp()
const project = tmp()
mkdirSync(join(home, '.env'))
writeFileSync(join(project, '.env'), `${NAMES[2]}=project-only\n`)
clear()
vi.stubEnv('DSH_HOME', home)
const write = vi.spyOn(process.stderr, 'write').mockReturnValue(true)
try {
const snapshot = loadLayeredEnv(NAME, project)
expect(write).toHaveBeenCalledWith(expect.stringContaining(`${NAME}: failed to load .env`))
expect(snapshot.get(NAMES[2])).toEqual({ value: 'project-only', source: 'project-env', path: join(project, '.env') })
expect(process.env[NAMES[2]]).toBe('project-only')
} finally {
write.mockRestore()
clear()
vi.unstubAllEnvs()
}
})
it('passes over an absent layer without reporting it', () => {
const home = tmp()
const project = tmp()
writeFileSync(join(project, '.env'), `${NAMES[2]}=project-only\n`)
clear()
vi.stubEnv('DSH_HOME', home)
const warn = vi.fn()
try {
const snapshot = loadLayeredEnv(NAME, project, warn)
expect(warn).not.toHaveBeenCalled()
expect(snapshot.get(NAMES[2])).toEqual({ value: 'project-only', source: 'project-env', path: join(project, '.env') })
} finally {
clear()
vi.unstubAllEnvs()
}
})
it('carries only the inherited environment when neither file exists', () => {
const home = tmp()
const project = tmp()
clear()
vi.stubEnv('DSH_HOME', home)
vi.stubEnv('APP_BOOT_LAYERED_INHERITED', 'inherited')
try {
const snapshot = loadLayeredEnv(NAME, project, vi.fn())
expect(snapshot.get('APP_BOOT_LAYERED_INHERITED')).toEqual({ value: 'inherited', source: 'process' })
} finally {
clear()
vi.unstubAllEnvs()
}
})
it('reads a harness home that is also the invocation directory exactly once', () => {
const both = tmp()
writeFileSync(join(both, '.env'), `${NAMES[2]}=one-file\n`)
clear()
vi.stubEnv('DSH_HOME', both)
try {
const snapshot = loadLayeredEnv(NAME, both, vi.fn())
expect(snapshot.get(NAMES[2])).toEqual({ value: 'one-file', source: 'project-env', path: join(both, '.env') })
} finally {
clear()
vi.unstubAllEnvs()
}
})
})
describe('installFailLoud', () => {
function fakeProc(): FailLoudProcess & { handlers: Array<(err: unknown) => void>; written: string[]; exits: number[] } {
const handlers: Array<(err: unknown) => void> = []

View File

@@ -49,17 +49,17 @@ describe('renderConfigDump', () => {
' name: ./noop.mjs',
'',
].join('\n'))
const personal = join(dir, 'personal.yml')
writeFileSync(personal, [
const user = join(dir, 'user.yml')
writeFileSync(user, [
'- id: surface-extra',
' config:',
' value: personal',
' value: user',
'',
].join('\n'))
const dump = renderConfigDump(NAME, base, [
{ label: 'surface.yml', patches: loadOverlayPatches(NAME, surface) },
{ label: 'personal.yml', patches: loadOverlayPatches(NAME, personal) },
{ label: 'user.yml', patches: loadOverlayPatches(NAME, user) },
], () => {})
// Comments do not break loadability: the dump parses as one document
// equal to what boot() would mount.
@@ -74,7 +74,7 @@ describe('renderConfigDump', () => {
config: { value: 'surface', key: { __jsExpr: 'process.env.DSH_DUMP_SPEC' } },
},
{ id: 'untouched', name: './noop.mjs' },
{ id: 'surface-extra', name: './noop.mjs', config: { value: 'personal' } },
{ id: 'surface-extra', name: './noop.mjs', config: { value: 'user' } },
])
// Unevaluated: the expression text round-trips as a !!js scalar.
expect(dump).toContain('!!js process.env.DSH_DUMP_SPEC')
@@ -82,7 +82,7 @@ describe('renderConfigDump', () => {
// row; an inserted row carries the inserting layer as its origin.
expect(dump).toContain('# == base.yml, patched by surface.yml')
expect(dump).toContain('# == base.yml\n- id: untouched')
expect(dump).toContain('# == surface.yml, patched by personal.yml\n- id: surface-extra')
expect(dump).toContain('# == surface.yml, patched by user.yml\n- id: surface-extra')
expect(dump.indexOf('# == base.yml, patched by surface.yml')).toBeLessThan(dump.indexOf('# == base.yml\n- id: untouched'))
})