The analyzer normalizes its root with fs.realpathSync, which keeps a
Windows 8.3 short name such as RUNNER~1 in the runner's TEMP, while
TypeScript reports module-resolution results through
fs.realpathSync.native, which expands it. The guard compared the two
spellings, found the resolved lib/ declaration outside the workspace,
and let a missing alias through on Windows. It now canonicalizes the
root and every file with realpathSync.native and reports paths spelled
under the caller's root; the guard specs also run with the workspace
root spelled through a directory link.
Refs #5852
rejectBuildOutputs caught a missing paths alias only when the package's
lib/types already existed. On a tree whose packages are not yet compiled,
as when host-typert runs beside host-src on a clean checkout, the import
resolved to nothing and checkDiagnostics: false hid it. The guard now also
fails when a face program cannot resolve an import of a workspace package,
found through its node_modules link, and names the paths entry derived
from the package's exports types condition.
Refs #5852
Type checks only need Host declarations and Typert-generated
declarations, but typecheck, lint, lint:fix, doc-typecheck, and the CI
typert-contracts gate rebuilt the whole Host tsdown pass, Desktop bundle
included, to obtain them. A source-only scripts/generate-typert.ts now
runs the same generator and artifact writer as the tsdown plugin, beside
Host package compilation: Typert reads only sources once the missing
@deepseek-ai/dsh-client-file-upload/types path alias exists, and
rejectBuildOutputs fails the pass when a workspace lib/ declaration
enters its program. typecheck runs as a build.ts scope that checks both
aggregates in build mode after their own face compiles.
Refs #5852