@githolon/dsl 0.108.0 → 0.108.1
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 +5 -0
- package/dart/lib/src/application_framework_calls.dart +299 -0
- package/dart/lib/src/generated_call.dart +96 -0
- package/dart/lib/src/nms_generated_runtime.dart +29 -0
- package/dart/lib/src/node_runner_transport.dart +77 -1
- package/dart/lib/src/result_usda.dart +487 -0
- package/dart/lib/src/runner/node-entry.mjs +6401 -2102
- package/dart/lib/src/runner/offline-install.mjs +1538 -163
- package/dart/lib/src/runtime_v2_gateway.dart +54 -0
- package/dart/lib/src/runtime_v2_transport.dart +117 -0
- package/dart/lib/src/session_bound.dart +7 -2
- package/dart/lib/src/test_harness.dart +193 -112
- package/dart/lib/src/webview_bridge.dart +2120 -569
- package/dart/pubspec.yaml +2 -2
- package/dart/test/acquire_session_credentials_test.dart +1 -1
- package/dart/test/acquire_session_test.dart +68 -14
- package/dart/test/adv_realm_interference_test.dart +6 -4
- package/dart/test/cluster_births_test.dart +11 -8
- package/dart/test/cluster_local_autosync_test.dart +1 -1
- package/dart/test/cluster_scale_test.dart +3 -2
- package/dart/test/dlq_session_surface_test.dart +52 -35
- package/dart/test/first_app_gauntlet_test.dart +1 -1
- package/dart/test/local_sync_inert_test.dart +23 -26
- package/dart/test/offer_authentication_proof_test.dart +193 -0
- package/dart/test/result_usda_test.dart +49 -0
- package/dart/test/session_bound_test.dart +8 -11
- package/dart/test/stale_bundle_test.dart +18 -3
- package/dart/test/test_harness_test.dart +14 -27
- package/dart/test/webview_bridge_test.dart +504 -83
- package/dart_types/CHANGELOG.md +7 -0
- package/dart_types/lib/nomos_kernel_protocol.dart +3 -2
- package/dart_types/lib/src/custody.dart +64 -19
- package/dart_types/lib/src/local_work_rejected.dart +30 -45
- package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pb.dart +169 -0
- package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +2021 -234
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +175 -8
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +8664 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +369 -0
- package/dart_types/lib/src/surfaced.dart +30 -25
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/surfaced_test.dart +2 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +5736 -2047
- package/src/authoring.ts +3 -2
- package/src/births.ts +21 -0
- package/src/build_package.ts +30 -0
- package/src/business_birth.ts +39 -35
- package/src/codegen_call_usda.ts +1111 -0
- package/src/codegen_dart.ts +207 -282
- package/src/codegen_dart_application.ts +195 -252
- package/src/codegen_dart_client.ts +1978 -593
- package/src/codegen_dart_framework_calls.ts +291 -0
- package/src/codegen_dart_scenario.ts +7 -0
- package/src/codegen_proof.ts +3 -4
- package/src/codegen_provider_dart.ts +21 -7
- package/src/codegen_query_usda.ts +214 -0
- package/src/codegen_result_usda.ts +685 -0
- package/src/codegen_ts.ts +3945 -1111
- package/src/compile_package_main.ts +360 -32
- package/src/directive.ts +19 -4
- package/src/engine_entry.ts +45 -4
- package/src/framework/application_home.ts +2 -0
- package/src/framework/auth_provider_law.ts +262 -20
- package/src/framework/home.ts +32 -28
- package/src/framework/owned_custody.ts +19 -11
- package/src/framework/owned_custody_value.ts +51 -0
- package/src/framework/relations.ts +47 -21
- package/src/framework/signing_identity.ts +34 -0
- package/src/framework/workspaces.ts +31 -9
- package/src/framework_call_definitions.ts +53 -0
- package/src/framework_read_definitions.ts +45 -0
- package/src/identity_frontier.ts +58 -0
- package/src/index.ts +20 -1
- package/src/intent.ts +216 -16
- package/src/law_check.ts +19 -1
- package/src/law_graph.ts +57 -8
- package/src/law_graph_usda.ts +73 -5
- package/src/law_value_type.ts +106 -19
- package/src/read.ts +47 -0
- package/src/read_projection_namespace.ts +7 -0
- package/src/shape_compat.ts +38 -39
- package/src/stable_ids.ts +37 -2
- package/src/test_call_usda.ts +83 -0
- package/src/wire.ts +36 -2
- package/src/wire_encode.ts +45 -1
- package/src/workspace_sharing.ts +27 -10
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbjson.dart +0 -6096
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbserver.dart +0 -50
- package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pbjson.dart +0 -178
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pb.dart +0 -828
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbenum.dart +0 -465
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbjson.dart +0 -573
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbserver.dart +0 -50
|
@@ -66,7 +66,9 @@ import type { ContractHandle } from "./contract.js";
|
|
|
66
66
|
import { bindEnumTypeExports } from "./enum_type.js";
|
|
67
67
|
import { discoverEvolutionModulePaths, isEvolutionModulePath } from "./evolution_files.js";
|
|
68
68
|
import { assertEvolutionModuleExports } from "./evolution.js";
|
|
69
|
+
import { readHistoricalIdentityFrontier } from "./identity_frontier.js";
|
|
69
70
|
import { generateDartBridgeClient } from "./codegen_dart_client.js";
|
|
71
|
+
import { generateDartApplicationFrameworkCalls } from "./codegen_dart_framework_calls.js";
|
|
70
72
|
import {
|
|
71
73
|
dartApplicationClassName,
|
|
72
74
|
dartApplicationPublicClassNames,
|
|
@@ -88,7 +90,10 @@ import {
|
|
|
88
90
|
} from "./framework/framework_aggregates.js";
|
|
89
91
|
import { RelationTuple, relationTuplesByObject } from "./framework/relations.js";
|
|
90
92
|
import { isNamespacedAggregate } from "./read_projection_namespace.js";
|
|
91
|
-
import {
|
|
93
|
+
import {
|
|
94
|
+
collectPayloadValueObjectDescriptors,
|
|
95
|
+
collectValueObjectDescriptors,
|
|
96
|
+
} from "./value_object.js";
|
|
92
97
|
import { finishCount, type AnyCount } from "./count.js";
|
|
93
98
|
import type { QueryDecl } from "./query.js";
|
|
94
99
|
import type { SpatialDecl } from "./spatial.js";
|
|
@@ -112,6 +117,7 @@ import {
|
|
|
112
117
|
expandBusinessBirthExports,
|
|
113
118
|
} from "./business_birth.js";
|
|
114
119
|
import { withOwnedCustodyExports } from "./framework/owned_custody.js";
|
|
120
|
+
import { OwnedCustodyValue, OwnedDeviceRequestValue } from "./framework/owned_custody_value.js";
|
|
115
121
|
import { expandRoleExports, rolesOf } from "./role.js";
|
|
116
122
|
import { collectEngineRouting } from "./engine_entry.js";
|
|
117
123
|
import {
|
|
@@ -158,9 +164,9 @@ import {
|
|
|
158
164
|
import { reconcileStableIdsWithIdentity } from "./stable_id_identity_bridge.js";
|
|
159
165
|
import { LAW_FRAMEWORK_PARENT } from "./law_identity.js";
|
|
160
166
|
import { discoverLawGraph, type LawGraph } from "./law_graph.js";
|
|
161
|
-
import {
|
|
167
|
+
import { compileSparseLawGraphUsda, emitFrameworkLawUsda } from "./law_graph_usda.js";
|
|
162
168
|
import { assertNoDartBarrelCollisions, type BarrelExportedFile } from "./dart_barrel_guard.js";
|
|
163
|
-
import { generateTsClient, tsApplicationName, tsClientFactoryName, recursiveLazyTypes } from "./codegen_ts.js";
|
|
169
|
+
import { generateTsClient, generateTsLifecycleOperator, tsApplicationName, tsClientFactoryName, recursiveLazyTypes } from "./codegen_ts.js";
|
|
164
170
|
import { generateOpenApiFragment, mergeOpenApiFragments } from "./codegen_openapi.js";
|
|
165
171
|
import { domainInterface, type DomainInterface } from "./shape_compat.js";
|
|
166
172
|
import { generateTsProof, proofLegsIndex } from "./codegen_proof.js";
|
|
@@ -174,6 +180,7 @@ import { applicationHomePolicyLaw } from "./framework/application_home.js";
|
|
|
174
180
|
import { isApplicationHomeGenesis } from "./application_home_genesis.js";
|
|
175
181
|
import { resolveApplicationTopology } from "./application_topology.js";
|
|
176
182
|
import { isBusinessIntent } from "./intent.js";
|
|
183
|
+
import { emitTsCallUsdaEncoder, TS_CALL_USDA_PRELUDE } from "./codegen_call_usda.js";
|
|
177
184
|
import {
|
|
178
185
|
compileApplicationComposition,
|
|
179
186
|
isApplicationCompositionConfig,
|
|
@@ -861,6 +868,11 @@ const DART_SUPPORT_RUNTIME_SRC = [
|
|
|
861
868
|
"webview_bridge.dart",
|
|
862
869
|
"session_bound.dart",
|
|
863
870
|
"record_origin.dart",
|
|
871
|
+
// Canonical USDA application-call/result syntax. Generated clients refer to
|
|
872
|
+
// these through the support barrel; omitting them from a vendored package
|
|
873
|
+
// silently resurrected the old map bridge at integration time.
|
|
874
|
+
"generated_call.dart",
|
|
875
|
+
"result_usda.dart",
|
|
864
876
|
] as const;
|
|
865
877
|
const DART_SUPPORT_SRC = [...DART_SUPPORT_CORE_SRC, ...DART_SUPPORT_RUNTIME_SRC] as const;
|
|
866
878
|
/** The local shim replacing `package:nomos_types/nomos_types.dart` inside vendored runtime files. */
|
|
@@ -1115,6 +1127,7 @@ function dartValueObjectsForModule(
|
|
|
1115
1127
|
const byName = new Map<string, NonNullable<DomainModule["valueObjects"]>[number]>();
|
|
1116
1128
|
for (const descriptor of [
|
|
1117
1129
|
...(mod.valueObjects ?? []),
|
|
1130
|
+
...collectValueObjectDescriptors(mod.aggregates),
|
|
1118
1131
|
...collectPayloadValueObjectDescriptors(codegenDirectives),
|
|
1119
1132
|
]) {
|
|
1120
1133
|
const prior = byName.get(descriptor.name);
|
|
@@ -1174,9 +1187,23 @@ function collectDartSharedSymbols(
|
|
|
1174
1187
|
}
|
|
1175
1188
|
}
|
|
1176
1189
|
}
|
|
1190
|
+
const frameworkVoByName = new Map(
|
|
1191
|
+
collectValueObjectDescriptors(frameworkAggs).map((descriptor) => [descriptor.name, descriptor]),
|
|
1192
|
+
);
|
|
1193
|
+
for (const [name, descriptor] of frameworkVoByName) {
|
|
1194
|
+
const prior = voDescriptorByName.get(name);
|
|
1195
|
+
if (prior !== undefined && JSON.stringify(prior) !== JSON.stringify(descriptor)) {
|
|
1196
|
+
throw new Error(
|
|
1197
|
+
`value object '${name}' has DIVERGENT framework/domain shapes — one name, one shape`,
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
voDescriptorByName.set(name, descriptor);
|
|
1201
|
+
}
|
|
1202
|
+
const frameworkVoNames = new Set(frameworkVoByName.keys());
|
|
1177
1203
|
const sharedVoNames: ReadonlySet<string> = new Set([
|
|
1178
1204
|
...[...voDomainsByName.entries()].filter(([, n]) => n > 1).map(([name]) => name),
|
|
1179
1205
|
...contractVoNames,
|
|
1206
|
+
...frameworkVoNames,
|
|
1180
1207
|
]);
|
|
1181
1208
|
const sharedVos = [...sharedVoNames].sort().map((name) => voDescriptorByName.get(name)!);
|
|
1182
1209
|
const hasFrameworkSymbols =
|
|
@@ -1317,6 +1344,8 @@ function emitDart(
|
|
|
1317
1344
|
modules: readonly DomainModule[],
|
|
1318
1345
|
dartOut: string,
|
|
1319
1346
|
domainHash: string,
|
|
1347
|
+
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
1348
|
+
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
1320
1349
|
packageInterface: Record<string, DomainInterface> = {},
|
|
1321
1350
|
supportImport: DartSupportImport = "vendored",
|
|
1322
1351
|
barrelName = "nomos_domains",
|
|
@@ -1364,9 +1393,20 @@ function emitDart(
|
|
|
1364
1393
|
const generatedKernelProto = path.join(DSL_DIR, "dart_types", "lib", "src", "proto", "nomos", "kernel", "v1");
|
|
1365
1394
|
const vendoredKernelProto = path.join(genDir, "src", "proto", "nomos", "kernel", "v1");
|
|
1366
1395
|
mkdirSync(vendoredKernelProto, { recursive: true });
|
|
1367
|
-
for (const f of [
|
|
1396
|
+
for (const f of [
|
|
1397
|
+
"kernel.pb.dart",
|
|
1398
|
+
"kernel.pbenum.dart",
|
|
1399
|
+
"progress.pb.dart",
|
|
1400
|
+
"progress.pbenum.dart",
|
|
1401
|
+
]) {
|
|
1368
1402
|
copyFileSync(path.join(generatedKernelProto, f), path.join(vendoredKernelProto, f));
|
|
1369
1403
|
}
|
|
1404
|
+
const generatedRuntimeProto = path.join(DSL_DIR, "dart_types", "lib", "src", "proto", "nomos", "runtime", "v2");
|
|
1405
|
+
const vendoredRuntimeProto = path.join(genDir, "src", "proto", "nomos", "runtime", "v2");
|
|
1406
|
+
mkdirSync(vendoredRuntimeProto, { recursive: true });
|
|
1407
|
+
for (const f of ["runtime.pb.dart", "runtime.pbenum.dart"]) {
|
|
1408
|
+
copyFileSync(path.join(generatedRuntimeProto, f), path.join(vendoredRuntimeProto, f));
|
|
1409
|
+
}
|
|
1370
1410
|
writeFileSync(
|
|
1371
1411
|
path.join(genDir, "src", VENDORED_KERNEL_PROTOCOL_SHIM),
|
|
1372
1412
|
[
|
|
@@ -1374,6 +1414,8 @@ function emitDart(
|
|
|
1374
1414
|
"library;",
|
|
1375
1415
|
"",
|
|
1376
1416
|
"export 'proto/nomos/kernel/v1/kernel.pb.dart';",
|
|
1417
|
+
"export 'proto/nomos/kernel/v1/progress.pb.dart';",
|
|
1418
|
+
"export 'proto/nomos/runtime/v2/runtime.pb.dart';",
|
|
1377
1419
|
"",
|
|
1378
1420
|
].join("\n"),
|
|
1379
1421
|
"utf8",
|
|
@@ -1445,10 +1487,51 @@ function emitDart(
|
|
|
1445
1487
|
return p;
|
|
1446
1488
|
};
|
|
1447
1489
|
|
|
1490
|
+
// Compiler-owned framework ceremonies (birth policy, signer seating, genesis, invitation
|
|
1491
|
+
// redemption) need the same generated USDA call types in flat/vendored output as in layered pub
|
|
1492
|
+
// packages. Keeping this file private to `src/generated` gives tests and generated application
|
|
1493
|
+
// infrastructure a typed setup lane without reintroducing raw payload maps.
|
|
1494
|
+
const applicationFrameworkCallsSource = generateDartApplicationFrameworkCalls(
|
|
1495
|
+
modules.flatMap((module) => {
|
|
1496
|
+
const graph = lawGraphs.get(module.name);
|
|
1497
|
+
const paths = lawPaths.get(module.name);
|
|
1498
|
+
return graph === undefined || paths === undefined ? [] : [{ module, graph, paths }];
|
|
1499
|
+
}),
|
|
1500
|
+
);
|
|
1501
|
+
if (applicationFrameworkCallsSource !== undefined) {
|
|
1502
|
+
const source = supportImport === "vendored"
|
|
1503
|
+
? applicationFrameworkCallsSource
|
|
1504
|
+
.replace(
|
|
1505
|
+
"import 'package:nomos_types/nomos_kernel_protocol.dart' show BirthCertificate;",
|
|
1506
|
+
`import 'src/${VENDORED_KERNEL_PROTOCOL_SHIM}' show BirthCertificate;`,
|
|
1507
|
+
)
|
|
1508
|
+
.replace(
|
|
1509
|
+
"import 'package:nomos_types/nomos_types.dart' show NomosSlot, Sha256Digest;",
|
|
1510
|
+
`import 'src/${VENDORED_TYPES_SHIM}' show NomosSlot, Sha256Digest;`,
|
|
1511
|
+
)
|
|
1512
|
+
.replace(
|
|
1513
|
+
"import 'package:nomos_client/src/application_framework_calls.dart';",
|
|
1514
|
+
"import 'src/application_framework_calls.dart';",
|
|
1515
|
+
)
|
|
1516
|
+
.replace(
|
|
1517
|
+
"import 'package:nomos_client/src/generated_call.dart';",
|
|
1518
|
+
"import 'src/generated_call.dart';",
|
|
1519
|
+
)
|
|
1520
|
+
: applicationFrameworkCallsSource;
|
|
1521
|
+
const applicationFrameworkCallsPath = path.join(genDir, "application.framework_calls.dart");
|
|
1522
|
+
writeFileSync(applicationFrameworkCallsPath, source, "utf8");
|
|
1523
|
+
written.push(applicationFrameworkCallsPath);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1448
1526
|
// 2a. the shared framework file — the framework aggregates + directives + queries, ONCE. Its own
|
|
1449
1527
|
// surface is emitted in full (no skip). Imported by every domain that folds any framework symbol.
|
|
1450
1528
|
if (shared.frameworkMod !== undefined) {
|
|
1451
|
-
writeGenerated(
|
|
1529
|
+
writeGenerated(
|
|
1530
|
+
FRAMEWORK_FILE,
|
|
1531
|
+
generateDartDomain(shared.frameworkMod, {
|
|
1532
|
+
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
1533
|
+
}),
|
|
1534
|
+
);
|
|
1452
1535
|
}
|
|
1453
1536
|
// 2a-bis. the shared DOMAIN CONTRACTS file (`contracts.dart`) — every public DTO class, ONCE. Pure
|
|
1454
1537
|
// (nomos_types + VOs). A foreignRef targeting a contract imports THIS, never the concrete domain.
|
|
@@ -1541,6 +1624,10 @@ function emitDart(
|
|
|
1541
1624
|
|
|
1542
1625
|
const clientSrc = generateDartBridgeClient(modForDart, {
|
|
1543
1626
|
domainHash,
|
|
1627
|
+
callUsda: {
|
|
1628
|
+
graph: lawGraphs.get(mod.name)!,
|
|
1629
|
+
paths: lawPaths.get(mod.name)!,
|
|
1630
|
+
},
|
|
1544
1631
|
interface: packageInterface[modForDart.domain ?? modForDart.name],
|
|
1545
1632
|
...(compat !== undefined ? { compat } : {}),
|
|
1546
1633
|
supportImport,
|
|
@@ -1560,6 +1647,7 @@ function emitDart(
|
|
|
1560
1647
|
applicationSrc,
|
|
1561
1648
|
clientFile,
|
|
1562
1649
|
applicationFile,
|
|
1650
|
+
new Set(dartApplicationPublicClassNames(modForDart)),
|
|
1563
1651
|
);
|
|
1564
1652
|
const cp = path.join(genDir, clientFile);
|
|
1565
1653
|
writeFileSync(cp, encapsulated.clientPart, "utf8");
|
|
@@ -1678,12 +1766,12 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
1678
1766
|
* just the floor generated code needs — a lagging pin forces tenants into dependency_overrides. */
|
|
1679
1767
|
// 0.3.0: SurfacedValue<T>/SurfacedObservation/PendingConflictRow — generated Surfaced-field typing +
|
|
1680
1768
|
// the pendingConflicts read rows.
|
|
1681
|
-
const NOMOS_TYPES_DEP = "^0.
|
|
1769
|
+
const NOMOS_TYPES_DEP = "^0.10.0";
|
|
1682
1770
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
1683
1771
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
1684
1772
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
1685
|
-
const NOMOS_CLIENT_DEP = "^0.65.
|
|
1686
|
-
const NOMOS_FLUTTER_DEP = "^0.64.
|
|
1773
|
+
const NOMOS_CLIENT_DEP = "^0.65.1";
|
|
1774
|
+
const NOMOS_FLUTTER_DEP = "^0.64.1";
|
|
1687
1775
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in dsl/dart/pubspec.yaml
|
|
1688
1776
|
// and dsl/dart_types/pubspec.yaml — a Dart release without this bump fails the suite, so tenants never
|
|
1689
1777
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -1746,6 +1834,7 @@ function encapsulateDartClient(
|
|
|
1746
1834
|
applicationSrc: string,
|
|
1747
1835
|
clientFile: string,
|
|
1748
1836
|
applicationFile: string,
|
|
1837
|
+
publicClientNames: ReadonlySet<string>,
|
|
1749
1838
|
): { readonly clientPart: string; readonly applicationLibrary: string } {
|
|
1750
1839
|
const directive = /^(import|export)\s+'([^']+)'(?:\s+[^;]+)?;\s*$/;
|
|
1751
1840
|
const clientImportUri = clientFile.replace(/\.dart$/, "");
|
|
@@ -1820,17 +1909,20 @@ function encapsulateDartClient(
|
|
|
1820
1909
|
"// ignore_for_file: unused_element, unused_element_parameter",
|
|
1821
1910
|
`part of '${applicationFile}';`,
|
|
1822
1911
|
"",
|
|
1823
|
-
privatize(client.body.join("\n")).trimStart(),
|
|
1912
|
+
privatize(client.body.join("\n"), publicClientNames).trimStart(),
|
|
1824
1913
|
"",
|
|
1825
1914
|
].join("\n"),
|
|
1826
1915
|
applicationLibrary: [
|
|
1827
1916
|
"// AUTO-GENERATED by nomos-compile — the sole importable application library.",
|
|
1828
|
-
"// ignore_for_file: unused_import, unused_field, invalid_use_of_internal_member",
|
|
1917
|
+
"// ignore_for_file: unused_import, unnecessary_import, unused_field, invalid_use_of_internal_member",
|
|
1829
1918
|
...imports.values(),
|
|
1830
1919
|
...exports.values(),
|
|
1831
1920
|
`part '${clientFile}';`,
|
|
1832
1921
|
"",
|
|
1833
|
-
privatize(
|
|
1922
|
+
privatize(
|
|
1923
|
+
application.body.join("\n"),
|
|
1924
|
+
new Set([...applicationNames, ...publicClientNames]),
|
|
1925
|
+
).trimStart(),
|
|
1834
1926
|
"",
|
|
1835
1927
|
].join("\n"),
|
|
1836
1928
|
};
|
|
@@ -1862,6 +1954,7 @@ function generatedPackageApplication(
|
|
|
1862
1954
|
}[],
|
|
1863
1955
|
homeDomain: string,
|
|
1864
1956
|
rootDomains: readonly string[],
|
|
1957
|
+
hasApplicationFrameworkCalls: boolean,
|
|
1865
1958
|
): string {
|
|
1866
1959
|
const application = dartApplicationClassName(packageName);
|
|
1867
1960
|
const root = domains.find(({ domain }) => domain === homeDomain);
|
|
@@ -1921,6 +2014,9 @@ function generatedPackageApplication(
|
|
|
1921
2014
|
`import 'package:nomos_flutter/src/application_status.dart' show ApplicationSignIn, ApplicationStatus;`,
|
|
1922
2015
|
`import 'package:nomos_client/src/nms_generated_runtime.dart' show NmsInternalUsers, NomosSession, User${hasInvitations ? ", Invitation, Recipient" : ""};`,
|
|
1923
2016
|
`import 'package:nomos_flutter/src/generated_application_host.dart' show ApplicationModelChange, NomosApplicationStartupState, NmsInternalApplicationHost, NmsInternalApplicationUserBinding${hasInvitations ? ", NmsInternalInvitationPolicy" : ""};`,
|
|
2017
|
+
...(hasApplicationFrameworkCalls
|
|
2018
|
+
? [`import 'application.framework_calls.dart' show nomosInternalApplicationFrameworkCalls;`]
|
|
2019
|
+
: []),
|
|
1924
2020
|
...members.map(({ file, prefix }) =>
|
|
1925
2021
|
`import '${file}.application.dart' as ${prefix};`),
|
|
1926
2022
|
``,
|
|
@@ -1985,6 +2081,7 @@ function generatedPackageApplication(
|
|
|
1985
2081
|
` /// Redeem a transported invitation as [currentUser].`,
|
|
1986
2082
|
` Future<void> redeemInvitation(String link) => NmsInternalApplicationHost.redeemInvitation<User>(`,
|
|
1987
2083
|
` _nmsSession,`,
|
|
2084
|
+
` frameworkCalls: nomosInternalApplicationFrameworkCalls,`,
|
|
1988
2085
|
` link: link,`,
|
|
1989
2086
|
` identity: _nmsUser.nmsInternalActor,`,
|
|
1990
2087
|
` policies: [`,
|
|
@@ -2023,6 +2120,9 @@ function generatedPackageApplication(
|
|
|
2023
2120
|
` Duration startupTimeout = const Duration(minutes: 3),`,
|
|
2024
2121
|
` }) => NmsInternalApplicationHost.home<${application}>(`,
|
|
2025
2122
|
` key: key, cloud: cloud, application: application, signIn: signIn,`,
|
|
2123
|
+
...(hasApplicationFrameworkCalls
|
|
2124
|
+
? [` frameworkCalls: nomosInternalApplicationFrameworkCalls,`]
|
|
2125
|
+
: []),
|
|
2026
2126
|
` bind: nomosInternalBind${application}, builder: builder,`,
|
|
2027
2127
|
` loadingBuilder: loadingBuilder, errorBuilder: errorBuilder,`,
|
|
2028
2128
|
` onModelChange: onModelChange,`,
|
|
@@ -2212,6 +2312,8 @@ function emitDartPackages(
|
|
|
2212
2312
|
modules: readonly DomainModule[],
|
|
2213
2313
|
dartOut: string,
|
|
2214
2314
|
domainHash: string,
|
|
2315
|
+
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
2316
|
+
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
2215
2317
|
packageInterface: Record<string, DomainInterface>,
|
|
2216
2318
|
packages: { readonly types: string; readonly client: string; readonly test?: string; readonly compat?: string; readonly barrelExports?: "all" | "explicit" },
|
|
2217
2319
|
names: Readonly<Record<string, string>> | undefined,
|
|
@@ -2219,6 +2321,7 @@ function emitDartPackages(
|
|
|
2219
2321
|
describePackageName = packages.client,
|
|
2220
2322
|
lawUsdzPath?: string,
|
|
2221
2323
|
applicationMaxChildWorkspacesPerUser?: number,
|
|
2324
|
+
frameworkModules: readonly DomainModule[] = modules,
|
|
2222
2325
|
): { written: string[]; cursed: string[] } {
|
|
2223
2326
|
for (const [role, name] of Object.entries(packages)) {
|
|
2224
2327
|
if (typeof name !== "string" || !isPubPackageName(name)) {
|
|
@@ -2291,7 +2394,14 @@ function emitDartPackages(
|
|
|
2291
2394
|
written.push(p);
|
|
2292
2395
|
};
|
|
2293
2396
|
|
|
2294
|
-
if (shared.frameworkMod !== undefined)
|
|
2397
|
+
if (shared.frameworkMod !== undefined) {
|
|
2398
|
+
writeTypes(
|
|
2399
|
+
FRAMEWORK_FILE,
|
|
2400
|
+
generateDartDomain(shared.frameworkMod, {
|
|
2401
|
+
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
2402
|
+
}),
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2295
2405
|
// DOMAIN CONTRACTS (layered): the shared `contracts.dart` DTO file in the TYPES package (pure —
|
|
2296
2406
|
// nomos_types + VOs). A contract-target foreignRef imports THIS sibling, never the concrete domain.
|
|
2297
2407
|
const contractsImportUri = packageContracts.length > 0 ? `${CONTRACTS_FILE}.dart` : undefined;
|
|
@@ -2492,6 +2602,22 @@ function emitDartPackages(
|
|
|
2492
2602
|
|
|
2493
2603
|
// ── the CLIENT package — effectful runtime, depends on types + nomos_client ──
|
|
2494
2604
|
const clientGen = freshGenDir(packages.client);
|
|
2605
|
+
const applicationFrameworkCallsFile = "application.framework_calls";
|
|
2606
|
+
const applicationFrameworkCallsSource = generateDartApplicationFrameworkCalls(
|
|
2607
|
+
frameworkModules.flatMap((module) => {
|
|
2608
|
+
const graph = lawGraphs.get(module.name);
|
|
2609
|
+
const paths = lawPaths.get(module.name);
|
|
2610
|
+
return graph === undefined || paths === undefined ? [] : [{ module, graph, paths }];
|
|
2611
|
+
}),
|
|
2612
|
+
);
|
|
2613
|
+
if (applicationFrameworkCallsSource !== undefined) {
|
|
2614
|
+
const applicationFrameworkCallsPath = path.join(
|
|
2615
|
+
clientGen,
|
|
2616
|
+
`${applicationFrameworkCallsFile}.dart`,
|
|
2617
|
+
);
|
|
2618
|
+
writeFileSync(applicationFrameworkCallsPath, applicationFrameworkCallsSource, "utf8");
|
|
2619
|
+
written.push(applicationFrameworkCallsPath);
|
|
2620
|
+
}
|
|
2495
2621
|
const embeddedLawName = `${describePackageName}.law.usdz`;
|
|
2496
2622
|
const applicationLawPath = lawUsdzPath === undefined
|
|
2497
2623
|
? undefined
|
|
@@ -2512,10 +2638,18 @@ function emitDartPackages(
|
|
|
2512
2638
|
: undefined;
|
|
2513
2639
|
const frameworkTypeNames = frameworkImplementationImport === undefined
|
|
2514
2640
|
? []
|
|
2515
|
-
: [...declaredDartTypeNames(typesSources.get(FRAMEWORK_FILE) ?? "")]
|
|
2641
|
+
: [...declaredDartTypeNames(typesSources.get(FRAMEWORK_FILE) ?? "")]
|
|
2642
|
+
// These private framework values are supplied by nomos_client itself. A
|
|
2643
|
+
// tenant implementation mentioning them must not manufacture an import of
|
|
2644
|
+
// the package-local framework file's duplicate private projection helper.
|
|
2645
|
+
.filter((name) => name !== OwnedCustodyValue.name && name !== OwnedDeviceRequestValue.name);
|
|
2516
2646
|
for (const { mod, dd } of perDomain) {
|
|
2517
2647
|
const makeClient = (imports: readonly string[]) => generateDartBridgeClient(dd.modForDart, {
|
|
2518
2648
|
domainHash,
|
|
2649
|
+
callUsda: {
|
|
2650
|
+
graph: lawGraphs.get(mod.name)!,
|
|
2651
|
+
paths: lawPaths.get(mod.name)!,
|
|
2652
|
+
},
|
|
2519
2653
|
...(applicationLawAssetKey !== undefined
|
|
2520
2654
|
? { lawAssetKey: applicationLawAssetKey }
|
|
2521
2655
|
: {}),
|
|
@@ -2540,6 +2674,9 @@ function emitDartPackages(
|
|
|
2540
2674
|
packageAggregateDomains: buildPackageAggregateDomains(modules),
|
|
2541
2675
|
flutterHost: true,
|
|
2542
2676
|
tenantRoot: perDomain.length === 1,
|
|
2677
|
+
...(applicationFrameworkCallsSource === undefined
|
|
2678
|
+
? {}
|
|
2679
|
+
: { applicationFrameworkCallsImportUri: `${applicationFrameworkCallsFile}.dart` }),
|
|
2543
2680
|
...(imports.length > 0
|
|
2544
2681
|
? { explicitTypeImports: imports }
|
|
2545
2682
|
: {}),
|
|
@@ -2565,6 +2702,7 @@ function emitDartPackages(
|
|
|
2565
2702
|
applicationSrc,
|
|
2566
2703
|
clientFile,
|
|
2567
2704
|
applicationFile,
|
|
2705
|
+
new Set(dartApplicationPublicClassNames(dd.modForDart)),
|
|
2568
2706
|
);
|
|
2569
2707
|
const cp = path.join(clientGen, clientFile);
|
|
2570
2708
|
writeFileSync(cp, encapsulated.clientPart, "utf8");
|
|
@@ -2595,6 +2733,7 @@ function emitDartPackages(
|
|
|
2595
2733
|
})),
|
|
2596
2734
|
topology.homeDomain,
|
|
2597
2735
|
topology.rootDomains,
|
|
2736
|
+
applicationFrameworkCallsSource !== undefined,
|
|
2598
2737
|
),
|
|
2599
2738
|
"utf8",
|
|
2600
2739
|
);
|
|
@@ -2726,6 +2865,9 @@ function emitDartPackages(
|
|
|
2726
2865
|
surfaceName,
|
|
2727
2866
|
applicationFile,
|
|
2728
2867
|
applicationModules: perDomain.map(({ dd: candidate }) => candidate.modForDart),
|
|
2868
|
+
...(applicationFrameworkCallsSource === undefined
|
|
2869
|
+
? {}
|
|
2870
|
+
: { applicationFrameworkCallsFile }),
|
|
2729
2871
|
...(applicationMaxChildWorkspacesPerUser === undefined
|
|
2730
2872
|
? {}
|
|
2731
2873
|
: { applicationMaxChildWorkspacesPerUser }),
|
|
@@ -3092,6 +3234,13 @@ async function main(): Promise<void> {
|
|
|
3092
3234
|
const nativeWorkspaceInvariantReadIds = new Set<string>();
|
|
3093
3235
|
const routingInput: Record<string, Mod[]> = {};
|
|
3094
3236
|
const domainModules: DomainModule[] = [];
|
|
3237
|
+
const directiveExportSources: Array<{
|
|
3238
|
+
readonly directive: object;
|
|
3239
|
+
readonly domainKey: string;
|
|
3240
|
+
readonly graphName: string;
|
|
3241
|
+
readonly modulePath: string;
|
|
3242
|
+
readonly exportName: string;
|
|
3243
|
+
}> = [];
|
|
3095
3244
|
// THE SELF-DESCRIBE DECLS (G1): per domain key, the FINISHED plain read/maintenance decls the
|
|
3096
3245
|
// lump's `globalThis.describe` needs that it cannot rediscover by shape alone (mins/maxes are
|
|
3097
3246
|
// config-named; sharding sums are framework-appended). Plain JSON (finishCount/Sum/Extremum
|
|
@@ -3189,6 +3338,13 @@ async function main(): Promise<void> {
|
|
|
3189
3338
|
typeof (value as { plan?: unknown }).plan === "function" &&
|
|
3190
3339
|
typeof (value as { aggregateId?: unknown }).aggregateId === "string"
|
|
3191
3340
|
) {
|
|
3341
|
+
directiveExportSources.push({
|
|
3342
|
+
directive: value,
|
|
3343
|
+
domainKey: d.key,
|
|
3344
|
+
graphName: d.name ?? d.key,
|
|
3345
|
+
modulePath: abs,
|
|
3346
|
+
exportName,
|
|
3347
|
+
});
|
|
3192
3348
|
directOfferExports.set((value as { id: string }).id, {
|
|
3193
3349
|
modulePath: abs,
|
|
3194
3350
|
exportName,
|
|
@@ -3794,6 +3950,10 @@ async function main(): Promise<void> {
|
|
|
3794
3950
|
const priorLock: CompilerIdentityModel | undefined = existsSync(lockPath)
|
|
3795
3951
|
? parseIdentityUsda(readFileSync(lockPath, "utf8"))
|
|
3796
3952
|
: undefined;
|
|
3953
|
+
const historicalFrontier = readHistoricalIdentityFrontier(lockPath);
|
|
3954
|
+
const historicalLock: CompilerIdentityModel | undefined = historicalFrontier === undefined
|
|
3955
|
+
? undefined
|
|
3956
|
+
: parseIdentityUsda(historicalFrontier.source);
|
|
3797
3957
|
const inferredRenames: { domain: string; renames: InferredRename[] }[] = [];
|
|
3798
3958
|
let nextIdentity = identityRegistryFromModel(priorLock);
|
|
3799
3959
|
const typedLawGraphs = new Map<string, LawGraph>();
|
|
@@ -3849,6 +4009,7 @@ async function main(): Promise<void> {
|
|
|
3849
4009
|
currentAggs,
|
|
3850
4010
|
prior,
|
|
3851
4011
|
priorSchemas,
|
|
4012
|
+
mod.retirements,
|
|
3852
4013
|
);
|
|
3853
4014
|
const reconciled = reconcileStableIdsWithIdentity(
|
|
3854
4015
|
nextIdentity,
|
|
@@ -3942,9 +4103,9 @@ async function main(): Promise<void> {
|
|
|
3942
4103
|
// The identity file is project-wide while a package may own only some of its domains. Scope the
|
|
3943
4104
|
// prior side to the modules in this compile so compiling one sibling never reads another sibling's
|
|
3944
4105
|
// absence as a domain retirement.
|
|
3945
|
-
if (
|
|
4106
|
+
if (historicalLock !== undefined) {
|
|
3946
4107
|
const priorDomainsForPackage: CompilerIdentityModel["domains"] = {};
|
|
3947
|
-
const priorIdentity = identityRegistryFromModel(
|
|
4108
|
+
const priorIdentity = identityRegistryFromModel(historicalLock);
|
|
3948
4109
|
const frameworkAggregateSids = new Set(
|
|
3949
4110
|
Object.values(priorIdentity.entities)
|
|
3950
4111
|
.filter((entity) => entity.kind === "aggregate" && entity.parent === LAW_FRAMEWORK_PARENT)
|
|
@@ -3952,7 +4113,7 @@ async function main(): Promise<void> {
|
|
|
3952
4113
|
);
|
|
3953
4114
|
for (const mod of domainModules) {
|
|
3954
4115
|
const domainKey = mod.domain ?? mod.name;
|
|
3955
|
-
const locked =
|
|
4116
|
+
const locked = historicalLock.domains[mod.name] ?? historicalLock.domains[domainKey];
|
|
3956
4117
|
if (locked !== undefined) {
|
|
3957
4118
|
const currentImplementationDetailAggregateIds = new Set(
|
|
3958
4119
|
mod.aggregates
|
|
@@ -3990,7 +4151,7 @@ async function main(): Promise<void> {
|
|
|
3990
4151
|
const priorLaw = evolveLawFromLockfile({
|
|
3991
4152
|
v: 1,
|
|
3992
4153
|
domains: priorDomainsForPackage,
|
|
3993
|
-
...(
|
|
4154
|
+
...(historicalLock.identity === undefined ? {} : { identity: historicalLock.identity }),
|
|
3994
4155
|
});
|
|
3995
4156
|
const candidateLaw = currentEvolveLaw(domainModules, nextLock);
|
|
3996
4157
|
const evolutionFindings = evolveDiff(priorLaw, candidateLaw).findings;
|
|
@@ -4080,10 +4241,12 @@ async function main(): Promise<void> {
|
|
|
4080
4241
|
const v3Closure = [...typedLawGraphs.values()];
|
|
4081
4242
|
const v3DomainAssets: EmittedLawClosureAsset[] = [];
|
|
4082
4243
|
const typedDomainIdentityByName = new Map<string, string>();
|
|
4244
|
+
const typedLawPathsByName = new Map<string, ReadonlyMap<string, string>>();
|
|
4083
4245
|
for (const [domain, graph] of typedLawGraphs) {
|
|
4084
4246
|
const safeDomain = domain.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
4085
4247
|
const logicalPath = `domains/${safeDomain}.usda`;
|
|
4086
|
-
const
|
|
4248
|
+
const compiledLayer = compileSparseLawGraphUsda(graph, logicalPath, v3Closure);
|
|
4249
|
+
const layerText = compiledLayer.text;
|
|
4087
4250
|
const sha256 = sha256HexUtf8(layerText);
|
|
4088
4251
|
v3DomainAssets.push({
|
|
4089
4252
|
logicalPath,
|
|
@@ -4091,6 +4254,66 @@ async function main(): Promise<void> {
|
|
|
4091
4254
|
utf8: layerText,
|
|
4092
4255
|
});
|
|
4093
4256
|
typedDomainIdentityByName.set(domain, sha256);
|
|
4257
|
+
typedLawPathsByName.set(domain, compiledLayer.paths);
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4260
|
+
// Cross-workspace effects retain the exact target Directive object in the typed application
|
|
4261
|
+
// language. Resolve that object back to its configured export once, then generate its nominal
|
|
4262
|
+
// USDA encoder from the target's own canonical graph. Runtime law receives no schema descriptor,
|
|
4263
|
+
// operation string or host mapping: only one generated function per exact target declaration.
|
|
4264
|
+
const workspaceEffectRuntimeBindings: Array<{
|
|
4265
|
+
readonly sourceDomain: string;
|
|
4266
|
+
readonly sourceModulePath: string;
|
|
4267
|
+
readonly sourceExportName: string;
|
|
4268
|
+
readonly targetModulePath: string;
|
|
4269
|
+
readonly targetExportName: string;
|
|
4270
|
+
readonly encoderName: string;
|
|
4271
|
+
readonly encoderSource: readonly string[];
|
|
4272
|
+
}> = [];
|
|
4273
|
+
for (const module of domainModules) {
|
|
4274
|
+
const sourceDomain = module.domain ?? module.name;
|
|
4275
|
+
for (const directive of module.directives ?? []) {
|
|
4276
|
+
if (!isBusinessIntent(directive)) continue;
|
|
4277
|
+
for (const effect of directive.workspaceEffects) {
|
|
4278
|
+
const sourceMatches = directiveExportSources.filter((candidate) => candidate.directive === directive);
|
|
4279
|
+
if (sourceMatches.length !== 1) {
|
|
4280
|
+
fail(
|
|
4281
|
+
`workspace effect source '${sourceDomain}/${directive.id}' is exported by ` +
|
|
4282
|
+
`${sourceMatches.length} configured law modules; export it once`,
|
|
4283
|
+
);
|
|
4284
|
+
}
|
|
4285
|
+
const source = sourceMatches[0]!;
|
|
4286
|
+
const matches = directiveExportSources.filter((candidate) => candidate.directive === effect.target);
|
|
4287
|
+
if (matches.length !== 1) {
|
|
4288
|
+
fail(
|
|
4289
|
+
`workspace effect '${sourceDomain}/${directive.id}' targets '${effect.target.id}', but that exact ` +
|
|
4290
|
+
`Directive object is exported by ${matches.length} configured law modules; export it once`,
|
|
4291
|
+
);
|
|
4292
|
+
}
|
|
4293
|
+
const target = matches[0]!;
|
|
4294
|
+
const graph = typedLawGraphs.get(target.graphName);
|
|
4295
|
+
const paths = typedLawPathsByName.get(target.graphName);
|
|
4296
|
+
if (graph === undefined || paths === undefined) {
|
|
4297
|
+
fail(`workspace effect target '${target.graphName}/${effect.target.id}' has no canonical law graph`);
|
|
4298
|
+
}
|
|
4299
|
+
const generated = emitTsCallUsdaEncoder(
|
|
4300
|
+
graph,
|
|
4301
|
+
paths,
|
|
4302
|
+
target.domainKey,
|
|
4303
|
+
effect.target.id,
|
|
4304
|
+
"any",
|
|
4305
|
+
);
|
|
4306
|
+
workspaceEffectRuntimeBindings.push({
|
|
4307
|
+
sourceDomain,
|
|
4308
|
+
sourceModulePath: source.modulePath,
|
|
4309
|
+
sourceExportName: source.exportName,
|
|
4310
|
+
targetModulePath: target.modulePath,
|
|
4311
|
+
targetExportName: target.exportName,
|
|
4312
|
+
encoderName: generated.functionName,
|
|
4313
|
+
encoderSource: generated.source,
|
|
4314
|
+
});
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4094
4317
|
}
|
|
4095
4318
|
|
|
4096
4319
|
// ── reports ──
|
|
@@ -4170,11 +4393,13 @@ async function main(): Promise<void> {
|
|
|
4170
4393
|
}
|
|
4171
4394
|
}
|
|
4172
4395
|
|
|
4173
|
-
// Resolve
|
|
4174
|
-
//
|
|
4175
|
-
//
|
|
4176
|
-
//
|
|
4177
|
-
|
|
4396
|
+
// Resolve the compiler's pinned esbuild before any application-local copy.
|
|
4397
|
+
// Application dependencies are authoring inputs, not part of the compiler
|
|
4398
|
+
// toolchain: allowing a stray nested node_modules to win makes identical law
|
|
4399
|
+
// source emit a different content-addressed runtime than a clean checkout.
|
|
4400
|
+
// Node's resolver still handles hoisted/workspace installs without relying on
|
|
4401
|
+
// node_modules/.bin paths.
|
|
4402
|
+
const esbuildPkgJson = [DSL_DIR, cfgDir]
|
|
4178
4403
|
.map((dir) => {
|
|
4179
4404
|
try {
|
|
4180
4405
|
return createRequire(pathToFileURL(path.join(dir, "noop.js"))).resolve("esbuild/package.json");
|
|
@@ -4186,7 +4411,9 @@ async function main(): Promise<void> {
|
|
|
4186
4411
|
if (!esbuildPkgJson) fail(`esbuild not found — reinstall @githolon/dsl (esbuild is one of its dependencies)`);
|
|
4187
4412
|
const esbuildMod = (await import(pathToFileURL(path.join(path.dirname(esbuildPkgJson), "lib", "main.js")).href)) as typeof import("esbuild");
|
|
4188
4413
|
|
|
4189
|
-
const compact =
|
|
4414
|
+
const compact = process.env.NOMOS_READABLE === "1"
|
|
4415
|
+
? false
|
|
4416
|
+
: compactFlag || cfg.compact === true;
|
|
4190
4417
|
const runtimeZodPath = path.join(DSL_DIR, "src", "runtime_zod.ts");
|
|
4191
4418
|
const runtimeZodPackage = createRequire(import.meta.url).resolve("zod/package.json");
|
|
4192
4419
|
const runtimeZodV4Path = path.join(path.dirname(runtimeZodPackage), "v4", "index.js");
|
|
@@ -4273,6 +4500,41 @@ async function main(): Promise<void> {
|
|
|
4273
4500
|
),
|
|
4274
4501
|
};
|
|
4275
4502
|
};
|
|
4503
|
+
const workspaceEffectRuntimeFor = (
|
|
4504
|
+
domainKeys: readonly string[],
|
|
4505
|
+
sourceSlice?: readonly PlanSourceSliceTarget[],
|
|
4506
|
+
) => {
|
|
4507
|
+
const wanted = new Set(domainKeys);
|
|
4508
|
+
const slicedSources = sourceSlice === undefined
|
|
4509
|
+
? undefined
|
|
4510
|
+
: new Set(sourceSlice.map((target) => `${target.modulePath}\0${target.exportName}`));
|
|
4511
|
+
const selected = workspaceEffectRuntimeBindings.filter((binding) =>
|
|
4512
|
+
wanted.has(binding.sourceDomain) &&
|
|
4513
|
+
(slicedSources === undefined ||
|
|
4514
|
+
slicedSources.has(`${binding.sourceModulePath}\0${binding.sourceExportName}`))
|
|
4515
|
+
);
|
|
4516
|
+
const unique = [...new Map(selected.map((binding) => [
|
|
4517
|
+
`${binding.targetModulePath}\0${binding.targetExportName}`,
|
|
4518
|
+
binding,
|
|
4519
|
+
])).values()];
|
|
4520
|
+
return {
|
|
4521
|
+
selected: unique,
|
|
4522
|
+
declarations: unique.length === 0
|
|
4523
|
+
? []
|
|
4524
|
+
: [...TS_CALL_USDA_PRELUDE, ...unique.flatMap((binding) => binding.encoderSource), ""],
|
|
4525
|
+
config: unique.length === 0
|
|
4526
|
+
? []
|
|
4527
|
+
: [
|
|
4528
|
+
` workspaceEffectTargets: [`,
|
|
4529
|
+
...unique.map((binding) =>
|
|
4530
|
+
` { target: require(${JSON.stringify(binding.targetModulePath)})` +
|
|
4531
|
+
`[${JSON.stringify(binding.targetExportName)}] as any, encode: (payload: unknown, workspace: string) => ` +
|
|
4532
|
+
`${binding.encoderName}(payload as any, workspace).canonicalUsda },`
|
|
4533
|
+
),
|
|
4534
|
+
` ],`,
|
|
4535
|
+
],
|
|
4536
|
+
};
|
|
4537
|
+
};
|
|
4276
4538
|
const planEntrySource = (
|
|
4277
4539
|
domainKeys: readonly string[],
|
|
4278
4540
|
includeReports: boolean,
|
|
@@ -4283,13 +4545,16 @@ async function main(): Promise<void> {
|
|
|
4283
4545
|
routedDomainFallback?: string,
|
|
4284
4546
|
includeMintInstalls = true,
|
|
4285
4547
|
sharedRuntime = false,
|
|
4548
|
+
sourceSlice?: readonly PlanSourceSliceTarget[],
|
|
4286
4549
|
): string => {
|
|
4550
|
+
const workspaceEffects = workspaceEffectRuntimeFor(domainKeys, sourceSlice);
|
|
4287
4551
|
return [
|
|
4288
4552
|
`// AUTO-GENERATED Nomos plan asset from ${path.basename(configPath)} — do not edit.`,
|
|
4289
4553
|
`declare function require(id: string): Record<string, unknown>;`,
|
|
4290
4554
|
...(sharedRuntime ? [] : zodSeedImports),
|
|
4291
4555
|
`import { registerEngine } from "@githolon/dsl/engine-entry";`,
|
|
4292
4556
|
``,
|
|
4557
|
+
...workspaceEffects.declarations,
|
|
4293
4558
|
`registerEngine({`,
|
|
4294
4559
|
` domains: {`,
|
|
4295
4560
|
...domainKeys.map((key) => {
|
|
@@ -4313,6 +4578,7 @@ async function main(): Promise<void> {
|
|
|
4313
4578
|
...(!sharedRuntime && zodSeedNames.length > 0 ? [` seeds: [${zodSeedNames.join(", ")}],`] : []),
|
|
4314
4579
|
...(includeDescribe ? [` openapiDocument: ${JSON.stringify(runtimeOpenApiDocument)},`] : []),
|
|
4315
4580
|
...(includeDescribe ? [` packageTitle: ${JSON.stringify(`${cfg.name} (nomos package)`)},`] : []),
|
|
4581
|
+
...workspaceEffects.config,
|
|
4316
4582
|
`});`,
|
|
4317
4583
|
...(includeMintInstalls
|
|
4318
4584
|
? domainKeys.flatMap((key) => {
|
|
@@ -4444,11 +4710,21 @@ async function main(): Promise<void> {
|
|
|
4444
4710
|
} = {},
|
|
4445
4711
|
): Promise<UsdPlanAsset> => {
|
|
4446
4712
|
const ordered = orderedDomainKeys.filter((key) => domainKeys.includes(key));
|
|
4713
|
+
const selectedWorkspaceEffects = workspaceEffectRuntimeFor(ordered, options.sliceTargets);
|
|
4714
|
+
const effectiveSliceTargets = options.sliceTargets === undefined
|
|
4715
|
+
? undefined
|
|
4716
|
+
: [...new Map([
|
|
4717
|
+
...options.sliceTargets,
|
|
4718
|
+
...selectedWorkspaceEffects.selected.map((binding) => ({
|
|
4719
|
+
modulePath: binding.targetModulePath,
|
|
4720
|
+
exportName: binding.targetExportName,
|
|
4721
|
+
})),
|
|
4722
|
+
].map((target) => [`${target.modulePath}\0${target.exportName}`, target] as const)).values()];
|
|
4447
4723
|
const signature = JSON.stringify({
|
|
4448
4724
|
domains: ordered,
|
|
4449
4725
|
reports: includeReports,
|
|
4450
4726
|
describe: includeDescribe,
|
|
4451
|
-
slice:
|
|
4727
|
+
slice: effectiveSliceTargets?.map((target) => [target.modulePath, target.exportName]) ?? null,
|
|
4452
4728
|
cacheKey: options.cacheKey ?? null,
|
|
4453
4729
|
});
|
|
4454
4730
|
const hit = planBySignature.get(signature);
|
|
@@ -4464,6 +4740,7 @@ async function main(): Promise<void> {
|
|
|
4464
4740
|
options.routedDomainFallback,
|
|
4465
4741
|
options.includeMintInstalls ?? true,
|
|
4466
4742
|
true,
|
|
4743
|
+
options.sliceTargets,
|
|
4467
4744
|
));
|
|
4468
4745
|
let planProfile: readonly { readonly module: string; readonly bytesInOutput: number }[] | undefined;
|
|
4469
4746
|
const profilePlan = process.env.NOMOS_PROFILE_PLANS === "1";
|
|
@@ -4504,9 +4781,9 @@ async function main(): Promise<void> {
|
|
|
4504
4781
|
external: [...sharedRuntimeModuleIds],
|
|
4505
4782
|
metafile: true,
|
|
4506
4783
|
logLevel: "silent",
|
|
4507
|
-
...(
|
|
4784
|
+
...(effectiveSliceTargets === undefined
|
|
4508
4785
|
? {}
|
|
4509
|
-
: { plugins: [planSourceSlicer.plugin(
|
|
4786
|
+
: { plugins: [planSourceSlicer.plugin(effectiveSliceTargets)] }),
|
|
4510
4787
|
});
|
|
4511
4788
|
rmSync(sourcePath, { force: true });
|
|
4512
4789
|
const output = result.outputFiles?.[0];
|
|
@@ -4958,7 +5235,7 @@ async function main(): Promise<void> {
|
|
|
4958
5235
|
` for (const [domain, directiveId] of workerData.checks) {`,
|
|
4959
5236
|
` let found;`,
|
|
4960
5237
|
` try { found = globalThis.__nomosHasDirective(domain, directiveId); }`,
|
|
4961
|
-
` catch (e) { parentPort.postMessage({ domain, error: String((e && e.message) || e) }); return; }`,
|
|
5238
|
+
` catch (e) { parentPort.postMessage({ domain, error: String((e && (e.stack || e.message)) || e) }); return; }`,
|
|
4962
5239
|
` if (directiveId !== "" && found !== true) {`,
|
|
4963
5240
|
` parentPort.postMessage({ domain, error: "routed offer '" + directiveId + "' is absent from its selected plan registry" });`,
|
|
4964
5241
|
` return;`,
|
|
@@ -4966,7 +5243,7 @@ async function main(): Promise<void> {
|
|
|
4966
5243
|
` }`,
|
|
4967
5244
|
` parentPort.postMessage({ ok: true });`,
|
|
4968
5245
|
` } catch (e) {`,
|
|
4969
|
-
` parentPort.postMessage({ domain: workerData.checks[0]?.[0] || "?", error: String((e && e.message) || e) });`,
|
|
5246
|
+
` parentPort.postMessage({ domain: workerData.checks[0]?.[0] || "?", error: String((e && (e.stack || e.message)) || e) });`,
|
|
4970
5247
|
` }`,
|
|
4971
5248
|
`} else {`,
|
|
4972
5249
|
` const jobs = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));`,
|
|
@@ -5367,6 +5644,8 @@ async function main(): Promise<void> {
|
|
|
5367
5644
|
const clientDeclarationPath = path.join(outDir, `${cfg.name}.client.d.mts`);
|
|
5368
5645
|
const headlessClientPath = path.join(outDir, `${cfg.name}.headless.mjs`);
|
|
5369
5646
|
const headlessClientDeclarationPath = path.join(outDir, `${cfg.name}.headless.d.mts`);
|
|
5647
|
+
const operatorPath = path.join(outDir, `${cfg.name}.operator.mjs`);
|
|
5648
|
+
const operatorDeclarationPath = path.join(outDir, `${cfg.name}.operator.d.mts`);
|
|
5370
5649
|
const clientOptions = {
|
|
5371
5650
|
packageName: cfg.name,
|
|
5372
5651
|
domainHash,
|
|
@@ -5374,12 +5653,18 @@ async function main(): Promise<void> {
|
|
|
5374
5653
|
interface: packageInterface,
|
|
5375
5654
|
compat: nomosCompat,
|
|
5376
5655
|
homeDomain: resolveApplicationTopology(presentationDomainModules).homeDomain,
|
|
5656
|
+
callUsda: [...typedLawGraphs].map(([name, graph]) => {
|
|
5657
|
+
const paths = typedLawPathsByName.get(name);
|
|
5658
|
+
if (paths === undefined) throw new Error(`domain '${name}' has no rendered USDA path index`);
|
|
5659
|
+
return { graph, paths };
|
|
5660
|
+
}),
|
|
5377
5661
|
} as const;
|
|
5378
5662
|
const clientSource = generateTsClient(presentationDomainModules, clientOptions);
|
|
5379
5663
|
const headlessClientSource = generateTsClient(presentationDomainModules, {
|
|
5380
5664
|
...clientOptions,
|
|
5381
5665
|
exportHolonFactory: true,
|
|
5382
5666
|
});
|
|
5667
|
+
const operatorSource = generateTsLifecycleOperator(clientOptions.callUsda);
|
|
5383
5668
|
const runtimePath = path.join(DSL_DIR, "runtime", "generated-application-host.js");
|
|
5384
5669
|
if (!existsSync(runtimePath)) {
|
|
5385
5670
|
fail("the compiler-private generated application runtime is missing — reinstall @githolon/dsl");
|
|
@@ -5396,7 +5681,7 @@ async function main(): Promise<void> {
|
|
|
5396
5681
|
const temporaryHeadlessDeclarationPath = temporaryHeadlessClientPath.replace(/\.ts$/, ".d.ts");
|
|
5397
5682
|
const runtimeTypesSource = [
|
|
5398
5683
|
`export declare function nomosInternalOpenGeneratedApplication<T extends object>(`,
|
|
5399
|
-
` options: { cloud: string; application: string; signIn: (request?: { readonly deviceChallenge?: string }) => Promise<string>; onPerformance?: (sample: { readonly operation: "open" | "offer" | "birth" | "read" | "sync" | "maintenance"; readonly name: string; readonly durationMs: number; readonly domain?: string; readonly directive?: string }) => void; approveModel?: (decision: { readonly summary: string; readonly review: { checkedActions: number; candidateActions: number; sameOutcome: boolean | null; differences: { kind: "rules" | "outcome" | "evidence"; area?: string; action?: string; summary: string }[] } }) => Promise<{ readonly because: string }>; lawHash: string; readyCommands?: readonly { readonly domain: string; readonly packageHash: string; readonly directiveId: string }[] },`,
|
|
5684
|
+
` options: { cloud: string; application: string; signIn: (request?: { readonly deviceChallenge?: string }) => Promise<string>; onPerformance?: (sample: { readonly operation: "open" | "offer" | "birth" | "read" | "sync" | "maintenance"; readonly name: string; readonly durationMs: number; readonly domain?: string; readonly directive?: string }) => void; approveModel?: (decision: { readonly summary: string; readonly review: { checkedActions: number; candidateActions: number; sameOutcome: boolean | null; differences: { kind: "rules" | "outcome" | "evidence"; area?: string; action?: string; summary: string }[] } }) => Promise<{ readonly because: string }>; lawHash: string; readyCommands?: readonly { readonly domain: string; readonly packageHash: string; readonly directiveId: string }[]; frameworkCalls: unknown },`,
|
|
5400
5685
|
` bind: (holon: unknown, user: { readonly identityId: string; readonly identityAddress: string }) => T,`,
|
|
5401
5686
|
`): Promise<T & {`,
|
|
5402
5687
|
` currentStatus(): Promise<any>;`,
|
|
@@ -5414,6 +5699,7 @@ async function main(): Promise<void> {
|
|
|
5414
5699
|
` holon: unknown,`,
|
|
5415
5700
|
` link: string,`,
|
|
5416
5701
|
` policies: readonly { readonly domain: string; readonly domainHash: string; readonly query: string; readonly redeem: string; readonly personField: string; readonly roleField: string; readonly scopeField: string }[],`,
|
|
5702
|
+
` frameworkCalls: unknown,`,
|
|
5417
5703
|
`): Promise<void>;`,
|
|
5418
5704
|
``,
|
|
5419
5705
|
].join("\n");
|
|
@@ -5723,6 +6009,47 @@ async function main(): Promise<void> {
|
|
|
5723
6009
|
if (!new RegExp(`export\\s*\\{[^}]*${tsClientFactoryName(resolveApplicationTopology(presentationDomainModules).homeDomain)}`, "s").test(headlessBundled)) {
|
|
5724
6010
|
fail("generated headless application omitted its structural holon factory");
|
|
5725
6011
|
}
|
|
6012
|
+
if (operatorSource !== undefined) {
|
|
6013
|
+
const operatorDeclaration = ts.transpileDeclaration(operatorSource, {
|
|
6014
|
+
fileName: `${cfg.name}.operator.ts`,
|
|
6015
|
+
compilerOptions: {
|
|
6016
|
+
target: ts.ScriptTarget.ES2022,
|
|
6017
|
+
module: ts.ModuleKind.ESNext,
|
|
6018
|
+
strict: true,
|
|
6019
|
+
},
|
|
6020
|
+
reportDiagnostics: true,
|
|
6021
|
+
});
|
|
6022
|
+
const operatorErrors = (operatorDeclaration.diagnostics ?? []).filter(
|
|
6023
|
+
(diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error,
|
|
6024
|
+
);
|
|
6025
|
+
if (operatorErrors.length > 0) {
|
|
6026
|
+
fail(`generated TypeScript lifecycle operator declarations are invalid — this is a Nomos codegen bug:\n${operatorErrors.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")).join("\n")}`);
|
|
6027
|
+
}
|
|
6028
|
+
writeFileSync(operatorDeclarationPath, operatorDeclaration.outputText, "utf8");
|
|
6029
|
+
await esbuildMod.build({
|
|
6030
|
+
stdin: {
|
|
6031
|
+
contents: operatorSource,
|
|
6032
|
+
loader: "ts",
|
|
6033
|
+
resolveDir: outDir,
|
|
6034
|
+
sourcefile: `${cfg.name}.operator.ts`,
|
|
6035
|
+
},
|
|
6036
|
+
outfile: operatorPath,
|
|
6037
|
+
bundle: true,
|
|
6038
|
+
platform: "neutral",
|
|
6039
|
+
format: "esm",
|
|
6040
|
+
target: "es2022",
|
|
6041
|
+
legalComments: "none",
|
|
6042
|
+
logLevel: "silent",
|
|
6043
|
+
});
|
|
6044
|
+
writeFileSync(
|
|
6045
|
+
operatorPath,
|
|
6046
|
+
canonicalizeGeneratedClientJavascript(readFileSync(operatorPath, "utf8")),
|
|
6047
|
+
"utf8",
|
|
6048
|
+
);
|
|
6049
|
+
} else {
|
|
6050
|
+
rmSync(operatorPath, { force: true });
|
|
6051
|
+
rmSync(operatorDeclarationPath, { force: true });
|
|
6052
|
+
}
|
|
5726
6053
|
} catch (e) {
|
|
5727
6054
|
fail(`generated TypeScript application could not be sealed — this is a Nomos codegen bug: ${(e as Error).message}`);
|
|
5728
6055
|
} finally {
|
|
@@ -5779,8 +6106,9 @@ async function main(): Promise<void> {
|
|
|
5779
6106
|
// restores the prior good packages instead of leaving them wiped/partial. Finalized at process exit.
|
|
5780
6107
|
if (dartPackages !== undefined) {
|
|
5781
6108
|
const r = emitDartPackages(
|
|
5782
|
-
presentationDomainModules, dartOut, domainHash, packageInterface, dartPackages,
|
|
6109
|
+
presentationDomainModules, dartOut, domainHash, typedLawGraphs, typedLawPathsByName, packageInterface, dartPackages,
|
|
5783
6110
|
dartNames, nomosCompat, cfg.name, lawUsdzPath, cfg.application?.maxChildWorkspacesPerUser,
|
|
6111
|
+
closedDomainModules,
|
|
5784
6112
|
);
|
|
5785
6113
|
dartFiles = r.written;
|
|
5786
6114
|
dartCursedHints = r.cursed;
|
|
@@ -5794,7 +6122,7 @@ async function main(): Promise<void> {
|
|
|
5794
6122
|
.replace(/^(?=[0-9])/, "n");
|
|
5795
6123
|
const dartBarrel =
|
|
5796
6124
|
typeof dartCfg === "object" && dartCfg.barrel !== undefined ? dartCfg.barrel : defaultBarrel;
|
|
5797
|
-
dartFiles = emitDart(presentationDomainModules, dartOut, domainHash, packageInterface, dartSupportImport, dartBarrel, nomosCompat, dartNames, cfg.name);
|
|
6125
|
+
dartFiles = emitDart(presentationDomainModules, dartOut, domainHash, typedLawGraphs, typedLawPathsByName, packageInterface, dartSupportImport, dartBarrel, nomosCompat, dartNames, cfg.name);
|
|
5798
6126
|
}
|
|
5799
6127
|
// COMPILE-VALID MUST MEAN COMPILABLE (co2): `githolon compile` reported success while the generated Dart
|
|
5800
6128
|
// had hard compiler errors (a duplicate id symbol, missing contract-id defs). Run `dart analyze` over the
|