A test file under packages/client now says which face it covers:
`*.client.spec.{ts,tsx}` and its `*.client.{ts,tsx}` helpers belong to the
Client aggregate, `*.host.spec.ts` to the host aggregate. The carrier's four
node-half specs take the Host suffix.
The two suffixes are mutually exclusive, so each aggregate excludes the
other's and both keep one broad test glob: `exclude` wins over `include`, and
`packages/client/**` no longer has to be excluded wholesale from the host
program with per-file `files` entries carved back out of it. A Host-face spec
that reaches only Host source therefore needs no cross-face project
reference, which the split-project rule rejects.
vitest still discovers every file through `**/*.spec.{ts,tsx}`.
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.
Close the per-file coverage gaps the new UI behavior introduced: MenuView
pointer-outside dismiss (all guard branches), the GoalBar pause action,
the ui-slash injected onDismiss face, and the non-kebab permission name
passthrough.
Unify the /plan claimed hint with the plan placeholder through a locale
namespace, localize slash menu group titles, replace the PermissionSelect
native select with the Menu primitive, add a goal pause verb chain, clamp
anchored popups to the viewport with scroll-into-view and outside-dismiss,
and fix onPasteUpgrade insertedRange to account for the chip trailing gap.
The keyless fixture now carries the goal chain end to end, mirroring the
host: /goal enters the command catalog and its execute path brackets a
goal/change create with the command lifecycle pair; the six mutation verbs
CAS-check the projected current goal and append whole-value changes (the
shared append path broadcasts the session event and the goal projection
frame); the tail-page projections block and the mux-open baseline always
carry the goal key (null before create / after clear). Connection specs
follow: the lifecycle round-trip replaces the not-implemented stubs, and
the mux baseline expects the third unit frame.
Also: GoalBar inline errors use ASCII parens around the code (review
feedback on #842).
The runtime's new outward session contract exposes projections as a
ProjectionsFace (faceOf only); the ui-goal verb closure reads the current
value through faceOf('goal').getSnapshot() instead of the store-level get.
Catalogs regenerated after the merge.
- projection.spec covers applyGoalProjection's non-message early return and
the foreign-change-kind arm directly (the pure-function posture the unit
requires — a throwing apply would tear down the registry drive).
- New ui-goal browser-plugin spec exercises the plugin body over a real
cordis Context with fake faces: dock registration (id/order), verbs
reading the CAS ref from the current projected value, the
no-current-goal short circuit, RPC-error mapping, HMR disposal, the
GoalDock adapter's three projection states, and the inert node half.
New client plugin package. The GoalBar component migrates verbatim from the
original PR (phase labels, inline edit form, resume-when-paused, pending
lockout, inline errors); its data path is rebuilt for the projection model:
- GoalDock adapter reads useProjection('goal') from the standard kit — no
controller, no store, no refresh chain, no event listener (the original
PR's Session goal fields, write-revision fence, and coalesced refetch all
dissolve into the value store's seq rule).
- The inject face carries only the three mutation verbs; each reads the CAS
ref from the session's current projected value at call time and maps the
settled RPC result inline (callbacks from inject, live state from
useProjection).
- Seats at conversation.input.dock order 1 (the slot contract names GoalBar
as a resident of this strip), below TodoPanel/QueueDock, tucked against
the composer; hero phase renders nothing for free.
- IconSparkle16 is package-local (sole consumer) — ui-primitives keeps only
the shared action icons.
- goalbar.spec migrates with GoalSnapshot props (activation is process-local
and absent from the projection; the strip renders durable phase only).