@camstack/system 1.2.313 → 1.2.314

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.
Files changed (106) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/autotrack/index.js +1 -1
  10. package/dist/builtins/autotrack/index.mjs +1 -1
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  13. package/dist/builtins/camera-grid/index.js +1 -1
  14. package/dist/builtins/camera-grid/index.mjs +1 -1
  15. package/dist/builtins/composer/claim-gate.d.ts +32 -0
  16. package/dist/builtins/composer/composed-device-set.d.ts +38 -0
  17. package/dist/builtins/composer/composed-device.d.ts +4 -3
  18. package/dist/builtins/composer/composer-grafts.d.ts +54 -0
  19. package/dist/builtins/composer/composer-plan.d.ts +89 -0
  20. package/dist/builtins/composer/composer-verdict.d.ts +19 -0
  21. package/dist/builtins/composer/composer.addon.js +2500 -422
  22. package/dist/builtins/composer/composer.addon.mjs +2493 -415
  23. package/dist/builtins/composer/composer.d.ts +66 -51
  24. package/dist/builtins/composer/composition-runtime.d.ts +84 -9
  25. package/dist/builtins/composer/confirmed-seed.d.ts +32 -0
  26. package/dist/builtins/composer/existing-target.d.ts +87 -0
  27. package/dist/builtins/composer/field-record.d.ts +41 -0
  28. package/dist/builtins/composer/graft-host.d.ts +47 -0
  29. package/dist/builtins/composer/held-claims.d.ts +12 -0
  30. package/dist/builtins/composer/owned-fields-target.d.ts +55 -0
  31. package/dist/builtins/composer/slice-assembler.d.ts +10 -0
  32. package/dist/builtins/composer/source-readings.d.ts +122 -0
  33. package/dist/builtins/composer/source-tracker.d.ts +35 -42
  34. package/dist/builtins/console-logging/index.js +1 -1
  35. package/dist/builtins/console-logging/index.mjs +1 -1
  36. package/dist/builtins/core-blocks/composition-api.d.ts +7 -4
  37. package/dist/builtins/core-blocks/composition-peers.d.ts +9 -0
  38. package/dist/builtins/core-blocks/composition-sources.d.ts +14 -3
  39. package/dist/builtins/core-blocks/core-block-store.d.ts +8 -1
  40. package/dist/builtins/core-blocks/core-blocks.addon.d.ts +4 -3
  41. package/dist/builtins/core-blocks/core-blocks.addon.js +326 -50
  42. package/dist/builtins/core-blocks/core-blocks.addon.mjs +326 -50
  43. package/dist/builtins/device-manager/claimed-status-overlay.d.ts +12 -0
  44. package/dist/builtins/device-manager/device-manager.addon.d.ts +16 -0
  45. package/dist/builtins/device-manager/device-manager.addon.js +1825 -317
  46. package/dist/builtins/device-manager/device-manager.addon.mjs +1825 -317
  47. package/dist/builtins/device-manager/device-provider-context.d.ts +24 -2
  48. package/dist/builtins/device-manager/device-row-store.d.ts +2 -0
  49. package/dist/builtins/device-manager/device-state-claim-views.d.ts +77 -0
  50. package/dist/builtins/device-manager/device-state-claims.d.ts +43 -0
  51. package/dist/builtins/device-manager/device-state-mirror.d.ts +145 -61
  52. package/dist/builtins/device-manager/field-claims-index.d.ts +69 -0
  53. package/dist/builtins/device-manager/field-ownership.d.ts +53 -0
  54. package/dist/builtins/device-manager/migrate-device.d.ts +27 -0
  55. package/dist/builtins/device-manager/migrate-guard.d.ts +7 -0
  56. package/dist/builtins/device-manager/migrate-hardware-state.d.ts +55 -0
  57. package/dist/builtins/device-manager/migration-refused.d.ts +23 -0
  58. package/dist/builtins/device-manager/mirror-row-writer.d.ts +138 -0
  59. package/dist/builtins/device-manager/runtime-state-persist-gate.d.ts +4 -0
  60. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -3
  61. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -3
  62. package/dist/builtins/hub-forwarder/index.js +1 -1
  63. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  64. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  65. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  66. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  67. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  68. package/dist/builtins/local-network/local-network.addon.js +1 -1
  69. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  70. package/dist/builtins/loki-logging/index.js +1 -1
  71. package/dist/builtins/loki-logging/index.mjs +1 -1
  72. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  73. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  74. package/dist/builtins/platform-probe/index.js +1 -1
  75. package/dist/builtins/platform-probe/index.mjs +1 -1
  76. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  77. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  78. package/dist/builtins/snapshot/index.js +1 -1
  79. package/dist/builtins/snapshot/index.mjs +1 -1
  80. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  81. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  82. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  83. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  84. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  85. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  86. package/dist/builtins/system-config/system-config.addon.js +1 -1
  87. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  88. package/dist/builtins/winston-logging/index.js +1 -1
  89. package/dist/builtins/winston-logging/index.mjs +1 -1
  90. package/dist/{child-cap-dispatch-CHTiHbsv.mjs → child-cap-dispatch-AAltfBUH.mjs} +1484 -1417
  91. package/dist/{child-cap-dispatch-Dyn_7ezH.js → child-cap-dispatch-DzcUd_ct.js} +1503 -1424
  92. package/dist/{dist-CkRwnhbo.js → dist-BtNkk3Qz.js} +4577 -3824
  93. package/dist/{dist-Cj7pJmXq.mjs → dist-cH4t1ZEm.mjs} +4541 -3824
  94. package/dist/index.js +137 -8
  95. package/dist/index.mjs +133 -8
  96. package/dist/kernel/capability-registry.d.ts +43 -1
  97. package/dist/kernel/index.d.ts +3 -1
  98. package/dist/kernel/moleculer/device-cap-proxy.d.ts +0 -10
  99. package/dist/kernel/status-overlay.d.ts +18 -0
  100. package/dist/kernel/transport/claimed-get-status.d.ts +15 -0
  101. package/dist/kernel/transport/index.d.ts +2 -0
  102. package/dist/kernel/transport/local-child-registry.d.ts +23 -0
  103. package/dist/kernel/transport/parent-unowned-call.d.ts +25 -0
  104. package/dist/{retired-settings-keys-CGSuXhP8.js → retired-settings-keys-B7imb-qH.js} +1 -1
  105. package/dist/{retired-settings-keys-C1duPikd.mjs → retired-settings-keys-DQYHfZ0S.mjs} +1 -1
  106. package/package.json +1 -1
