@camstack/types 1.2.267 → 1.2.268

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 (56) hide show
  1. package/dist/addon.js +4 -4
  2. package/dist/addon.mjs +3 -3
  3. package/dist/capabilities/battery.cap.d.ts +17 -2
  4. package/dist/capabilities/capability-definition.d.ts +22 -0
  5. package/dist/capabilities/composer.cap.d.ts +99 -0
  6. package/dist/capabilities/consumables.cap.d.ts +79 -0
  7. package/dist/capabilities/core-blocks.cap.d.ts +1149 -91
  8. package/dist/capabilities/device-extension.cap.d.ts +12 -13
  9. package/dist/capabilities/device-state.cap.d.ts +186 -2
  10. package/dist/capabilities/index.d.ts +3 -3
  11. package/dist/composition/composition-graph.d.ts +42 -9
  12. package/dist/composition/composition-items.d.ts +25 -0
  13. package/dist/composition/composition-report.d.ts +93 -2
  14. package/dist/composition/composition.d.ts +154 -3
  15. package/dist/composition/customization-name.d.ts +6 -0
  16. package/dist/composition/evaluate-field.d.ts +12 -0
  17. package/dist/composition/examples.d.ts +33 -0
  18. package/dist/composition/field-kinds.d.ts +42 -0
  19. package/dist/composition/index.d.ts +1 -0
  20. package/dist/composition/plan-result.d.ts +16 -0
  21. package/dist/composition/state-fields.d.ts +6 -0
  22. package/dist/composition/validate-composition.d.ts +44 -9
  23. package/dist/composition-CPFIlFfw.mjs +1759 -0
  24. package/dist/composition-QlOB7QTG.js +2184 -0
  25. package/dist/device/device-context.d.ts +9 -0
  26. package/dist/device/device-runtime-state.d.ts +15 -1
  27. package/dist/device/index.d.ts +1 -1
  28. package/dist/device-extension/slot-descriptor.d.ts +8 -11
  29. package/dist/device-extension/slot-provider.d.ts +0 -2
  30. package/dist/enums/event-category.d.ts +25 -0
  31. package/dist/enums.js +1 -1
  32. package/dist/enums.mjs +1 -1
  33. package/dist/err-msg-DX6i_MY4.mjs +339 -0
  34. package/dist/err-msg-Dx2Kor0g.js +368 -0
  35. package/dist/{event-category-BVDXG4tB.mjs → event-category-C5xZWqz6.mjs} +31 -1
  36. package/dist/{event-category-BVfsrBYA.js → event-category-MbnB-6AN.js} +48 -0
  37. package/dist/generated/addon-api.d.ts +42 -0
  38. package/dist/generated/device-proxy.d.ts +1 -1
  39. package/dist/generated/method-access-map.d.ts +1 -1
  40. package/dist/generated/method-device-selectors.d.ts +2 -2
  41. package/dist/generated/system-proxy.d.ts +2 -2
  42. package/dist/index.d.ts +4 -3
  43. package/dist/index.js +1513 -1656
  44. package/dist/index.mjs +1208 -1384
  45. package/dist/interfaces/kernel-abstractions.d.ts +16 -0
  46. package/dist/interfaces/status-overlay.d.ts +42 -0
  47. package/dist/node.d.ts +1 -0
  48. package/dist/node.js +29 -8
  49. package/dist/node.mjs +23 -3
  50. package/dist/{sleep-8K9gue-H.js → sleep-BSzia-xT.js} +6 -352
  51. package/dist/{sleep-DC-wdyeS.mjs → sleep-jkRQgtSc.mjs} +7 -329
  52. package/package.json +1 -1
  53. package/dist/canonical-hash-CPK2Dy60.mjs +0 -715
  54. package/dist/canonical-hash-CSE4ioRi.js +0 -792
  55. package/dist/err-msg-COpsHMw2.js +0 -18
  56. package/dist/err-msg-IQTHeDzc.mjs +0 -13
@@ -2,11 +2,10 @@
2
2
  * `device-extension` — ONE place to see and author what a device is extended
3
3
  * with by OTHER devices (D648).
4
4
  *
