@githolon/dsl 0.114.0 → 0.116.2
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/assets/operation-contract.wasm +0 -0
- package/dart/CHANGELOG.md +55 -0
- package/dart/lib/src/application_framework_calls.dart +7 -1
- package/dart/lib/src/console_enrolment.dart +7 -0
- package/dart/lib/src/console_http_io.dart +22 -15
- package/dart/lib/src/dev_cloud.dart +62 -0
- package/dart/lib/src/nms_generated_runtime.dart +1 -0
- package/dart/lib/src/operation_receipts.dart +74 -7
- package/dart/lib/src/reception/dart_reception.dart +26 -6
- package/dart/lib/src/result_usda.dart +64 -27
- package/dart/lib/src/runner/node-entry.mjs +4733 -1534
- package/dart/lib/src/runtime_v2_transport.dart +3 -0
- package/dart/lib/src/sync_status_projection.dart +11 -0
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +2 -2
- package/dart/test/console_enrolment_test.dart +47 -0
- package/dart/test/kernel_refused_follow_test.dart +36 -0
- package/dart/test/model_adoption_test.dart +49 -0
- package/dart/test/result_usda_test.dart +67 -0
- package/dart/test/runtime_projections_test.dart +41 -0
- package/dart_types/CHANGELOG.md +30 -0
- package/dart_types/lib/src/approved_model.dart +78 -1
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +528 -2
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +24 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +1897 -112
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +98 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +11 -1
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +16 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +43 -2
- package/dart_types/lib/src/vo_canonical.dart +185 -0
- package/dart_types/pubspec.lock +1 -1
- package/dart_types/pubspec.yaml +3 -1
- package/dart_types/test/vo_canonical_test.dart +91 -0
- package/package.json +4 -2
- package/src/aggregate.ts +95 -0
- package/src/anonymous_value_interning.ts +205 -0
- package/src/baseline.ts +27 -0
- package/src/baseline_export.ts +432 -0
- package/src/baseline_import.ts +312 -0
- package/src/baseline_usda.ts +185 -0
- package/src/birth_key_rule.ts +472 -0
- package/src/births.ts +207 -24
- package/src/build_package.ts +47 -7
- package/src/build_provenance.ts +10 -0
- package/src/business_birth.ts +50 -4
- package/src/check_package_main.ts +50 -6
- package/src/codegen_call_proto.ts +5 -18
- package/src/codegen_call_usda.ts +6 -3
- package/src/codegen_dart.ts +114 -60
- package/src/codegen_dart_client.ts +52 -6
- package/src/codegen_dart_facade.ts +57 -35
- package/src/codegen_dart_framework_calls.ts +20 -1
- package/src/codegen_proof.ts +5 -2
- package/src/codegen_result_proto.ts +8 -6
- package/src/codegen_result_usda.ts +12 -4
- package/src/codegen_ts.ts +109 -10
- package/src/compatibility_graph.ts +41 -4
- package/src/compatibility_usda.ts +11 -1
- package/src/compile_package_main.ts +222 -52
- package/src/composed_wire_identity.ts +24 -0
- package/src/directive.ts +6 -0
- package/src/domain_requirements.ts +75 -0
- package/src/engine_entry.ts +12 -4
- package/src/engine_javascript.ts +12 -6
- package/src/fields.ts +109 -0
- package/src/identity_usda.ts +80 -103
- package/src/index.ts +35 -1
- package/src/intent.ts +33 -3
- package/src/law_check.ts +34 -0
- package/src/law_graph.ts +142 -1
- package/src/law_graph_usda.ts +27 -144
- package/src/law_layer_prims.ts +174 -0
- package/src/law_unit_selection.ts +45 -0
- package/src/law_units.ts +7 -6
- package/src/law_version.ts +108 -0
- package/src/package_config.ts +44 -0
- package/src/package_dependencies.ts +8 -0
- package/src/point_guard.ts +5 -1
- package/src/release_inspection.ts +6 -4
- package/src/release_publication.ts +6 -5
- package/src/usda_text.ts +78 -3
- package/src/value_identity.ts +355 -0
- package/src/value_object.ts +35 -4
- package/src/wire.ts +2 -0
- package/src/wire_paths.ts +17 -0
- package/src/workspace_routing.ts +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { collectPackageSources, findBirthKeyWrites, formatBirthKeyWriteWarnings } from "./birth_key_rule.js";
|
|
1
2
|
import type { Directive } from "./directive.js";
|
|
3
|
+
import { usdaString } from "./usda_text.js";
|
|
2
4
|
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
3
5
|
// remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
4
6
|
// wasm32-wasip1 artifact {kernel · projection · embedded
|
|
@@ -46,6 +48,7 @@ import type { Directive } from "./directive.js";
|
|
|
46
48
|
import { execFile, execFileSync } from "node:child_process";
|
|
47
49
|
import { promisify } from "node:util";
|
|
48
50
|
import { checkOperationContracts, deriveInterfaceOffer } from "./operation_contract_check.js";
|
|
51
|
+
import { lawVersionClaim, type LawVersionClaim } from "./law_version.js";
|
|
49
52
|
import { compilerIntermediateCacheRoot, compilerSourceName, compilerSourceRoot } from "./compiler_cache.js";
|
|
50
53
|
import {
|
|
51
54
|
APPLICATION_CONTRACT_MODULE,
|
|
@@ -80,6 +83,7 @@ import ts from "typescript";
|
|
|
80
83
|
import type { AggregateHandle } from "./aggregate.js";
|
|
81
84
|
import {
|
|
82
85
|
generateDartDomain,
|
|
86
|
+
dartBrandNamesForModule,
|
|
83
87
|
generateDartContracts,
|
|
84
88
|
generateDartActivityRegistry,
|
|
85
89
|
collectActivityDescriptors,
|
|
@@ -97,6 +101,8 @@ import {
|
|
|
97
101
|
} from "./evolution_files.js";
|
|
98
102
|
import { assertEvolutionModuleExports } from "./evolution.js";
|
|
99
103
|
import { readHistoricalIdentityFrontier } from "./identity_frontier.js";
|
|
104
|
+
import { parseBaselineUsda, type ReleasedBaseline } from "./baseline_usda.js";
|
|
105
|
+
import { BaselineRefusal, assertBaselineRetained, importBaseline, verifyBaselinePin } from "./baseline_import.js";
|
|
100
106
|
import {
|
|
101
107
|
dartBridgeClientOperationDirectiveIds,
|
|
102
108
|
generateDartDomainClient,
|
|
@@ -266,6 +272,7 @@ import {
|
|
|
266
272
|
splitLawUnits,
|
|
267
273
|
} from "./law_units.js";
|
|
268
274
|
import { lawUnitSetIdentityWith } from "./law_unit_set_identity.js";
|
|
275
|
+
import { domainRequirementsOf, type DomainUnitRequirement } from "./domain_requirements.js";
|
|
269
276
|
import { checkDomainModules, formatFindings, hasRefusal } from "./law_check.js";
|
|
270
277
|
import {
|
|
271
278
|
currentEvolveLaw,
|
|
@@ -624,6 +631,7 @@ const compareLogicalPath = (left: string, right: string): number =>
|
|
|
624
631
|
* inventories the USDZ/Git tree and re-hashes every logically named layer. */
|
|
625
632
|
function emitLawClosure(
|
|
626
633
|
packageName: string,
|
|
634
|
+
claimedVersion: LawVersionClaim | undefined,
|
|
627
635
|
exportedDomains: readonly string[],
|
|
628
636
|
runtimeDependencies: readonly RuntimePackageDependency[],
|
|
629
637
|
domainAssets: readonly EmittedLawClosureAsset[],
|
|
@@ -670,6 +678,7 @@ function emitLawClosure(
|
|
|
670
678
|
"package.usda",
|
|
671
679
|
packageContractUsda({
|
|
672
680
|
packageName,
|
|
681
|
+
...(claimedVersion === undefined ? {} : { claimedVersion }),
|
|
673
682
|
exportedDomains,
|
|
674
683
|
runtimeDependencies,
|
|
675
684
|
})
|
|
@@ -809,7 +818,7 @@ function emitLawClosure(
|
|
|
809
818
|
return [
|
|
810
819
|
` def NomosLawAsset "${primName}"`,
|
|
811
820
|
" {",
|
|
812
|
-
` custom string nomos:logicalPath = ${
|
|
821
|
+
` custom string nomos:logicalPath = ${usdaString(
|
|
813
822
|
asset.logicalPath
|
|
814
823
|
)}`,
|
|
815
824
|
` custom string nomos:sha256 = "${asset.sha256}"`,
|
|
@@ -1265,6 +1274,7 @@ function closeComposedBusinessBirthPresentation(
|
|
|
1265
1274
|
aggregateId?: unknown;
|
|
1266
1275
|
rootId?: unknown;
|
|
1267
1276
|
namespace?: unknown;
|
|
1277
|
+
keyMode?: unknown;
|
|
1268
1278
|
keyField?: unknown;
|
|
1269
1279
|
};
|
|
1270
1280
|
type BirthDirective = DomainModule["directives"][number] & {
|
|
@@ -1278,14 +1288,15 @@ function closeComposedBusinessBirthPresentation(
|
|
|
1278
1288
|
typeof birth.aggregateId !== "string" ||
|
|
1279
1289
|
typeof birth.rootId !== "string" ||
|
|
1280
1290
|
typeof birth.namespace !== "string" ||
|
|
1281
|
-
typeof birth.keyField !== "string"
|
|
1291
|
+
(typeof birth.keyField !== "string" && birth.keyMode !== "minted")
|
|
1282
1292
|
)
|
|
1283
1293
|
return undefined;
|
|
1284
1294
|
return [
|
|
1285
1295
|
birth.aggregateId,
|
|
1286
1296
|
birth.rootId,
|
|
1287
1297
|
birth.namespace,
|
|
1288
|
-
birth.
|
|
1298
|
+
// A minted birth has no key field; its identity here is the minted mode itself.
|
|
1299
|
+
typeof birth.keyField === "string" ? birth.keyField : "\u0001minted",
|
|
1289
1300
|
].join("\u0000");
|
|
1290
1301
|
};
|
|
1291
1302
|
|
|
@@ -1335,6 +1346,8 @@ interface DartSharedSymbols {
|
|
|
1335
1346
|
readonly frameworkDirIds: ReadonlySet<string>;
|
|
1336
1347
|
readonly frameworkQueryIds: ReadonlySet<string>;
|
|
1337
1348
|
readonly sharedVoNames: ReadonlySet<string>;
|
|
1349
|
+
/** Branded-id extension types used by ≥2 domains — declared ONCE in the framework file. */
|
|
1350
|
+
readonly sharedBrandNames: ReadonlySet<string>;
|
|
1338
1351
|
readonly hasFrameworkSymbols: boolean;
|
|
1339
1352
|
/** The synthetic module whose emit IS `nomos_framework.dart` — undefined when nothing is shared. */
|
|
1340
1353
|
readonly frameworkMod: DomainModule | undefined;
|
|
@@ -1496,11 +1509,23 @@ function collectDartSharedSymbols(
|
|
|
1496
1509
|
const sharedVos = [...sharedVoNames]
|
|
1497
1510
|
.sort()
|
|
1498
1511
|
.map((name) => voDescriptorByName.get(name)!);
|
|
1512
|
+
// TYPED IDS: a branded id used by two domains (a parent's business-birth payload and the child's key
|
|
1513
|
+
// field, typically) would otherwise declare one extension type per file and make the barrel ambiguous.
|
|
1514
|
+
const brandDomains = new Map<string, number>();
|
|
1515
|
+
for (const mod of modules) {
|
|
1516
|
+
for (const brand of dartBrandNamesForModule(mod)) {
|
|
1517
|
+
brandDomains.set(brand, (brandDomains.get(brand) ?? 0) + 1);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
const sharedBrandNames: ReadonlySet<string> = new Set(
|
|
1521
|
+
[...brandDomains.entries()].filter(([, n]) => n > 1).map(([name]) => name).sort()
|
|
1522
|
+
);
|
|
1499
1523
|
const hasFrameworkSymbols =
|
|
1500
1524
|
frameworkAggs.length > 0 ||
|
|
1501
1525
|
frameworkDirs.length > 0 ||
|
|
1502
1526
|
frameworkQueries.length > 0 ||
|
|
1503
|
-
sharedVos.length > 0
|
|
1527
|
+
sharedVos.length > 0 ||
|
|
1528
|
+
sharedBrandNames.size > 0;
|
|
1504
1529
|
const frameworkMod: DomainModule | undefined = hasFrameworkSymbols
|
|
1505
1530
|
? {
|
|
1506
1531
|
name: FRAMEWORK_FILE,
|
|
@@ -1518,6 +1543,7 @@ function collectDartSharedSymbols(
|
|
|
1518
1543
|
frameworkDirIds: new Set(frameworkDirById.keys()),
|
|
1519
1544
|
frameworkQueryIds: new Set(frameworkQueryById.keys()),
|
|
1520
1545
|
sharedVoNames,
|
|
1546
|
+
sharedBrandNames,
|
|
1521
1547
|
hasFrameworkSymbols,
|
|
1522
1548
|
frameworkMod,
|
|
1523
1549
|
};
|
|
@@ -1535,6 +1561,7 @@ function domainDedupOpts(
|
|
|
1535
1561
|
readonly skipDirectiveIds: Set<string>;
|
|
1536
1562
|
readonly skipQueryIds: Set<string>;
|
|
1537
1563
|
readonly skipValueObjectNames: Set<string>;
|
|
1564
|
+
readonly skipBrandNames: Set<string>;
|
|
1538
1565
|
};
|
|
1539
1566
|
readonly foldsFramework: boolean;
|
|
1540
1567
|
} {
|
|
@@ -1562,11 +1589,17 @@ function domainDedupOpts(
|
|
|
1562
1589
|
.filter((d) => shared.sharedVoNames.has(d.name))
|
|
1563
1590
|
.map((d) => d.name)
|
|
1564
1591
|
);
|
|
1592
|
+
const skipBrandNames = new Set(
|
|
1593
|
+
[...dartBrandNamesForModule(modForDart)].filter((name) =>
|
|
1594
|
+
shared.sharedBrandNames.has(name)
|
|
1595
|
+
)
|
|
1596
|
+
);
|
|
1565
1597
|
const foldsFramework =
|
|
1566
1598
|
skipAggregateIds.size > 0 ||
|
|
1567
1599
|
skipDirectiveIds.size > 0 ||
|
|
1568
1600
|
skipQueryIds.size > 0 ||
|
|
1569
|
-
skipValueObjectNames.size > 0
|
|
1601
|
+
skipValueObjectNames.size > 0 ||
|
|
1602
|
+
skipBrandNames.size > 0;
|
|
1570
1603
|
return {
|
|
1571
1604
|
modForDart,
|
|
1572
1605
|
skips: {
|
|
@@ -1574,6 +1607,7 @@ function domainDedupOpts(
|
|
|
1574
1607
|
skipDirectiveIds,
|
|
1575
1608
|
skipQueryIds,
|
|
1576
1609
|
skipValueObjectNames,
|
|
1610
|
+
skipBrandNames,
|
|
1577
1611
|
},
|
|
1578
1612
|
foldsFramework,
|
|
1579
1613
|
};
|
|
@@ -2146,6 +2180,8 @@ function emitDartOperationProto(
|
|
|
2146
2180
|
interface CompiledLawIdentities {
|
|
2147
2181
|
readonly unitSet: string;
|
|
2148
2182
|
readonly packageSha256: string;
|
|
2183
|
+
/** One requirement per application domain (CAP-666): its unit hash and its generated requirement identity. */
|
|
2184
|
+
readonly domainRequirements: readonly DomainUnitRequirement[];
|
|
2149
2185
|
}
|
|
2150
2186
|
|
|
2151
2187
|
function emitDart(
|
|
@@ -2227,7 +2263,7 @@ function emitDart(
|
|
|
2227
2263
|
? []
|
|
2228
2264
|
: [{ module, graph, paths }];
|
|
2229
2265
|
}),
|
|
2230
|
-
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256 }
|
|
2266
|
+
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256, domainRequirements: law.domainRequirements }
|
|
2231
2267
|
);
|
|
2232
2268
|
if (applicationFrameworkCallsSource !== undefined) {
|
|
2233
2269
|
const applicationFrameworkCallsPath = path.join(
|
|
@@ -2249,6 +2285,7 @@ function emitDart(
|
|
|
2249
2285
|
FRAMEWORK_FILE,
|
|
2250
2286
|
generateDartDomain(shared.frameworkMod, {
|
|
2251
2287
|
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
2288
|
+
extraBrandNames: [...shared.sharedBrandNames],
|
|
2252
2289
|
})
|
|
2253
2290
|
);
|
|
2254
2291
|
}
|
|
@@ -2519,6 +2556,11 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
2519
2556
|
`import 'package:nomos_types/src/foreign_ref.dart' show NmsInternalForeignRefs;`,
|
|
2520
2557
|
]
|
|
2521
2558
|
: []),
|
|
2559
|
+
...(generatedSource.includes("NmsInternalValueIdentity.")
|
|
2560
|
+
? [
|
|
2561
|
+
`import 'package:nomos_types/src/vo_canonical.dart' show NmsInternalValueIdentity;`,
|
|
2562
|
+
]
|
|
2563
|
+
: []),
|
|
2522
2564
|
];
|
|
2523
2565
|
const invitationHelpers = [
|
|
2524
2566
|
...(generatedSource.includes("NmsInternalInvitations.")
|
|
@@ -2542,12 +2584,12 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
2542
2584
|
* just the floor generated code needs — a lagging pin forces tenants into dependency_overrides. */
|
|
2543
2585
|
// 0.3.0: SurfacedValue<T>/SurfacedObservation/PendingConflictRow — generated Surfaced-field typing +
|
|
2544
2586
|
// the pendingConflicts read rows.
|
|
2545
|
-
const NOMOS_TYPES_DEP = "^0.
|
|
2587
|
+
const NOMOS_TYPES_DEP = "^0.15.0";
|
|
2546
2588
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
2547
2589
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
2548
2590
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
2549
|
-
const NOMOS_CLIENT_DEP = "^0.
|
|
2550
|
-
const NOMOS_FLUTTER_DEP = "^0.
|
|
2591
|
+
const NOMOS_CLIENT_DEP = "^0.70.1";
|
|
2592
|
+
const NOMOS_FLUTTER_DEP = "^0.68.2";
|
|
2551
2593
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in the Dart and Flutter
|
|
2552
2594
|
// package pubspecs — a release without this bump fails the suite, so tenants never
|
|
2553
2595
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -3370,6 +3412,7 @@ function emitDartPackages(
|
|
|
3370
3412
|
m[1] !== "package:nomos_types/src/versioned_nomos_ref.dart" &&
|
|
3371
3413
|
m[1] !== "package:nomos_types/src/foreign_ref.dart" &&
|
|
3372
3414
|
m[1] !== "package:nomos_types/src/invitation.dart" &&
|
|
3415
|
+
m[1] !== "package:nomos_types/src/vo_canonical.dart" &&
|
|
3373
3416
|
m[1] !== `${FRAMEWORK_FILE}.dart` &&
|
|
3374
3417
|
!siblingTypeFiles.has(m[1]!)
|
|
3375
3418
|
) {
|
|
@@ -3390,6 +3433,7 @@ function emitDartPackages(
|
|
|
3390
3433
|
FRAMEWORK_FILE,
|
|
3391
3434
|
generateDartDomain(shared.frameworkMod, {
|
|
3392
3435
|
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
3436
|
+
extraBrandNames: [...shared.sharedBrandNames],
|
|
3393
3437
|
})
|
|
3394
3438
|
);
|
|
3395
3439
|
}
|
|
@@ -3680,7 +3724,7 @@ function emitDartPackages(
|
|
|
3680
3724
|
? []
|
|
3681
3725
|
: [{ module, graph, paths }];
|
|
3682
3726
|
}),
|
|
3683
|
-
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256 }
|
|
3727
|
+
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256, domainRequirements: law.domainRequirements }
|
|
3684
3728
|
);
|
|
3685
3729
|
const workspaceAccessReadImports = new Map<string, string>();
|
|
3686
3730
|
for (const module of operationProtoModules) {
|
|
@@ -4205,6 +4249,7 @@ async function main(): Promise<void> {
|
|
|
4205
4249
|
"--preflight",
|
|
4206
4250
|
"--inspect-sqlite",
|
|
4207
4251
|
"--inspect-law",
|
|
4252
|
+
"--publishable",
|
|
4208
4253
|
]);
|
|
4209
4254
|
for (const flag of argv.filter((arg) => arg.startsWith("--"))) {
|
|
4210
4255
|
if (supportedFlags.has(flag)) continue;
|
|
@@ -4240,6 +4285,9 @@ async function main(): Promise<void> {
|
|
|
4240
4285
|
// `dart analyze` on the generated Dart package after emission and fails the compile on red.
|
|
4241
4286
|
const analyzeFlag =
|
|
4242
4287
|
argv.includes("--analyze") || process.env.NOMOS_ANALYZE === "1";
|
|
4288
|
+
// A PUBLISHABLE compile (architecture/domain_release_lifecycle.md, step 1) must start from the
|
|
4289
|
+
// baseline exported from released custody: it refuses without a pinned `nomos.baseline.usda`.
|
|
4290
|
+
const publishableFlag = argv.includes("--publishable");
|
|
4243
4291
|
const configArg = argv.find((a) => !a.startsWith("--")) ?? "nomos.project.ts";
|
|
4244
4292
|
const configPath = path.resolve(process.cwd(), configArg);
|
|
4245
4293
|
if (!existsSync(configPath)) fail(`config not found: ${configPath}`);
|
|
@@ -4324,6 +4372,39 @@ async function main(): Promise<void> {
|
|
|
4324
4372
|
"nomos.project.ts no longer accepts 'layered': every law closure is layered, with no alternate compile lane"
|
|
4325
4373
|
);
|
|
4326
4374
|
}
|
|
4375
|
+
// ── THE RELEASED BASELINE (CAP-660) ──────────────────────────────────────────────────────────
|
|
4376
|
+
// `nomos.project.ts` pins the baseline by content address. Verify the bytes are the pinned ones
|
|
4377
|
+
// and read it now, before any identity is touched; the import and the retention proof follow.
|
|
4378
|
+
const baselineRefused = (error: unknown): never => {
|
|
4379
|
+
if (error instanceof BaselineRefusal) fail(`[${error.code}] ${error.message}`);
|
|
4380
|
+
throw error;
|
|
4381
|
+
};
|
|
4382
|
+
let releasedBaseline: ReleasedBaseline | undefined;
|
|
4383
|
+
let releasedBaselineSha256: string | undefined;
|
|
4384
|
+
if (cfg.baseline === undefined) {
|
|
4385
|
+
if (publishableFlag) {
|
|
4386
|
+
fail(
|
|
4387
|
+
"[baseline-required] a publishable compile must name the released baseline it extends: " +
|
|
4388
|
+
`run \`githolon baseline export --units build/${cfg.name}.units\` (or --release <id>) against the release ` +
|
|
4389
|
+
"you are extending, commit nomos.baseline.usda, and pin it in nomos.project.ts as " +
|
|
4390
|
+
"baseline: { artifact: \"./nomos.baseline.usda\", sha256: \"<printed sha256>\" }"
|
|
4391
|
+
);
|
|
4392
|
+
}
|
|
4393
|
+
} else {
|
|
4394
|
+
const baselinePath = path.resolve(cfgDir, cfg.baseline.artifact);
|
|
4395
|
+
if (!existsSync(baselinePath)) {
|
|
4396
|
+
fail(`[baseline-unreadable] pinned baseline not found: ${baselinePath}`);
|
|
4397
|
+
}
|
|
4398
|
+
const baselineText = readFileSync(baselinePath, "utf8");
|
|
4399
|
+
try {
|
|
4400
|
+
verifyBaselinePin(baselineText, cfg.baseline);
|
|
4401
|
+
releasedBaseline = parseBaselineUsda(baselineText);
|
|
4402
|
+
} catch (error) {
|
|
4403
|
+
if (error instanceof BaselineRefusal) baselineRefused(error);
|
|
4404
|
+
fail(`[baseline-unreadable] ${cfg.baseline.artifact}: ${(error as Error).message}`);
|
|
4405
|
+
}
|
|
4406
|
+
releasedBaselineSha256 = cfg.baseline.sha256;
|
|
4407
|
+
}
|
|
4327
4408
|
let sourceTopologyDiagnostics: ReturnType<
|
|
4328
4409
|
typeof assertPackageFeatureTopology
|
|
4329
4410
|
> = [];
|
|
@@ -4395,6 +4476,7 @@ async function main(): Promise<void> {
|
|
|
4395
4476
|
if (cfg.rootPart !== undefined) {
|
|
4396
4477
|
applicationBirthPolicyDomains.push(APPLICATION_HOME_DOMAIN);
|
|
4397
4478
|
}
|
|
4479
|
+
const authoredDomainModules: Mod[] = [];
|
|
4398
4480
|
for (const domain of cfg.domains) {
|
|
4399
4481
|
let authored: Mod = {};
|
|
4400
4482
|
for (const rel of domain.modules) {
|
|
@@ -4420,10 +4502,32 @@ async function main(): Promise<void> {
|
|
|
4420
4502
|
}
|
|
4421
4503
|
}
|
|
4422
4504
|
const expanded = expandBusinessBirthExports(authored, domain.key);
|
|
4505
|
+
authoredDomainModules.push(authored);
|
|
4423
4506
|
if (directivesOf(expanded).some((dir) => dir.birthsChild === true)) {
|
|
4424
4507
|
applicationBirthPolicyDomains.push(domain.key);
|
|
4425
4508
|
}
|
|
4426
4509
|
}
|
|
4510
|
+
// A workspace name is fixed at birth, and the framework enforces it at the kernel: every field-keyed
|
|
4511
|
+
// birth's key is write-once (aggregate.ts BIRTH_KEY_WRITE_ONCE_CODE). Statically WARN at each source line
|
|
4512
|
+
// that writes a key outside the birth in a way that rule will refuse, or that keys another instance
|
|
4513
|
+
// (CAP-804; architecture/choosing_a_birth_key.md). Advisory only — the runtime rule is the guarantee.
|
|
4514
|
+
{
|
|
4515
|
+
const birthKeyWarnings = findBirthKeyWrites(
|
|
4516
|
+
authoredDomainModules,
|
|
4517
|
+
collectPackageSources(
|
|
4518
|
+
cfg.domains.flatMap((domain) => domain.modules.map((rel) => path.resolve(cfgDir, rel))),
|
|
4519
|
+
cfgDir
|
|
4520
|
+
),
|
|
4521
|
+
{ root: cfgDir }
|
|
4522
|
+
);
|
|
4523
|
+
if (birthKeyWarnings.length > 0) {
|
|
4524
|
+
console.warn(
|
|
4525
|
+
`nomos-compile: ${birthKeyWarnings.length} birth-key write warning(s)`
|
|
4526
|
+
);
|
|
4527
|
+
for (const line of formatBirthKeyWriteWarnings(birthKeyWarnings))
|
|
4528
|
+
console.warn(line);
|
|
4529
|
+
}
|
|
4530
|
+
}
|
|
4427
4531
|
stage("domain discovery imports");
|
|
4428
4532
|
if (
|
|
4429
4533
|
cfg.application?.homeGenesis !== undefined &&
|
|
@@ -5617,12 +5721,36 @@ async function main(): Promise<void> {
|
|
|
5617
5721
|
? parseIdentityUsda(readFileSync(lockPath, "utf8"))
|
|
5618
5722
|
: undefined;
|
|
5619
5723
|
const historicalFrontier = readHistoricalIdentityFrontier(lockPath);
|
|
5724
|
+
// Outside Git custody (a clean export, a CI checkout without history) the released baseline IS
|
|
5725
|
+
// the evolution frontier: it carries every released aggregate and field by sid, so a removal
|
|
5726
|
+
// without a declared retirement still refuses. It carries no value contracts, so it never
|
|
5727
|
+
// produces a false in-place refusal.
|
|
5620
5728
|
const historicalLock: CompilerIdentityModel | undefined =
|
|
5621
5729
|
historicalFrontier === undefined
|
|
5622
|
-
?
|
|
5730
|
+
? releasedBaseline?.continuity
|
|
5623
5731
|
: parseIdentityUsda(historicalFrontier.source);
|
|
5624
5732
|
const inferredRenames: { domain: string; renames: InferredRename[] }[] = [];
|
|
5625
5733
|
let nextIdentity = identityRegistryFromModel(priorLock);
|
|
5734
|
+
if (releasedBaseline !== undefined) {
|
|
5735
|
+
// Verify the ledger against released custody and import what it lacks, so a clean checkout
|
|
5736
|
+
// allocates the released sids and wire keys rather than fresh ones, and a diverged branch
|
|
5737
|
+
// refuses with the coordinate named (baseline_import.ts).
|
|
5738
|
+
try {
|
|
5739
|
+
const imported = importBaseline(
|
|
5740
|
+
nextIdentity,
|
|
5741
|
+
releasedBaseline,
|
|
5742
|
+
cfg.domains.flatMap((domain) => [domain.key, ...(domain.name === undefined ? [] : [domain.name])])
|
|
5743
|
+
);
|
|
5744
|
+
nextIdentity = imported.registry;
|
|
5745
|
+
console.log(
|
|
5746
|
+
`baseline: ${releasedBaseline.release === "none" ? "unreleased units" : `release ${releasedBaseline.release}`} ` +
|
|
5747
|
+
`(law ${releasedBaseline.unitSet}) — ${imported.verified} verified, ${imported.imported.length} identit${imported.imported.length === 1 ? "y" : "ies"} ` +
|
|
5748
|
+
`and ${imported.allocated.length} wire allocation(s) imported${imported.relabelled.length === 0 ? "" : `, ${imported.relabelled.length} released rename(s) carried`}`
|
|
5749
|
+
);
|
|
5750
|
+
} catch (error) {
|
|
5751
|
+
baselineRefused(error);
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5626
5754
|
const typedLawGraphs = new Map<string, LawGraph>();
|
|
5627
5755
|
// The lock is project-wide, not package-local. Several package configs commonly live beside one
|
|
5628
5756
|
// application stage; compiling one must not erase the stable identity of domains owned by its siblings.
|
|
@@ -5832,6 +5960,18 @@ async function main(): Promise<void> {
|
|
|
5832
5960
|
return;
|
|
5833
5961
|
}
|
|
5834
5962
|
|
|
5963
|
+
// ── BASELINE RETENTION PROOF (CAP-660) ───────────────────────────────────────────
|
|
5964
|
+
// Every released identity still resolves to its released sid and every released wire key is still
|
|
5965
|
+
// the canonical allocation. Reconciliation never rewrites an allocation, so this holds by
|
|
5966
|
+
// construction; proving it here keeps "the candidate extends the release" a checked fact.
|
|
5967
|
+
if (releasedBaseline !== undefined) {
|
|
5968
|
+
try {
|
|
5969
|
+
assertBaselineRetained(nextIdentity, releasedBaseline);
|
|
5970
|
+
} catch (error) {
|
|
5971
|
+
baselineRefused(error);
|
|
5972
|
+
}
|
|
5973
|
+
}
|
|
5974
|
+
|
|
5835
5975
|
// ── ORDINARY-COMPILE EVOLUTION GATE ──────────────────────────────────────────────
|
|
5836
5976
|
// Agents reliably run `compile`; they do not reliably discover an optional migration command.
|
|
5837
5977
|
// Compare the candidate against the committed identity frontier here, after stable-id
|
|
@@ -5910,6 +6050,44 @@ async function main(): Promise<void> {
|
|
|
5910
6050
|
// giant formatting-only diff in an established lock.
|
|
5911
6051
|
writeFileSync(lockPath, serializeIdentityUsda(nextLock), "utf8");
|
|
5912
6052
|
|
|
6053
|
+
// USDA is rendered directly from the typed graph. The final closure writer below publishes these
|
|
6054
|
+
// exact texts under their logical paths; no parallel layer directory or JSON reconstruction exists.
|
|
6055
|
+
const v3Closure = [...typedLawGraphs.values()];
|
|
6056
|
+
const v3DomainAssets: EmittedLawClosureAsset[] = [];
|
|
6057
|
+
const v3DomainRoots: string[] = [];
|
|
6058
|
+
const v3LawPathByNode = new Map<LawGraph["nodes"][number], string>();
|
|
6059
|
+
const v3CompiledGraphs = new Map<LawGraph, ReturnType<typeof compileSparseLawGraphUsda>>();
|
|
6060
|
+
const typedDomainIdentityByName = new Map<string, string>();
|
|
6061
|
+
const typedLawPathsByName = new Map<string, ReadonlyMap<string, string>>();
|
|
6062
|
+
for (const [domain, graph] of typedLawGraphs) {
|
|
6063
|
+
const safeDomain = domain.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
6064
|
+
const logicalPath = `domains/${safeDomain}.usda`;
|
|
6065
|
+
const compiledLayer = compileSparseLawGraphUsda(
|
|
6066
|
+
graph,
|
|
6067
|
+
logicalPath,
|
|
6068
|
+
v3Closure
|
|
6069
|
+
);
|
|
6070
|
+
v3CompiledGraphs.set(graph, compiledLayer);
|
|
6071
|
+
const layerText = compiledLayer.text;
|
|
6072
|
+
const sha256 = sha256HexUtf8(layerText);
|
|
6073
|
+
v3DomainAssets.push({
|
|
6074
|
+
logicalPath,
|
|
6075
|
+
sha256,
|
|
6076
|
+
utf8: layerText,
|
|
6077
|
+
});
|
|
6078
|
+
const domainRoot = compiledLayer.paths.get(graph.domain.entity.id);
|
|
6079
|
+
if (domainRoot === undefined) {
|
|
6080
|
+
fail(`domain '${domain}' did not emit its canonical OpenUSD root path`);
|
|
6081
|
+
}
|
|
6082
|
+
v3DomainRoots.push(domainRoot);
|
|
6083
|
+
for (const node of graph.nodes) {
|
|
6084
|
+
const lawPath = compiledLayer.paths.get(node.entity.id);
|
|
6085
|
+
if (lawPath !== undefined) v3LawPathByNode.set(node, lawPath);
|
|
6086
|
+
}
|
|
6087
|
+
typedDomainIdentityByName.set(domain, sha256);
|
|
6088
|
+
typedLawPathsByName.set(domain, compiledLayer.paths);
|
|
6089
|
+
}
|
|
6090
|
+
|
|
5913
6091
|
// ── THE STRUCTURAL INTERFACE (#72) — directives (payload shapes) + aggregates (read
|
|
5914
6092
|
// shapes, sid-keyed), keyed by DOMAIN. The SAME object is (a) baked into the generated
|
|
5915
6093
|
// clients as their requirement and (b) staged on the deploy as the workspace's offer, so
|
|
@@ -5924,7 +6102,12 @@ async function main(): Promise<void> {
|
|
|
5924
6102
|
`compiler surface invariant: domain '${key}' has no typed USDA graph`
|
|
5925
6103
|
);
|
|
5926
6104
|
}
|
|
5927
|
-
|
|
6105
|
+
// Nested record members carry the allocation the generated codecs encode them under, which
|
|
6106
|
+
// follows the composed layer's canonical prim (CAP-681).
|
|
6107
|
+
const offeredInterface = domainInterfaceFromLawGraph(
|
|
6108
|
+
graph,
|
|
6109
|
+
typedLawPathsByName.get(mod.name)
|
|
6110
|
+
);
|
|
5928
6111
|
const di = publicClientInterface([mod], { [key]: offeredInterface })[key]!;
|
|
5929
6112
|
const graphRoutes = graph.nodes
|
|
5930
6113
|
.filter((node) => node.kind === "intent" && node.public)
|
|
@@ -6017,44 +6200,6 @@ async function main(): Promise<void> {
|
|
|
6017
6200
|
}
|
|
6018
6201
|
}
|
|
6019
6202
|
|
|
6020
|
-
// USDA is rendered directly from the typed graph. The final closure writer below publishes these
|
|
6021
|
-
// exact texts under their logical paths; no parallel layer directory or JSON reconstruction exists.
|
|
6022
|
-
const v3Closure = [...typedLawGraphs.values()];
|
|
6023
|
-
const v3DomainAssets: EmittedLawClosureAsset[] = [];
|
|
6024
|
-
const v3DomainRoots: string[] = [];
|
|
6025
|
-
const v3LawPathByNode = new Map<LawGraph["nodes"][number], string>();
|
|
6026
|
-
const v3CompiledGraphs = new Map<LawGraph, ReturnType<typeof compileSparseLawGraphUsda>>();
|
|
6027
|
-
const typedDomainIdentityByName = new Map<string, string>();
|
|
6028
|
-
const typedLawPathsByName = new Map<string, ReadonlyMap<string, string>>();
|
|
6029
|
-
for (const [domain, graph] of typedLawGraphs) {
|
|
6030
|
-
const safeDomain = domain.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
6031
|
-
const logicalPath = `domains/${safeDomain}.usda`;
|
|
6032
|
-
const compiledLayer = compileSparseLawGraphUsda(
|
|
6033
|
-
graph,
|
|
6034
|
-
logicalPath,
|
|
6035
|
-
v3Closure
|
|
6036
|
-
);
|
|
6037
|
-
v3CompiledGraphs.set(graph, compiledLayer);
|
|
6038
|
-
const layerText = compiledLayer.text;
|
|
6039
|
-
const sha256 = sha256HexUtf8(layerText);
|
|
6040
|
-
v3DomainAssets.push({
|
|
6041
|
-
logicalPath,
|
|
6042
|
-
sha256,
|
|
6043
|
-
utf8: layerText,
|
|
6044
|
-
});
|
|
6045
|
-
const domainRoot = compiledLayer.paths.get(graph.domain.entity.id);
|
|
6046
|
-
if (domainRoot === undefined) {
|
|
6047
|
-
fail(`domain '${domain}' did not emit its canonical OpenUSD root path`);
|
|
6048
|
-
}
|
|
6049
|
-
v3DomainRoots.push(domainRoot);
|
|
6050
|
-
for (const node of graph.nodes) {
|
|
6051
|
-
const lawPath = compiledLayer.paths.get(node.entity.id);
|
|
6052
|
-
if (lawPath !== undefined) v3LawPathByNode.set(node, lawPath);
|
|
6053
|
-
}
|
|
6054
|
-
typedDomainIdentityByName.set(domain, sha256);
|
|
6055
|
-
typedLawPathsByName.set(domain, compiledLayer.paths);
|
|
6056
|
-
}
|
|
6057
|
-
|
|
6058
6203
|
// Index the transient graph once. Both projections follow the same nominal edges, including
|
|
6059
6204
|
// transitive cross-domain dependencies. Per-command selection also follows reverse guard edges;
|
|
6060
6205
|
// the retained package command projection remains the compatibility consumer until the runtime
|
|
@@ -7729,6 +7874,7 @@ async function main(): Promise<void> {
|
|
|
7729
7874
|
};
|
|
7730
7875
|
let lawClosure = emitLawClosure(
|
|
7731
7876
|
cfg.name,
|
|
7877
|
+
cfg.version === undefined ? undefined : lawVersionClaim(cfg.version),
|
|
7732
7878
|
domainModules.map((module) => module.domain ?? module.name),
|
|
7733
7879
|
runtimeDependencies,
|
|
7734
7880
|
v3DomainAssets,
|
|
@@ -7890,6 +8036,7 @@ async function main(): Promise<void> {
|
|
|
7890
8036
|
};
|
|
7891
8037
|
lawClosure = emitLawClosure(
|
|
7892
8038
|
cfg.name,
|
|
8039
|
+
cfg.version === undefined ? undefined : lawVersionClaim(cfg.version),
|
|
7893
8040
|
domainModules.map((module) => module.domain ?? module.name),
|
|
7894
8041
|
runtimeDependencies,
|
|
7895
8042
|
v3DomainAssets,
|
|
@@ -7941,6 +8088,10 @@ async function main(): Promise<void> {
|
|
|
7941
8088
|
// THE LAW IDENTITY (CAP-773): the unit set identity of the units below, the kernel's own definition
|
|
7942
8089
|
// (law_unit_set_identity.ts). Releases, generated clients and qualification name the law by it.
|
|
7943
8090
|
let unitSetIdentity: string;
|
|
8091
|
+
// THE PER-DOMAIN REQUIREMENTS (CAP-666): each application domain's unit hash beside the identity of its own
|
|
8092
|
+
// compatibility requirement, derived from the units just split and the interfaces just emitted. Written into
|
|
8093
|
+
// no law or package (the era rule); the generated clients, the approved model and the inventory carry them.
|
|
8094
|
+
let domainRequirements: readonly DomainUnitRequirement[];
|
|
7944
8095
|
{
|
|
7945
8096
|
const lawUnits = (() => {
|
|
7946
8097
|
try {
|
|
@@ -7968,6 +8119,7 @@ async function main(): Promise<void> {
|
|
|
7968
8119
|
);
|
|
7969
8120
|
// The law identity on its own line, for publishers and gates that need it and nothing else.
|
|
7970
8121
|
writeFileSync(path.join(outDir, `${cfg.name}.units.sha256`), `${unitSetIdentity}\n`, "utf8");
|
|
8122
|
+
domainRequirements = domainRequirementsOf(lawUnits, packageInterface, sha256HexUtf8);
|
|
7971
8123
|
}
|
|
7972
8124
|
const layeredRootPath = path.join(
|
|
7973
8125
|
lawClosureAssetsPath,
|
|
@@ -8163,6 +8315,7 @@ async function main(): Promise<void> {
|
|
|
8163
8315
|
const summaryTxt = [
|
|
8164
8316
|
`${cfg.name} — compiled Nomos domain package`,
|
|
8165
8317
|
`law (unit set): ${unitSetIdentity} # THE law identity: ${cfg.name}.units/, as releases, clients and qualification name it (${cfg.name}.units.sha256)`,
|
|
8318
|
+
`claimed version: ${cfg.version ?? "none"} # orders versions of law '${cfg.name}' (nomos.project.ts version); covered by the unit set identity`,
|
|
8166
8319
|
`package closure: ${domainHash} # package — not what targets serve: this compiler's closure of ${cfg.name}.law.usdz (${cfg.name}.law.sha256)`,
|
|
8167
8320
|
`served law: githolon domains status <ws> # each target's kernel composes the units into its own closure (it depends on that kernel's composer)`,
|
|
8168
8321
|
`law transport: ${path.basename(
|
|
@@ -8186,6 +8339,11 @@ async function main(): Promise<void> {
|
|
|
8186
8339
|
d.counts.join(", ") || "—"
|
|
8187
8340
|
} sums: ${d.sums.join(", ") || "—"}`,
|
|
8188
8341
|
]),
|
|
8342
|
+
...(releasedBaseline === undefined
|
|
8343
|
+
? [`baseline: NONE # not a publishable build; githolon compile --publishable needs a pinned nomos.baseline.usda`]
|
|
8344
|
+
: [
|
|
8345
|
+
`baseline: ${releasedBaselineSha256} # extends ${releasedBaseline.release === "none" ? "unreleased units" : `release ${releasedBaseline.release}`}, law ${releasedBaseline.unitSet} (${releasedBaseline.source})`,
|
|
8346
|
+
]),
|
|
8189
8347
|
`deploy: githolon deploy <ws> --file ${cfg.name}.law.usdz`,
|
|
8190
8348
|
packageAssetPath !== undefined
|
|
8191
8349
|
? `package asset: ${path.basename(
|
|
@@ -8242,6 +8400,16 @@ async function main(): Promise<void> {
|
|
|
8242
8400
|
id: "https://github.com/Captain-App/nomos2",
|
|
8243
8401
|
version: dslVersion,
|
|
8244
8402
|
},
|
|
8403
|
+
...(releasedBaseline === undefined || releasedBaselineSha256 === undefined
|
|
8404
|
+
? {}
|
|
8405
|
+
: {
|
|
8406
|
+
baseline: {
|
|
8407
|
+
sha256: releasedBaselineSha256,
|
|
8408
|
+
source: releasedBaseline.source,
|
|
8409
|
+
release: releasedBaseline.release,
|
|
8410
|
+
unitSet: releasedBaseline.unitSet,
|
|
8411
|
+
},
|
|
8412
|
+
}),
|
|
8245
8413
|
});
|
|
8246
8414
|
writeFileSync(
|
|
8247
8415
|
path.join(outDir, `${cfg.name}.provenance.json`),
|
|
@@ -8271,6 +8439,7 @@ async function main(): Promise<void> {
|
|
|
8271
8439
|
packageName: cfg.name,
|
|
8272
8440
|
// THE LAW the generated clients name: the unit set (CAP-773), never the package closure.
|
|
8273
8441
|
domainHash: unitSetIdentity,
|
|
8442
|
+
domainRequirements,
|
|
8274
8443
|
lawAssetName: `${cfg.name}.law.usdz`,
|
|
8275
8444
|
interface: packageInterface,
|
|
8276
8445
|
kernelContracts,
|
|
@@ -8860,7 +9029,7 @@ async function main(): Promise<void> {
|
|
|
8860
9029
|
const r = emitDartPackages(
|
|
8861
9030
|
presentationDomainModules,
|
|
8862
9031
|
dartOut,
|
|
8863
|
-
{ unitSet: unitSetIdentity, packageSha256: domainHash },
|
|
9032
|
+
{ unitSet: unitSetIdentity, packageSha256: domainHash, domainRequirements },
|
|
8864
9033
|
typedLawGraphs,
|
|
8865
9034
|
typedLawPathsByName,
|
|
8866
9035
|
packageInterface,
|
|
@@ -8888,7 +9057,7 @@ async function main(): Promise<void> {
|
|
|
8888
9057
|
dartFiles = emitDart(
|
|
8889
9058
|
presentationDomainModules,
|
|
8890
9059
|
dartOut,
|
|
8891
|
-
{ unitSet: unitSetIdentity, packageSha256: domainHash },
|
|
9060
|
+
{ unitSet: unitSetIdentity, packageSha256: domainHash, domainRequirements },
|
|
8892
9061
|
typedLawGraphs,
|
|
8893
9062
|
typedLawPathsByName,
|
|
8894
9063
|
packageInterface,
|
|
@@ -9272,6 +9441,7 @@ async function main(): Promise<void> {
|
|
|
9272
9441
|
const rel = (p: string) => path.relative(process.cwd(), p);
|
|
9273
9442
|
console.log(`nomos-compile: ${cfg.name}`);
|
|
9274
9443
|
console.log(` law unit set ${unitSetIdentity} (${rel(path.join(outDir, `${cfg.name}.units`))})`);
|
|
9444
|
+
if (cfg.version !== undefined) console.log(` version ${cfg.name}@${cfg.version} (claimed; covered by the unit set identity)`);
|
|
9275
9445
|
console.log(
|
|
9276
9446
|
` package ${domainHash} — package — not what targets serve (${rel(lawUsdzPath)}, ${lawUsdz.byteLength} transport bytes)`
|
|
9277
9447
|
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// NOMOS — The wire identity of an operation field under OpenUSD composition.
|
|
2
|
+
//
|
|
3
|
+
// Node-free on purpose: the compatibility graph reaches this from the law bundle (the release law's
|
|
4
|
+
// plans bundle for a neutral platform), where `codegen_call_proto.ts` cannot live (it mints stable
|
|
5
|
+
// ids through `node:crypto`). Both the generated codecs and the compatibility requirement derive a
|
|
6
|
+
// nested member's allocation here, so the two can never disagree (CAP-681).
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* OpenUSD composition may share structurally identical anonymous records between
|
|
10
|
+
* operation contracts. `compileSparseLawGraphUsda` records that sharing by
|
|
11
|
+
* redirecting each duplicate field path to the canonical field prim. The wire
|
|
12
|
+
* identity must follow that composed path too; using the duplicate graph-local
|
|
13
|
+
* SID makes generated clients speak a different Protobuf schema from the law the
|
|
14
|
+
* kernel actually installs.
|
|
15
|
+
*/
|
|
16
|
+
export function composedWireIdentity(
|
|
17
|
+
paths: ReadonlyMap<string, string>,
|
|
18
|
+
entity: { readonly id: string; readonly sid: string; readonly wireKey?: string },
|
|
19
|
+
): string {
|
|
20
|
+
if (entity.wireKey !== undefined) return entity.wireKey;
|
|
21
|
+
const path = paths.get(entity.id);
|
|
22
|
+
const canonical = path?.match(/\/(?:Fields\/f_|Variants\/v_)([0-9a-f]{16})$/i)?.[1];
|
|
23
|
+
return canonical ?? entity.sid;
|
|
24
|
+
}
|
package/src/directive.ts
CHANGED
|
@@ -536,6 +536,12 @@ export interface Directive<P = unknown> extends AuthenticatedMember {
|
|
|
536
536
|
* `attestationAuthorizedGate`/`.attestationAuthorized()` naming convention; the declaration is the noun.)
|
|
537
537
|
*/
|
|
538
538
|
readonly birthsChild?: boolean;
|
|
539
|
+
/** THE TYPED BIRTH KEY of a business birth (`birth(Aggregate, spec)`): the key's typed-id family, brand and
|
|
540
|
+
* the name's namespace. Lowered to the `nomos:birthKeyType` / `nomos:birthKeyBrand` /
|
|
541
|
+
* `nomos:birthKeyNamespace` era keys on the birthing intent; the kernel then requires every carried recipe
|
|
542
|
+
* of this intent to carry `nomos:birthKey`, checks its shape, and re-derives the child's name from it.
|
|
543
|
+
* Absent on every other directive (and on all historical law), so those chains replay unchanged. */
|
|
544
|
+
readonly birthKey?: import("./births.js").BirthKeyDeclaration;
|
|
539
545
|
/** Additional ordinary offers which the born workspace's typed law requires in genesis.
|
|
540
546
|
* This is compiler/runtime metadata attached only to a birthing directive. It contains no
|
|
541
547
|
* payload or fallback value: the kernel checks that the re-derived recipe invokes each named
|