Every release member now declares publishConfig.access: public, so the scope no
longer mixes levels: the 221 packages/*/* and apps/* manifests join the vendored
framework and the native packages.
check-workspace-constraints drops the per-sequence expectation and holds every
release member to public, which is what stops a member from drifting back.
Access is a property of the package, not of a version: the dsh packages already
published as restricted become world-readable at their next publication.
The browse and native backends were dual-face packages: a Node backend plus a
browser surface under one tsconfig that referenced Client packages. That put
Client projects — and through them the Client runtime — inside the Host
compiler aggregate, which builds before the generated Remote contributions
exist. Each browser half moves to its own Client package, and both backends
become Node-only.
The interaction is still one choice: the adaptive chooser mounts the backend
and its surface as a pair of Loader entries and tears both down in reverse, so
a resolved kind still swaps both faces. Compositions that pin an interaction
directly now pin the pair, and the chooser's runtime-string package list keeps
naming everything a composing app must resolve.
1504 hand-written ranges pointing at workspace members become workspace:^, so
pnpm pack substitutes each member's real version at publication: sibling
peerDependencies follow the family version instead of being pinned at ^0.0.1,
and a reference to a vendored package follows that package's own line. Without
this, publishing 0.0.2 ships peer ranges naming a version that does not exist,
and 0.0.1-rc.1 does not satisfy ^0.0.1 either.
It also retires ranges that had gone stale against the workspace: ^4.0.0-rc.6
for a 4.0.0-rc.7 checkout, ^3.17.0 for schemastery 3.18.0.
workspace:* stays where an exact published version is the point, which is how
the Landlock entry pins its platform packages.
A workspace constraint now requires the protocol, so a new package cannot
reintroduce a hand-written range. The same constraint caught packages/boot/cmdline
arriving on master without the publishable trio, which this change completes.
Every package under packages/, apps/, and vendor/ drops "private": true and
declares publishConfig.access "restricted": the repository now states which
packages it publishes instead of deciding it at publish time. Each one also
declares its repository and directory, which is how a consumer of a private
package reaches its source.
The Landlock packages move to restricted with them. They have never been
published, so nothing anonymous depends on them today, and the whole
@deepseek-ai scope stays private.
The workspace constraint that required every package to be private now applies
to non-members only, and asserts the publishable trio on each release member.
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it
prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`,
`verify-translation-pairing --write` for the touched bilingual pairs,
`gen-doc-graphs`, and one typert snapshot whose ids embed character offsets.
`pnpm run rescope-vendor --check` verifies the result.
Renames nine vendored packages (cordis, cosmokit, schemastery and the six
@cordisjs plugins) and every reference that resolves them: manifest names and
dependency keys, module specifiers including declare-module merges, cordis.yml
plugin names, tsconfig paths, every Markdown fence, and `docs/` prose.
Directory names, upstream versions, and dependency ranges are unchanged, so
vendor/README.md still reads as an upstream snapshot; its manifest table gains
an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed
at each fork's origin.
The tutorial tier follows the rename end to end: its yaml fences named plugins
the Loader can no longer resolve, its `ts ignore-check` fences disagreed with
the compiled fences beside them, and its prose quoted both. The contracts that
told readers to keep upstream names — the root convention and the vendoring
cookbook's tree comment and manifest invariant — now say to rescope instead.
Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle
purity gate now names the vendored libraries a browser bundle inlines, and the
files where a bare `cordis` is an agent-preset id keep that product data.
Purge the residual task/phase ordinals review caught ((T2), (queue cut 1)
×3, T6, P-I, 'this cut' ×6 including battery-expansion finds in two
untouched notes and a workflow JSDoc); drop the 'externally logged as
Decision 21' parenthetical and rename the remaining bare decision-21
mentions; mark the gui-layering IPC bridge row as a hypothetical example;
restore the GATE_NOTICE doc-typecheck clause and the py-types 'measured'
provenance; say subprocess-backed in filesystem.md; add the picker note
path. Amend the citations note: merged-PR evidence anchors in Agent Notes
are sanctioned, and the candidate gate patterns gain the four shapes the
sweep missed. All nine touched pairs re-recorded.
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
The mocked process.send consumed vitest's own fork-pool IPC messages and immediately ran the post callback, whose disconnect() severed the test worker's channel (process.connected is true under forks) — the whole spec's results vanished and win32-dialog-bindings.ts/win32-dialog-worker.ts fell to near-zero coverage on CI. The mock now records without invoking the callback or disconnecting; the real close lifecycle stays with built-worker.e2e.ts. Verified under both the threads and forks pools.
The win32 tier is exactly the koffi IFileOpenDialog child process; any failure surfaces as-is. The pwsh -> Windows PowerShell 5.1 cascade, the shared WinForms script, and the triple-miss AggregateError are deleted: koffi is a packaged dependency whose availability the install guarantees, so no mechanism fallback exists (the browse backend remains the fallback at the composition level). The pwsh-first DPI picker-fix note is consolidated into a new simplification note recording the reversal.
The koffi IFileOpenDialog conversation runs in a spawned child process instead of a worker thread: the dialog is the child's first window, so Windows activates it without a foreground call, and a native fault stays contained to the child. The driver maps the child's message protocol onto a promise and services aborts by posting WM_CLOSE to the dialog thread's windows, killing the child when the close budget is exhausted. The built worker ships as lib/worker.cjs (the ./worker export) under plain node, and win32-dialog.spec.ts returns to the thread-safe pool.
The koffi redesign moved the dialog from a spawned child process (which
inherits a foreground-activation right from the spawning app) onto a worker
thread of the same process, so Windows shows the dialog without activating
it — it opens behind the app with a taskbar flash. The app has no native
HWND to hand the seam, so raise from the driver: on the 'showing' notice
(the worker posts it right before Show, before the dialog window exists),
attach this thread's input queue to the dialog thread's, call
SetForegroundWindow on its top-level window, and detach — retried on the
close cadence until the window appears, stopped on settle/abort/success,
never blocking the pick. Injectable seam mirrors closeThreadWindows; driver
tests pin the raise and its retry; the in-process note records the
mechanism (both languages, pairing re-recorded).
The driver's switch over Win32DialogWorkerMessage handled all three current
kinds but had no default, so a fourth kind added to the worker protocol
would compile cleanly and silently no-op — settle() never called and the
pick dangles until worker exit. Add the local assertNever backstop (the
command-compact shape; this package does not depend on dsh-llm for the
helper) and the return the error case needs to avoid falling into it.
Round-five review finding.
The round-four review's v6 pass found three factual gaps and the v5 pass two
nits. Correct them before merge:
- The in-process note claimed a koffi signature mistake is 'contained to
the worker thread' — worker_threads share the process, so a native access
violation takes down the whole Node process with no PowerShell fallback.
State the real blast radius and record the deferred pkg-VFS worker-spawn
arm in Consequences (both languages, pairing re-recorded).
- The 2026-07-27 picker note claimed unconditional 'per-monitor-v2 DPI';
PMv2-less hosts (Server 2016 / Win10 1607) cascade to per-monitor or
system-aware. Say 'the best thread DPI awareness the host accepts'
(both languages, pairing re-recorded).
- built-worker.e2e.ts was not in any keyless gate (vitest.e2e config is
not part of the default unit run and builtBinSmokeGate's explicit list
missed it), so lib/worker.cjs load regressions passed keyless CI. Add it
to builtBinSmokeGate alongside the workflow-workerthread sibling.
- Remove the dead trailing 'void bindings' in win32-dialog-logic.spec.ts
and give native-picker.spec.ts the sibling module header it lacked.
The @module header still described the Windows adapter as the pre-PR 'STA
PowerShell FolderBrowserDialog' while the README and Agent Notes document
the koffi IFileOpenDialog primary with the PowerShell chain as fallback;
mirror the README's platform summary.
- setThreadDpiAwareness checks SetThreadDpiAwarenessContext's return value
and cascades per-monitor-v2 -> per-monitor -> system-aware; DPI stays a
deliberate cosmetic best-effort - a host accepting none (or lacking the
API, pre-1607) still gets the modern dialog instead of a downgrade to the
legacy fallback chain over a cosmetic concern.
- The mocked-koffi world now uses a distinctive 4-byte pointer width and
rejects mis-sized out-buffers and mis-divided vtable offsets, so a
regression to hardcoded 8s fails the suite (the ia32 bug class).
- A keyless built-worker e2e guard loads lib/worker.cjs under plain
worker_threads on POSIX (the workflow-workerthread shape).
- The 'loaded lazily' module claims are reworded to attribute laziness to
the dynamic import('koffi') calls, and the discarded close-attempt
rejection is named at its catch.
Review round two on the in-process dialog:
- Vtable slots and out-pointers use koffi.sizeof('void *') instead of a
hardcoded 8 - win32-ia32 (which Node and koffi both ship) would have read
method pointers from the wrong address and crashed in-process before any
fallback could run.
- runFolderDialog pairs every successful (incl. S_FALSE) CoInitializeEx
with CoUninitialize in the outermost finally, releasing the dialog first;
a failed init is deliberately unpaired. Pinned across fake-bindings and
mocked-koffi suites.
- The abort close budget starts unconditionally: a worker hung before the
showing notice (koffi import or COM init) now ends in terminate instead
of a dangling promise; WM_CLOSE posting still waits for the thread id.
- A triple miss (dialog + pwsh + 5.1) surfaces an AggregateError carrying
all three causes - the in-process tier's reason was previously
unrecoverable from the final PowerShell error.
- The stray '=>{ ' formatter artifacts are normalized to real blocks.
Both stale note claims from the review are fixed: the DPI note's
Consequences no longer claims an ENOENT classification or zero new
dependencies, and the 2026-07-27 picker note's Windows bullet now names
the in-process primary and keeps the PowerShell chain as fallback (both
languages, pairings re-recorded).
The workspace files constraint keys worker bundles on the ./worker export
(lib/worker.cjs, the workflow-workerthread shape); the descriptive source
entry stays win32-dialog-worker.ts and tsdown renames the bundle.
On a fast host the 1ms close budget can exhaust and reject between waitFor
ticks; a rejection with no listener yet counted as an unhandled error in the
Linux run.
The modern IFileOpenDialog becomes the primary win32 tier: a koffi-driven
COM conversation on a worker_threads worker (the modal Show never blocks
the host event loop), per-monitor-v2 DPI via SetThreadDpiAwarenessContext,
and abort service by re-posting WM_CLOSE to the dialog thread's windows,
with terminate+unref as the last resort (Node cannot interrupt a thread
blocked in native code, and such a worker must never hold the process open).
The PowerShell chain stays as the fallback tier with its trigger widened
from ENOENT to any pwsh failure, closing the review-flagged PowerShell 6
regression (no WinForms: exit 1, not ENOENT, so 5.1 never ran).
Layering keeps per-file coverage honest on every host: pure sequencing and
the driver test against fakes anywhere; the bindings run against a mocked
koffi COM world (the session-persistence-jsonl technique); POSIX hosts
drive the real spawn plumbing to its koffi-load rejection; win32 hosts run
a real open-and-abort-close smoke. The smoke joins processBoundTests: a
worker blocked in a native modal wedges the threads pool's teardown, while
a fork contains it. The worker bundles as its own CJS tsdown entry
(workflow-workerthread's pattern; no TLA), and the host module is imported
statically so the node-half bundle stays chunk-free.
Built-plane and real-COM behavior verified on native Windows: standalone
probes for the source worker, the built CJS worker, and the driver's abort
path all open and close the real dialog.
Agent Notes: new implemented/feature/2026-08-02-win32-in-process-folder-dialog
(bilingual) owns the decision; the DPI note is re-scoped to the fallback tier
it now describes and its AutoUpgradeEnabled attribution corrected (.NET Core
3.0 rewrote FolderBrowserDialog; the opt-out arrived in .NET 6).
.NET 10's modern FolderBrowserDialog renders Description as a bottom
strip above the folder input, and the 5.1 classic dialog as an unthemed
white box; the property is dropped entirely and a regression assertion
pins its absence.
README pairs document the pwsh-preferred adapter and the PowerShell 7
requirement for the modern dialog; the 2026-07-27 picker note's Windows
adapter fact is updated in place, and a new bug-fix note records the
defect, the fallback decision, and the DPI awareness rationale.
The win32 branch now spawns pwsh.exe (PowerShell 7) first and falls back
to powershell.exe (Windows PowerShell 5.1) only when pwsh is missing
(ENOENT), mirroring the Zenity-KDialog fallback. PowerShell 7 renders the
modern IFileDialog folder picker; the 5.1 fallback keeps the legacy tree
functional. Both runtimes execute the identical script, which opts the
process into system DPI awareness (SetProcessDPIAware) before any window
exists, fixing the blurry bitmap-stretched dialog on scaled displays.
The construction-rollback + late-conflict-rollback + loud-rethrow block was
about to be a verbatim clone across the two flow packages; ui-slots now owns
it as deferGroupRegistration (one occupant, several holes, as a unit), with
direct specs for all three arms, and the native flow consumes it.
Holes declared after two flow providers activated left the loser throwing
out of the slot flush with partial occupancy. deferRegistration gains an
onFailure channel (late failures unsubscribe, then hand over instead of
throwing through the flush); the native flow's pair rolls back wholesale
and re-raises on the global channel the boot's fail-loud handler owns.
Duplicate rows of the SAME package stay silently idempotent (the component
identity guard skips an occupied hole).
- Directory-flow occupancy moves onto the inject face's reserved hooks
compartment: apply publishes a stable observable per surface and the
renderer binds useDirectoryFlow — no hand-rolled component subscriptions
(the client contract's channel for registrant-private reactive facts).
- The native flow's alive guard re-arms in effect setup: StrictMode's
development replay ran the cleanup once and every later outcome was
discarded.
- NativeDirectoryFlow moves to a package-internal module; ./client exports
only the Loader surface, tests import the internal module directly.
- The composition swap comment no longer advertises -browse as a complete
swap before its dialog lands (stacked follow-up).
An HMR replacement left the old instance's pick promise able to adopt a
second path through the shared owner callbacks; settlements now check a
component-lifetime ref (an injected-face identity change alone keeps the
pending settlement — the host-side dialog is unchanged, and the wire has no
per-request abort). Both settlement arms covered (ds-review-bot).
A declared-but-occupied second hole registers synchronously, so the pair
construction can throw after the first deferral installed its subscription;
that orphan then fires against the failed fiber's inactive context. The
effect now disposes already-created deferrals before rethrowing
(ds-review-bot on the browse twin; same shape here).
A fresh injected face while the same request is open re-fires the effect;
the armed guard must not relaunch the chooser (the uncovered branch CI's
per-file gate flagged).