5
- * **A contract, not a store.** Every slot (`linked-devices`,
6
- * `doorbell-source`, later `consumables-graft`) is declared by the cap that
7
- * owns the function (`extensionSlots` in its `*.cap.ts`, D4) and SERVED by the
8
- * addon that already owns its store, over that store and its existing write
9
- * path. This cap persists nothing and has no config method (guarded by
5
+ * **A contract, not a store.** Every slot (`linked-devices`, `doorbell-source`)
6
+ * is declared by the cap that owns the function (`extensionSlots` in its
7
+ * `*.cap.ts`, D4) and SERVED by the addon that already owns its store, over
8
+ * that store and its existing write path. This cap persists nothing and has no config method (guarded by
10
9
  * `scripts/check-extension-slots.ts`): D62 applied to the whole feature, and
11
10
  * D3 — no shadow registry.
12
11
  *
@@ -27,6 +26,11 @@
27
26
  * The slot's value travels as the generated discriminated union
28
27
  * (`ExtensionSlotValue`, keyed on `slot`), so a value under the wrong slot is
29
28
  * a schema error before it reaches any owner.
29
+ *
30
+ * **Associations only.** A slot LISTS other devices on its host. A host that
31
+ * GAINS a capability from other devices is a composition (D663, amends D648:
32
+ * the reserved `graft` shape, its `projects` and its `enabled` switch were
33
+ * retired unimplemented).
30
34
  */
31
35
  import { z } from 'zod';
32
36
  import { type InferProvider } from './capability-definition.js';
@@ -58,7 +62,7 @@ export type ExtensionSource = z.infer<typeof ExtensionSourceSchema>;
58
62
  /**
59
63
  * How one picked source stands. `missing` — no such device (deleted, or an id
60
64
  * that never existed); `foreign` — a device the slot's owner cannot read from
61
- * (slice 2's cross-owner graft source); `unavailable` — it exists but is not a
65
+ * (a source owned by another addon); `unavailable` — it exists but is not a
62
66
  * valid source now (a container, which is never a pick). A source in any of
63
67
  * these states is SHOWN, never silently dropped or re-pointed.
64
68
  */
@@ -107,8 +111,6 @@ export declare const ExtensionSlotStateSchema: z.ZodObject<{
107
111
  "doorbell-source": "doorbell-source";
108
112
  }>;
109
113
  authority: z.ZodString;
110
- enabled: z.ZodNullable<z.ZodBoolean>;
111
- projects: z.ZodNullable<z.ZodString>;
112
114
  activation: z.ZodNullable<z.ZodObject<{
113
115
  state: z.ZodEnum<{
114
116
  unknown: "unknown";
@@ -169,8 +171,6 @@ export declare const ExtensionSlotRowSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
169
171
  "doorbell-source": "doorbell-source";
170
172
  }>;
171
173
  authority: z.ZodString;
172
- enabled: z.ZodNullable<z.ZodBoolean>;
173
- projects: z.ZodNullable<z.ZodString>;
174
174
  activation: z.ZodNullable<z.ZodObject<{
175
175
  state: z.ZodEnum<{
176
176
  unknown: "unknown";
@@ -244,7 +244,8 @@ export type ExtensionCandidates = z.infer<typeof ExtensionCandidatesSchema>;
244
244
  /**
245
245
  * What a write did. `none` — applied in place. `host` / `parent` — the owner
246
246
  * reloaded the host (or, for an accessory child, its parent) because the
247
- * write changed what the host REGISTERS (a graft switched on or off, slice 2).
247
+ * write changed what the host REGISTERS. A slot never adds a capability to its
248
+ * host — that is a composition (D663) — so today's owners answer `none`.
248
249
  */
249
250
  export declare const ExtensionSetResultSchema: z.ZodObject<{
250
251
  applied: z.ZodLiteral<true>;
@@ -318,8 +319,6 @@ export declare const deviceExtensionCapability: {
318
319
  "doorbell-source": "doorbell-source";
319
320
  }>;
320
321
  authority: z.ZodString;
321
- enabled: z.ZodNullable<z.ZodBoolean>;
322
- projects: z.ZodNullable<z.ZodString>;
323
322
  activation: z.ZodNullable<z.ZodObject<{
324
323
  state: z.ZodEnum<{
325
324
  unknown: "unknown";
@@ -1,4 +1,69 @@
1
1
  import { z } from 'zod';
2
+ /**
3
+ * Per-field ownership (D663). A composition may CLAIM fields of a native
4
+ * cap's runtime-state slice on an existing device: `replace` overlays the
5
+ * claimed fields on the native slice, `add` builds a slice the device does
6
+ * not natively have. Declared here — once — so the hub mirror (Task 5) and
7
+ * the claim methods (Task 6) share one union.
8
+ */
9
+ export declare const FieldClaimModeSchema: z.ZodEnum<{
10
+ replace: "replace";
11
+ add: "add";
12
+ }>;
13
+ export type FieldClaimMode = z.infer<typeof FieldClaimModeSchema>;
14
+ /** What a claim, patch or release answers. A refusal always names its reason. */
15
+ export declare const ClaimOutcomeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
16
+ ok: z.ZodLiteral<true>;
17
+ changed: z.ZodBoolean;
18
+ }, z.core.$strip>, z.ZodObject<{
19
+ ok: z.ZodLiteral<false>;
20
+ code: z.ZodEnum<{
21
+ "unknown-device": "unknown-device";
22
+ "owned-by-other": "owned-by-other";
23
+ "not-claimed": "not-claimed";
24
+ "field-not-claimed": "field-not-claimed";
25
+ "invalid-slice": "invalid-slice";
26
+ "row-unreadable": "row-unreadable";
27
+ "migration-in-flight": "migration-in-flight";
28
+ }>;
29
+ message: z.ZodString;
30
+ }, z.core.$strip>], "ok">;
31
+ export type ClaimOutcome = z.infer<typeof ClaimOutcomeSchema>;
32
+ /** One claim as `listClaims` reports it. `fields` is the PLANNED set, explicit (ruling S5). */
33
+ export declare const FieldClaimSchema: z.ZodObject<{
34
+ deviceId: z.ZodNumber;
35
+ capName: z.ZodString;
36
+ owner: z.ZodString;
37
+ mode: z.ZodEnum<{
38
+ replace: "replace";
39
+ add: "add";
40
+ }>;
41
+ fields: z.ZodArray<z.ZodString>;
42
+ }, z.core.$strip>;
43
+ export type FieldClaim = z.infer<typeof FieldClaimSchema>;
44
+ /**
45
+ * What `listClaims` answers. The claims INDEX is a listing projection loaded
46
+ * from the settings store at boot; until a load has succeeded it is
47
+ * `not-loaded`, never `[]` — an unanswered question must not look like an
48
+ * empty answer (D315).
49
+ */
50
+ export declare const ClaimsListingSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
51
+ state: z.ZodLiteral<"loaded">;
52
+ claims: z.ZodArray<z.ZodObject<{
53
+ deviceId: z.ZodNumber;
54
+ capName: z.ZodString;
55
+ owner: z.ZodString;
56
+ mode: z.ZodEnum<{
57
+ replace: "replace";
58
+ add: "add";
59
+ }>;
60
+ fields: z.ZodArray<z.ZodString>;
61
+ }, z.core.$strip>>;
62
+ }, z.core.$strip>, z.ZodObject<{
63
+ state: z.ZodLiteral<"not-loaded">;
64
+ reason: z.ZodString;
65
+ }, z.core.$strip>], "state">;
66
+ export type ClaimsListing = z.infer<typeof ClaimsListingSchema>;
2
67
  /**
3
68
  * `deviceState` — generic, cap-agnostic surface for cross-process
4
69
  * access to per-device runtime state. Read pendant for every cap's
@@ -32,8 +97,12 @@ export declare const deviceStateCapability: {
32
97
  readonly getSnapshot: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
33
98
  deviceId: z.ZodNumber;
34
99
  }, z.core.$strip>, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>, import("./capability-definition.js").CapabilityMethodKind>;
35
- /** Single cap slice. Returns null when the slice hasn't been
36
- * written or the device isn't registered. */
100
+ /**
101
+ * Single cap slice — the EFFECTIVE one: the merge every consumer sees, null
102
+ * when the slice hasn't been written, the device isn't registered, or a
103
+ * claim HOLDS the cap (D663). Never the native shadow — that is
104
+ * `getNativeCapSlice`, admin-only.
105
+ */
37
106
  readonly getCapSlice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
38
107
  deviceId: z.ZodNumber;
39
108
  capName: z.ZodString;
@@ -79,6 +148,121 @@ export declare const deviceStateCapability: {
79
148
  capName: z.ZodString;
80
149
  slice: z.ZodRecord<z.ZodString, z.ZodUnknown>;
81
150
  }, z.core.$strip>, z.ZodVoid, "mutation">;
151
+ /**
152
+ * Claim `fields` of `capName` on a device for `owner`. The PLANNED field set
153
+ * is explicit (ruling S5): `values` may be partial and MUST be a subset of
154
+ * `fields` (else `field-not-claimed`); a claimed field with no value is HELD,
155
+ * never answered from the native. A re-claim by the same owner REPLACES
156
+ * `fields` and MERGES `values` — a field dropped from `fields` loses its
157
+ * value. Another owner's claim → `owned-by-other`.
158
+ */
159
+ readonly claimFields: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
160
+ deviceId: z.ZodNumber;
161
+ capName: z.ZodString;
162
+ owner: z.ZodString;
163
+ mode: z.ZodEnum<{
164
+ replace: "replace";
165
+ add: "add";
166
+ }>;
167
+ fields: z.ZodArray<z.ZodString>;
168
+ values: z.ZodRecord<z.ZodString, z.ZodUnknown>;
169
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
170
+ ok: z.ZodLiteral<true>;
171
+ changed: z.ZodBoolean;
172
+ }, z.core.$strip>, z.ZodObject<{
173
+ ok: z.ZodLiteral<false>;
174
+ code: z.ZodEnum<{
175
+ "unknown-device": "unknown-device";
176
+ "owned-by-other": "owned-by-other";
177
+ "not-claimed": "not-claimed";
178
+ "field-not-claimed": "field-not-claimed";
179
+ "invalid-slice": "invalid-slice";
180
+ "row-unreadable": "row-unreadable";
181
+ "migration-in-flight": "migration-in-flight";
182
+ }>;
183
+ message: z.ZodString;
184
+ }, z.core.$strip>], "ok">, "mutation">;
185
+ /**
186
+ * Write owned values. Every key of `values` must be in the claim's `fields`
187
+ * (`field-not-claimed`); no claim → `not-claimed`; another owner's →
188
+ * `owned-by-other`. Partial patches merge (S5); debounced like a native slice.
189
+ */
190
+ readonly patchOwnedFields: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
191
+ deviceId: z.ZodNumber;
192
+ capName: z.ZodString;
193
+ owner: z.ZodString;
194
+ values: z.ZodRecord<z.ZodString, z.ZodUnknown>;
195
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
196
+ ok: z.ZodLiteral<true>;
197
+ changed: z.ZodBoolean;
198
+ }, z.core.$strip>, z.ZodObject<{
199
+ ok: z.ZodLiteral<false>;
200
+ code: z.ZodEnum<{
201
+ "unknown-device": "unknown-device";
202
+ "owned-by-other": "owned-by-other";
203
+ "not-claimed": "not-claimed";
204
+ "field-not-claimed": "field-not-claimed";
205
+ "invalid-slice": "invalid-slice";
206
+ "row-unreadable": "row-unreadable";
207
+ "migration-in-flight": "migration-in-flight";
208
+ }>;
209
+ message: z.ZodString;
210
+ }, z.core.$strip>], "ok">, "mutation">;
211
+ /**
212
+ * Hand the cap back. A `replace` re-emits the native slice exactly as last
213
+ * written; an `add` leaves the mirror. `not-claimed` also removes a stale
214
+ * index entry — the index self-heals through this method.
215
+ */
216
+ readonly releaseClaim: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
217
+ deviceId: z.ZodNumber;
218
+ capName: z.ZodString;
219
+ owner: z.ZodString;
220
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
221
+ ok: z.ZodLiteral<true>;
222
+ changed: z.ZodBoolean;
223
+ }, z.core.$strip>, z.ZodObject<{
224
+ ok: z.ZodLiteral<false>;
225
+ code: z.ZodEnum<{
226
+ "unknown-device": "unknown-device";
227
+ "owned-by-other": "owned-by-other";
228
+ "not-claimed": "not-claimed";
229
+ "field-not-claimed": "field-not-claimed";
230
+ "invalid-slice": "invalid-slice";
231
+ "row-unreadable": "row-unreadable";
232
+ "migration-in-flight": "migration-in-flight";
233
+ }>;
234
+ message: z.ZodString;
235
+ }, z.core.$strip>], "ok">, "mutation">;
236
+ /** Every claim the index lists, optionally those whose owner starts with `ownerPrefix`. */
237
+ readonly listClaims: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
238
+ ownerPrefix: z.ZodOptional<z.ZodString>;
239
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
240
+ state: z.ZodLiteral<"loaded">;
241
+ claims: z.ZodArray<z.ZodObject<{
242
+ deviceId: z.ZodNumber;
243
+ capName: z.ZodString;
244
+ owner: z.ZodString;
245
+ mode: z.ZodEnum<{
246
+ replace: "replace";
247
+ add: "add";
248
+ }>;
249
+ fields: z.ZodArray<z.ZodString>;
250
+ }, z.core.$strip>>;
251
+ }, z.core.$strip>, z.ZodObject<{
252
+ state: z.ZodLiteral<"not-loaded">;
253
+ reason: z.ZodString;
254
+ }, z.core.$strip>], "state">, import("./capability-definition.js").CapabilityMethodKind>;
255
+ /**
256
+ * The NATIVE slice — what the provider wrote, the shadow under a `replace`
257
+ * claim — for the owner's derived reads. Admin-only (D224, ruled in the
258
+ * Task 6 review): the shadow is a second truth beside the merge, and the
259
+ * event channel already refuses it to everyone but the composer; a
260
+ * protected read of it would hand out what the events withhold.
261
+ */
262
+ readonly getNativeCapSlice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
263
+ deviceId: z.ZodNumber;
264
+ capName: z.ZodString;
265
+ }, z.core.$strip>, z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>, import("./capability-definition.js").CapabilityMethodKind>;
82
266
  };
