@mhome/app-facade-protocol 1.127.1 → 1.129.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,15 +39,18 @@ conversion belongs at the Facade implementation boundary.
39
39
 
40
40
  Agent Profile get/save use `content` for the complete document. LLM mode get/save
41
41
  use `llmMode`; summary and default-provider metadata use that same field.
42
- `control.mode` selects response detail. Each LLM use case has one current model. The existing
42
+ `control.responseDetail` selects response detail. Each LLM use case has one current model. The existing
43
43
  `/app/agent/llm/summary` operation owns the combined LLM read used by UI and CLI.
44
44
  See the Agent cases in the shared [presentation fixtures](fixtures/presentation/cases.json).
45
45
 
46
- Client workflows may coordinate input, login, polling and local files. Native
47
- Profile updates may run model-based merging. These workflows own explicit final
48
- results and compose real Facade calls; they are not alternative DTOs for a single
49
- Facade operation. A UI view model may derive display state after the SDK boundary.
50
- Composition does not imply a distributed transaction or automatic rollback.
46
+ Business aggregation, multi-write orchestration and overall outcome settlement belong
47
+ behind a Facade. Clients may make independent reads needed by the caller and adapt
48
+ arguments, local files and terminal/UI input. They may drive defined prepare/commit,
49
+ interactive-session and asynchronous-operation protocols; the backend owns business
50
+ steps, transitions and final DTOs. Do not implement product business composites or
51
+ alternative DTOs in CLI, SDK or surface adapters. A UI view model may derive display
52
+ state after the SDK boundary. Backend composition does not imply a distributed
53
+ transaction or automatic rollback.
51
54
 
52
55
  ## Full values and Essential presentation
53
56
 
@@ -65,8 +65,13 @@ Package caching does not install, select, upgrade, or grant additional device au
65
65
  All platforms retain the renderer isolation requirement, including for cached files.
66
66
 
67
67
  The publication service validates metadata and bytes, not JavaScript behavior.
68
- The renderer contract remains `apiVersion: 1` during development and changes in
69
- place. Hosts and skins use that current contract without a compatibility layer.
68
+ The renderer contract is `apiVersion: 2`. Renderers supply content in a
69
+ framework-owned surface, both standalone and embedded. The host owns background,
70
+ radius, clipping, menus, editing and composition dividers. A content root stays
71
+ transparent and uses the inherited foreground; the renderer may arrange its title,
72
+ values and controls without a reserved header. Each member receives its own grid
73
+ and measured content viewport. Whole-card API 1 packages are rejected and must be
74
+ adapted and rebuilt; there is no legacy rendering mode.
70
75
  The authoring build verifies the bundled ESM structure; the browser host verifies
71
76
  renderer exports against the manifest before using them. Each base owns its
72
77
  presentation adapter and renderer host; common card state and actions do not
@@ -0,0 +1,59 @@
1
+ # Canvas layout and card composition
2
+
3
+ Canvas owns one versioned layout document for every Dashboard placement. Card
4
+ bodies own content, views, business references and size-only `defaultSizes`.
5
+ `cardIds`, absolute leaf positions and parent membership are read projections,
6
+ never independent stored placement authorities. Physical Device parentage does
7
+ not change this presentation model; arbitrary logical Cards can be composed.
8
+
9
+ The layout schema is `schema/canvas-layout.v1.schema.json`. Root coordinates are
10
+ Canvas-global; member coordinates are relative to their composition. Each item
11
+ has independent sm/md/lg layouts, limited to 2/4/6 columns respectively. Members
12
+ are leaf Card references, never nested compositions. IDs are unique and leaves
13
+ cannot be placed twice. Siblings cannot overlap; children must fit within their
14
+ outer rectangle. Coordinates use nonnegative signed-32-bit integers. The UTF-8
15
+ layout document is at most 256 KiB.
16
+
17
+ `/app/dashboard/canvas/content/get` returns all leaf definitions, `revision` and
18
+ `layoutDocument`. Observations remain independent and do not advance layout
19
+ revision. Opening the Dashboard or switching profiles never repacks a saved
20
+ layout. Default dimensions are used only when creating a placement.
21
+
22
+ ## Commands
23
+
24
+ All three composition commands require current-Space write authorization and
25
+ `expectedRevision`. They return `{spaceId, canvasId, revision, layoutDocument}`;
26
+ creation also returns `createdItemId`. The backend owns validation and the whole
27
+ operation. A stale revision changes nothing. An optional `rootDrafts` array includes unsaved root placement changes for up to
28
+ three distinct profiles in that same commit. `rootDraft` remains supported for a
29
+ single profile; the two fields are mutually exclusive. Ordinary layout updates
30
+ may include `rootDrafts` for profiles other than their main `layoutSize`; organize
31
+ may include all edited profiles before arranging its selected profile.
32
+
33
+ - `/app/dashboard/canvas/composition/create`: `itemIds` selects two or more roots.
34
+ Existing compositions flatten to leaves; leaf identities and current dimensions
35
+ remain. Fixed-pass first-fit packing compares original, area, height and width
36
+ order across available widths. Choose smaller bounding area, then greater
37
+ width, with deterministic ties. No rotations, resizing or optimality guarantee.
38
+ Place the resulting outer rectangle near the selection without moving others.
39
+ - `/app/dashboard/canvas/composition/ungroup`: `compositionId` expands members
40
+ at outer-position plus local-position in every profile, preserving current size.
41
+ - `/app/dashboard/canvas/composition/layout/update`: `compositionId`, `layoutSize`
42
+ and all `members` replace that profile's local layout. Alternatively `reset:true`
43
+ repacks within current outer width and height. Omit `members` when resetting.
44
+
45
+ Ordinary drag, resize and organize also save Canvas layout and advance revision.
46
+ Organize treats a composition as one root, keeping its internal layout intact.
47
+ Group copy creates fresh container and Card IDs while retaining business refs;
48
+ move preserves member identity and internal layout. Cross-Canvas move commits
49
+ source and target Canvas documents together. Delete and resource cleanup prune
50
+ leaf references: one surviving member becomes an independent Card at its current
51
+ absolute position; zero members removes the container.
52
+
53
+ Existing data is converted explicitly with old writers stopped, a verified
54
+ backup and conflict checks. Runtime startup never converts legacy placement or
55
+ silently deletes a database. Cloud Canvas records stay in the existing `canvas`
56
+ table with unchanged primary keys. Existing records require an explicit in-place
57
+ conversion and a verified backup before cutover. Aliyun must have local
58
+ transactions enabled on that table; existing tables without the feature require
59
+ provider support. No replacement Canvas table is introduced.
@@ -49,7 +49,42 @@ login and Hub authorization retain their independently owned wire DTOs.
49
49
 
