@githolon/dsl 0.103.3 → 0.103.5
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/CHANGELOG.md +15 -0
- package/dart/lib/src/runner/node-entry.mjs +411 -149
- package/dart/lib/src/runner/offline-install.mjs +222 -99
- package/dart/lib/src/session_bound.dart +111 -2
- package/dart/lib/src/test_harness.dart +117 -66
- package/dart/lib/src/webview_bridge.dart +726 -61
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +4 -5
- package/dart/test/acquire_session_test.dart +62 -5
- package/dart/test/cloud_bound_topology_test.dart +59 -38
- package/dart/test/session_bound_test.dart +25 -10
- package/dart/test/webview_bridge_test.dart +357 -9
- package/dart_types/CHANGELOG.md +5 -0
- package/dart_types/lib/nomos_types.dart +1 -0
- package/dart_types/lib/src/git_object_id.dart +37 -0
- package/dart_types/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +425 -145
- package/src/births.ts +16 -1
- package/src/business_birth.ts +67 -46
- package/src/codegen_dart.ts +68 -12
- package/src/codegen_dart_application.ts +114 -19
- package/src/codegen_dart_client.ts +149 -6
- package/src/codegen_proof.ts +16 -9
- package/src/codegen_provider_dart.ts +5 -0
- package/src/codegen_ts.ts +115 -19
- package/src/compile_package_main.ts +142 -40
- package/src/fields.ts +43 -0
- package/src/framework/attested_receipts.ts +34 -1
- package/src/framework/domain_lifecycle.ts +140 -83
- package/src/framework/genesis.ts +2 -1
- package/src/framework/home.ts +20 -45
- package/src/framework/workspaces.ts +62 -29
- package/src/idof_lint.ts +65 -51
- package/src/index.ts +21 -1
- package/src/intent.ts +11 -1
- package/src/law_graph.ts +81 -11
- package/src/law_graph_usda.ts +45 -54
- package/src/relation_schema.ts +18 -0
- package/src/shape_compat.ts +3 -0
- package/src/stable_ids_for_module.ts +7 -1
- package/src/value_object.ts +40 -0
package/src/law_graph_usda.ts
CHANGED
|
@@ -1589,74 +1589,71 @@ function defaultOpinions(
|
|
|
1589
1589
|
owner: string,
|
|
1590
1590
|
indent: number,
|
|
1591
1591
|
): string[] {
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1592
|
+
// Every default, including a scalar, uses the same nominal value algebra as a call. Presence of
|
|
1593
|
+
// the typed `Default` child is the fact; there is no parallel property/tag representation.
|
|
1594
|
+
return emitNominalConstant("Default", value, owner, indent);
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
enum NominalConstantPrim {
|
|
1598
|
+
Null = "NomosNullValue",
|
|
1599
|
+
Boolean = "NomosBoolValue",
|
|
1600
|
+
Integer = "NomosIntValue",
|
|
1601
|
+
Number = "NomosNumberValue",
|
|
1602
|
+
String = "NomosStringValue",
|
|
1603
|
+
List = "NomosListValue",
|
|
1604
|
+
Record = "NomosRecordValue",
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
function nominalConstantPrim(value: import("./law_value_type.js").LawConstant): NominalConstantPrim {
|
|
1608
|
+
if (value === null) return NominalConstantPrim.Null;
|
|
1609
|
+
if (typeof value === "string") return NominalConstantPrim.String;
|
|
1610
|
+
if (typeof value === "boolean") return NominalConstantPrim.Boolean;
|
|
1595
1611
|
if (typeof value === "number") {
|
|
1596
|
-
return
|
|
1597
|
-
? `${pad}custom uniform int64 nomos:default = ${value}`
|
|
1598
|
-
: `${pad}custom uniform double nomos:default = ${value}`];
|
|
1612
|
+
return Number.isInteger(value) ? NominalConstantPrim.Integer : NominalConstantPrim.Number;
|
|
1599
1613
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
// USDA dictionaries cannot faithfully represent heterogeneous/nested arrays. Preserve the
|
|
1603
|
-
// complete constant instead as a typed prim tree: generic USD tools can traverse it, humans can
|
|
1604
|
-
// inspect it, and the kernel parser retains every opinion without an embedded JSON sub-language.
|
|
1605
|
-
const kind = Array.isArray(value) ? "array" : "record";
|
|
1606
|
-
return [
|
|
1607
|
-
`${pad}custom uniform token nomos:defaultKind = ${quote(kind)}`,
|
|
1608
|
-
`${pad}def Scope "Default"`,
|
|
1609
|
-
`${pad}{`,
|
|
1610
|
-
...emitDefaultValue(value, owner, indent + 4),
|
|
1611
|
-
`${pad}}`,
|
|
1612
|
-
];
|
|
1614
|
+
return Array.isArray(value) ? NominalConstantPrim.List : NominalConstantPrim.Record;
|
|
1613
1615
|
}
|
|
1614
1616
|
|
|
1615
|
-
function
|
|
1617
|
+
function emitNominalConstant(
|
|
1618
|
+
name: string,
|
|
1616
1619
|
value: import("./law_value_type.js").LawConstant,
|
|
1617
1620
|
owner: string,
|
|
1618
1621
|
indent: number,
|
|
1619
1622
|
): string[] {
|
|
1620
1623
|
const pad = " ".repeat(indent);
|
|
1624
|
+
const lines = [
|
|
1625
|
+
`${pad}def ${nominalConstantPrim(value)} ${quote(name)}`,
|
|
1626
|
+
`${pad}{`,
|
|
1627
|
+
];
|
|
1621
1628
|
if (typeof value === "string") {
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
`${pad}custom uniform string nomos:value = ${quote(value)}`,
|
|
1625
|
-
];
|
|
1629
|
+
lines.push(`${pad} custom uniform string nomos:value = ${quote(value)}`);
|
|
1630
|
+
return [...lines, `${pad}}`];
|
|
1626
1631
|
}
|
|
1627
1632
|
if (typeof value === "boolean") {
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
`${pad}custom uniform bool nomos:value = ${value}`,
|
|
1631
|
-
];
|
|
1633
|
+
lines.push(`${pad} custom uniform bool nomos:value = ${value}`);
|
|
1634
|
+
return [...lines, `${pad}}`];
|
|
1632
1635
|
}
|
|
1633
1636
|
if (typeof value === "number") {
|
|
1634
1637
|
if (!Number.isFinite(value)) fail(`field '${owner}' has a non-finite numeric default`);
|
|
1635
|
-
|
|
1636
|
-
`${pad}custom uniform
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
: `${pad}custom uniform double nomos:value = ${value}`,
|
|
1640
|
-
];
|
|
1638
|
+
lines.push(Number.isInteger(value)
|
|
1639
|
+
? `${pad} custom uniform int64 nomos:value = ${value}`
|
|
1640
|
+
: `${pad} custom uniform double nomos:value = ${value}`);
|
|
1641
|
+
return [...lines, `${pad}}`];
|
|
1641
1642
|
}
|
|
1642
|
-
if (value === null) return [`${pad}
|
|
1643
|
+
if (value === null) return [...lines, `${pad}}`];
|
|
1643
1644
|
|
|
1644
1645
|
const entries: readonly [string, import("./law_value_type.js").LawConstant][] = Array.isArray(value)
|
|
1645
1646
|
? value.map((item, index) => [String(index), item] as const)
|
|
1646
1647
|
: Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
1647
|
-
const kind = Array.isArray(value) ? "array" : "record";
|
|
1648
|
-
const lines = [`${pad}custom uniform token nomos:valueKind = ${quote(kind)}`];
|
|
1649
1648
|
for (const [index, [key, item]] of entries.entries()) {
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
`${pad}{
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
`${pad}}`,
|
|
1657
|
-
);
|
|
1649
|
+
const childName = `${Array.isArray(value) ? "i" : "f"}_${String(index).padStart(8, "0")}`;
|
|
1650
|
+
const child = emitNominalConstant(childName, item, owner, indent + 4);
|
|
1651
|
+
if (!Array.isArray(value)) {
|
|
1652
|
+
child.splice(2, 0, `${pad} custom uniform string nomos:name = ${quote(key)}`);
|
|
1653
|
+
}
|
|
1654
|
+
lines.push("", ...child);
|
|
1658
1655
|
}
|
|
1659
|
-
return lines;
|
|
1656
|
+
return [...lines, `${pad}}`];
|
|
1660
1657
|
}
|
|
1661
1658
|
|
|
1662
1659
|
function emitField(
|
|
@@ -1703,14 +1700,8 @@ function emitField(
|
|
|
1703
1700
|
body.push(
|
|
1704
1701
|
`${pad} def NomosFieldEvolutionCase "c_${String(caseIndex).padStart(8, "0")}"`,
|
|
1705
1702
|
`${pad} {`,
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
...emitDefaultValue(evolutionCase.from as import("./law_value_type.js").LawConstant, field.entity.label, indent + 24),
|
|
1709
|
-
`${pad} }`,
|
|
1710
|
-
`${pad} def Scope "To"`,
|
|
1711
|
-
`${pad} {`,
|
|
1712
|
-
...emitDefaultValue(evolutionCase.to as import("./law_value_type.js").LawConstant, field.entity.label, indent + 24),
|
|
1713
|
-
`${pad} }`,
|
|
1703
|
+
...emitNominalConstant("From", evolutionCase.from as import("./law_value_type.js").LawConstant, field.entity.label, indent + 20),
|
|
1704
|
+
...emitNominalConstant("To", evolutionCase.to as import("./law_value_type.js").LawConstant, field.entity.label, indent + 20),
|
|
1714
1705
|
`${pad} }`,
|
|
1715
1706
|
);
|
|
1716
1707
|
}
|
package/src/relation_schema.ts
CHANGED
|
@@ -108,6 +108,24 @@ export interface RelationTypeDecl {
|
|
|
108
108
|
readonly __isRelationType: true;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* A relation name that has deliberately crossed the authoring boundary.
|
|
113
|
+
*
|
|
114
|
+
* Plain strings remain accepted by the low-level DSL while existing tenant law migrates, but framework
|
|
115
|
+
* vocabulary should be coined once with {@link relationRef} and then reused by relation declarations,
|
|
116
|
+
* gates and tuple writes. That makes a rename a compiler-guided change instead of three unrelated string
|
|
117
|
+
* edits which can produce valid-looking, permanently unauthorized law.
|
|
118
|
+
*/
|
|
119
|
+
declare const NOMOS_RELATION_REF: unique symbol;
|
|
120
|
+
export type RelationRef<Name extends string = string> = Name & {
|
|
121
|
+
readonly [NOMOS_RELATION_REF]: "NomosRelationRef";
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/** Create one typed relation handle after validating the wire token once. */
|
|
125
|
+
export function relationRef<const Name extends string>(name: Name): RelationRef<Name> {
|
|
126
|
+
return requireName(name, "relation") as RelationRef<Name>;
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
export function isRelationTypeDecl(v: unknown): v is RelationTypeDecl {
|
|
112
130
|
return typeof v === "object" && v !== null && (v as { __isRelationType?: unknown }).__isRelationType === true;
|
|
113
131
|
}
|
package/src/shape_compat.ts
CHANGED
|
@@ -130,6 +130,9 @@ function payloadFieldKind(spec: PayloadFieldSpec): string {
|
|
|
130
130
|
case "ref":
|
|
131
131
|
// NomosRef<T> is aggregate-typed in the client and remains a string id on the wire.
|
|
132
132
|
return "string";
|
|
133
|
+
case "addressRef":
|
|
134
|
+
// A workspace-qualified NomosRef<T> preserves its complete address object.
|
|
135
|
+
return "json";
|
|
133
136
|
case "recipient":
|
|
134
137
|
// Recipient<User> is nominal in clients and an opaque delivery address on the law wire.
|
|
135
138
|
return "string";
|
|
@@ -254,7 +254,13 @@ function safeIdentityProjection(sourceShape: unknown, targetShape: unknown): boo
|
|
|
254
254
|
const target = targetShape as Record<string, unknown>;
|
|
255
255
|
const physical = (shape: Record<string, unknown>) => {
|
|
256
256
|
const { kind, mapValueKind, jsonShape, encrypted } = shape;
|
|
257
|
-
|
|
257
|
+
// `t.ref` and `t.foreignRef` store the target aggregate id as the same Str
|
|
258
|
+
// value as `t.string`; `ref` is a semantic/codegen contract, not a distinct
|
|
259
|
+
// kernel encoding. The JSON-schema subset check below still prevents an
|
|
260
|
+
// atomic NomosRef object (or any other non-string reference contract) from
|
|
261
|
+
// being mistaken for this identity migration.
|
|
262
|
+
const encodingKind = kind === "ref" ? "string" : kind;
|
|
263
|
+
return { kind: encodingKind, mapValueKind, jsonShape, encrypted };
|
|
258
264
|
};
|
|
259
265
|
return canonicalJson(physical(source)) === canonicalJson(physical(target))
|
|
260
266
|
&& jsonSchemaSubset(source.jsonSchema, target.jsonSchema);
|
package/src/value_object.ts
CHANGED
|
@@ -321,6 +321,46 @@ const nomosAddressSchema = z.object({
|
|
|
321
321
|
id: z.string().min(1),
|
|
322
322
|
});
|
|
323
323
|
|
|
324
|
+
/**
|
|
325
|
+
* THE WORKSPACE-QUALIFIED REFERENCE BRAND — `refOf(CatalogueWorkspace)` is
|
|
326
|
+
* wire-identical to Nomos' typed `{ workspace, type, id }` address, while
|
|
327
|
+
* generated clients expose it as `NomosRef<CatalogueWorkspace>`. Unlike
|
|
328
|
+
* `idOf(...)`, this deliberately preserves the workspace because it is the
|
|
329
|
+
* canonical payload shape for cross-workspace navigation and custody effects.
|
|
330
|
+
*/
|
|
331
|
+
export const NOMOS_REFOF_BRAND: unique symbol = Symbol.for("nomos.refOf");
|
|
332
|
+
|
|
333
|
+
export interface RefOfMeta {
|
|
334
|
+
readonly aggregateType: string;
|
|
335
|
+
readonly targetKind: "aggregate" | "contract";
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function refOf(target: RefTarget): z.ZodType<z.infer<typeof nomosAddressSchema>> {
|
|
339
|
+
const resolved = refTargetMeta(target, "refOf");
|
|
340
|
+
const schema = nomosAddressSchema.strict();
|
|
341
|
+
Object.defineProperty(schema, NOMOS_REFOF_BRAND, {
|
|
342
|
+
value: {
|
|
343
|
+
aggregateType: resolved.type,
|
|
344
|
+
targetKind: resolved.kind,
|
|
345
|
+
} satisfies RefOfMeta,
|
|
346
|
+
enumerable: false,
|
|
347
|
+
});
|
|
348
|
+
return schema;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** Resolve `refOf(...)` metadata through omission/null wrappers. */
|
|
352
|
+
export function refOfMetaOf(zt: z.ZodTypeAny): RefOfMeta | undefined {
|
|
353
|
+
let cur: z.ZodTypeAny | undefined = zt;
|
|
354
|
+
for (let hops = 0; cur !== undefined && hops < 16; hops++) {
|
|
355
|
+
const branded = (cur as unknown as Record<symbol, unknown>)[NOMOS_REFOF_BRAND];
|
|
356
|
+
if (typeof branded === "object" && branded !== null) return branded as RefOfMeta;
|
|
357
|
+
const kind = zodKind(cur);
|
|
358
|
+
if (kind !== "optional" && kind !== "default" && kind !== "nullable") return undefined;
|
|
359
|
+
cur = zodDef(cur).innerType;
|
|
360
|
+
}
|
|
361
|
+
return undefined;
|
|
362
|
+
}
|
|
363
|
+
|
|
324
364
|
/**
|
|
325
365
|
* A payload field holding an immutable publication and its stable current-version
|
|
326
366
|
* series. The kernel receives `{pinned, series}`; `current` is compiled law and
|