83
267
  readonly events: {
84
268
  /**
@@ -38,7 +38,7 @@ export { cameraStreamsCapability, type ICameraStreamsProvider, type PickedCamStr
38
38
  export { emitsCollectionSelector, extractNestedAddonId, isArrayOutputSchema, isCollectionArrayMethod, isObjectInput, isVoidInput, kebabToCamel, looseSchema, objectInputDeclaresAddonId, objectInputDeclaresRequiredDeviceId, procedureAuthKey, resolveMethodAuth, } from './cap-router-predicates.js';
39
39
  export type { CapabilityDefinition, CapabilityEventSchema, CapabilityMethodAuth, CapabilityMethodCaller, CapabilityMethodKind, CapabilityMethodOptions, CapabilityMethodSchema, CapabilityMountHint, CapabilityMountKind, CapabilityStatusItemArray, CapabilityStatusKind, CapabilityStatusSchema, CapCaller, DeviceConfigDerivedFormUi, DeviceConfigSpec, DeviceConfigUiSpec, DeviceConfigWidgetUi, DeviceSettingsContribution, InferDeviceProxyCap, InferEvents, InferName, InferNativeProvider, InferProvider, InferRuntimeState, ProviderKind, RuntimeStateDurability, UiContribution, UiContributionKind, UiContributionRemote, } from './capability-definition.js';
40
40
  export { DEFAULT_RUNTIME_STATE_DURABILITY, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, event, expandCapMethods, isDeviceConfigCap, method, optionalMethod, PROVIDER_PIN_FIELD, resolveCapMount, } from './capability-definition.js';
41
- export { CORE_BLOCK_ADDON_PREFIX, CORE_BLOCKS_ADDON_ID, type CompositionBlockInput, CompositionBlockInputSchema, type CompositionBlockPatch, type CoreBlock, type CoreBlockCompileResult, CoreBlockCompileResultSchema, type CoreBlockInput, CoreBlockInputSchema, type CoreBlockPlacement, CoreBlockPlacementSchema, CoreBlockSchema, type CoreBlockSource, type CoreBlockSourceKind, CoreBlockSourceSchema, type CoreBlockStatus, CoreBlockStatusSchema, coreBlockAddonId, coreBlockComposition, coreBlockIdFromAddonId, coreBlockSourceKind, coreBlocksCapability, type CompositionGetRead, CompositionGetReadSchema, type CompositionListRead, CompositionListReadSchema, type CompositionStateRead, CompositionStateReadSchema, type CompositionView, CompositionViewSchema, type ICoreBlocksProvider, } from './core-blocks.cap.js';
41
+ export { CORE_BLOCK_ADDON_PREFIX, CORE_BLOCKS_ADDON_ID, type CompositionBlockInput, CompositionBlockInputSchema, type CompositionBlockPatch, type CoreBlock, type CoreBlockCompileResult, CoreBlockCompileResultSchema, type CoreBlockInput, CoreBlockInputSchema, type CoreBlockPlacement, CoreBlockPlacementSchema, CoreBlockSchema, type CoreBlockSource, type CoreBlockSourceKind, CoreBlockSourceSchema, type CoreBlockStatus, CoreBlockStatusSchema, coreBlockAddonId, coreBlockComposition, coreBlockIdFromAddonId, coreBlockSourceKind, coreBlocksCapability, type CompositionCustomizationRead, CompositionCustomizationReadSchema, type CompositionGetRead, CompositionGetReadSchema, type CompositionListRead, CompositionListReadSchema, type CompositionStateRead, CompositionStateReadSchema, type CompositionView, CompositionViewSchema, type ICoreBlocksProvider, } from './core-blocks.cap.js';
42
42
  export { COMPOSER_RUNNER_ID, type ComposerApplyInput, ComposerApplyInputSchema, type ComposerApplyResult, ComposerApplyResultSchema, type ComposerBlock, ComposerBlockSchema, type ComposerBlockVerdict, ComposerBlockVerdictSchema, type ComposerUnreadableBlock, ComposerUnreadableBlockSchema, composerCapability, type IComposerProvider, } from './composer.cap.js';
43
43
  export * from './custom-actions.js';
44
44
  export type { CustomModelDescriptor, ICustomModelRegistryProvider, } from './custom-model-registry.cap.js';
@@ -55,7 +55,7 @@ export { DeviceExportStatusSchema, deviceExportCapability, ExportSetupFieldSchem
55
55
  export type { DeviceInfo, DeviceManagerApplyInitialMetaInput } from './device-manager.cap.js';
56
56
  export { ConfigEntrySchema, DEVICE_CHILDREN_BATCH_MAX, DeviceInfoSchema, deviceManagerCapability, type IDeviceManagerProvider, type LinkedDevice, LinkedDeviceSchema, type LinkedDevicesMode, LinkedDevicesModeSchema, LINKED_DEVICES_SLOT, type LinkedDevicesSlotValue, LinkedDevicesSlotValueSchema, type MigrateDeviceResult, MigrateDeviceResultSchema, type MigrateSwitchOutcome, MigrateSwitchOutcomeSchema, type MigrateSwitchReport, MigrateSwitchReportSchema, } from './device-manager.cap.js';
57
57
  export { DiscoveredDeviceSchema, deviceProviderCapability, ProviderStatusSchema, } from './device-provider.cap.js';
58
- export { deviceStateCapability } from './device-state.cap.js';
58
+ export { type ClaimOutcome, ClaimOutcomeSchema, type ClaimsListing, ClaimsListingSchema, deviceStateCapability, type FieldClaim, type FieldClaimMode, FieldClaimModeSchema, FieldClaimSchema, } from './device-state.cap.js';
59
59
  export type { EmbeddingFailedModel, EmbeddingFailedRequirement, EmbeddingModelFailure, EmbeddingRefusal, EmbeddingRefusalCode, EmbeddingTower, IEmbeddingEncoderProvider, } from './embedding-encoder.cap.js';
60
60
  export { EMBEDDING_MODEL_FAILED, EMBEDDING_REQUIREMENTS_FAILED, EMBEDDING_REQUIREMENTS_UNAVAILABLE, EmbeddingFailedModelSchema, EmbeddingFailedRequirementSchema, EmbeddingInfoSchema, EmbeddingRefusalCodeSchema, EmbeddingResultSchema, EmbeddingTowerSchema, embeddingEncoderCapability, embeddingModelFailedError, embeddingModelFailedOf, embeddingRefusalOf, embeddingRequirementsFailedError, embeddingRequirementsUnavailableError, isEmbeddingModelFailed, } from './embedding-encoder.cap.js';
61
61
  export type { FailureContribution, IFailureContributionProvider, } from './failure-contribution.cap.js';
@@ -145,7 +145,7 @@ export { type ClimateControlStatus, ClimateControlStatusSchema, climateControlCa
145
145
  export { type ColorHsvTriplet, type ColorInput, type ColorRgbTriplet, type ColorStatus, ColorStatusSchema, colorCapability, type IColorProvider, } from './color.cap.js';
146
146
  export { CONNECTION_TEST_TIMEOUT_MS, ConnectionTestDescriptorSchema, ConnectionTestInputSchema, type ConnectionTestOutcome, ConnectionTestOutcomeSchema, connectionTestCapability, type IConnectionTestProvider, } from './connection-test.cap.js';
147
147
  export { type ConnectivityStatus, ConnectivityStatusSchema, connectivityCapability, type IConnectivityProvider, } from './connectivity.cap.js';
148
- export { type ConsumableItem, ConsumableItemSchema, type ConsumablesStatus, ConsumablesStatusSchema, consumablesCapability, type IConsumablesProvider, } from './consumables.cap.js';
148
+ export { type ConsumableItem, ConsumableItemSchema, type ConsumableRemaining, ConsumableRemainingSchema, type ConsumableRemainingUnit, ConsumableRemainingUnitSchema, type ConsumablesStatus, ConsumablesStatusSchema, consumablesCapability, type IConsumablesProvider, } from './consumables.cap.js';
149
149
  export { type ContactStatus, ContactStatusSchema, contactCapability, type IContactProvider, } from './contact.cap.js';
150
150
  export { type ControlKind, ControlKindSchema, type ControlSetValueInput, type ControlStatus, ControlStatusSchema, controlCapability, type IControlProvider, } from './control.cap.js';
151
151
  export { type CoverState, CoverStateSchema, type CoverStatus, CoverStatusSchema, coverCapability, type ICoverProvider, } from './cover.cap.js';
@@ -6,31 +6,64 @@
6
6
  * through another composition, is refused at save by name (spec §2).
7
7
  *
8
8
  * The graph is built for ONE save: the CANDIDATE composition (the one being
9
- * validated) plus every STORED composition. The candidate ALWAYS replaces any
10
- * stored peer that targets the same device, regardless of where that stored
11
- * peer sits in `stored` — whether a save introduces or removes a cycle must
12
- * never depend on array order. Two DIFFERENT stored peers that (wrongly)
13
- * target the same device are corrupted state, not a cycle to resolve by
14
- * picking one silently; that is refused by name (D391).
9
+ * validated) plus every STORED composition. The candidate replaces its own old
10
+ * version, identified BY BLOCK ID wherever it sits in `stored` — whether a save
11
+ * introduces or removes a cycle must never depend on array order. A DIFFERENT
12
+ * block targeting the candidate's device is refused by name: one composition
13
+ * per device (D663). Two different stored peers that (wrongly) target the same
14
+ * device are corrupted state, not a cycle to resolve by picking one silently;
15
+ * that is refused by name too (D391).
16
+ *
17
+ * A customization of an EXISTING device reads that device's NATIVE value for a
18
+ * field it replaces or does not write ("Invert state" reads the `on` it
19
+ * replaces): such a self-read is no edge, so it is never a cycle (D663).
20
+ * Another composition reading that field reads the customizer's output.
15
21
  *
16
22
  * `findCompositionCycles` reports at least one cycle per cycle-SET (the DFS
17
- * marks a node `done` after its first expansion) — enough to refuse a save,
18
- * not to enumerate every elementary cycle through a shared node. A dotted
23
+ * marks a node `done` after its first expansion) — not every elementary cycle
24
+ * through a shared node, so the path it names may AVOID the candidate while
25
+ * one through it goes unreported. What a save refuses is therefore decided per
26
+ * strongly connected component (`findCandidateCycles`, C-1). A dotted
19
27
  * `fieldPath` is matched only as an exact string: a write to `state.value` and
20
28
  * a read of `state` would not connect (no nested field writes exist yet).
29
+ *
30
+ * An item leaf is its own node, `…#consumables.items[desiccant].status`
31
+ * (`featureFieldEntries`), so two items sharing an inner path never merge. No
32
+ * READ can name an array element (`describeStateField` never describes one),
33
+ * so an item node is write-only: its edges to sources are what the check needs.
21
34
  */
22
35
  import { type Composition, type CompositionSourceRef } from './composition.js';
23
36
  export interface CompositionPeer {
37
+ /** The block that stores this composition — its identity (D663). */
38
+ readonly blockId: string;
24
39
  /** The device this composition writes: `composedDeviceRef(blockId)` for a new target. */
25
40
  readonly target: CompositionSourceRef;
26
41
  readonly composition: Composition;
42
+ /** `"cap.field"` keys this composition REPLACES on an existing target; its reads of them are native. */
43
+ readonly replaced?: ReadonlySet<string>;
27
44
  }
28
45
  export interface CompositionCycle {
29
46
  /** Node keys, first and last equal. */
30
47
  readonly path: readonly string[];
31
48
  }
32
- /** Two stored compositions both target the same device — refused by name, never silently resolved. */
49
+ /** Two blocks' compositions target the same device — refused by name, never silently resolved. */
33
50
  export declare class CompositionGraphError extends Error {
34
51
  }
35
52
  export declare function compositionEdges(candidate: CompositionPeer, stored: readonly CompositionPeer[]): ReadonlyMap<string, readonly string[]>;
36
53
  export declare function findCompositionCycles(candidate: CompositionPeer, stored: readonly CompositionPeer[]): readonly CompositionCycle[];
54
+ /** A cycle-bearing strongly connected component that holds one of the candidate's nodes. */
55
+ export interface CandidateCycle {
56
+ /** One representative cycle through a candidate node inside the component: first and last equal. */
57
+ readonly path: readonly string[];
58
+ /** Every node of the component — what the save would close a loop through. */
59
+ readonly component: ReadonlySet<string>;
60
+ }
61
+ /**
62
+ * The cycles THIS save closes, decided per strongly connected component — never
63
+ * per reported DFS path, which names one back-edge per revisit and can report a
64
+ * component's cycle by a path that avoids the candidate while the one through it
65
+ * goes unreported. A component refuses when it holds a candidate node and a
66
+ * cycle (more than one node, or a self-loop). Components without a candidate
67
+ * node are not this save's cycles.
68
+ */
69
+ export declare function findCandidateCycles(candidate: CompositionPeer, stored: readonly CompositionPeer[]): readonly CandidateCycle[];
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Item-array fields of a composition (D663): `consumables.items[<key>]`.
3
+ *
4
+ * Items are addressed through the cap's `status.itemArray` descriptor — the
5
+ * one the source picker already uses — so a cap without one is refused
6
+ * (`not-item-array`). A composition that names `items` owns the WHOLE array.
7
+ * Each item leaf is planned as its own field, carrying `item`, and keyed by
8
+ * `compositionFieldKey` so two items sharing an inner path never share a
9
+ * record or a graph node.
10
+ *
11
+ * The composer sets some item fields itself: the key and label (from the
12
+ * entry) and {@link COMPOSED_ITEM_FIXED_FIELDS}. A source for any of them is
13
+ * refused by name (`item-field-reserved`) — `resettable` is fixed `false`
14
+ * because `reset` is refused until commands arrive (slice 3).
15
+ */
16
+ import type { CapabilityDefinition } from '../capabilities/capability-definition.js';
17
+ import { type CompositionFieldsFeature } from './composition.js';
18
+ import type { CompositionFeatureMode } from './composition-report.js';
19
+ import { type CompositionPlanResult } from './plan-result.js';
20
+ import type { CapabilityLookup } from './validate-composition.js';
21
+ /** Item fields the composer writes itself, with the value it writes. */
22
+ export declare const COMPOSED_ITEM_FIXED_FIELDS: {
23
+ readonly resettable: false;
24
+ };
25
+ export declare function planItems(def: CapabilityDefinition, feature: CompositionFieldsFeature, featureIndex: number, lookupCap: CapabilityLookup, mode?: CompositionFeatureMode): CompositionPlanResult;
@@ -21,6 +21,11 @@ export declare const CompositionProblemCodeSchema: z.ZodEnum<{
21
21
  "expression-invalid": "expression-invalid";
22
22
  cycle: "cycle";
23
23
  "duplicate-target": "duplicate-target";
24
+ "not-item-array": "not-item-array";
25
+ "item-field-reserved": "item-field-reserved";
26
+ "target-missing": "target-missing";
27
+ "target-unreadable": "target-unreadable";
28
+ "not-replaceable": "not-replaceable";
24
29
  }>;
25
30
  export type CompositionProblemCode = z.infer<typeof CompositionProblemCodeSchema>;
26
31
  /** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.celsius`. */
@@ -43,6 +48,11 @@ export declare const CompositionProblemSchema: z.ZodObject<{
43
48
  "expression-invalid": "expression-invalid";
44
49
  cycle: "cycle";
45
50
  "duplicate-target": "duplicate-target";
51
+ "not-item-array": "not-item-array";
52
+ "item-field-reserved": "item-field-reserved";
53
+ "target-missing": "target-missing";
54
+ "target-unreadable": "target-unreadable";
55
+ "not-replaceable": "not-replaceable";
46
56
  }>;
47
57
  path: z.ZodString;
48
58
  message: z.ZodString;
@@ -55,10 +65,17 @@ export declare const CompositionFieldKindSchema: z.ZodEnum<{
55
65
  enum: "enum";
56
66
  }>;
57
67
  export type CompositionFieldKind = z.infer<typeof CompositionFieldKindSchema>;
58
- /** How a field says "unavailable": `null` when its schema allows it, else the device goes offline (D393). */
68
+ /**
69
+ * How a field says "unavailable" (D393, D663): `null` when its schema allows it;
70
+ * `unknown` — the enum's own word — for an ADDED field that has one; `release`
71
+ * for a REPLACED field of an existing device, whose claim is released so the
72
+ * native provider's reading shows again; else the (composed) device goes offline.
73
+ */
59
74
  export declare const CompositionUnavailableModeSchema: z.ZodEnum<{
60
75
  null: "null";
76
+ unknown: "unknown";
61
77
  offline: "offline";
78
+ release: "release";
62
79
  }>;
63
80
  export type CompositionUnavailableMode = z.infer<typeof CompositionUnavailableModeSchema>;
64
81
  /**
@@ -71,9 +88,21 @@ export declare const CompositionFieldRoleSchema: z.ZodEnum<{
71
88
  constant: "constant";
72
89
  }>;
73
90
  export type CompositionFieldRole = z.infer<typeof CompositionFieldRoleSchema>;
91
+ /** The item a planned field belongs to; its `path` is then the dotted path INSIDE the item. */
92
+ export declare const CompositionFieldItemSchema: z.ZodObject<{
93
+ arrayPath: z.ZodString;
94
+ key: z.ZodString;
95
+ label: z.ZodString;
96
+ }, z.core.$strip>;
97
+ export type CompositionFieldItem = z.infer<typeof CompositionFieldItemSchema>;
74
98
  export declare const CompositionFieldPlanSchema: z.ZodObject<{
75
99
  cap: z.ZodString;
76
100
  path: z.ZodString;
101
+ item: z.ZodOptional<z.ZodObject<{
102
+ arrayPath: z.ZodString;
103
+ key: z.ZodString;
104
+ label: z.ZodString;
105
+ }, z.core.$strip>>;
77
106
  featureIndex: z.ZodNumber;
78
107
  kind: z.ZodEnum<{
79
108
  string: "string";
@@ -85,7 +114,9 @@ export declare const CompositionFieldPlanSchema: z.ZodObject<{
85
114
  required: z.ZodBoolean;
86
115
  unavailable: z.ZodEnum<{
87
116
  null: "null";
117
+ unknown: "unknown";
88
118
  offline: "offline";
119
+ release: "release";
89
120
  }>;
90
121
  role: z.ZodEnum<{
91
122
  derived: "derived";
@@ -129,6 +160,29 @@ export declare const CompositionFieldPlanSchema: z.ZodObject<{
129
160
  }, z.core.$strip>>;
130
161
  }, z.core.$strip>;
131
162
  export type CompositionFieldPlan = z.infer<typeof CompositionFieldPlanSchema>;
163
+ /** The key every record map, log line and graph node uses for a planned field. Two items' `status` are two keys. */
164
+ export declare function compositionFieldKey(plan: Pick<CompositionFieldPlan, 'cap' | 'path' | 'item'>): string;
165
+ /**
166
+ * What a feature does to its target (D663): `new` builds a capability on a new
167
+ * device; on an existing device it `add`s a capability the device lacks, or
168
+ * `replace`s named fields of one it has natively.
169
+ */
170
+ export declare const CompositionFeatureModeSchema: z.ZodEnum<{
171
+ new: "new";
172
+ replace: "replace";
173
+ add: "add";
174
+ }>;
175
+ export type CompositionFeatureMode = z.infer<typeof CompositionFeatureModeSchema>;
176
+ export declare const CompositionFeaturePlanSchema: z.ZodObject<{
177
+ featureIndex: z.ZodNumber;
178
+ cap: z.ZodString;
179
+ mode: z.ZodEnum<{
180
+ new: "new";
181
+ replace: "replace";
182
+ add: "add";
183
+ }>;
184
+ }, z.core.$strip>;
185
+ export type CompositionFeaturePlan = z.infer<typeof CompositionFeaturePlanSchema>;
132
186
  export declare const CompositionValidationSchema: z.ZodObject<{
133
187
  ok: z.ZodBoolean;
134
188
  problems: z.ZodArray<z.ZodObject<{
@@ -150,6 +204,11 @@ export declare const CompositionValidationSchema: z.ZodObject<{
150
204
  "expression-invalid": "expression-invalid";
151
205
  cycle: "cycle";
152
206
  "duplicate-target": "duplicate-target";
207
+ "not-item-array": "not-item-array";
208
+ "item-field-reserved": "item-field-reserved";
209
+ "target-missing": "target-missing";
210
+ "target-unreadable": "target-unreadable";
211
+ "not-replaceable": "not-replaceable";
153
212
  }>;
154
213
  path: z.ZodString;
155
214
  message: z.ZodString;
@@ -157,6 +216,11 @@ export declare const CompositionValidationSchema: z.ZodObject<{
157
216
  fields: z.ZodArray<z.ZodObject<{
158
217
  cap: z.ZodString;
159
218
  path: z.ZodString;
219
+ item: z.ZodOptional<z.ZodObject<{
220
+ arrayPath: z.ZodString;
221
+ key: z.ZodString;
222
+ label: z.ZodString;
223
+ }, z.core.$strip>>;
160
224
  featureIndex: z.ZodNumber;
161
225
  kind: z.ZodEnum<{
162
226
  string: "string";
@@ -168,7 +232,9 @@ export declare const CompositionValidationSchema: z.ZodObject<{
168
232
  required: z.ZodBoolean;
169
233
  unavailable: z.ZodEnum<{
170
234
  null: "null";
235
+ unknown: "unknown";
171
236
  offline: "offline";
237
+ release: "release";
172
238
  }>;
173
239
  role: z.ZodEnum<{
174
240
  derived: "derived";
@@ -211,14 +277,28 @@ export declare const CompositionValidationSchema: z.ZodObject<{
211
277
  fieldPath: z.ZodString;
212
278
  }, z.core.$strip>>;
213
279
  }, z.core.$strip>>;
280
+ features: z.ZodArray<z.ZodObject<{
281
+ featureIndex: z.ZodNumber;
282
+ cap: z.ZodString;
283
+ mode: z.ZodEnum<{
284
+ new: "new";
285
+ replace: "replace";
286
+ add: "add";
287
+ }>;
288
+ }, z.core.$strip>>;
214
289
  }, z.core.$strip>;
215
290
  export type CompositionValidation = z.infer<typeof CompositionValidationSchema>;
216
- /** Mirrors `CoreBlockStatus`, pinned by `core-blocks-source.spec.ts` (Task 11). */
291
+ /**
292
+ * Mirrors `CoreBlockStatus`, pinned by `core-blocks-source.spec.ts`. `degraded`:
293
+ * running, but a replaced field is released to the native provider while its
294
+ * source is unavailable (ruling S1b, D663) — the reason names each such field.
295
+ */
217
296
  export declare const CompositionRunStatusSchema: z.ZodEnum<{
218
297
  running: "running";
219
298
  failed: "failed";
220
299
  stopped: "stopped";
221
300
  starting: "starting";
301
+ degraded: "degraded";
222
302
  }>;
223
303
  export type CompositionRunStatus = z.infer<typeof CompositionRunStatusSchema>;
224
304
  export declare const CompositionFieldStateKindSchema: z.ZodEnum<{
@@ -230,6 +310,11 @@ export type CompositionFieldStateKind = z.infer<typeof CompositionFieldStateKind
230
310
  export declare const CompositionFieldStateSchema: z.ZodObject<{
231
311
  cap: z.ZodString;
232
312
  path: z.ZodString;
313
+ item: z.ZodOptional<z.ZodObject<{
314
+ arrayPath: z.ZodString;
315
+ key: z.ZodString;
316
+ label: z.ZodString;
317
+ }, z.core.$strip>>;
233
318
  state: z.ZodEnum<{
234
319
  unavailable: "unavailable";
235
320
  fresh: "fresh";
@@ -247,11 +332,17 @@ export declare const CompositionBlockStateSchema: z.ZodObject<{
247
332
  failed: "failed";
248
333
  stopped: "stopped";
249
334
  starting: "starting";
335
+ degraded: "degraded";
250
336
  }>;
251
337
  reason: z.ZodOptional<z.ZodString>;
252
338
  fields: z.ZodArray<z.ZodObject<{
253
339
  cap: z.ZodString;
254
340
  path: z.ZodString;
341
+ item: z.ZodOptional<z.ZodObject<{
342
+ arrayPath: z.ZodString;
343
+ key: z.ZodString;
344
+ label: z.ZodString;
345
+ }, z.core.$strip>>;
255
346
  state: z.ZodEnum<{
256
347
  unavailable: "unavailable";
257
348
  fresh: "fresh";