@githolon/dsl 0.14.0 → 0.15.0
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/dart/example/nomos_webview_transport.dart +2 -2
- package/dart/lib/nomos_dsl.dart +4 -4
- package/dart/lib/src/{dispatch.dart → offer.dart} +7 -7
- package/dart/lib/src/provider.dart +30 -30
- package/dart/lib/src/subscriptions.dart +3 -3
- package/dart/lib/src/webview_bridge.dart +4 -21
- package/dart/test/webview_bridge_test.dart +35 -34
- package/package.json +5 -3
- package/src/build_package.ts +1 -1
- package/src/capability_exports.ts +2 -2
- package/src/codegen_dart.ts +12 -12
- package/src/codegen_dart_client.ts +20 -7
- package/src/codegen_provider_dart.ts +67 -61
- package/src/codegen_ts.ts +18 -15
- package/src/compile_package_main.ts +13 -16
- package/src/framework/capability.ts +10 -10
- package/src/framework/impure_capability.ts +73 -67
- package/src/framework/sync_lifecycle.ts +3 -3
- package/src/index.ts +1 -1
- package/src/usd.ts +156 -0
- package/src/usd_layers.ts +170 -26
- package/src/workspace_sharding.ts +2 -7
package/src/usd.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
type CanonicalManifest,
|
|
34
34
|
type CanonicalProjectionReturn,
|
|
35
35
|
} from "./manifest.js";
|
|
36
|
+
import type { AggregateHandle } from "./aggregate.js";
|
|
36
37
|
import {
|
|
37
38
|
mergeRequiresScope,
|
|
38
39
|
CompositionViolation,
|
|
@@ -126,10 +127,46 @@ export interface UsdCombined {
|
|
|
126
127
|
readonly returns: CanonicalProjectionReturn;
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
/** One field's read-projection descriptor: the field kind plus a map's value kind. */
|
|
131
|
+
export interface UsdFieldKindDescriptor {
|
|
132
|
+
readonly kind: string;
|
|
133
|
+
readonly mapValueKind?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface UsdReadProjection {
|
|
137
|
+
readonly aggregateFieldKinds: Record<string, Record<string, UsdFieldKindDescriptor>>;
|
|
138
|
+
readonly queries: { id: string; key: { field: string; kind: string }[]; returns: string }[];
|
|
139
|
+
readonly counts: { id: string; of: string; by: string | null; where?: unknown }[];
|
|
140
|
+
readonly spatials: { id: string; of: string; on: string }[];
|
|
141
|
+
readonly deriveds: { id: string; of: string; returns: CanonicalProjectionReturn }[];
|
|
142
|
+
readonly combineds: { id: string; of: string; refField: string; reads: string; returns: CanonicalProjectionReturn }[];
|
|
143
|
+
readonly sums?: { id: string; of: string; field: string; by: string | null; where?: unknown }[];
|
|
144
|
+
readonly mins?: { id: string; of: string; field: string; by: string | null; where?: unknown }[];
|
|
145
|
+
readonly maxes?: { id: string; of: string; field: string; by: string | null; where?: unknown }[];
|
|
146
|
+
readonly orderedReads?: {
|
|
147
|
+
id: string;
|
|
148
|
+
of: string;
|
|
149
|
+
orderKey: string;
|
|
150
|
+
orderDesc?: true;
|
|
151
|
+
where?: unknown;
|
|
152
|
+
limit: number;
|
|
153
|
+
}[];
|
|
154
|
+
}
|
|
155
|
+
|
|
129
156
|
/** One USD layer: a stage path + its prims (canonically sorted by prim path). */
|
|
130
157
|
export interface UsdLayer {
|
|
131
158
|
readonly path: string;
|
|
132
159
|
readonly prims: UsdPrim[];
|
|
160
|
+
/**
|
|
161
|
+
* The canonical admission/merge manifest for this layer, committed inside the package.
|
|
162
|
+
* Hosts must not stage or mutate this view; holons derive it from active installed law.
|
|
163
|
+
*/
|
|
164
|
+
readonly nomosIdentityManifest?: CanonicalManifest;
|
|
165
|
+
/**
|
|
166
|
+
* The projection schema/read-routing fragment for this layer, committed inside the package.
|
|
167
|
+
* It carries the projection-only field-kind data that cannot be recovered from merge drivers.
|
|
168
|
+
*/
|
|
169
|
+
readonly nomosReadProjection?: UsdReadProjection;
|
|
133
170
|
/**
|
|
134
171
|
* The layer's NAMED, INDEXED read declarations (read-side closure step 1), SORTED
|
|
135
172
|
* by id. OMITTED (`undefined`) when the module declares no query, so a query-free
|
|
@@ -363,6 +400,123 @@ function encodeModuleToPrims(layerPath: string, mod: DomainModule): UsdPrim[] {
|
|
|
363
400
|
return sortPrims(prims);
|
|
364
401
|
}
|
|
365
402
|
|
|
403
|
+
function aggregateFieldKindsForModule(
|
|
404
|
+
mod: DomainModule,
|
|
405
|
+
): Record<string, Record<string, UsdFieldKindDescriptor>> {
|
|
406
|
+
const out: Record<string, Record<string, UsdFieldKindDescriptor>> = {};
|
|
407
|
+
for (const agg of [...(mod.aggregates as AggregateHandle[])].sort((a, b) =>
|
|
408
|
+
a.id < b.id ? -1 : a.id > b.id ? 1 : 0,
|
|
409
|
+
)) {
|
|
410
|
+
const fields: Record<string, UsdFieldKindDescriptor> = {};
|
|
411
|
+
for (const name of Object.keys(agg.fields).sort()) {
|
|
412
|
+
const field = agg.fields[name]!;
|
|
413
|
+
fields[name] = {
|
|
414
|
+
kind: field.kind,
|
|
415
|
+
...(field.mapValueKind !== undefined ? { mapValueKind: field.mapValueKind } : {}),
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
out[agg.id] = fields;
|
|
419
|
+
}
|
|
420
|
+
return out;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function readKeyFieldKind(
|
|
424
|
+
byType: Record<string, Record<string, UsdFieldKindDescriptor>>,
|
|
425
|
+
queryId: string,
|
|
426
|
+
returns: string,
|
|
427
|
+
keyField: string,
|
|
428
|
+
): string {
|
|
429
|
+
const schema = byType[returns];
|
|
430
|
+
if (schema === undefined) {
|
|
431
|
+
throw new Error(
|
|
432
|
+
`usd: query '${queryId}' returns '${returns}', which has no field schema in nomosReadProjection`,
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const lookup = keyField.includes(".") ? keyField.split(".")[0]! : keyField;
|
|
436
|
+
const descriptor = schema[lookup];
|
|
437
|
+
if (descriptor === undefined) {
|
|
438
|
+
throw new Error(
|
|
439
|
+
`usd: query '${queryId}' is keyed on '${keyField}' (field '${lookup}'), which '${returns}' does not declare`,
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
return descriptor.kind;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function readProjectionForModule(mod: DomainModule, manifest: CanonicalManifest): UsdReadProjection {
|
|
446
|
+
const aggregateFieldKinds = aggregateFieldKindsForModule(mod);
|
|
447
|
+
return {
|
|
448
|
+
aggregateFieldKinds,
|
|
449
|
+
queries: (manifest.queries ?? []).map((q) => ({
|
|
450
|
+
id: q.id,
|
|
451
|
+
key: q.key.map((field) => ({
|
|
452
|
+
field,
|
|
453
|
+
kind: readKeyFieldKind(aggregateFieldKinds, q.id, q.returns, field),
|
|
454
|
+
})),
|
|
455
|
+
returns: q.returns,
|
|
456
|
+
})),
|
|
457
|
+
counts: (manifest.counts ?? []).map((c) => ({
|
|
458
|
+
id: c.id,
|
|
459
|
+
of: c.of,
|
|
460
|
+
by: c.by ?? null,
|
|
461
|
+
...(c.where !== undefined ? { where: c.where } : {}),
|
|
462
|
+
})),
|
|
463
|
+
spatials: (manifest.spatials ?? []).map((s) => ({ id: s.id, of: s.of, on: s.on })),
|
|
464
|
+
deriveds: (manifest.deriveds ?? []).map((d) => ({ id: d.id, of: d.of, returns: d.returns })),
|
|
465
|
+
combineds: (manifest.combineds ?? []).map((c) => ({
|
|
466
|
+
id: c.id,
|
|
467
|
+
of: c.of,
|
|
468
|
+
refField: c.refField,
|
|
469
|
+
reads: c.reads,
|
|
470
|
+
returns: c.returns,
|
|
471
|
+
})),
|
|
472
|
+
...((manifest.sums ?? []).length > 0
|
|
473
|
+
? {
|
|
474
|
+
sums: manifest.sums!.map((s) => ({
|
|
475
|
+
id: s.id,
|
|
476
|
+
of: s.of,
|
|
477
|
+
field: s.sumField,
|
|
478
|
+
by: s.by ?? null,
|
|
479
|
+
...(s.where !== undefined ? { where: s.where } : {}),
|
|
480
|
+
})),
|
|
481
|
+
}
|
|
482
|
+
: {}),
|
|
483
|
+
...((manifest.mins ?? []).length > 0
|
|
484
|
+
? {
|
|
485
|
+
mins: manifest.mins!.map((e) => ({
|
|
486
|
+
id: e.id,
|
|
487
|
+
of: e.of,
|
|
488
|
+
field: e.valueField,
|
|
489
|
+
by: e.by ?? null,
|
|
490
|
+
...(e.where !== undefined ? { where: e.where } : {}),
|
|
491
|
+
})),
|
|
492
|
+
}
|
|
493
|
+
: {}),
|
|
494
|
+
...((manifest.maxes ?? []).length > 0
|
|
495
|
+
? {
|
|
496
|
+
maxes: manifest.maxes!.map((e) => ({
|
|
497
|
+
id: e.id,
|
|
498
|
+
of: e.of,
|
|
499
|
+
field: e.valueField,
|
|
500
|
+
by: e.by ?? null,
|
|
501
|
+
...(e.where !== undefined ? { where: e.where } : {}),
|
|
502
|
+
})),
|
|
503
|
+
}
|
|
504
|
+
: {}),
|
|
505
|
+
...((manifest.orderedReads ?? []).length > 0
|
|
506
|
+
? {
|
|
507
|
+
orderedReads: manifest.orderedReads!.map((r) => ({
|
|
508
|
+
id: r.id,
|
|
509
|
+
of: r.of,
|
|
510
|
+
orderKey: r.orderKey,
|
|
511
|
+
...(r.orderDesc ? { orderDesc: true as const } : {}),
|
|
512
|
+
...(r.where !== undefined ? { where: r.where } : {}),
|
|
513
|
+
limit: r.limit,
|
|
514
|
+
})),
|
|
515
|
+
}
|
|
516
|
+
: {}),
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
366
520
|
/**
|
|
367
521
|
* Lower a layer's `relationType` decls into the canonical `nomosRelations` wire object (P1) —
|
|
368
522
|
* keys SORTED for byte-determinism, omit-when-empty (the era rule). Multiple decls for one type
|
|
@@ -549,6 +703,8 @@ export function emitUsd(
|
|
|
549
703
|
return {
|
|
550
704
|
path: l.path,
|
|
551
705
|
prims: encodeModuleToPrims(l.path, l.module),
|
|
706
|
+
nomosIdentityManifest: manifest,
|
|
707
|
+
nomosReadProjection: readProjectionForModule(l.module, manifest),
|
|
552
708
|
...(manifest.queries !== undefined ? { queries: manifest.queries } : {}),
|
|
553
709
|
...(manifest.deriveds !== undefined ? { deriveds: manifest.deriveds } : {}),
|
|
554
710
|
...(manifest.combineds !== undefined ? { combineds: manifest.combineds } : {}),
|
package/src/usd_layers.ts
CHANGED
|
@@ -143,6 +143,40 @@ function sortedSchema(schema: WireSchema): WireSchema {
|
|
|
143
143
|
return out;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
function domainLayerAttrLines(domain: string, layer: UsdLayer, indent: string): string[] {
|
|
147
|
+
return [
|
|
148
|
+
`${indent}custom string nomos:kind = "domain"`,
|
|
149
|
+
`${indent}custom string nomos:domain = ${usdaString(domain)}`,
|
|
150
|
+
...(layer.nomosIdentityManifest !== undefined
|
|
151
|
+
? [`${indent}custom string nomos:identityManifestHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosIdentityManifest)))}`]
|
|
152
|
+
: []),
|
|
153
|
+
...(layer.nomosReadProjection !== undefined
|
|
154
|
+
? [`${indent}custom string nomos:readProjectionHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadProjection)))}`]
|
|
155
|
+
: []),
|
|
156
|
+
...(layer.nomosStableIds !== undefined
|
|
157
|
+
? [`${indent}custom string nomos:stableIdsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosStableIds)))}`]
|
|
158
|
+
: []),
|
|
159
|
+
...(layer.nomosReadGate !== undefined
|
|
160
|
+
? [`${indent}custom string nomos:readGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadGate)))}`]
|
|
161
|
+
: []),
|
|
162
|
+
...(layer.nomosReadVisibility !== undefined
|
|
163
|
+
? [`${indent}custom string nomos:readVisibilityHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadVisibility)))}`]
|
|
164
|
+
: []),
|
|
165
|
+
...(layer.nomosEncryption !== undefined
|
|
166
|
+
? [`${indent}custom string nomos:encryptionHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosEncryption)))}`]
|
|
167
|
+
: []),
|
|
168
|
+
...(layer.nomosRelations !== undefined
|
|
169
|
+
? [`${indent}custom string nomos:relationsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelations)))}`]
|
|
170
|
+
: []),
|
|
171
|
+
...(layer.nomosRelationGate !== undefined
|
|
172
|
+
? [`${indent}custom string nomos:relationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelationGate)))}`]
|
|
173
|
+
: []),
|
|
174
|
+
...(layer.nomosAttestationGate !== undefined
|
|
175
|
+
? [`${indent}custom string nomos:attestationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosAttestationGate)))}`]
|
|
176
|
+
: []),
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
|
|
146
180
|
// ── per-module layer emission ────────────────────────────────────────────────────────
|
|
147
181
|
|
|
148
182
|
/** One authored module of a domain's ordered module list (weak → strong). */
|
|
@@ -349,31 +383,9 @@ export function usdaLayerText(
|
|
|
349
383
|
`{`,
|
|
350
384
|
` def Scope ${usdaString(primName(domain))}`,
|
|
351
385
|
` {`,
|
|
352
|
-
|
|
353
|
-
` custom string nomos:domain = ${usdaString(domain)}`,
|
|
354
|
-
// STABLE IDS + the captured-read gate (#58): layer-level law keys, hex-carried
|
|
386
|
+
// Stable ids + holon-owned manifests: layer-level law keys, hex-carried
|
|
355
387
|
// so the .usda round-trips byte-faithfully to the IR layer.
|
|
356
|
-
...(layer
|
|
357
|
-
? [` custom string nomos:stableIdsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosStableIds)))}`]
|
|
358
|
-
: []),
|
|
359
|
-
...(layer.nomosReadGate !== undefined
|
|
360
|
-
? [` custom string nomos:readGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadGate)))}`]
|
|
361
|
-
: []),
|
|
362
|
-
...(layer.nomosReadVisibility !== undefined
|
|
363
|
-
? [` custom string nomos:readVisibilityHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosReadVisibility)))}`]
|
|
364
|
-
: []),
|
|
365
|
-
...(layer.nomosEncryption !== undefined
|
|
366
|
-
? [` custom string nomos:encryptionHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosEncryption)))}`]
|
|
367
|
-
: []),
|
|
368
|
-
...(layer.nomosRelations !== undefined
|
|
369
|
-
? [` custom string nomos:relationsHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelations)))}`]
|
|
370
|
-
: []),
|
|
371
|
-
...(layer.nomosRelationGate !== undefined
|
|
372
|
-
? [` custom string nomos:relationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosRelationGate)))}`]
|
|
373
|
-
: []),
|
|
374
|
-
...(layer.nomosAttestationGate !== undefined
|
|
375
|
-
? [` custom string nomos:attestationGateHex = ${usdaString(hexUtf8(JSON.stringify(layer.nomosAttestationGate)))}`]
|
|
376
|
-
: []),
|
|
388
|
+
...domainLayerAttrLines(domain, layer, " "),
|
|
377
389
|
``,
|
|
378
390
|
...body,
|
|
379
391
|
` }`,
|
|
@@ -388,8 +400,30 @@ export function usdaLayerText(
|
|
|
388
400
|
* list is STRONGEST-FIRST, so the list is emitted REVERSED. Same monoid, opposite
|
|
389
401
|
* notation — the reversal IS the correspondence, recorded in the doc string.
|
|
390
402
|
*/
|
|
391
|
-
export function layeredRootUsda(
|
|
403
|
+
export function layeredRootUsda(
|
|
404
|
+
sublayerRelPathsWeakToStrong: readonly string[],
|
|
405
|
+
composed?: UsdDocument,
|
|
406
|
+
): string {
|
|
392
407
|
const strongestFirst = [...sublayerRelPathsWeakToStrong].reverse();
|
|
408
|
+
const composedDomainOpinions =
|
|
409
|
+
composed === undefined || composed.layers.length === 0
|
|
410
|
+
? []
|
|
411
|
+
: [
|
|
412
|
+
``,
|
|
413
|
+
`over "Nomos"`,
|
|
414
|
+
`{`,
|
|
415
|
+
...composed.layers.flatMap((layer) => {
|
|
416
|
+
const domain = layer.path.slice(layer.path.lastIndexOf("/") + 1);
|
|
417
|
+
return [
|
|
418
|
+
` over ${usdaString(primName(domain))}`,
|
|
419
|
+
` {`,
|
|
420
|
+
...domainLayerAttrLines(domain, layer, " "),
|
|
421
|
+
` }`,
|
|
422
|
+
];
|
|
423
|
+
}),
|
|
424
|
+
`}`,
|
|
425
|
+
``,
|
|
426
|
+
];
|
|
393
427
|
return [
|
|
394
428
|
`#usda 1.0`,
|
|
395
429
|
`(`,
|
|
@@ -406,6 +440,7 @@ export function layeredRootUsda(sublayerRelPathsWeakToStrong: readonly string[])
|
|
|
406
440
|
),
|
|
407
441
|
` ]`,
|
|
408
442
|
`)`,
|
|
443
|
+
...composedDomainOpinions,
|
|
409
444
|
``,
|
|
410
445
|
].join("\n");
|
|
411
446
|
}
|
|
@@ -461,6 +496,97 @@ function foldById<T extends { readonly id: string }>(
|
|
|
461
496
|
return [...byId.keys()].sort().map((id) => byId.get(id)!);
|
|
462
497
|
}
|
|
463
498
|
|
|
499
|
+
function foldByKey<T>(
|
|
500
|
+
lists: readonly (readonly T[] | undefined)[],
|
|
501
|
+
keyOf: (item: T) => string,
|
|
502
|
+
): T[] | undefined {
|
|
503
|
+
const byKey = new Map<string, T>();
|
|
504
|
+
for (const list of lists) for (const item of list ?? []) byKey.set(keyOf(item), item);
|
|
505
|
+
if (byKey.size === 0) return undefined;
|
|
506
|
+
return [...byKey.keys()].sort().map((key) => byKey.get(key)!);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function foldRecord<T>(
|
|
510
|
+
records: readonly (Readonly<Record<string, T>> | undefined)[],
|
|
511
|
+
): Record<string, T> | undefined {
|
|
512
|
+
const byKey = new Map<string, T>();
|
|
513
|
+
for (const record of records) {
|
|
514
|
+
if (record === undefined) continue;
|
|
515
|
+
for (const [key, value] of Object.entries(record)) byKey.set(key, value);
|
|
516
|
+
}
|
|
517
|
+
if (byKey.size === 0) return undefined;
|
|
518
|
+
const out: Record<string, T> = {};
|
|
519
|
+
for (const key of [...byKey.keys()].sort()) out[key] = byKey.get(key)!;
|
|
520
|
+
return out;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function foldIdentityManifest(
|
|
524
|
+
stack: readonly UsdLayer[],
|
|
525
|
+
stableIds: UsdLayer["nomosStableIds"],
|
|
526
|
+
): UsdLayer["nomosIdentityManifest"] {
|
|
527
|
+
const manifests = stack
|
|
528
|
+
.map((l) => l.nomosIdentityManifest)
|
|
529
|
+
.filter((m): m is NonNullable<UsdLayer["nomosIdentityManifest"]> => m !== undefined);
|
|
530
|
+
if (manifests.length === 0) return undefined;
|
|
531
|
+
const domain = manifests[manifests.length - 1]!.domain;
|
|
532
|
+
const workspaceInvariants = foldById(manifests.map((m) => m.workspaceInvariants));
|
|
533
|
+
const queries = foldById(manifests.map((m) => m.queries));
|
|
534
|
+
const counts = foldById(manifests.map((m) => m.counts));
|
|
535
|
+
const spatials = foldById(manifests.map((m) => m.spatials));
|
|
536
|
+
const sums = foldById(manifests.map((m) => m.sums));
|
|
537
|
+
const deriveds = foldById(manifests.map((m) => m.deriveds));
|
|
538
|
+
const combineds = foldById(manifests.map((m) => m.combineds));
|
|
539
|
+
const mins = foldById(manifests.map((m) => m.mins));
|
|
540
|
+
const maxes = foldById(manifests.map((m) => m.maxes));
|
|
541
|
+
const orderedReads = foldById(manifests.map((m) => m.orderedReads));
|
|
542
|
+
const workspaceTypes = foldById(manifests.map((m) => m.workspaceTypes));
|
|
543
|
+
const homes = foldRecord(manifests.map((m) => m.homes));
|
|
544
|
+
const routes = foldByKey(manifests.map((m) => m.routes), (r) => r.directive);
|
|
545
|
+
return {
|
|
546
|
+
domain,
|
|
547
|
+
aggregates: foldById(manifests.map((m) => m.aggregates)) ?? [],
|
|
548
|
+
directives: foldById(manifests.map((m) => m.directives)) ?? [],
|
|
549
|
+
...(stableIds !== undefined ? { stableIds } : {}),
|
|
550
|
+
...(workspaceInvariants !== undefined ? { workspaceInvariants } : {}),
|
|
551
|
+
...(queries !== undefined ? { queries } : {}),
|
|
552
|
+
...(counts !== undefined ? { counts } : {}),
|
|
553
|
+
...(spatials !== undefined ? { spatials } : {}),
|
|
554
|
+
...(sums !== undefined ? { sums } : {}),
|
|
555
|
+
...(deriveds !== undefined ? { deriveds } : {}),
|
|
556
|
+
...(combineds !== undefined ? { combineds } : {}),
|
|
557
|
+
...(mins !== undefined ? { mins } : {}),
|
|
558
|
+
...(maxes !== undefined ? { maxes } : {}),
|
|
559
|
+
...(orderedReads !== undefined ? { orderedReads } : {}),
|
|
560
|
+
...(workspaceTypes !== undefined ? { workspaceTypes } : {}),
|
|
561
|
+
...(homes !== undefined ? { homes } : {}),
|
|
562
|
+
...(routes !== undefined ? { routes } : {}),
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function foldReadProjection(stack: readonly UsdLayer[]): UsdLayer["nomosReadProjection"] {
|
|
567
|
+
const projections = stack
|
|
568
|
+
.map((l) => l.nomosReadProjection)
|
|
569
|
+
.filter((p): p is NonNullable<UsdLayer["nomosReadProjection"]> => p !== undefined);
|
|
570
|
+
if (projections.length === 0) return undefined;
|
|
571
|
+
const aggregateFieldKinds = foldRecord(projections.map((p) => p.aggregateFieldKinds)) ?? {};
|
|
572
|
+
const sums = foldById(projections.map((p) => p.sums));
|
|
573
|
+
const mins = foldById(projections.map((p) => p.mins));
|
|
574
|
+
const maxes = foldById(projections.map((p) => p.maxes));
|
|
575
|
+
const orderedReads = foldById(projections.map((p) => p.orderedReads));
|
|
576
|
+
return {
|
|
577
|
+
aggregateFieldKinds,
|
|
578
|
+
queries: foldById(projections.map((p) => p.queries)) ?? [],
|
|
579
|
+
counts: foldById(projections.map((p) => p.counts)) ?? [],
|
|
580
|
+
spatials: foldById(projections.map((p) => p.spatials)) ?? [],
|
|
581
|
+
deriveds: foldById(projections.map((p) => p.deriveds)) ?? [],
|
|
582
|
+
combineds: foldById(projections.map((p) => p.combineds)) ?? [],
|
|
583
|
+
...(sums !== undefined ? { sums } : {}),
|
|
584
|
+
...(mins !== undefined ? { mins } : {}),
|
|
585
|
+
...(maxes !== undefined ? { maxes } : {}),
|
|
586
|
+
...(orderedReads !== undefined ? { orderedReads } : {}),
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
464
590
|
/**
|
|
465
591
|
* THE ORDERED OPINION-MAP FOLD: flatten module layers (weak → strong within each
|
|
466
592
|
* stage path) into the effective single-layer-per-domain document. Strongest
|
|
@@ -509,6 +635,8 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
509
635
|
stableIds = { v: 1, domain: domainSid, aggregates };
|
|
510
636
|
}
|
|
511
637
|
}
|
|
638
|
+
const identityManifest = foldIdentityManifest(stack, stableIds);
|
|
639
|
+
const readProjection = foldReadProjection(stack);
|
|
512
640
|
// The captured-read gate (#58): queries + per-directive read sets merged
|
|
513
641
|
// later-wins, SORTED keys (matching the composed emission).
|
|
514
642
|
let readGate: UsdLayer["nomosReadGate"];
|
|
@@ -606,6 +734,8 @@ export function flattenLayeredUsd(layers: readonly UsdLayer[]): UsdDocument {
|
|
|
606
734
|
return {
|
|
607
735
|
path,
|
|
608
736
|
prims: [...prims.keys()].sort().map((p) => prims.get(p)!),
|
|
737
|
+
...(identityManifest !== undefined ? { nomosIdentityManifest: identityManifest } : {}),
|
|
738
|
+
...(readProjection !== undefined ? { nomosReadProjection: readProjection } : {}),
|
|
609
739
|
...(queries !== undefined ? { queries } : {}),
|
|
610
740
|
...(deriveds !== undefined ? { deriveds } : {}),
|
|
611
741
|
...(combineds !== undefined ? { combineds } : {}),
|
|
@@ -733,6 +863,8 @@ function attrStringArray(prim: ParsedPrim, name: string): string[] {
|
|
|
733
863
|
export function parseUsdaDocument(text: string): UsdDocument {
|
|
734
864
|
const prims = parseUsdaPrims(text);
|
|
735
865
|
const domainByScope = new Map<string, string>();
|
|
866
|
+
const identityManifestByDomain = new Map<string, UsdLayer["nomosIdentityManifest"]>();
|
|
867
|
+
const readProjectionByDomain = new Map<string, UsdLayer["nomosReadProjection"]>();
|
|
736
868
|
const stableIdsByDomain = new Map<string, UsdLayer["nomosStableIds"]>();
|
|
737
869
|
const readGateByDomain = new Map<string, UsdLayer["nomosReadGate"]>();
|
|
738
870
|
const readVisibilityByDomain = new Map<string, UsdLayer["nomosReadVisibility"]>();
|
|
@@ -744,7 +876,15 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
744
876
|
if (p.attrs.get("nomos:kind") === "domain") {
|
|
745
877
|
const domain = attrString(p, "nomos:domain");
|
|
746
878
|
domainByScope.set(p.path, domain);
|
|
747
|
-
//
|
|
879
|
+
// Holon-owned manifests + gates: the hex-carried layer-level law keys.
|
|
880
|
+
const idHex = p.attrs.get("nomos:identityManifestHex");
|
|
881
|
+
if (typeof idHex === "string") {
|
|
882
|
+
identityManifestByDomain.set(domain, JSON.parse(unhexUtf8(idHex)) as UsdLayer["nomosIdentityManifest"]);
|
|
883
|
+
}
|
|
884
|
+
const rpHex = p.attrs.get("nomos:readProjectionHex");
|
|
885
|
+
if (typeof rpHex === "string") {
|
|
886
|
+
readProjectionByDomain.set(domain, JSON.parse(unhexUtf8(rpHex)) as UsdLayer["nomosReadProjection"]);
|
|
887
|
+
}
|
|
748
888
|
const sidHex = p.attrs.get("nomos:stableIdsHex");
|
|
749
889
|
if (typeof sidHex === "string") {
|
|
750
890
|
stableIdsByDomain.set(domain, JSON.parse(unhexUtf8(sidHex)) as UsdLayer["nomosStableIds"]);
|
|
@@ -865,6 +1005,8 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
865
1005
|
const layers: UsdLayer[] = [...buckets.keys()]
|
|
866
1006
|
.map((domain) => {
|
|
867
1007
|
const b = buckets.get(domain)!;
|
|
1008
|
+
const identity = identityManifestByDomain.get(domain);
|
|
1009
|
+
const readProjection = readProjectionByDomain.get(domain);
|
|
868
1010
|
const sids = stableIdsByDomain.get(domain);
|
|
869
1011
|
const rg = readGateByDomain.get(domain);
|
|
870
1012
|
const rv = readVisibilityByDomain.get(domain);
|
|
@@ -875,6 +1017,8 @@ export function parseUsdaDocument(text: string): UsdDocument {
|
|
|
875
1017
|
return {
|
|
876
1018
|
path: `/Nomos/${domain}`,
|
|
877
1019
|
prims: [...b.prims].sort(byPath),
|
|
1020
|
+
...(identity !== undefined ? { nomosIdentityManifest: identity } : {}),
|
|
1021
|
+
...(readProjection !== undefined ? { nomosReadProjection: readProjection } : {}),
|
|
878
1022
|
...(b.queries.length > 0 ? { queries: [...b.queries].sort(byId) } : {}),
|
|
879
1023
|
...(b.deriveds.length > 0 ? { deriveds: [...b.deriveds].sort(byId) } : {}),
|
|
880
1024
|
...(b.combineds.length > 0 ? { combineds: [...b.combineds].sort(byId) } : {}),
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* invariants, slice 3 delta lane + least-loaded placement).
|
|
11
11
|
*
|
|
12
12
|
* `nomos-compile` APPENDS this module to a TAXONOMY-BEARING domain's module list —
|
|
13
|
-
* both in the
|
|
13
|
+
* both in the compiled package metadata (the placement law is hash-bearing law) and in the
|
|
14
14
|
* generated engine entry (the plans ship in the lump). A taxonomy-FREE package never
|
|
15
15
|
* imports it (subpath `@githolon/dsl/workspace-sharding`, never the runtime barrel —
|
|
16
16
|
* the slice-1 hash-stability law: its bytes must not enter other tenants' lumps).
|
|
@@ -110,7 +110,7 @@ export interface ShardingRouteSpec {
|
|
|
110
110
|
export interface ShardingLawSpec {
|
|
111
111
|
readonly axes: readonly ShardingAxisSpec[];
|
|
112
112
|
/**
|
|
113
|
-
* THE DERIVED ROUTES (slice 2's
|
|
113
|
+
* THE DERIVED ROUTES (slice 2's package route facts, fed back into the law):
|
|
114
114
|
* per routed directive, the homing invariant `nomosWrongHome:<directive>` is derived
|
|
115
115
|
* so THE CHAIN GATE ITSELF refuses a wrong-home write (#41 — slice 3a; the edge
|
|
116
116
|
* bailiff stays as defense-in-depth). OMITTED routes ⇒ no invariants (slice-2 shape).
|
|
@@ -317,7 +317,6 @@ export const NomosSummarySubtotal = aggregate("NomosSummarySubtotal", {
|
|
|
317
317
|
export const NomosSummaryFrontier = aggregate("NomosSummaryFrontier", {
|
|
318
318
|
shard: t.string().merge(Lww),
|
|
319
319
|
frontier: t.string().merge(Lww), // the shard main oid the subtotals are true at
|
|
320
|
-
readManifestHash: t.string().merge(Lww),
|
|
321
320
|
updatedAt: t.string().merge(Lww),
|
|
322
321
|
});
|
|
323
322
|
|
|
@@ -530,7 +529,6 @@ export const nomosAmendSummaryFrontier = directive("nomosAmendSummaryFrontier")
|
|
|
530
529
|
z.object({
|
|
531
530
|
shard: z.string().regex(/^s\d+$/),
|
|
532
531
|
frontier: z.string(),
|
|
533
|
-
readManifestHash: z.string(),
|
|
534
532
|
updatedAt: z.string(),
|
|
535
533
|
}),
|
|
536
534
|
)
|
|
@@ -539,7 +537,6 @@ export const nomosAmendSummaryFrontier = directive("nomosAmendSummaryFrontier")
|
|
|
539
537
|
return [
|
|
540
538
|
withMarker(set(wm, "shard", p.shard), "ensures"),
|
|
541
539
|
set(wm, "frontier", p.frontier),
|
|
542
|
-
set(wm, "readManifestHash", p.readManifestHash),
|
|
543
540
|
set(wm, "updatedAt", p.updatedAt),
|
|
544
541
|
];
|
|
545
542
|
});
|
|
@@ -656,7 +653,6 @@ export const nomosPropagateSummary = directive("nomosPropagateSummary")
|
|
|
656
653
|
shard: z.string().regex(/^s\d+$/),
|
|
657
654
|
fromOid: z.string(), // "" = the shard's first delta (a virgin coordinator record)
|
|
658
655
|
toOid: z.string().min(1),
|
|
659
|
-
readManifestHash: z.string(),
|
|
660
656
|
propagatedAt: z.string(),
|
|
661
657
|
subtotals: z.array(summarySubtotalSchema).min(1).max(1024),
|
|
662
658
|
events: z.array(summaryEventSchema).max(4096),
|
|
@@ -762,7 +758,6 @@ export const nomosPropagateSummary = directive("nomosPropagateSummary")
|
|
|
762
758
|
ops.push(
|
|
763
759
|
withMarker(set(wm, "shard", p.shard), "ensures"),
|
|
764
760
|
set(wm, "frontier", p.toOid),
|
|
765
|
-
set(wm, "readManifestHash", p.readManifestHash),
|
|
766
761
|
set(wm, "updatedAt", p.propagatedAt),
|
|
767
762
|
);
|
|
768
763
|
return ops;
|