@@ -0,0 +1,122 @@
1
+ import { CompositionSourceRef, DeviceType, EventCatalog, IScopedLogger } from '@camstack/types';
2
+ /** One row of the slim device listing: what resolves a `(addonId, stableId)` ref and types an existing target. */
3
+ export interface SourceRow {
4
+ readonly id: number;
5
+ readonly stableId: string;
6
+ readonly type: DeviceType;
7
+ }
8
+ export interface SourceRowsRead {
9
+ readonly kind: 'rows';
10
+ readonly rows: readonly SourceRow[];
11
+ }
12
+ export interface SourceUnreadable {
13
+ readonly kind: 'unreadable';
14
+ readonly error: string;
15
+ }
16
+ export type SourceListRead = SourceRowsRead | SourceUnreadable;
17
+ export interface SliceFound {
18
+ readonly kind: 'slice';
19
+ readonly slice: Readonly<Record<string, unknown>>;
20
+ }
21
+ export interface SliceNone {
22
+ readonly kind: 'none';
23
+ }
24
+ export type SliceRead = SliceFound | SliceNone | SourceUnreadable;
25
+ /** The caps bound on a device, each with the addon serving it natively (`getBindings`, one read). */
26
+ export interface BoundCaps {
27
+ readonly kind: 'caps';
28
+ readonly caps: ReadonlyMap<string, string>;
29
+ }
30
+ export type BoundCapsRead = BoundCaps | SourceUnreadable;
31
+ /** Which slice of a cap is read: what every consumer sees, or what the provider wrote (the shadow under a claim, D663). */
32
+ export type SliceView = 'effective' | 'native';
33
+ export interface SourceTrackerPorts {
34
+ readonly logger: IScopedLogger;
35
+ /** `deviceManager.listAll({ addonId, projection: 'slim' })`: one call per owning addon per pass. */
36
+ readonly listDevicesOf: (addonId: string) => Promise<SourceListRead>;
37
+ /** `deviceState.getCapSlice` for the effective view; `deviceState.getNativeCapSlice` for the native one. */
38
+ readonly readSlice: (deviceId: number, capName: string, view: SliceView) => Promise<SliceRead>;
39
+ readonly readBoundCaps: (deviceId: number) => Promise<BoundCapsRead>;
40
+ }
41
+ /** Why a `device.bindings-changed` fired — the catalog's own closed union. */
42
+ export type SourceBindingsChangeReason = EventCatalog['device.bindings-changed']['reason'];
43
+ export interface TrackedSourceRequest {
44
+ readonly ref: CompositionSourceRef;
45
+ /** Caps read in the effective view — what every consumer sees. */
46
+ readonly caps: readonly string[];
47
+ /** Caps of the REF read in the NATIVE view: the target's own replaced or uncomposed fields (rule 6). */
48
+ readonly nativeCaps?: readonly string[];
49
+ /** The block whose own claims decide whether `device.state-changed` of a native cap is the native (N-7). */
50
+ readonly nativeOwner?: string;
51
+ }
52
+ /** How a `(addonId, stableId)` ref resolves against the device index. */
53
+ export interface SourceFound {
54
+ readonly kind: 'found';
55
+ readonly deviceId: number;
56
+ readonly type: DeviceType;
57
+ }
58
+ export interface SourceMissing {
59
+ readonly kind: 'missing';
60
+ readonly reason: string;
61
+ }
62
+ export interface SourceUnknown {
63
+ readonly kind: 'unknown';
64
+ readonly error: string;
65
+ }
66
+ export type SourceResolution = SourceFound | SourceMissing | SourceUnknown;
67
+ export interface CapSlice {
68
+ readonly kind: 'slice';
69
+ readonly slice: Readonly<Record<string, unknown>>;
70
+ readonly staleReason: string | null;
71
+ }
72
+ export interface CapNoValue {
73
+ readonly kind: 'none';
74
+ readonly reason: string;
75
+ /** An ANSWER — the provider unregistered the cap and a bindings re-read agreed — not an empty or first read (D49). */
76
+ readonly confirmed: boolean;
77
+ }
78
+ /** Not bound on a device whose row exists: non-fatal, healed by `native-registered` (R7b). */
79
+ export interface CapUnbound {
80
+ readonly kind: 'unbound';
81
+ readonly reason: string;
82
+ }
83
+ /** Nothing is known: the read failed with no value held, or read empty under a held claim. Re-read by the next `sync` (D49). */
84
+ export interface CapUnread {
85
+ readonly kind: 'unread';
86
+ readonly reason: string;
87
+ }
88
+ export type CapReading = CapSlice | CapNoValue | CapUnbound | CapUnread;
89
+ /** One cap in one view — the unit a reading is held for. */
90
+ export interface CapEntry {
91
+ readonly cap: string;
92
+ readonly view: SliceView;
93
+ }
94
+ export interface TrackedSource {
95
+ readonly ref: CompositionSourceRef;
96
+ readonly deviceId: number | null;
97
+ readonly type: DeviceType | null;
98
+ readonly missingReason: string | null;
99
+ /** The index could not be read the last time: retried on the next apply. */
100
+ readonly indexError: string | null;
101
+ readonly online: boolean | null;
102
+ /** Keyed by `entryKey`: an effective and a native reading of one cap are two entries. */
103
+ readonly caps: ReadonlyMap<string, CapReading>;
104
+ /** Whose claims decide what a `device.state-changed` is for the native-view caps; null: nobody claims here. */
105
+ readonly nativeOwner: string | null;
106
+ }
107
+ export interface Absent {
108
+ readonly kind: 'absent';
109
+ }
110
+ export type RowVerdict = SourceFound | Absent | SourceUnknown;
111
+ export type Resolution = SourceFound | SourceMissing | SourceUnknown;
112
+ export type BindingVerdict = 'bound' | 'unbound' | 'unknown';
113
+ export declare const DEVICE_STATUS_CAP = "device-status";
114
+ export declare const NATIVE_SUFFIX = "@native";
115
+ export declare const NO_CAPS: readonly string[];
116
+ export declare function entryKey(entry: CapEntry): string;
117
+ export declare function entryOf(key: string): CapEntry;
118
+ export declare function entriesOf(request: TrackedSourceRequest): readonly CapEntry[];
119
+ export declare function valueAtPath(slice: Readonly<Record<string, unknown>>, path: string): unknown;
120
+ export declare function onlineOf(slice: Readonly<Record<string, unknown>>): boolean | null;
121
+ export declare function findRow(read: SourceListRead, stableId: string): RowVerdict;
122
+ export declare function resolutionOf(source: TrackedSource): SourceResolution;
@@ -1,46 +1,12 @@
1
- import { CompositionFieldRead, CompositionSourceRef, EventCatalog, IScopedLogger, SourceReading } from '@camstack/types';
2
- export interface SourceRow {
3
- readonly id: number;
4
- readonly stableId: string;
5
- }
6
- export interface SourceRowsRead {
7
- readonly kind: 'rows';
8
- readonly rows: readonly SourceRow[];
9
- }
10
- export interface SourceUnreadable {
11
- readonly kind: 'unreadable';
12
- readonly error: string;
13
- }
14
- export type SourceListRead = SourceRowsRead | SourceUnreadable;
15
- export interface SliceFound {
16
- readonly kind: 'slice';
17
- readonly slice: Readonly<Record<string, unknown>>;
18
- }
19
- export interface SliceNone {
20
- readonly kind: 'none';
21
- }
22
- export type SliceRead = SliceFound | SliceNone | SourceUnreadable;
23
- export interface BoundCaps {
24
- readonly kind: 'caps';
25
- readonly caps: ReadonlySet<string>;
26
- }
27
- export type BoundCapsRead = BoundCaps | SourceUnreadable;
28
- export interface SourceTrackerPorts {
29
- readonly logger: IScopedLogger;
30
- /** `deviceManager.listAll({ addonId, projection: 'slim' })`: one call per owning addon per pass. */
31
- readonly listDevicesOf: (addonId: string) => Promise<SourceListRead>;
32
- readonly readSlice: (deviceId: number, capName: string) => Promise<SliceRead>;
33
- readonly readBoundCaps: (deviceId: number) => Promise<BoundCapsRead>;
34
- }
35
- /** Why a `device.bindings-changed` fired — the catalog's own closed union. */
36
- export type SourceBindingsChangeReason = EventCatalog['device.bindings-changed']['reason'];
37
- export interface TrackedSourceRequest {
38
- readonly ref: CompositionSourceRef;
39
- readonly caps: readonly string[];
40
- }
1
+ import { CompositionFieldRead, CompositionSourceRef, FieldClaim, SourceReading } from '@camstack/types';
2
+ import { ClaimEvent } from './held-claims.js';
3
+ import { SliceView, SourceBindingsChangeReason, SourceResolution, SourceTrackerPorts, TrackedSourceRequest } from './source-readings.js';
4
+ export type { BoundCaps, BoundCapsRead, SliceFound, SliceNone, SliceRead, SliceView, SourceBindingsChangeReason, SourceFound, SourceListRead, SourceMissing, SourceResolution, SourceRow, SourceRowsRead, SourceTrackerPorts, SourceUnknown, SourceUnreadable, TrackedSourceRequest, } from './source-readings.js';
41
5
  export declare class SourceTracker {
42
6
  private readonly ports;
43
7
  private sources;
8
+ /** The claims the hub holds — what LANDED, never what a plan wants (C-1). */
9
+ private readonly held;
44
10
  /** The one chain every entry point joins (R3); the pattern is `BlockSupervisor.inFlight`. */
45
11
  private chain;
46
12
  constructor(ports: SourceTrackerPorts);
@@ -50,20 +16,45 @@ export declare class SourceTracker {
50
16
  * or restart): only those lose a sticky `missing`.
51
17
  */
52
18
  sync(requests: readonly TrackedSourceRequest[], reset: ReadonlySet<string>): Promise<ReadonlySet<string>>;
19
+ /**
20
+ * Resolve a ref against the device index through the same path as a source
21
+ * (D663 rule 1): one list read; two agreeing absent reads make it `missing`,
22
+ * sticky until `reset` (an operator edit or restart). A source already
23
+ * resolved is answered from memory; one whose index read FAILED is read
24
+ * again. The bare source stays tracked, so a later `sync` that names it keeps
25
+ * its resolution and reads only the caps it asks for.
26
+ */
27
+ resolve(ref: CompositionSourceRef, reset: boolean): Promise<SourceResolution>;
28
+ /** The claims the hub held at boot (the claims index seed). Nothing is read: no native self-read is tracked before it. */
29
+ seedClaims(claims: readonly FieldClaim[]): void;
30
+ /**
31
+ * A claim RPC of `owner` on `(deviceId, cap)`: dispatched (`claiming`), or
32
+ * answered — the hub holds it (`held`), holds none of it (`free`), or said
33
+ * nothing that changes it (`unsettled`). Every ANSWER re-reads the owner's
34
+ * native-view readings of that cap ONCE: while the RPC was in flight (or a
35
+ * release was being applied) the provider's writes arrived as a
36
+ * `device.state-changed` the tracker could not take as the native.
37
+ */
38
+ claimEvent(deviceId: number, cap: string, owner: string, event: ClaimEvent): Promise<ReadonlySet<string>>;
39
+ /** The last settled resolution of a ref; `unknown` when it was never resolved. Synchronous, from memory. */
40
+ resolution(ref: CompositionSourceRef): SourceResolution;
53
41
  onStateChanged(deviceId: number, capName: string, slice: Readonly<Record<string, unknown>>): Promise<ReadonlySet<string>>;
42
+ /** `device.native-shadow-changed`: the provider's own slice of a cap under a claim (owner-only, D224). */
43
+ onNativeChanged(deviceId: number, capName: string, native: Readonly<Record<string, unknown>>): Promise<ReadonlySet<string>>;
54
44
  onDeviceUnregistered(deviceId: number): Promise<ReadonlySet<string>>;
55
45
  onBindingsChanged(deviceId: number, capName: string, reason: SourceBindingsChangeReason): Promise<ReadonlySet<string>>;
56
46
  /** Run `work` after everything already queued, whether that settled or failed; never let one failure stall the chain. */
57
47
  private serialized;
58
48
  private syncNow;
59
- read(read: CompositionFieldRead): SourceReading;
49
+ read(read: CompositionFieldRead, view?: SliceView): SourceReading;
60
50
  private applyStateChanged;
51
+ private applyNativeChanged;
61
52
  private confirmUnregistered;
62
53
  private applyBindingsChanged;
63
54
  /** A source found under a NEW id is a re-registration: read it there now (R7c). */
64
55
  private rereadUnderNewId;
65
56
  private hydrate;
66
- /** Read `toRead` (bindings first, then slices); every other requested cap keeps what `known` holds. */
57
+ /** Read `toRead` (bindings first, then slices); every other requested entry keeps what `known` holds. */
67
58
  private readCaps;
68
59
  private resolveConfirmed;
69
60
  /**
@@ -73,6 +64,8 @@ export declare class SourceTracker {
73
64
  */
74
65
  private readBindings;
75
66
  private readCap;
67
+ /** A claim or release of `owner` on `(deviceId, cap)` was answered: read the owner's native-view readings of it once, in place. */
68
+ private rereadNative;
76
69
  private logHealed;
77
70
  private readOnline;
78
71
  }
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-CkRwnhbo.js");
6
+ const require_dist = require("../../dist-BtNkk3Qz.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { Ut as logDestinationCapability, jn as BaseAddon } from "../../dist-Cj7pJmXq.mjs";
1
+ import { Bn as BaseAddon, Ht as logDestinationCapability } from "../../dist-cH4t1ZEm.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -1,21 +1,24 @@
1
- import { CapabilityLookup, CompositionBlockInput, CompositionBlockPatch, CompositionBlockState, CompositionSourceDescription, CompositionSourceRef, CoreBlock, ICoreBlocksProvider, IScopedLogger } from '@camstack/types';
1
+ import { CapabilityLookup, CompositionBlockPatch, CompositionBlockState, CompositionSourceRef, CoreBlock, ICoreBlocksProvider, IScopedLogger } from '@camstack/types';
2
+ import { NamedCompositionInput } from './core-block-store.js';
3
+ import { CompositionDescriptions } from './composition-sources.js';
2
4
  export interface CompositionStoreView {
3
5
  /** False until the table has been READ; a verdict against an empty peer set would hide a cycle. */
4
6
  isLoaded(): boolean;
5
7
  list(): readonly CoreBlock[];
6
8
  get(blockId: string): CoreBlock | null;
7
- createComposition(input: CompositionBlockInput, createdBy: string): Promise<CoreBlock>;
9
+ createComposition(input: NamedCompositionInput, createdBy: string): Promise<CoreBlock>;
8
10
  updateComposition(blockId: string, patch: CompositionBlockPatch): Promise<CoreBlock>;
9
11
  }
10
12
  export interface CompositionApiDeps {
11
13
  readonly store: CompositionStoreView;
12
- readonly describeSources: (refs: readonly CompositionSourceRef[]) => Promise<ReadonlyMap<string, CompositionSourceDescription>>;
14
+ /** One read of every source and every existing target a save names (`describeCompositionSources`). */
15
+ readonly describe: (sources: readonly CompositionSourceRef[], targets: readonly CompositionSourceRef[]) => Promise<CompositionDescriptions>;
13
16
  readonly lookupCap: CapabilityLookup;
14
17
  readonly composerStates: (blockIds: readonly string[]) => Promise<readonly CompositionBlockState[]>;
15
18
  readonly convergeSoon: () => void;
16
19
  readonly logger: IScopedLogger;
17
20
  }
18
- export type CompositionApi = Pick<ICoreBlocksProvider, 'createComposition' | 'updateComposition' | 'getComposition' | 'listCompositions' | 'validateComposition'>;
21
+ export type CompositionApi = Pick<ICoreBlocksProvider, 'createComposition' | 'updateComposition' | 'getComposition' | 'listCompositions' | 'validateComposition' | 'getCustomization'>;
19
22
  /**
20
23
  * Every write runs validate-then-persist on ONE chain. Validation awaits a
21
24
  * source read before the save lands; two unserialized saves (A reads B, B
@@ -0,0 +1,9 @@
1
+ import { CapabilityLookup, CompositionPeer, CompositionSourceRef, CompositionTargetDescription, CoreBlock } from '@camstack/types';
2
+ export interface StoredPeers {
3
+ readonly peers: readonly CompositionPeer[];
4
+ /** `compositionSourceKey` → why, for each OTHER stored customization whose device could not be read. */
5
+ readonly unread: ReadonlyMap<string, string>;
6
+ }
7
+ /** The existing devices the stored customizations write — each read once with the candidate's. */
8
+ export declare function storedCustomizationTargets(blocks: readonly CoreBlock[]): readonly CompositionSourceRef[];
9
+ export declare function storedPeers(blocks: readonly CoreBlock[], targets: ReadonlyMap<string, CompositionTargetDescription>, lookupCap: CapabilityLookup, candidateBlockId: string | null): StoredPeers;
@@ -1,10 +1,21 @@
1
- import { CompositionSourceDescription, CompositionSourceRef } from '@camstack/types';
1
+ import { CompositionSourceDescription, CompositionSourceRef, CompositionTargetDescription, DeviceType } from '@camstack/types';
2
2
  export interface SourceRowView {
3
3
  readonly id: number;
4
4
  readonly stableId: string;
5
+ readonly type: DeviceType;
6
+ }
7
+ /** One `getBindings` entry: the cap, and the addon serving it natively. */
8
+ export interface BoundCapView {
9
+ readonly capName: string;
10
+ readonly nativeAddonId: string;
5
11
  }
