@githolon/dsl 0.2.3 → 0.4.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/package.json +4 -1
- package/src/build_package.ts +124 -3
- package/src/codegen_dart.ts +15 -0
- package/src/codegen_ts.ts +235 -7
- package/src/compile_package_main.ts +263 -5
- package/src/engine_entry.ts +124 -4
- package/src/framework/workspace_invariant.ts +7 -0
- package/src/index.ts +6 -0
- package/src/manifest.ts +67 -9
- package/src/usd.ts +37 -0
- package/src/workspace_routing.ts +585 -0
- package/src/workspace_sharding.ts +1284 -0
- package/src/workspace_type.ts +611 -0
package/src/manifest.ts
CHANGED
|
@@ -43,6 +43,11 @@ import type { DerivedDecl } from "./derived.js";
|
|
|
43
43
|
import type { CombinedDecl } from "./combined.js";
|
|
44
44
|
import type { CertifiedReadDecl } from "./certified_read.js";
|
|
45
45
|
import type { RelationDecl } from "./relation.js";
|
|
46
|
+
import { type CanonicalWorkspaceType } from "./workspace_type.js";
|
|
47
|
+
import {
|
|
48
|
+
canonicalTaxonomyFragment,
|
|
49
|
+
type CanonicalDirectiveRoute,
|
|
50
|
+
} from "./workspace_routing.js";
|
|
46
51
|
|
|
47
52
|
/** One captured `[fieldName, zodKind]` payload field, with optionality. */
|
|
48
53
|
export interface CanonicalPayloadField {
|
|
@@ -221,6 +226,13 @@ export interface CanonicalCount {
|
|
|
221
226
|
readonly where?: CanonicalPred;
|
|
222
227
|
/** The group-by field, in DECLARED form. OMITTED for a grand-total count. */
|
|
223
228
|
readonly by?: string;
|
|
229
|
+
/**
|
|
230
|
+
* THE ESTATE SCOPE (sharding §5, slice 3): the workspace-type id this read is
|
|
231
|
+
* lifted to via `scoped(read, Ws)` — its per-shard values ride the §5.2 delta
|
|
232
|
+
* lane as gate-recomputed coordinator subtotals. OMITTED for home-scope reads
|
|
233
|
+
* (every pre-slice-3 count is byte-identical — the `cap(n)` discipline).
|
|
234
|
+
*/
|
|
235
|
+
readonly scope?: string;
|
|
224
236
|
}
|
|
225
237
|
|
|
226
238
|
/**
|
|
@@ -263,6 +275,8 @@ export interface CanonicalSum {
|
|
|
263
275
|
readonly where?: CanonicalPred;
|
|
264
276
|
/** The group-by field. OMITTED for a grand-total sum. */
|
|
265
277
|
readonly by?: string;
|
|
278
|
+
/** THE ESTATE SCOPE (sharding §5, slice 3) — see {@link CanonicalCount.scope}. */
|
|
279
|
+
readonly scope?: string;
|
|
266
280
|
}
|
|
267
281
|
|
|
268
282
|
/**
|
|
@@ -320,6 +334,12 @@ export interface CanonicalExtremum {
|
|
|
320
334
|
readonly where?: CanonicalPred;
|
|
321
335
|
/** The group-by field. OMITTED for a grand-total extremum. */
|
|
322
336
|
readonly by?: string;
|
|
337
|
+
/** THE ESTATE SCOPE (sharding §5, slice 8) — see {@link CanonicalCount.scope}:
|
|
338
|
+
* per-shard extremums ride the §5.2 delta lane as gate-adjudicated coordinator
|
|
339
|
+
* subtotals (extremize-on-monotone; retractions re-derive). OMITTED for
|
|
340
|
+
* home-scope extremums, so an unscoped declaration is byte-identical to before
|
|
341
|
+
* this key existed (golden hashes UNCHANGED). */
|
|
342
|
+
readonly scope?: string;
|
|
323
343
|
}
|
|
324
344
|
|
|
325
345
|
/**
|
|
@@ -428,6 +448,29 @@ export interface CanonicalManifest {
|
|
|
428
448
|
* (non-optional at both TS and manifest levels), optional predicate, and `limit`.
|
|
429
449
|
*/
|
|
430
450
|
readonly orderedReads?: CanonicalOrderedRead[];
|
|
451
|
+
/**
|
|
452
|
+
* The domain's FIRST-CLASS WORKSPACE TYPES (sharding §10 RATIFIED, slice 1), SORTED
|
|
453
|
+
* by id. OMITTED ENTIRELY when the domain declares none — so a taxonomy-free domain
|
|
454
|
+
* is byte-identical to before this key existed (pinned golden hashes UNCHANGED; the
|
|
455
|
+
* `cap(n)` discipline). The taxonomy IS law: a type's root/mode/children/globals/
|
|
456
|
+
* pool/cap all move the domain hash (per-type optional keys omitted-when-absent).
|
|
457
|
+
*/
|
|
458
|
+
readonly workspaceTypes?: CanonicalWorkspaceType[];
|
|
459
|
+
/**
|
|
460
|
+
* The DERIVED HOMING TABLE (aggregate wire id → workspace-type id) — present iff
|
|
461
|
+
* {@link workspaceTypes} is. Derived (never hand-written) by the fail-closed homing
|
|
462
|
+
* walk over the aggregates' `t.ref` chains, and HASH-BEARING: a homing move is a
|
|
463
|
+
* law change (placement of FACTS is custody, but which chain a fact is BORN into
|
|
464
|
+
* is law — the shard gate's `wrong-home` invariant pins to this table).
|
|
465
|
+
*/
|
|
466
|
+
readonly homes?: Record<string, string>;
|
|
467
|
+
/**
|
|
468
|
+
* THE DERIVED DIRECTIVE ROUTING TABLE (sharding slice 2) — present only when the
|
|
469
|
+
* domain declares a taxonomy with at least one packed-homed directive, SORTED by
|
|
470
|
+
* directive id, HASH-BEARING (the client routes by it; the shard gate's typed
|
|
471
|
+
* `wrong-home` refusal pins to it). OMITTED ENTIRELY otherwise (hash-stable).
|
|
472
|
+
*/
|
|
473
|
+
readonly routes?: CanonicalDirectiveRoute[];
|
|
431
474
|
}
|
|
432
475
|
|
|
433
476
|
/** Minimal structural view of Zod 4 schema internals we read deterministically. */
|
|
@@ -690,15 +733,16 @@ function canonicalCounts(
|
|
|
690
733
|
): { counts?: CanonicalCount[] } {
|
|
691
734
|
if (declared === undefined || declared.length === 0) return {};
|
|
692
735
|
const counts: CanonicalCount[] = [...declared]
|
|
693
|
-
.map(finishCount)
|
|
694
|
-
.map((c) => ({
|
|
736
|
+
.map((raw) => ({ finished: finishCount(raw), scope: (raw as { scope?: unknown }).scope }))
|
|
737
|
+
.map(({ finished: c, scope }) => ({
|
|
695
738
|
id: c.id,
|
|
696
739
|
of: c.of,
|
|
697
|
-
// OMIT-WHEN-ABSENT: `where` and `
|
|
698
|
-
// predicate-free
|
|
699
|
-
// (hash-stable — the same discipline as every other optional
|
|
740
|
+
// OMIT-WHEN-ABSENT: `where`, `by` and `scope` are omitted when not declared so
|
|
741
|
+
// a predicate-free / grand-total / home-scope count is byte-identical to the
|
|
742
|
+
// legacy form (hash-stable — the same discipline as every other optional key).
|
|
700
743
|
...(c.where !== undefined ? { where: c.where } : {}),
|
|
701
744
|
...(c.by !== undefined ? { by: c.by } : {}),
|
|
745
|
+
...(typeof scope === "string" ? { scope } : {}),
|
|
702
746
|
}))
|
|
703
747
|
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
704
748
|
return { counts };
|
|
@@ -733,13 +777,14 @@ function canonicalSpatials(
|
|
|
733
777
|
function canonicalSums(declared: AnySum[] | undefined): { sums?: CanonicalSum[] } {
|
|
734
778
|
if (declared === undefined || declared.length === 0) return {};
|
|
735
779
|
const sums: CanonicalSum[] = [...declared]
|
|
736
|
-
.map(finishSum)
|
|
737
|
-
.map((s) => ({
|
|
780
|
+
.map((raw) => ({ finished: finishSum(raw), scope: (raw as { scope?: unknown }).scope }))
|
|
781
|
+
.map(({ finished: s, scope }) => ({
|
|
738
782
|
id: s.id,
|
|
739
783
|
of: s.of,
|
|
740
784
|
sumField: s.sumField,
|
|
741
785
|
...(s.where !== undefined ? { where: s.where } : {}),
|
|
742
786
|
...(s.by !== undefined ? { by: s.by } : {}),
|
|
787
|
+
...(typeof scope === "string" ? { scope } : {}),
|
|
743
788
|
}))
|
|
744
789
|
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
745
790
|
return { sums };
|
|
@@ -802,14 +847,17 @@ function canonicalExtrema(
|
|
|
802
847
|
): { mins?: CanonicalExtremum[] } | { maxes?: CanonicalExtremum[] } {
|
|
803
848
|
if (declared === undefined || declared.length === 0) return {};
|
|
804
849
|
const items: CanonicalExtremum[] = [...declared]
|
|
805
|
-
.map(finishExtremum)
|
|
806
|
-
.map((e) => ({
|
|
850
|
+
.map((raw) => ({ finished: finishExtremum(raw), scope: (raw as { scope?: unknown }).scope }))
|
|
851
|
+
.map(({ finished: e, scope }) => ({
|
|
807
852
|
id: e.id,
|
|
808
853
|
kind: e.kind,
|
|
809
854
|
of: e.of,
|
|
810
855
|
valueField: e.valueField,
|
|
811
856
|
...(e.where !== undefined ? { where: e.where } : {}),
|
|
812
857
|
...(e.by !== undefined ? { by: e.by } : {}),
|
|
858
|
+
// OMIT-WHEN-ABSENT (the canonicalSums discipline): a home-scope extremum is
|
|
859
|
+
// byte-identical to before the scope key existed — hash-stable by default.
|
|
860
|
+
...(typeof scope === "string" ? { scope } : {}),
|
|
813
861
|
}))
|
|
814
862
|
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
815
863
|
return { [keyName]: items };
|
|
@@ -901,6 +949,16 @@ export function domainManifest(mod: DomainModule): CanonicalManifest {
|
|
|
901
949
|
...(canonicalExtrema(mod.mins, "mins") as { mins?: CanonicalExtremum[] }),
|
|
902
950
|
...(canonicalExtrema(mod.maxes, "maxes") as { maxes?: CanonicalExtremum[] }),
|
|
903
951
|
...canonicalOrderedReads(mod.orderedReads),
|
|
952
|
+
// Omit-when-empty: a taxonomy-free domain contributes NO taxonomy key (hash-
|
|
953
|
+
// stable). When declared, this RUNS the fail-closed homing walk AND the slice-2
|
|
954
|
+
// route derivation — an unhomeable or unroutable taxonomy never produces an
|
|
955
|
+
// identity (workspace_type.ts + workspace_routing.ts).
|
|
956
|
+
...canonicalTaxonomyFragment({
|
|
957
|
+
name: mod.name,
|
|
958
|
+
aggregates: mod.aggregates,
|
|
959
|
+
directives: mod.directives,
|
|
960
|
+
...(mod.workspaceTypes !== undefined ? { workspaceTypes: mod.workspaceTypes } : {}),
|
|
961
|
+
}),
|
|
904
962
|
};
|
|
905
963
|
}
|
|
906
964
|
|
package/src/usd.ts
CHANGED
|
@@ -170,6 +170,24 @@ export interface UsdLayer {
|
|
|
170
170
|
* same discipline as `queries`/`references`/`reads`/`emits`).
|
|
171
171
|
*/
|
|
172
172
|
readonly variantSets?: Record<string, Record<string, UsdPrim[]>>;
|
|
173
|
+
/**
|
|
174
|
+
* THE INVARIANT-GATE DECLARATION (#41 — "the law is the era"). Present IFF the layer's
|
|
175
|
+
* module declares ≥1 invariant (aggregate or workspace): the law's EXPLICIT opt-in to
|
|
176
|
+
* invariant EXECUTION at the one gate. The wasm gate runs the engine-backed invariant
|
|
177
|
+
* oracles for an intent only when the law resolved for that intent carries this key —
|
|
178
|
+
* every bundle compiled before #41 (whose declared invariants the gate held as hashed-
|
|
179
|
+
* but-inert law) lacks it, so chains sealed under the inert gate replay green forever.
|
|
180
|
+
* OMITTED (`undefined`) for invariant-free law — byte-identical hash, same discipline
|
|
181
|
+
* as `queries`/`references`. Hand-adding it to a foreign bundle only opts IN to
|
|
182
|
+
* stricter checking; removing it makes new law, for that law's own chains (status quo).
|
|
183
|
+
*/
|
|
184
|
+
readonly nomosInvariantGate?: {
|
|
185
|
+
readonly v: 1;
|
|
186
|
+
/** Aggregate types whose declared `invariant` bodies the gate executes, sorted. */
|
|
187
|
+
readonly aggregates?: string[];
|
|
188
|
+
/** Declared workspace invariants `{id, on}` the gate executes, sorted by id. */
|
|
189
|
+
readonly workspaceInvariants?: { id: string; on: string }[];
|
|
190
|
+
};
|
|
173
191
|
}
|
|
174
192
|
|
|
175
193
|
/** The reserved variant name declaring a set's DEFAULT (USD has a default variant). */
|
|
@@ -239,12 +257,31 @@ export function emitUsd(
|
|
|
239
257
|
// which already applies omit-when-empty: `queries` is present here ONLY when the
|
|
240
258
|
// module declared them, so a query-free layer is byte-identical to before.
|
|
241
259
|
const manifest = domainManifest(l.module);
|
|
260
|
+
// THE INVARIANT-GATE DECLARATION (#41): presence-only, derived from the SAME module
|
|
261
|
+
// the lump's executable bodies come from — sorted, omit-when-empty (hash-stable for
|
|
262
|
+
// invariant-free law; see the `UsdLayer.nomosInvariantGate` banner for the era rule).
|
|
263
|
+
const invariantAggregates = l.module.aggregates
|
|
264
|
+
.filter((a) => a.hasInvariant === true)
|
|
265
|
+
.map((a) => a.id)
|
|
266
|
+
.sort();
|
|
267
|
+
const wsInvariants = [...(l.module.workspaceInvariants ?? [])]
|
|
268
|
+
.map((w) => ({ id: w.id, on: w.on }))
|
|
269
|
+
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
242
270
|
return {
|
|
243
271
|
path: l.path,
|
|
244
272
|
prims: encodeModuleToPrims(l.path, l.module),
|
|
245
273
|
...(manifest.queries !== undefined ? { queries: manifest.queries } : {}),
|
|
246
274
|
...(manifest.deriveds !== undefined ? { deriveds: manifest.deriveds } : {}),
|
|
247
275
|
...(manifest.combineds !== undefined ? { combineds: manifest.combineds } : {}),
|
|
276
|
+
...(invariantAggregates.length > 0 || wsInvariants.length > 0
|
|
277
|
+
? {
|
|
278
|
+
nomosInvariantGate: {
|
|
279
|
+
v: 1 as const,
|
|
280
|
+
...(invariantAggregates.length > 0 ? { aggregates: invariantAggregates } : {}),
|
|
281
|
+
...(wsInvariants.length > 0 ? { workspaceInvariants: wsInvariants } : {}),
|
|
282
|
+
},
|
|
283
|
+
}
|
|
284
|
+
: {}),
|
|
248
285
|
};
|
|
249
286
|
})
|
|
250
287
|
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|