@githolon/dsl 0.107.4 → 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 +24 -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 +10634 -6122
- package/dart/lib/src/runner/offline-install.mjs +4187 -2716
- 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 +373 -282
- package/dart/lib/src/webview_bridge.dart +2146 -725
- package/dart/pubspec.lock +17 -1
- package/dart/pubspec.yaml +3 -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 +17 -0
- package/dart_types/lib/nomos_kernel_protocol.dart +11 -0
- 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 +17945 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +933 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pb.dart +245 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pbenum.dart +160 -0
- 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.lock +16 -0
- package/dart_types/pubspec.yaml +3 -1
- package/dart_types/test/surfaced_test.dart +2 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +5760 -1879
- package/src/authoring.ts +3 -2
- package/src/birth_meter_ensure.ts +2 -0
- package/src/births.ts +21 -0
- package/src/build_package.ts +30 -0
- package/src/business_birth.ts +41 -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 +392 -46
- package/src/directive.ts +19 -4
- package/src/engine_entry.ts +45 -4
- package/src/framework/application_home.ts +4 -0
- package/src/framework/auth_provider_law.ts +296 -20
- package/src/framework/birth_certificate_law.ts +24 -0
- package/src/framework/home.ts +83 -40
- package/src/framework/owned_custody.ts +25 -12
- package/src/framework/owned_custody_value.ts +51 -0
- package/src/framework/relations.ts +47 -21
- package/src/framework/signing_identity.ts +100 -17
- package/src/framework/workspaces.ts +39 -10
- 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 +22 -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 +44 -42
- 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
|
@@ -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,11 +868,19 @@ 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. */
|
|
867
879
|
const VENDORED_TYPES_SHIM = "nomos_types.dart";
|
|
880
|
+
const VENDORED_KERNEL_PROTOCOL_SHIM = "nomos_kernel_protocol.dart";
|
|
868
881
|
const VENDORED_META_DEP = "^1.12.0";
|
|
882
|
+
const VENDORED_PROTOBUF_DEP = "^5.0.0";
|
|
883
|
+
const VENDORED_FIXNUM_DEP = "^1.1.1";
|
|
869
884
|
const VENDORED_DART_SDK_FLOOR = "3.3.0";
|
|
870
885
|
|
|
871
886
|
/**
|
|
@@ -909,21 +924,12 @@ function ensureVendoredPackageRequirements(dartOut: string): void {
|
|
|
909
924
|
`${sdkLine[1]}\">=${VENDORED_DART_SDK_FLOOR} <4.0.0\"${sdkLine[3] ?? ""}`,
|
|
910
925
|
);
|
|
911
926
|
}
|
|
912
|
-
if (
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
writeFileSync(
|
|
920
|
-
pubspec,
|
|
921
|
-
next.replace(
|
|
922
|
-
/^dependencies:\s*$/m,
|
|
923
|
-
"dependencies:\n meta: " + VENDORED_META_DEP,
|
|
924
|
-
),
|
|
925
|
-
"utf8",
|
|
926
|
-
);
|
|
927
|
+
if (next !== source) writeFileSync(pubspec, next, "utf8");
|
|
928
|
+
reconcilePubspec(dir, "", {
|
|
929
|
+
meta: VENDORED_META_DEP,
|
|
930
|
+
protobuf: VENDORED_PROTOBUF_DEP,
|
|
931
|
+
fixnum: VENDORED_FIXNUM_DEP,
|
|
932
|
+
});
|
|
927
933
|
}
|
|
928
934
|
|
|
929
935
|
/** The generated-owned subdirectory, relative to `dartOut` (the pub package's `lib/`). WIPED and
|
|
@@ -1121,6 +1127,7 @@ function dartValueObjectsForModule(
|
|
|
1121
1127
|
const byName = new Map<string, NonNullable<DomainModule["valueObjects"]>[number]>();
|
|
1122
1128
|
for (const descriptor of [
|
|
1123
1129
|
...(mod.valueObjects ?? []),
|
|
1130
|
+
...collectValueObjectDescriptors(mod.aggregates),
|
|
1124
1131
|
...collectPayloadValueObjectDescriptors(codegenDirectives),
|
|
1125
1132
|
]) {
|
|
1126
1133
|
const prior = byName.get(descriptor.name);
|
|
@@ -1180,9 +1187,23 @@ function collectDartSharedSymbols(
|
|
|
1180
1187
|
}
|
|
1181
1188
|
}
|
|
1182
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());
|
|
1183
1203
|
const sharedVoNames: ReadonlySet<string> = new Set([
|
|
1184
1204
|
...[...voDomainsByName.entries()].filter(([, n]) => n > 1).map(([name]) => name),
|
|
1185
1205
|
...contractVoNames,
|
|
1206
|
+
...frameworkVoNames,
|
|
1186
1207
|
]);
|
|
1187
1208
|
const sharedVos = [...sharedVoNames].sort().map((name) => voDescriptorByName.get(name)!);
|
|
1188
1209
|
const hasFrameworkSymbols =
|
|
@@ -1323,6 +1344,8 @@ function emitDart(
|
|
|
1323
1344
|
modules: readonly DomainModule[],
|
|
1324
1345
|
dartOut: string,
|
|
1325
1346
|
domainHash: string,
|
|
1347
|
+
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
1348
|
+
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
1326
1349
|
packageInterface: Record<string, DomainInterface> = {},
|
|
1327
1350
|
supportImport: DartSupportImport = "vendored",
|
|
1328
1351
|
barrelName = "nomos_domains",
|
|
@@ -1357,9 +1380,46 @@ function emitDart(
|
|
|
1357
1380
|
.replace(
|
|
1358
1381
|
/import 'package:nomos_types\/src\/(?:nomos_ref|foreign_ref|versioned_nomos_ref)\.dart'/g,
|
|
1359
1382
|
`import '${VENDORED_TYPES_SHIM}'`,
|
|
1383
|
+
)
|
|
1384
|
+
.replace(
|
|
1385
|
+
/import 'package:nomos_types\/nomos_kernel_protocol\.dart'/g,
|
|
1386
|
+
`import '${VENDORED_KERNEL_PROTOCOL_SHIM}'`,
|
|
1360
1387
|
);
|
|
1361
1388
|
writeFileSync(path.join(genDir, "src", f), src, "utf8");
|
|
1362
1389
|
}
|
|
1390
|
+
// Protobuf is the sole kernel/host message schema. Flat vendored packages receive a generated
|
|
1391
|
+
// projection of that schema, never a handwritten certificate mirror. The compiler copies only the
|
|
1392
|
+
// generated kernel files this runtime uses; `generate:kernel-proto-dart` remains their source.
|
|
1393
|
+
const generatedKernelProto = path.join(DSL_DIR, "dart_types", "lib", "src", "proto", "nomos", "kernel", "v1");
|
|
1394
|
+
const vendoredKernelProto = path.join(genDir, "src", "proto", "nomos", "kernel", "v1");
|
|
1395
|
+
mkdirSync(vendoredKernelProto, { recursive: true });
|
|
1396
|
+
for (const f of [
|
|
1397
|
+
"kernel.pb.dart",
|
|
1398
|
+
"kernel.pbenum.dart",
|
|
1399
|
+
"progress.pb.dart",
|
|
1400
|
+
"progress.pbenum.dart",
|
|
1401
|
+
]) {
|
|
1402
|
+
copyFileSync(path.join(generatedKernelProto, f), path.join(vendoredKernelProto, f));
|
|
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
|
+
}
|
|
1410
|
+
writeFileSync(
|
|
1411
|
+
path.join(genDir, "src", VENDORED_KERNEL_PROTOCOL_SHIM),
|
|
1412
|
+
[
|
|
1413
|
+
"// GENERATED from proto/nomos/kernel/v1/kernel.proto by nomos-compile. DO NOT EDIT.",
|
|
1414
|
+
"library;",
|
|
1415
|
+
"",
|
|
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';",
|
|
1419
|
+
"",
|
|
1420
|
+
].join("\n"),
|
|
1421
|
+
"utf8",
|
|
1422
|
+
);
|
|
1363
1423
|
// The local shim the rewritten runtime imports resolve through (the vendored twin of the
|
|
1364
1424
|
// nomos_types barrel — core files only).
|
|
1365
1425
|
writeFileSync(
|
|
@@ -1427,10 +1487,51 @@ function emitDart(
|
|
|
1427
1487
|
return p;
|
|
1428
1488
|
};
|
|
1429
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
|
+
|
|
1430
1526
|
// 2a. the shared framework file — the framework aggregates + directives + queries, ONCE. Its own
|
|
1431
1527
|
// surface is emitted in full (no skip). Imported by every domain that folds any framework symbol.
|
|
1432
1528
|
if (shared.frameworkMod !== undefined) {
|
|
1433
|
-
writeGenerated(
|
|
1529
|
+
writeGenerated(
|
|
1530
|
+
FRAMEWORK_FILE,
|
|
1531
|
+
generateDartDomain(shared.frameworkMod, {
|
|
1532
|
+
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
1533
|
+
}),
|
|
1534
|
+
);
|
|
1434
1535
|
}
|
|
1435
1536
|
// 2a-bis. the shared DOMAIN CONTRACTS file (`contracts.dart`) — every public DTO class, ONCE. Pure
|
|
1436
1537
|
// (nomos_types + VOs). A foreignRef targeting a contract imports THIS, never the concrete domain.
|
|
@@ -1523,6 +1624,10 @@ function emitDart(
|
|
|
1523
1624
|
|
|
1524
1625
|
const clientSrc = generateDartBridgeClient(modForDart, {
|
|
1525
1626
|
domainHash,
|
|
1627
|
+
callUsda: {
|
|
1628
|
+
graph: lawGraphs.get(mod.name)!,
|
|
1629
|
+
paths: lawPaths.get(mod.name)!,
|
|
1630
|
+
},
|
|
1526
1631
|
interface: packageInterface[modForDart.domain ?? modForDart.name],
|
|
1527
1632
|
...(compat !== undefined ? { compat } : {}),
|
|
1528
1633
|
supportImport,
|
|
@@ -1542,6 +1647,7 @@ function emitDart(
|
|
|
1542
1647
|
applicationSrc,
|
|
1543
1648
|
clientFile,
|
|
1544
1649
|
applicationFile,
|
|
1650
|
+
new Set(dartApplicationPublicClassNames(modForDart)),
|
|
1545
1651
|
);
|
|
1546
1652
|
const cp = path.join(genDir, clientFile);
|
|
1547
1653
|
writeFileSync(cp, encapsulated.clientPart, "utf8");
|
|
@@ -1660,12 +1766,12 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
1660
1766
|
* just the floor generated code needs — a lagging pin forces tenants into dependency_overrides. */
|
|
1661
1767
|
// 0.3.0: SurfacedValue<T>/SurfacedObservation/PendingConflictRow — generated Surfaced-field typing +
|
|
1662
1768
|
// the pendingConflicts read rows.
|
|
1663
|
-
const NOMOS_TYPES_DEP = "^0.
|
|
1769
|
+
const NOMOS_TYPES_DEP = "^0.10.0";
|
|
1664
1770
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
1665
1771
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
1666
1772
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
1667
|
-
const NOMOS_CLIENT_DEP = "^0.
|
|
1668
|
-
const NOMOS_FLUTTER_DEP = "^0.
|
|
1773
|
+
const NOMOS_CLIENT_DEP = "^0.65.1";
|
|
1774
|
+
const NOMOS_FLUTTER_DEP = "^0.64.1";
|
|
1669
1775
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in dsl/dart/pubspec.yaml
|
|
1670
1776
|
// and dsl/dart_types/pubspec.yaml — a Dart release without this bump fails the suite, so tenants never
|
|
1671
1777
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -1728,6 +1834,7 @@ function encapsulateDartClient(
|
|
|
1728
1834
|
applicationSrc: string,
|
|
1729
1835
|
clientFile: string,
|
|
1730
1836
|
applicationFile: string,
|
|
1837
|
+
publicClientNames: ReadonlySet<string>,
|
|
1731
1838
|
): { readonly clientPart: string; readonly applicationLibrary: string } {
|
|
1732
1839
|
const directive = /^(import|export)\s+'([^']+)'(?:\s+[^;]+)?;\s*$/;
|
|
1733
1840
|
const clientImportUri = clientFile.replace(/\.dart$/, "");
|
|
@@ -1802,17 +1909,20 @@ function encapsulateDartClient(
|
|
|
1802
1909
|
"// ignore_for_file: unused_element, unused_element_parameter",
|
|
1803
1910
|
`part of '${applicationFile}';`,
|
|
1804
1911
|
"",
|
|
1805
|
-
privatize(client.body.join("\n")).trimStart(),
|
|
1912
|
+
privatize(client.body.join("\n"), publicClientNames).trimStart(),
|
|
1806
1913
|
"",
|
|
1807
1914
|
].join("\n"),
|
|
1808
1915
|
applicationLibrary: [
|
|
1809
1916
|
"// AUTO-GENERATED by nomos-compile — the sole importable application library.",
|
|
1810
|
-
"// 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",
|
|
1811
1918
|
...imports.values(),
|
|
1812
1919
|
...exports.values(),
|
|
1813
1920
|
`part '${clientFile}';`,
|
|
1814
1921
|
"",
|
|
1815
|
-
privatize(
|
|
1922
|
+
privatize(
|
|
1923
|
+
application.body.join("\n"),
|
|
1924
|
+
new Set([...applicationNames, ...publicClientNames]),
|
|
1925
|
+
).trimStart(),
|
|
1816
1926
|
"",
|
|
1817
1927
|
].join("\n"),
|
|
1818
1928
|
};
|
|
@@ -1844,6 +1954,7 @@ function generatedPackageApplication(
|
|
|
1844
1954
|
}[],
|
|
1845
1955
|
homeDomain: string,
|
|
1846
1956
|
rootDomains: readonly string[],
|
|
1957
|
+
hasApplicationFrameworkCalls: boolean,
|
|
1847
1958
|
): string {
|
|
1848
1959
|
const application = dartApplicationClassName(packageName);
|
|
1849
1960
|
const root = domains.find(({ domain }) => domain === homeDomain);
|
|
@@ -1903,6 +2014,9 @@ function generatedPackageApplication(
|
|
|
1903
2014
|
`import 'package:nomos_flutter/src/application_status.dart' show ApplicationSignIn, ApplicationStatus;`,
|
|
1904
2015
|
`import 'package:nomos_client/src/nms_generated_runtime.dart' show NmsInternalUsers, NomosSession, User${hasInvitations ? ", Invitation, Recipient" : ""};`,
|
|
1905
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
|
+
: []),
|
|
1906
2020
|
...members.map(({ file, prefix }) =>
|
|
1907
2021
|
`import '${file}.application.dart' as ${prefix};`),
|
|
1908
2022
|
``,
|
|
@@ -1967,6 +2081,7 @@ function generatedPackageApplication(
|
|
|
1967
2081
|
` /// Redeem a transported invitation as [currentUser].`,
|
|
1968
2082
|
` Future<void> redeemInvitation(String link) => NmsInternalApplicationHost.redeemInvitation<User>(`,
|
|
1969
2083
|
` _nmsSession,`,
|
|
2084
|
+
` frameworkCalls: nomosInternalApplicationFrameworkCalls,`,
|
|
1970
2085
|
` link: link,`,
|
|
1971
2086
|
` identity: _nmsUser.nmsInternalActor,`,
|
|
1972
2087
|
` policies: [`,
|
|
@@ -2005,6 +2120,9 @@ function generatedPackageApplication(
|
|
|
2005
2120
|
` Duration startupTimeout = const Duration(minutes: 3),`,
|
|
2006
2121
|
` }) => NmsInternalApplicationHost.home<${application}>(`,
|
|
2007
2122
|
` key: key, cloud: cloud, application: application, signIn: signIn,`,
|
|
2123
|
+
...(hasApplicationFrameworkCalls
|
|
2124
|
+
? [` frameworkCalls: nomosInternalApplicationFrameworkCalls,`]
|
|
2125
|
+
: []),
|
|
2008
2126
|
` bind: nomosInternalBind${application}, builder: builder,`,
|
|
2009
2127
|
` loadingBuilder: loadingBuilder, errorBuilder: errorBuilder,`,
|
|
2010
2128
|
` onModelChange: onModelChange,`,
|
|
@@ -2194,6 +2312,8 @@ function emitDartPackages(
|
|
|
2194
2312
|
modules: readonly DomainModule[],
|
|
2195
2313
|
dartOut: string,
|
|
2196
2314
|
domainHash: string,
|
|
2315
|
+
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
2316
|
+
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
2197
2317
|
packageInterface: Record<string, DomainInterface>,
|
|
2198
2318
|
packages: { readonly types: string; readonly client: string; readonly test?: string; readonly compat?: string; readonly barrelExports?: "all" | "explicit" },
|
|
2199
2319
|
names: Readonly<Record<string, string>> | undefined,
|
|
@@ -2201,6 +2321,7 @@ function emitDartPackages(
|
|
|
2201
2321
|
describePackageName = packages.client,
|
|
2202
2322
|
lawUsdzPath?: string,
|
|
2203
2323
|
applicationMaxChildWorkspacesPerUser?: number,
|
|
2324
|
+
frameworkModules: readonly DomainModule[] = modules,
|
|
2204
2325
|
): { written: string[]; cursed: string[] } {
|
|
2205
2326
|
for (const [role, name] of Object.entries(packages)) {
|
|
2206
2327
|
if (typeof name !== "string" || !isPubPackageName(name)) {
|
|
@@ -2273,7 +2394,14 @@ function emitDartPackages(
|
|
|
2273
2394
|
written.push(p);
|
|
2274
2395
|
};
|
|
2275
2396
|
|
|
2276
|
-
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
|
+
}
|
|
2277
2405
|
// DOMAIN CONTRACTS (layered): the shared `contracts.dart` DTO file in the TYPES package (pure —
|
|
2278
2406
|
// nomos_types + VOs). A contract-target foreignRef imports THIS sibling, never the concrete domain.
|
|
2279
2407
|
const contractsImportUri = packageContracts.length > 0 ? `${CONTRACTS_FILE}.dart` : undefined;
|
|
@@ -2474,6 +2602,22 @@ function emitDartPackages(
|
|
|
2474
2602
|
|
|
2475
2603
|
// ── the CLIENT package — effectful runtime, depends on types + nomos_client ──
|
|
2476
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
|
+
}
|
|
2477
2621
|
const embeddedLawName = `${describePackageName}.law.usdz`;
|
|
2478
2622
|
const applicationLawPath = lawUsdzPath === undefined
|
|
2479
2623
|
? undefined
|
|
@@ -2494,10 +2638,18 @@ function emitDartPackages(
|
|
|
2494
2638
|
: undefined;
|
|
2495
2639
|
const frameworkTypeNames = frameworkImplementationImport === undefined
|
|
2496
2640
|
? []
|
|
2497
|
-
: [...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);
|
|
2498
2646
|
for (const { mod, dd } of perDomain) {
|
|
2499
2647
|
const makeClient = (imports: readonly string[]) => generateDartBridgeClient(dd.modForDart, {
|
|
2500
2648
|
domainHash,
|
|
2649
|
+
callUsda: {
|
|
2650
|
+
graph: lawGraphs.get(mod.name)!,
|
|
2651
|
+
paths: lawPaths.get(mod.name)!,
|
|
2652
|
+
},
|
|
2501
2653
|
...(applicationLawAssetKey !== undefined
|
|
2502
2654
|
? { lawAssetKey: applicationLawAssetKey }
|
|
2503
2655
|
: {}),
|
|
@@ -2522,6 +2674,9 @@ function emitDartPackages(
|
|
|
2522
2674
|
packageAggregateDomains: buildPackageAggregateDomains(modules),
|
|
2523
2675
|
flutterHost: true,
|
|
2524
2676
|
tenantRoot: perDomain.length === 1,
|
|
2677
|
+
...(applicationFrameworkCallsSource === undefined
|
|
2678
|
+
? {}
|
|
2679
|
+
: { applicationFrameworkCallsImportUri: `${applicationFrameworkCallsFile}.dart` }),
|
|
2525
2680
|
...(imports.length > 0
|
|
2526
2681
|
? { explicitTypeImports: imports }
|
|
2527
2682
|
: {}),
|
|
@@ -2547,6 +2702,7 @@ function emitDartPackages(
|
|
|
2547
2702
|
applicationSrc,
|
|
2548
2703
|
clientFile,
|
|
2549
2704
|
applicationFile,
|
|
2705
|
+
new Set(dartApplicationPublicClassNames(dd.modForDart)),
|
|
2550
2706
|
);
|
|
2551
2707
|
const cp = path.join(clientGen, clientFile);
|
|
2552
2708
|
writeFileSync(cp, encapsulated.clientPart, "utf8");
|
|
@@ -2577,6 +2733,7 @@ function emitDartPackages(
|
|
|
2577
2733
|
})),
|
|
2578
2734
|
topology.homeDomain,
|
|
2579
2735
|
topology.rootDomains,
|
|
2736
|
+
applicationFrameworkCallsSource !== undefined,
|
|
2580
2737
|
),
|
|
2581
2738
|
"utf8",
|
|
2582
2739
|
);
|
|
@@ -2708,6 +2865,9 @@ function emitDartPackages(
|
|
|
2708
2865
|
surfaceName,
|
|
2709
2866
|
applicationFile,
|
|
2710
2867
|
applicationModules: perDomain.map(({ dd: candidate }) => candidate.modForDart),
|
|
2868
|
+
...(applicationFrameworkCallsSource === undefined
|
|
2869
|
+
? {}
|
|
2870
|
+
: { applicationFrameworkCallsFile }),
|
|
2711
2871
|
...(applicationMaxChildWorkspacesPerUser === undefined
|
|
2712
2872
|
? {}
|
|
2713
2873
|
: { applicationMaxChildWorkspacesPerUser }),
|
|
@@ -3074,6 +3234,13 @@ async function main(): Promise<void> {
|
|
|
3074
3234
|
const nativeWorkspaceInvariantReadIds = new Set<string>();
|
|
3075
3235
|
const routingInput: Record<string, Mod[]> = {};
|
|
3076
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
|
+
}> = [];
|
|
3077
3244
|
// THE SELF-DESCRIBE DECLS (G1): per domain key, the FINISHED plain read/maintenance decls the
|
|
3078
3245
|
// lump's `globalThis.describe` needs that it cannot rediscover by shape alone (mins/maxes are
|
|
3079
3246
|
// config-named; sharding sums are framework-appended). Plain JSON (finishCount/Sum/Extremum
|
|
@@ -3171,6 +3338,13 @@ async function main(): Promise<void> {
|
|
|
3171
3338
|
typeof (value as { plan?: unknown }).plan === "function" &&
|
|
3172
3339
|
typeof (value as { aggregateId?: unknown }).aggregateId === "string"
|
|
3173
3340
|
) {
|
|
3341
|
+
directiveExportSources.push({
|
|
3342
|
+
directive: value,
|
|
3343
|
+
domainKey: d.key,
|
|
3344
|
+
graphName: d.name ?? d.key,
|
|
3345
|
+
modulePath: abs,
|
|
3346
|
+
exportName,
|
|
3347
|
+
});
|
|
3174
3348
|
directOfferExports.set((value as { id: string }).id, {
|
|
3175
3349
|
modulePath: abs,
|
|
3176
3350
|
exportName,
|
|
@@ -3776,6 +3950,10 @@ async function main(): Promise<void> {
|
|
|
3776
3950
|
const priorLock: CompilerIdentityModel | undefined = existsSync(lockPath)
|
|
3777
3951
|
? parseIdentityUsda(readFileSync(lockPath, "utf8"))
|
|
3778
3952
|
: undefined;
|
|
3953
|
+
const historicalFrontier = readHistoricalIdentityFrontier(lockPath);
|
|
3954
|
+
const historicalLock: CompilerIdentityModel | undefined = historicalFrontier === undefined
|
|
3955
|
+
? undefined
|
|
3956
|
+
: parseIdentityUsda(historicalFrontier.source);
|
|
3779
3957
|
const inferredRenames: { domain: string; renames: InferredRename[] }[] = [];
|
|
3780
3958
|
let nextIdentity = identityRegistryFromModel(priorLock);
|
|
3781
3959
|
const typedLawGraphs = new Map<string, LawGraph>();
|
|
@@ -3831,6 +4009,7 @@ async function main(): Promise<void> {
|
|
|
3831
4009
|
currentAggs,
|
|
3832
4010
|
prior,
|
|
3833
4011
|
priorSchemas,
|
|
4012
|
+
mod.retirements,
|
|
3834
4013
|
);
|
|
3835
4014
|
const reconciled = reconcileStableIdsWithIdentity(
|
|
3836
4015
|
nextIdentity,
|
|
@@ -3924,9 +4103,9 @@ async function main(): Promise<void> {
|
|
|
3924
4103
|
// The identity file is project-wide while a package may own only some of its domains. Scope the
|
|
3925
4104
|
// prior side to the modules in this compile so compiling one sibling never reads another sibling's
|
|
3926
4105
|
// absence as a domain retirement.
|
|
3927
|
-
if (
|
|
4106
|
+
if (historicalLock !== undefined) {
|
|
3928
4107
|
const priorDomainsForPackage: CompilerIdentityModel["domains"] = {};
|
|
3929
|
-
const priorIdentity = identityRegistryFromModel(
|
|
4108
|
+
const priorIdentity = identityRegistryFromModel(historicalLock);
|
|
3930
4109
|
const frameworkAggregateSids = new Set(
|
|
3931
4110
|
Object.values(priorIdentity.entities)
|
|
3932
4111
|
.filter((entity) => entity.kind === "aggregate" && entity.parent === LAW_FRAMEWORK_PARENT)
|
|
@@ -3934,7 +4113,7 @@ async function main(): Promise<void> {
|
|
|
3934
4113
|
);
|
|
3935
4114
|
for (const mod of domainModules) {
|
|
3936
4115
|
const domainKey = mod.domain ?? mod.name;
|
|
3937
|
-
const locked =
|
|
4116
|
+
const locked = historicalLock.domains[mod.name] ?? historicalLock.domains[domainKey];
|
|
3938
4117
|
if (locked !== undefined) {
|
|
3939
4118
|
const currentImplementationDetailAggregateIds = new Set(
|
|
3940
4119
|
mod.aggregates
|
|
@@ -3972,7 +4151,7 @@ async function main(): Promise<void> {
|
|
|
3972
4151
|
const priorLaw = evolveLawFromLockfile({
|
|
3973
4152
|
v: 1,
|
|
3974
4153
|
domains: priorDomainsForPackage,
|
|
3975
|
-
...(
|
|
4154
|
+
...(historicalLock.identity === undefined ? {} : { identity: historicalLock.identity }),
|
|
3976
4155
|
});
|
|
3977
4156
|
const candidateLaw = currentEvolveLaw(domainModules, nextLock);
|
|
3978
4157
|
const evolutionFindings = evolveDiff(priorLaw, candidateLaw).findings;
|
|
@@ -4062,10 +4241,12 @@ async function main(): Promise<void> {
|
|
|
4062
4241
|
const v3Closure = [...typedLawGraphs.values()];
|
|
4063
4242
|
const v3DomainAssets: EmittedLawClosureAsset[] = [];
|
|
4064
4243
|
const typedDomainIdentityByName = new Map<string, string>();
|
|
4244
|
+
const typedLawPathsByName = new Map<string, ReadonlyMap<string, string>>();
|
|
4065
4245
|
for (const [domain, graph] of typedLawGraphs) {
|
|
4066
4246
|
const safeDomain = domain.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
4067
4247
|
const logicalPath = `domains/${safeDomain}.usda`;
|
|
4068
|
-
const
|
|
4248
|
+
const compiledLayer = compileSparseLawGraphUsda(graph, logicalPath, v3Closure);
|
|
4249
|
+
const layerText = compiledLayer.text;
|
|
4069
4250
|
const sha256 = sha256HexUtf8(layerText);
|
|
4070
4251
|
v3DomainAssets.push({
|
|
4071
4252
|
logicalPath,
|
|
@@ -4073,6 +4254,66 @@ async function main(): Promise<void> {
|
|
|
4073
4254
|
utf8: layerText,
|
|
4074
4255
|
});
|
|
4075
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
|
+
}
|
|
4076
4317
|
}
|
|
4077
4318
|
|
|
4078
4319
|
// ── reports ──
|
|
@@ -4152,11 +4393,13 @@ async function main(): Promise<void> {
|
|
|
4152
4393
|
}
|
|
4153
4394
|
}
|
|
4154
4395
|
|
|
4155
|
-
// Resolve
|
|
4156
|
-
//
|
|
4157
|
-
//
|
|
4158
|
-
//
|
|
4159
|
-
|
|
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]
|
|
4160
4403
|
.map((dir) => {
|
|
4161
4404
|
try {
|
|
4162
4405
|
return createRequire(pathToFileURL(path.join(dir, "noop.js"))).resolve("esbuild/package.json");
|
|
@@ -4168,7 +4411,9 @@ async function main(): Promise<void> {
|
|
|
4168
4411
|
if (!esbuildPkgJson) fail(`esbuild not found — reinstall @githolon/dsl (esbuild is one of its dependencies)`);
|
|
4169
4412
|
const esbuildMod = (await import(pathToFileURL(path.join(path.dirname(esbuildPkgJson), "lib", "main.js")).href)) as typeof import("esbuild");
|
|
4170
4413
|
|
|
4171
|
-
const compact =
|
|
4414
|
+
const compact = process.env.NOMOS_READABLE === "1"
|
|
4415
|
+
? false
|
|
4416
|
+
: compactFlag || cfg.compact === true;
|
|
4172
4417
|
const runtimeZodPath = path.join(DSL_DIR, "src", "runtime_zod.ts");
|
|
4173
4418
|
const runtimeZodPackage = createRequire(import.meta.url).resolve("zod/package.json");
|
|
4174
4419
|
const runtimeZodV4Path = path.join(path.dirname(runtimeZodPackage), "v4", "index.js");
|
|
@@ -4255,6 +4500,41 @@ async function main(): Promise<void> {
|
|
|
4255
4500
|
),
|
|
4256
4501
|
};
|
|
4257
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
|
+
};
|
|
4258
4538
|
const planEntrySource = (
|
|
4259
4539
|
domainKeys: readonly string[],
|
|
4260
4540
|
includeReports: boolean,
|
|
@@ -4265,13 +4545,16 @@ async function main(): Promise<void> {
|
|
|
4265
4545
|
routedDomainFallback?: string,
|
|
4266
4546
|
includeMintInstalls = true,
|
|
4267
4547
|
sharedRuntime = false,
|
|
4548
|
+
sourceSlice?: readonly PlanSourceSliceTarget[],
|
|
4268
4549
|
): string => {
|
|
4550
|
+
const workspaceEffects = workspaceEffectRuntimeFor(domainKeys, sourceSlice);
|
|
4269
4551
|
return [
|
|
4270
4552
|
`// AUTO-GENERATED Nomos plan asset from ${path.basename(configPath)} — do not edit.`,
|
|
4271
4553
|
`declare function require(id: string): Record<string, unknown>;`,
|
|
4272
4554
|
...(sharedRuntime ? [] : zodSeedImports),
|
|
4273
4555
|
`import { registerEngine } from "@githolon/dsl/engine-entry";`,
|
|
4274
4556
|
``,
|
|
4557
|
+
...workspaceEffects.declarations,
|
|
4275
4558
|
`registerEngine({`,
|
|
4276
4559
|
` domains: {`,
|
|
4277
4560
|
...domainKeys.map((key) => {
|
|
@@ -4295,6 +4578,7 @@ async function main(): Promise<void> {
|
|
|
4295
4578
|
...(!sharedRuntime && zodSeedNames.length > 0 ? [` seeds: [${zodSeedNames.join(", ")}],`] : []),
|
|
4296
4579
|
...(includeDescribe ? [` openapiDocument: ${JSON.stringify(runtimeOpenApiDocument)},`] : []),
|
|
4297
4580
|
...(includeDescribe ? [` packageTitle: ${JSON.stringify(`${cfg.name} (nomos package)`)},`] : []),
|
|
4581
|
+
...workspaceEffects.config,
|
|
4298
4582
|
`});`,
|
|
4299
4583
|
...(includeMintInstalls
|
|
4300
4584
|
? domainKeys.flatMap((key) => {
|
|
@@ -4426,11 +4710,21 @@ async function main(): Promise<void> {
|
|
|
4426
4710
|
} = {},
|
|
4427
4711
|
): Promise<UsdPlanAsset> => {
|
|
4428
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()];
|
|
4429
4723
|
const signature = JSON.stringify({
|
|
4430
4724
|
domains: ordered,
|
|
4431
4725
|
reports: includeReports,
|
|
4432
4726
|
describe: includeDescribe,
|
|
4433
|
-
slice:
|
|
4727
|
+
slice: effectiveSliceTargets?.map((target) => [target.modulePath, target.exportName]) ?? null,
|
|
4434
4728
|
cacheKey: options.cacheKey ?? null,
|
|
4435
4729
|
});
|
|
4436
4730
|
const hit = planBySignature.get(signature);
|
|
@@ -4446,6 +4740,7 @@ async function main(): Promise<void> {
|
|
|
4446
4740
|
options.routedDomainFallback,
|
|
4447
4741
|
options.includeMintInstalls ?? true,
|
|
4448
4742
|
true,
|
|
4743
|
+
options.sliceTargets,
|
|
4449
4744
|
));
|
|
4450
4745
|
let planProfile: readonly { readonly module: string; readonly bytesInOutput: number }[] | undefined;
|
|
4451
4746
|
const profilePlan = process.env.NOMOS_PROFILE_PLANS === "1";
|
|
@@ -4486,9 +4781,9 @@ async function main(): Promise<void> {
|
|
|
4486
4781
|
external: [...sharedRuntimeModuleIds],
|
|
4487
4782
|
metafile: true,
|
|
4488
4783
|
logLevel: "silent",
|
|
4489
|
-
...(
|
|
4784
|
+
...(effectiveSliceTargets === undefined
|
|
4490
4785
|
? {}
|
|
4491
|
-
: { plugins: [planSourceSlicer.plugin(
|
|
4786
|
+
: { plugins: [planSourceSlicer.plugin(effectiveSliceTargets)] }),
|
|
4492
4787
|
});
|
|
4493
4788
|
rmSync(sourcePath, { force: true });
|
|
4494
4789
|
const output = result.outputFiles?.[0];
|
|
@@ -4940,7 +5235,7 @@ async function main(): Promise<void> {
|
|
|
4940
5235
|
` for (const [domain, directiveId] of workerData.checks) {`,
|
|
4941
5236
|
` let found;`,
|
|
4942
5237
|
` try { found = globalThis.__nomosHasDirective(domain, directiveId); }`,
|
|
4943
|
-
` 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; }`,
|
|
4944
5239
|
` if (directiveId !== "" && found !== true) {`,
|
|
4945
5240
|
` parentPort.postMessage({ domain, error: "routed offer '" + directiveId + "' is absent from its selected plan registry" });`,
|
|
4946
5241
|
` return;`,
|
|
@@ -4948,7 +5243,7 @@ async function main(): Promise<void> {
|
|
|
4948
5243
|
` }`,
|
|
4949
5244
|
` parentPort.postMessage({ ok: true });`,
|
|
4950
5245
|
` } catch (e) {`,
|
|
4951
|
-
` 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) });`,
|
|
4952
5247
|
` }`,
|
|
4953
5248
|
`} else {`,
|
|
4954
5249
|
` const jobs = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));`,
|
|
@@ -5349,6 +5644,8 @@ async function main(): Promise<void> {
|
|
|
5349
5644
|
const clientDeclarationPath = path.join(outDir, `${cfg.name}.client.d.mts`);
|
|
5350
5645
|
const headlessClientPath = path.join(outDir, `${cfg.name}.headless.mjs`);
|
|
5351
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`);
|
|
5352
5649
|
const clientOptions = {
|
|
5353
5650
|
packageName: cfg.name,
|
|
5354
5651
|
domainHash,
|
|
@@ -5356,12 +5653,18 @@ async function main(): Promise<void> {
|
|
|
5356
5653
|
interface: packageInterface,
|
|
5357
5654
|
compat: nomosCompat,
|
|
5358
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
|
+
}),
|
|
5359
5661
|
} as const;
|
|
5360
5662
|
const clientSource = generateTsClient(presentationDomainModules, clientOptions);
|
|
5361
5663
|
const headlessClientSource = generateTsClient(presentationDomainModules, {
|
|
5362
5664
|
...clientOptions,
|
|
5363
5665
|
exportHolonFactory: true,
|
|
5364
5666
|
});
|
|
5667
|
+
const operatorSource = generateTsLifecycleOperator(clientOptions.callUsda);
|
|
5365
5668
|
const runtimePath = path.join(DSL_DIR, "runtime", "generated-application-host.js");
|
|
5366
5669
|
if (!existsSync(runtimePath)) {
|
|
5367
5670
|
fail("the compiler-private generated application runtime is missing — reinstall @githolon/dsl");
|
|
@@ -5378,7 +5681,7 @@ async function main(): Promise<void> {
|
|
|
5378
5681
|
const temporaryHeadlessDeclarationPath = temporaryHeadlessClientPath.replace(/\.ts$/, ".d.ts");
|
|
5379
5682
|
const runtimeTypesSource = [
|
|
5380
5683
|
`export declare function nomosInternalOpenGeneratedApplication<T extends object>(`,
|
|
5381
|
-
` 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 },`,
|
|
5382
5685
|
` bind: (holon: unknown, user: { readonly identityId: string; readonly identityAddress: string }) => T,`,
|
|
5383
5686
|
`): Promise<T & {`,
|
|
5384
5687
|
` currentStatus(): Promise<any>;`,
|
|
@@ -5396,6 +5699,7 @@ async function main(): Promise<void> {
|
|
|
5396
5699
|
` holon: unknown,`,
|
|
5397
5700
|
` link: string,`,
|
|
5398
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,`,
|
|
5399
5703
|
`): Promise<void>;`,
|
|
5400
5704
|
``,
|
|
5401
5705
|
].join("\n");
|
|
@@ -5705,6 +6009,47 @@ async function main(): Promise<void> {
|
|
|
5705
6009
|
if (!new RegExp(`export\\s*\\{[^}]*${tsClientFactoryName(resolveApplicationTopology(presentationDomainModules).homeDomain)}`, "s").test(headlessBundled)) {
|
|
5706
6010
|
fail("generated headless application omitted its structural holon factory");
|
|
5707
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
|
+
}
|
|
5708
6053
|
} catch (e) {
|
|
5709
6054
|
fail(`generated TypeScript application could not be sealed — this is a Nomos codegen bug: ${(e as Error).message}`);
|
|
5710
6055
|
} finally {
|
|
@@ -5761,8 +6106,9 @@ async function main(): Promise<void> {
|
|
|
5761
6106
|
// restores the prior good packages instead of leaving them wiped/partial. Finalized at process exit.
|
|
5762
6107
|
if (dartPackages !== undefined) {
|
|
5763
6108
|
const r = emitDartPackages(
|
|
5764
|
-
presentationDomainModules, dartOut, domainHash, packageInterface, dartPackages,
|
|
6109
|
+
presentationDomainModules, dartOut, domainHash, typedLawGraphs, typedLawPathsByName, packageInterface, dartPackages,
|
|
5765
6110
|
dartNames, nomosCompat, cfg.name, lawUsdzPath, cfg.application?.maxChildWorkspacesPerUser,
|
|
6111
|
+
closedDomainModules,
|
|
5766
6112
|
);
|
|
5767
6113
|
dartFiles = r.written;
|
|
5768
6114
|
dartCursedHints = r.cursed;
|
|
@@ -5776,7 +6122,7 @@ async function main(): Promise<void> {
|
|
|
5776
6122
|
.replace(/^(?=[0-9])/, "n");
|
|
5777
6123
|
const dartBarrel =
|
|
5778
6124
|
typeof dartCfg === "object" && dartCfg.barrel !== undefined ? dartCfg.barrel : defaultBarrel;
|
|
5779
|
-
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);
|
|
5780
6126
|
}
|
|
5781
6127
|
// COMPILE-VALID MUST MEAN COMPILABLE (co2): `githolon compile` reported success while the generated Dart
|
|
5782
6128
|
// had hard compiler errors (a duplicate id symbol, missing contract-id defs). Run `dart analyze` over the
|