6
12
  export interface CompositionSourcePorts {
7
13
  readonly listByAddon: (addonId: string) => Promise<readonly SourceRowView[]>;
8
- readonly boundCaps: (deviceId: number) => Promise<readonly string[]>;
14
+ readonly bindings: (deviceId: number) => Promise<readonly BoundCapView[]>;
15
+ }
16
+ /** Every device a save reads, described once. Both maps are keyed by `compositionSourceKey`. */
17
+ export interface CompositionDescriptions {
18
+ readonly sources: ReadonlyMap<string, CompositionSourceDescription>;
19
+ readonly targets: ReadonlyMap<string, CompositionTargetDescription>;
9
20
  }
10
- export declare function describeCompositionSources(ports: CompositionSourcePorts, refs: readonly CompositionSourceRef[]): Promise<ReadonlyMap<string, CompositionSourceDescription>>;
21
+ export declare function describeCompositionSources(ports: CompositionSourcePorts, sources: readonly CompositionSourceRef[], targets?: readonly CompositionSourceRef[]): Promise<CompositionDescriptions>;
@@ -1,4 +1,11 @@
1
1
  import { ComposerUnreadableBlock, CompositionBlockInput, CompositionBlockPatch, CoreBlock, CoreBlockInput, IScopedLogger, SettingsStoreClient } from '@camstack/types';
