Root tsconfig.json becomes a pure solution (files:[] + two references);
the former root host aggregate moves verbatim to tsconfig.host.json.
New tsconfig.base.client.json carries the shared client compiler shape
(jsx/DOM lib/types:[]), and tsconfig.client.json plus the 12
packages/client tsconfigs extend it instead of restating the trio.
tsconfig.build.json is deleted: the solution covers the full emit graph,
absorbing the command-goal typecheck/build drift.
Consumers migrate to the single graph: typecheck/build scripts and the
lefthook pre-push hook run bare `tsc -b` (pre-push now covers the client
side); the run-gates build gate needs typecheck so two concurrent tsc -b
runs cannot race the same tsbuildinfo; ts-project.ts and the standalone
doc-typecheck mode seed tsconfig.host.json explicitly (never the root
solution — flattening host+client into one program collides the cordis
Context merges); verify-cordis-config BFS seeds the root solution alone.
Per missions/tsconfig-single-graph-migration.md §2–§3.
ctx.sandbox (dsh-sandbox): confine(argv, policy) returns the argv to spawn
instead — wrapped so the process and its children run confined — plus the
enforcement completeness and the backend denial/runner-failure dialects;
no usable backend throws the fail-closed SANDBOX_UNAVAILABLE. Policy rides
per call. dsh-sandbox-local selects by platform and caches the verdict:
multi-candidate chains probe FUNCTIONALLY in preference order (Linux:
bwrap → the registry-installed node-addon-landlock-run launcher), a sole
candidate is selected unprobed (darwin: sandbox-exec/Seatbelt) and fails
closed at execution via runnerFailureSignatures; win32 is a reserved empty
chain. Profile parity is honest per backend (documented temp-area and ABI
differences; enforcement full|partial is a structured result fact).
CI: the sandbox-e2e matrix proves real-kernel confinement per rung (bwrap,
Landlock per architecture through the registry-installed launcher,
Seatbelt), failing on a silent all-skip; the packed-install rehearsal
installs the launcher family from the registry and asserts the binary
executable apart from kernel enforcement.
Move the 18 flat packages/<name> packages into role-grouped dirs:
core/, llm/, bash/, session-persistence/, ui/, support/. Group dirs are
pure containers; each package keeps its @deepseek-ai/dsh-* name.
Collapse the per-package tsconfig paths maps (base + typecheck) into one
@deepseek-ai/dsh-* wildcard with a candidate per group, and derive the
publint list from the hierarchy. Update all depth-coupled globs/configs
(workspace, tsdown, vitest, eslint, knip, tsconfig includes/refs,
per-package tsconfigs, generators, doc-script scopes, type-equiv manifest)
and the cross-package/script relative imports in tests.
Fix doc-typecheck's workspacePaths() to parse tsconfig JSONC via the
TypeScript API instead of a regex comment-strip, which corrupted the
new wildcard `/*/` path candidates.
WIP: doc cross-links and package/RFC docs still to update.