@githolon/dsl 0.33.0 → 0.34.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 +1 -1
- package/src/aggregate.ts +12 -1
- package/src/authoring.ts +4 -1
- package/src/birth_meter.ts +300 -0
- package/src/birth_meter_ensure.ts +67 -0
- package/src/build_package.ts +34 -0
- package/src/compile_engine.ts +13 -2
- package/src/compile_package_main.ts +16 -0
- package/src/directive.ts +10 -1
- package/src/engine_entry.ts +56 -9
- package/src/framework/birth_meter.ts +125 -0
- package/src/framework/impure_capability.ts +5 -2
- package/src/framework/platform_admin.ts +4 -1
- package/src/framework/relations.ts +19 -0
- package/src/framework/workspaces.ts +42 -1
- package/src/index.ts +34 -0
- package/src/read.ts +22 -0
- package/src/read_projection_composition.ts +117 -0
- package/src/read_projection_manifest.ts +94 -0
- package/src/read_projection_namespace.ts +152 -0
- package/src/usd.ts +121 -11
- package/src/usd_layers.ts +71 -0
- package/src/value_object.ts +43 -0
- package/src/wire_encode.ts +34 -3
package/src/value_object.ts
CHANGED
|
@@ -411,3 +411,46 @@ export function collectValueObjectDescriptors(
|
|
|
411
411
|
}
|
|
412
412
|
return [...byName.values()].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
413
413
|
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* ONE VO↔FIELD ATTACHMENT (the IR pointer): aggregate `aggregate`'s field `field`
|
|
417
|
+
* stores value object `vo`. Rides the additive `nomosValueObjects` USD key as
|
|
418
|
+
* `usages` so tooling (the scene projector, the explorer glyphs) can attach a VO
|
|
419
|
+
* molecule to the exact field that carries it. NEVER in the canonical
|
|
420
|
+
* manifest/domainHash — a VO field's wire schema stays a plain `jsonObject` leaf.
|
|
421
|
+
*/
|
|
422
|
+
export interface ValueObjectUsage {
|
|
423
|
+
readonly aggregate: string;
|
|
424
|
+
readonly field: string;
|
|
425
|
+
readonly vo: string;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Collect the sorted VO↔field usage pointers of a set of aggregates (one entry per
|
|
430
|
+
* VO-typed field; sorted by aggregate then field — byte-deterministic). Returns `[]`
|
|
431
|
+
* when no field carries a VO — the omit-when-empty input to the `usages` entry of
|
|
432
|
+
* the `nomosValueObjects` era key.
|
|
433
|
+
*/
|
|
434
|
+
export function collectValueObjectUsages(
|
|
435
|
+
aggregates: readonly { id: string; fields: Record<string, Field> }[],
|
|
436
|
+
): ValueObjectUsage[] {
|
|
437
|
+
const usages: ValueObjectUsage[] = [];
|
|
438
|
+
for (const agg of aggregates) {
|
|
439
|
+
for (const fieldName of Object.keys(agg.fields)) {
|
|
440
|
+
const meta = agg.fields[fieldName]!.valueObject;
|
|
441
|
+
if (meta === undefined) continue;
|
|
442
|
+
usages.push({ aggregate: agg.id, field: fieldName, vo: meta.name });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return usages.sort((a, b) =>
|
|
446
|
+
a.aggregate !== b.aggregate
|
|
447
|
+
? a.aggregate < b.aggregate
|
|
448
|
+
? -1
|
|
449
|
+
: 1
|
|
450
|
+
: a.field < b.field
|
|
451
|
+
? -1
|
|
452
|
+
: a.field > b.field
|
|
453
|
+
? 1
|
|
454
|
+
: 0,
|
|
455
|
+
);
|
|
456
|
+
}
|
package/src/wire_encode.ts
CHANGED
|
@@ -20,9 +20,16 @@
|
|
|
20
20
|
* LATER coordinated migration — we target the current serde_json shape now.
|
|
21
21
|
*/
|
|
22
22
|
import { encodeDriver } from "./drivers.js";
|
|
23
|
+
import { __qualifyAggregateType } from "./framework/relations.js";
|
|
23
24
|
import { __resetAuthoring, __drainAuthoring } from "./authoring.js";
|
|
24
25
|
import { __resetReads, __drainReads } from "./read.js";
|
|
25
26
|
import { __resetBirths, __drainBirths } from "./births.js";
|
|
27
|
+
import {
|
|
28
|
+
birthMeterSubject,
|
|
29
|
+
birthMeterBornAt,
|
|
30
|
+
captureBirthMeterReads,
|
|
31
|
+
planBirthRecordOps,
|
|
32
|
+
} from "./birth_meter.js";
|
|
26
33
|
import type { AggregateHandle } from "./aggregate.js";
|
|
27
34
|
import type { Field, EvidenceRefValue } from "./fields.js";
|
|
28
35
|
import type { Directive, ReferentialMarker } from "./directive.js";
|
|
@@ -203,13 +210,33 @@ export function executeDirectiveToIntent<P>(
|
|
|
203
210
|
__resetReads();
|
|
204
211
|
__resetBirths();
|
|
205
212
|
const returned = directive.plan(parsed, ctx);
|
|
206
|
-
const planned = [...__drainAuthoring(), ...returned];
|
|
207
|
-
const reads = __drainReads();
|
|
208
213
|
// THE BIRTH EFFECT (G3 — birth is a declared kernel primitive): a `.births()` directive's plan records
|
|
209
214
|
// the child's genesis recipe via `birth(recipe)`; it rides the intent as a DECLARED output (like a
|
|
210
215
|
// captured read), drained here. Empty for every non-birth directive — OMITTED below so a birth-free
|
|
211
216
|
// intent is byte-identical (the era rule).
|
|
212
217
|
const births = __drainBirths();
|
|
218
|
+
// METERED BIRTH (slice A — architecture/metered_birth_and_attested_reads.md). For every PLANNED birth,
|
|
219
|
+
// the library — HERE, in the ONE plan-output assembly both lanes (client authoring + the sealed engine's
|
|
220
|
+
// `plan`) funnel through, so the halves are byte-identical by construction — does two things the tenant
|
|
221
|
+
// never writes:
|
|
222
|
+
// A1 THE AUTO-RECORD: append the `NomosBirthRecord` field ops (deterministic id per child; Lww upsert)
|
|
223
|
+
// to the SAME intent that carries the birth effect. The kernel's `nomosBirthRecordGate` era arm
|
|
224
|
+
// refuses a new-era birth whose intent carries no record — this is what satisfies it.
|
|
225
|
+
// A2 THE AUTO-CAPTURE: capture the three meter reads (records-by-subject + grant + policy — the #58
|
|
226
|
+
// lane `.births()` auto-declares) so the synthesized birth-quota invariant judges over COMMITTED,
|
|
227
|
+
// CAS-re-derived pre-apply state on every lane.
|
|
228
|
+
// A `.births()` dispatch that planned NO birth (e.g. birthChild without a genesis) appends/captures
|
|
229
|
+
// nothing — byte-identical to before (the era rule); pre-era bundles ship an older lump and are untouched.
|
|
230
|
+
const meterOps: PlannedOp[] = [];
|
|
231
|
+
if (births.length > 0) {
|
|
232
|
+
const payloadRecord = parsed as unknown as Record<string, unknown>;
|
|
233
|
+
const subject = birthMeterSubject(payloadRecord);
|
|
234
|
+
captureBirthMeterReads(subject);
|
|
235
|
+
const bornAt = birthMeterBornAt(payloadRecord);
|
|
236
|
+
for (const b of births) meterOps.push(...planBirthRecordOps(b, subject, bornAt));
|
|
237
|
+
}
|
|
238
|
+
const planned = [...__drainAuthoring(), ...returned, ...meterOps];
|
|
239
|
+
const reads = __drainReads();
|
|
213
240
|
|
|
214
241
|
// Partition the plan output: STRIKE ops route onto the intent's `strikes` channel
|
|
215
242
|
// (the kernel's strikeout / revert facet, folded by parity); FIELD ops group into
|
|
@@ -293,7 +320,11 @@ export function executeDirectiveToIntent<P>(
|
|
|
293
320
|
aggregate,
|
|
294
321
|
marker: eventMarker,
|
|
295
322
|
ops: [
|
|
296
|
-
|
|
323
|
+
// READ-PROJECTION NAMESPACING: the stamped TYPE is qualified by the dispatching domain iff
|
|
324
|
+
// the domain declares it non-global — so the folded row's `__type` equals the qualified
|
|
325
|
+
// schema key the SAME compile wrote (rows and read manifest agree by construction). Outside
|
|
326
|
+
// a plan dispatch (codegen probes) the type passes through bare.
|
|
327
|
+
{ field: "__type", op: { Set: { Str: __qualifyAggregateType(ty) } } },
|
|
297
328
|
{ field: "__id", op: { Set: { Str: aggregate } } },
|
|
298
329
|
...ops,
|
|
299
330
|
],
|