refactor: replace overloaded surface terminology

This commit is contained in:
Turtle
2026-07-24 19:54:25 +08:00
parent c172faed37
commit 0c708cb10d
626 changed files with 1396 additions and 1397 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/client/ui-layout/README.md
README.md: fa60520a20ac8a7f25d494879c68efb06a28998f
README.md: c58b9a26ac794131aaa197722d14bd04de9f0cae
README.zh.md: 2ce3d1972d39013d84216596dc57d48ab2d245d9

View File

@@ -6,7 +6,7 @@ Shell plugin: three-column AppFrame (drag handles and concession chain) plus the
AppFrame always mounts the conversation and details columns; a connected Session renders through `SessionProvider`. The transient layout store starts the sidebar at its default width and details closed, and it never reads or writes `localStorage`. Hero and other unselected states also derive a zero rendered details width without changing that stored preference. AppFrame retains the last non-blank Session id across those states: the first Session remains closed, an explicit details action opens the contract default width, returning to the same Session restores its unchanged width, and selecting a different Session closes details before paint. The conversation owner share is empty, while the sidebar owner share contains only `collapsed` and `width`; registrants obtain business data from standard hooks and actions from their own inject faces.
The `/client` export surface is the plugin body (`apply`/`inject`), `LayoutService`, and the four owner-share interfaces. AppFrame, the panel store, and the concession solver remain package-internal.
The `/client` exports are the plugin body (`apply`/`inject`), `LayoutService`, and the four owner-share interfaces. AppFrame, the panel store, and the concession solver remain package-internal.
## Model Experience

View File

@@ -15,7 +15,7 @@ import { createLayoutStore } from './stores.ts'
import { LayoutService } from './service.ts'
import { ThemePresenter } from './theme-presenter.ts'
// Contract surface only (export-convergence rule: cross-package consumers
// Contract exports only (export-convergence rule: cross-package consumers
// keep a symbol exported; test-only/package-internal symbols live off /src).
// ILayout: the ctx.layout face consumers and test fakes type against.
// OwnerShare contracts below are the render-side halves registrants compose
@@ -64,7 +64,7 @@ export interface ConvOwnerProps {}
/** Details owner share: empty — sessionId arrives as a framework-standard prop. */
export interface DetailsOwnerProps {}
/** Required services (cordis fiber inject — the loader passes the whole export surface as an object plugin). */
/** Required services (cordis fiber inject — the loader passes all module exports as an object plugin). */
export const inject = ['slots', 'theme']
/**

View File

@@ -3,7 +3,7 @@
// ONE register() call declares the three child slots + seats the store factory
// + wires the panel actions through the inject hook; teardown cascades
// (service unprovided + declarations gone + registration cleared). Node half
// and the invariant companion ride along — one-line surfaces the aggregate
// and the invariant companion ride along — one line exposes the aggregate
// coverage gate still requires exercised.
import { Context } from '@deepseek-ai/cordis'
@@ -111,7 +111,7 @@ describe('node half + invariant companion', () => {
const register = vi.fn().mockReturnValue(() => {})
const ctx = { invariants: { register } } as never
// The /invariant subpath types live in lib/types (build product); assert
// the surface so the call stays typed where lint runs without a build.
// the API so the call stays typed where lint runs without a build.
const dispose = await (invariant as { apply: (ctx: never) => Promise<() => void> }).apply(ctx)
expect(register).toHaveBeenCalledWith('@deepseek-ai/dsh-client-ui-layout', expect.any(Function))
// The installer is the declared no-op — calling it must not throw.