2
+ /**
3
+ * A composition block as the store keeps it: always NAMED. A customization's
4
+ * client input carries no name — the API derives it before the store sees it (D663).
5
+ */
6
+ export interface NamedCompositionInput extends CompositionBlockInput {
7
+ readonly name: string;
8
+ }
2
9
  /**
3
10
  * @durable class=config owner=core-blocks
4
11
  * write="`create` and `update` persist the operator's block after it compiles;
@@ -94,7 +101,7 @@ export declare class CoreBlockStore {
94
101
  * Store a composition block (D659): hub-placed, no code, never `running` on
95
102
  * creation — the composer's verdict, mirrored by the supervisor, says that.
96
103
  */
97
- createComposition(input: CompositionBlockInput, createdBy: string): Promise<CoreBlock>;
104
+ createComposition(input: NamedCompositionInput, createdBy: string): Promise<CoreBlock>;
98
105
  /** Patch a composition block. Immutable: returns the NEW block. Refuses a code block by name. */
99
106
  updateComposition(blockId: string, patch: CompositionBlockPatch): Promise<CoreBlock>;
100
107
  /**
@@ -56,9 +56,10 @@ export declare class CoreBlocksAddon extends BaseAddon {
56
56
  private gate;
57
57
  private buildProvider;
58
58
  /**
59
- * The composition methods (D659), flat. Sources are read over `ctx.api` at
60
- * SAVE time — one listing per owning addon, one binding read per found
61
- * device — and a read that fails refuses the save rather than skipping it.
59
+ * The composition methods (D659), flat. Sources and existing targets are read
60
+ * over `ctx.api` at SAVE time — one slim listing per owning addon, one binding
61
+ * read per found device — and a read that fails refuses the save rather than
62
+ * skipping it.
62
63
  */
63
64
  private buildCompositionApi;
64
65
  }