50
50
  Legacy `/scope/list`, `/scope/get`, `/scope/preference/get`, `/scope/agent/get`,
51
51
  and `/scope/location/list` readers are retired, without fallback aliases. Native
52
- UI membership refresh uses `/app/presentation/space/list`; the CLI uses
53
- `/app/space/list` for identity-only listing and selection checks, and presentation
54
- listing for its full management view. Neither lightweight flow expands per-Space
55
- context. `/focus` remains connection control, not a business Facade.
52
+ UI membership refresh uses `/app/presentation/space/list`. CLI `space list` forwards
53
+ `/app/space/list` and its canonical `{spaces}` DTO with `spaceId`, `name`, `mode`,
54
+ `llmMode` and `lifecycleState`. It never expands per-Space context or adds local
55
+ active-Space state and Hub routes. Read selected details, members and preferences
56
+ through their own Facades. CLI selection uses `/app/client/space/focus`; it returns
57
+ `{focusedSpaceId}` and leaves membership validation/persistence to the receiving
58
+ Client and authoritative executor. `/focus` has no compatibility alias.
59
+
60
+ Space commands pass the caller's Full/Essential choice to the Facade. Prepare
61
+ previews remain fixed control objects. Whole-Space deletion drives the existing
62
+ asynchronous protocol using structured Full control reads, then returns the
63
+ unchanged `/app/space/delete/status` DTO in the requested detail. It does not
64
+ rewrite `action` or hide operation fields. A successful status read may describe
65
+ `DELETE_FAILED`; waiting for that failed operation still exits unsuccessfully.
66
+
67
+ ## Space mutation outcomes
68
+
69
+ The backend settles member invite/remove outcomes before presentation. A request
70
+ with no failed items succeeds, including already-pending/already-member invitations
71
+ and removal of absent memberships. Fulfilled and failed items together return
72
+ `partial`; failure of every requested item returns `error` with the complete
73
+ per-item result in diagnostics. Full and Essential retain the same outcome.
74
+ Location writes with `NotCreated`, `NotUpdated` or `NotDeleted` return `error`,
75
+ with the original write result in diagnostics. Prepared previews describe planned
76
+ work and never prove effects. Reading a failed deletion operation remains a
77
+ successful read; accepting deletion never means erasure has completed.
78
+
79
+ `/app/space/member/update` accepts `{removeEmails?: string[], inviteEmails?: string[]}`
80
+ with at least one requested change. UI member editing and the human-operated CLI
81
+ share this business composite. The backend normalizes/resolves all inputs and
82
+ rejects an OWNER removal before any write. It then removes memberships and sends
83
+ invitations under one Space mutation lock; it does not promise rollback. The same
84
+ email cannot be removed and invited together. Its complete result is
85
+ `{action, spaceId, removal, invitation, problems}`; removal/invitation preserve
86
+ those individual operations' DTOs. If invitation execution becomes unconfirmed,
87
+ `invitation` is null and `problems` explains that membership must be inspected
88
+ before retrying. The backend settles the overall outcome. It supports direct and
89
+ prepared modes; previews perform no writes. This operation does not extend the
90
+ native Agent, MCP or external Skill boundary for member removal.
@@ -32,7 +32,7 @@
32
32
  "version": "1.0.0",
33
33
  "name": "Evening cards",
34
34
  "description": "Full-card skins for a color light, a playable speaker and a thermostat.",
35
- "apiVersion": 1,
35
+ "apiVersion": 2,
36
36
  "entry": "skin.test.mjs",
37
37
  "renderers": [
38
38
  {