@githolon/dsl 0.113.4 → 0.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/operation-contract.wasm +0 -0
- package/compile_package.mjs +23 -3
- package/compile_proof.d.mts +7 -0
- package/compile_proof.mjs +38 -3
- package/dart/CHANGELOG.md +60 -0
- package/dart/lib/src/application_framework_calls.dart +16 -6
- 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/generated_call.dart +14 -3
- package/dart/lib/src/nms_generated_runtime.dart +7 -0
- package/dart/lib/src/node_runner_transport.dart +77 -8
- package/dart/lib/src/nomos_trace.dart +107 -0
- package/dart/lib/src/operation_receipts.dart +74 -7
- package/dart/lib/src/reception/dart_reception.dart +174 -17
- package/dart/lib/src/rows_watch.dart +390 -0
- package/dart/lib/src/runner/node-entry.mjs +7678 -2860
- package/dart/lib/src/runtime_v2_transport.dart +3 -0
- package/dart/lib/src/sync_status_projection.dart +94 -1
- package/dart/lib/src/sync_status_reducer.dart +5 -2
- package/dart/lib/src/test_harness.dart +107 -41
- package/dart/lib/src/testing/test_peer.dart +107 -99
- package/dart/lib/src/testing/test_peer_host.dart +305 -0
- package/dart/lib/src/typed_watch_registry.dart +26 -3
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +2 -2
- package/dart/test/background_model_adoption_test.dart +1 -0
- package/dart/test/console_enrolment_test.dart +47 -0
- package/dart/test/custodian_warming_test.dart +105 -0
- package/dart/test/fixtures/offer_watch_order_peer.dart +74 -0
- package/dart/test/kernel_author_after_read_test.dart +6 -3
- package/dart/test/kernel_fence_test.dart +4 -1
- package/dart/test/model_adoption_test.dart +66 -0
- package/dart/test/nomos_trace_test.dart +91 -0
- package/dart/test/own_offer_watch_order_test.dart +90 -0
- package/dart/test/receiving_group_open_test.dart +4 -8
- package/dart/test/replica_readiness_test.dart +14 -4
- package/dart/test/rows_watch_test.dart +331 -0
- package/dart/test/runtime_projections_test.dart +41 -0
- package/dart/test/test_peer_host_selection_test.dart +49 -0
- package/dart_types/CHANGELOG.md +39 -0
- package/dart_types/lib/src/approved_model.dart +100 -6
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +1063 -3
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +89 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +14 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +2272 -130
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +65 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +118 -2
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +278 -9
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +7 -85
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +16 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +35 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +43 -2
- package/dart_types/pubspec.yaml +1 -1
- package/package.json +6 -2
- package/src/aggregate.ts +93 -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 +186 -0
- package/src/birth_key_rule.ts +472 -0
- package/src/births.ts +207 -24
- package/src/build_provenance.ts +17 -2
- 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_dart.ts +95 -3
- package/src/codegen_dart_client.ts +73 -15
- package/src/codegen_dart_facade.ts +58 -35
- package/src/codegen_dart_framework_calls.ts +32 -10
- package/src/codegen_dart_scenario.ts +7 -0
- package/src/codegen_proof.ts +5 -2
- package/src/codegen_result_proto.ts +8 -6
- package/src/codegen_result_usda.ts +4 -0
- package/src/codegen_ts.ts +135 -34
- package/src/compatibility_graph.ts +41 -4
- package/src/compatibility_usda.ts +11 -1
- package/src/compile_package_main.ts +272 -105
- 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 +4 -48
- package/src/engine_javascript.ts +12 -6
- package/src/fields.ts +109 -0
- package/src/identity_usda.ts +77 -51
- package/src/index.ts +25 -1
- package/src/intent.ts +5 -0
- package/src/law_graph.ts +142 -1
- package/src/law_graph_usda.ts +25 -141
- package/src/law_layer_prims.ts +199 -0
- package/src/law_unit_selection.ts +45 -0
- package/src/law_unit_set_identity.ts +44 -0
- package/src/law_version.ts +107 -0
- package/src/package_config.ts +44 -0
- package/src/package_dependencies.ts +8 -0
- package/src/query/compile.ts +0 -0
- package/src/release_inspection.ts +24 -0
- package/src/release_publication.ts +298 -0
- package/src/value_object.ts +6 -3
- package/src/wire.ts +2 -0
- package/src/wire_paths.ts +17 -0
- package/src/workspace_routing.ts +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { collectPackageSources, findBirthKeyWrites, formatBirthKeyWriteWarnings } from "./birth_key_rule.js";
|
|
1
2
|
import type { Directive } from "./directive.js";
|
|
2
3
|
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
3
4
|
// remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
@@ -46,6 +47,7 @@ import type { Directive } from "./directive.js";
|
|
|
46
47
|
import { execFile, execFileSync } from "node:child_process";
|
|
47
48
|
import { promisify } from "node:util";
|
|
48
49
|
import { checkOperationContracts, deriveInterfaceOffer } from "./operation_contract_check.js";
|
|
50
|
+
import { lawVersionClaim, type LawVersionClaim } from "./law_version.js";
|
|
49
51
|
import { compilerIntermediateCacheRoot, compilerSourceName, compilerSourceRoot } from "./compiler_cache.js";
|
|
50
52
|
import {
|
|
51
53
|
APPLICATION_CONTRACT_MODULE,
|
|
@@ -80,6 +82,7 @@ import ts from "typescript";
|
|
|
80
82
|
import type { AggregateHandle } from "./aggregate.js";
|
|
81
83
|
import {
|
|
82
84
|
generateDartDomain,
|
|
85
|
+
dartBrandNamesForModule,
|
|
83
86
|
generateDartContracts,
|
|
84
87
|
generateDartActivityRegistry,
|
|
85
88
|
collectActivityDescriptors,
|
|
@@ -97,6 +100,8 @@ import {
|
|
|
97
100
|
} from "./evolution_files.js";
|
|
98
101
|
import { assertEvolutionModuleExports } from "./evolution.js";
|
|
99
102
|
import { readHistoricalIdentityFrontier } from "./identity_frontier.js";
|
|
103
|
+
import { parseBaselineUsda, type ReleasedBaseline } from "./baseline_usda.js";
|
|
104
|
+
import { BaselineRefusal, assertBaselineRetained, importBaseline, verifyBaselinePin } from "./baseline_import.js";
|
|
100
105
|
import {
|
|
101
106
|
dartBridgeClientOperationDirectiveIds,
|
|
102
107
|
generateDartDomainClient,
|
|
@@ -251,10 +256,6 @@ import {
|
|
|
251
256
|
tsClientFactoryName,
|
|
252
257
|
recursiveLazyTypes,
|
|
253
258
|
} from "./codegen_ts.js";
|
|
254
|
-
import {
|
|
255
|
-
generateOpenApiFragment,
|
|
256
|
-
mergeOpenApiFragments,
|
|
257
|
-
} from "./codegen_openapi.js";
|
|
258
259
|
import {
|
|
259
260
|
domainInterfaceFromLawGraph,
|
|
260
261
|
publicClientInterface,
|
|
@@ -269,6 +270,8 @@ import {
|
|
|
269
270
|
packageRoutesLayerUsda,
|
|
270
271
|
splitLawUnits,
|
|
271
272
|
} from "./law_units.js";
|
|
273
|
+
import { lawUnitSetIdentityWith } from "./law_unit_set_identity.js";
|
|
274
|
+
import { domainRequirementsOf, type DomainUnitRequirement } from "./domain_requirements.js";
|
|
272
275
|
import { checkDomainModules, formatFindings, hasRefusal } from "./law_check.js";
|
|
273
276
|
import {
|
|
274
277
|
currentEvolveLaw,
|
|
@@ -627,6 +630,7 @@ const compareLogicalPath = (left: string, right: string): number =>
|
|
|
627
630
|
* inventories the USDZ/Git tree and re-hashes every logically named layer. */
|
|
628
631
|
function emitLawClosure(
|
|
629
632
|
packageName: string,
|
|
633
|
+
claimedVersion: LawVersionClaim | undefined,
|
|
630
634
|
exportedDomains: readonly string[],
|
|
631
635
|
runtimeDependencies: readonly RuntimePackageDependency[],
|
|
632
636
|
domainAssets: readonly EmittedLawClosureAsset[],
|
|
@@ -673,6 +677,7 @@ function emitLawClosure(
|
|
|
673
677
|
"package.usda",
|
|
674
678
|
packageContractUsda({
|
|
675
679
|
packageName,
|
|
680
|
+
...(claimedVersion === undefined ? {} : { claimedVersion }),
|
|
676
681
|
exportedDomains,
|
|
677
682
|
runtimeDependencies,
|
|
678
683
|
})
|
|
@@ -1268,6 +1273,7 @@ function closeComposedBusinessBirthPresentation(
|
|
|
1268
1273
|
aggregateId?: unknown;
|
|
1269
1274
|
rootId?: unknown;
|
|
1270
1275
|
namespace?: unknown;
|
|
1276
|
+
keyMode?: unknown;
|
|
1271
1277
|
keyField?: unknown;
|
|
1272
1278
|
};
|
|
1273
1279
|
type BirthDirective = DomainModule["directives"][number] & {
|
|
@@ -1281,14 +1287,15 @@ function closeComposedBusinessBirthPresentation(
|
|
|
1281
1287
|
typeof birth.aggregateId !== "string" ||
|
|
1282
1288
|
typeof birth.rootId !== "string" ||
|
|
1283
1289
|
typeof birth.namespace !== "string" ||
|
|
1284
|
-
typeof birth.keyField !== "string"
|
|
1290
|
+
(typeof birth.keyField !== "string" && birth.keyMode !== "minted")
|
|
1285
1291
|
)
|
|
1286
1292
|
return undefined;
|
|
1287
1293
|
return [
|
|
1288
1294
|
birth.aggregateId,
|
|
1289
1295
|
birth.rootId,
|
|
1290
1296
|
birth.namespace,
|
|
1291
|
-
birth.
|
|
1297
|
+
// A minted birth has no key field; its identity here is the minted mode itself.
|
|
1298
|
+
typeof birth.keyField === "string" ? birth.keyField : "\u0001minted",
|
|
1292
1299
|
].join("\u0000");
|
|
1293
1300
|
};
|
|
1294
1301
|
|
|
@@ -1338,6 +1345,8 @@ interface DartSharedSymbols {
|
|
|
1338
1345
|
readonly frameworkDirIds: ReadonlySet<string>;
|
|
1339
1346
|
readonly frameworkQueryIds: ReadonlySet<string>;
|
|
1340
1347
|
readonly sharedVoNames: ReadonlySet<string>;
|
|
1348
|
+
/** Branded-id extension types used by ≥2 domains — declared ONCE in the framework file. */
|
|
1349
|
+
readonly sharedBrandNames: ReadonlySet<string>;
|
|
1341
1350
|
readonly hasFrameworkSymbols: boolean;
|
|
1342
1351
|
/** The synthetic module whose emit IS `nomos_framework.dart` — undefined when nothing is shared. */
|
|
1343
1352
|
readonly frameworkMod: DomainModule | undefined;
|
|
@@ -1499,11 +1508,23 @@ function collectDartSharedSymbols(
|
|
|
1499
1508
|
const sharedVos = [...sharedVoNames]
|
|
1500
1509
|
.sort()
|
|
1501
1510
|
.map((name) => voDescriptorByName.get(name)!);
|
|
1511
|
+
// TYPED IDS: a branded id used by two domains (a parent's business-birth payload and the child's key
|
|
1512
|
+
// field, typically) would otherwise declare one extension type per file and make the barrel ambiguous.
|
|
1513
|
+
const brandDomains = new Map<string, number>();
|
|
1514
|
+
for (const mod of modules) {
|
|
1515
|
+
for (const brand of dartBrandNamesForModule(mod)) {
|
|
1516
|
+
brandDomains.set(brand, (brandDomains.get(brand) ?? 0) + 1);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
const sharedBrandNames: ReadonlySet<string> = new Set(
|
|
1520
|
+
[...brandDomains.entries()].filter(([, n]) => n > 1).map(([name]) => name).sort()
|
|
1521
|
+
);
|
|
1502
1522
|
const hasFrameworkSymbols =
|
|
1503
1523
|
frameworkAggs.length > 0 ||
|
|
1504
1524
|
frameworkDirs.length > 0 ||
|
|
1505
1525
|
frameworkQueries.length > 0 ||
|
|
1506
|
-
sharedVos.length > 0
|
|
1526
|
+
sharedVos.length > 0 ||
|
|
1527
|
+
sharedBrandNames.size > 0;
|
|
1507
1528
|
const frameworkMod: DomainModule | undefined = hasFrameworkSymbols
|
|
1508
1529
|
? {
|
|
1509
1530
|
name: FRAMEWORK_FILE,
|
|
@@ -1521,6 +1542,7 @@ function collectDartSharedSymbols(
|
|
|
1521
1542
|
frameworkDirIds: new Set(frameworkDirById.keys()),
|
|
1522
1543
|
frameworkQueryIds: new Set(frameworkQueryById.keys()),
|
|
1523
1544
|
sharedVoNames,
|
|
1545
|
+
sharedBrandNames,
|
|
1524
1546
|
hasFrameworkSymbols,
|
|
1525
1547
|
frameworkMod,
|
|
1526
1548
|
};
|
|
@@ -1538,6 +1560,7 @@ function domainDedupOpts(
|
|
|
1538
1560
|
readonly skipDirectiveIds: Set<string>;
|
|
1539
1561
|
readonly skipQueryIds: Set<string>;
|
|
1540
1562
|
readonly skipValueObjectNames: Set<string>;
|
|
1563
|
+
readonly skipBrandNames: Set<string>;
|
|
1541
1564
|
};
|
|
1542
1565
|
readonly foldsFramework: boolean;
|
|
1543
1566
|
} {
|
|
@@ -1565,11 +1588,17 @@ function domainDedupOpts(
|
|
|
1565
1588
|
.filter((d) => shared.sharedVoNames.has(d.name))
|
|
1566
1589
|
.map((d) => d.name)
|
|
1567
1590
|
);
|
|
1591
|
+
const skipBrandNames = new Set(
|
|
1592
|
+
[...dartBrandNamesForModule(modForDart)].filter((name) =>
|
|
1593
|
+
shared.sharedBrandNames.has(name)
|
|
1594
|
+
)
|
|
1595
|
+
);
|
|
1568
1596
|
const foldsFramework =
|
|
1569
1597
|
skipAggregateIds.size > 0 ||
|
|
1570
1598
|
skipDirectiveIds.size > 0 ||
|
|
1571
1599
|
skipQueryIds.size > 0 ||
|
|
1572
|
-
skipValueObjectNames.size > 0
|
|
1600
|
+
skipValueObjectNames.size > 0 ||
|
|
1601
|
+
skipBrandNames.size > 0;
|
|
1573
1602
|
return {
|
|
1574
1603
|
modForDart,
|
|
1575
1604
|
skips: {
|
|
@@ -1577,6 +1606,7 @@ function domainDedupOpts(
|
|
|
1577
1606
|
skipDirectiveIds,
|
|
1578
1607
|
skipQueryIds,
|
|
1579
1608
|
skipValueObjectNames,
|
|
1609
|
+
skipBrandNames,
|
|
1580
1610
|
},
|
|
1581
1611
|
foldsFramework,
|
|
1582
1612
|
};
|
|
@@ -2145,10 +2175,18 @@ function emitDartOperationProto(
|
|
|
2145
2175
|
return [protoPath, generatedBinding];
|
|
2146
2176
|
}
|
|
2147
2177
|
|
|
2178
|
+
/** The compiled law's identities (CAP-773): the unit set is the law; the package is the `.law.usdz` bytes. */
|
|
2179
|
+
interface CompiledLawIdentities {
|
|
2180
|
+
readonly unitSet: string;
|
|
2181
|
+
readonly packageSha256: string;
|
|
2182
|
+
/** One requirement per application domain (CAP-666): its unit hash and its generated requirement identity. */
|
|
2183
|
+
readonly domainRequirements: readonly DomainUnitRequirement[];
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2148
2186
|
function emitDart(
|
|
2149
2187
|
modules: readonly DomainModule[],
|
|
2150
2188
|
dartOut: string,
|
|
2151
|
-
|
|
2189
|
+
law: CompiledLawIdentities,
|
|
2152
2190
|
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
2153
2191
|
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
2154
2192
|
packageInterface: Record<string, DomainInterface> = {},
|
|
@@ -2224,7 +2262,7 @@ function emitDart(
|
|
|
2224
2262
|
? []
|
|
2225
2263
|
: [{ module, graph, paths }];
|
|
2226
2264
|
}),
|
|
2227
|
-
{
|
|
2265
|
+
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256, domainRequirements: law.domainRequirements }
|
|
2228
2266
|
);
|
|
2229
2267
|
if (applicationFrameworkCallsSource !== undefined) {
|
|
2230
2268
|
const applicationFrameworkCallsPath = path.join(
|
|
@@ -2246,6 +2284,7 @@ function emitDart(
|
|
|
2246
2284
|
FRAMEWORK_FILE,
|
|
2247
2285
|
generateDartDomain(shared.frameworkMod, {
|
|
2248
2286
|
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
2287
|
+
extraBrandNames: [...shared.sharedBrandNames],
|
|
2249
2288
|
})
|
|
2250
2289
|
);
|
|
2251
2290
|
}
|
|
@@ -2364,7 +2403,7 @@ function emitDart(
|
|
|
2364
2403
|
writeGenerated(mod.name, src);
|
|
2365
2404
|
|
|
2366
2405
|
const clientSrc = generateDartDomainClient(modForDart, {
|
|
2367
|
-
domainHash,
|
|
2406
|
+
domainHash: law.unitSet,
|
|
2368
2407
|
callUsda: {
|
|
2369
2408
|
graph: lawGraphs.get(mod.name)!,
|
|
2370
2409
|
paths: lawPaths.get(mod.name)!,
|
|
@@ -2539,12 +2578,12 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
2539
2578
|
* just the floor generated code needs — a lagging pin forces tenants into dependency_overrides. */
|
|
2540
2579
|
// 0.3.0: SurfacedValue<T>/SurfacedObservation/PendingConflictRow — generated Surfaced-field typing +
|
|
2541
2580
|
// the pendingConflicts read rows.
|
|
2542
|
-
const NOMOS_TYPES_DEP = "^0.
|
|
2581
|
+
const NOMOS_TYPES_DEP = "^0.14.0";
|
|
2543
2582
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
2544
2583
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
2545
2584
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
2546
|
-
const NOMOS_CLIENT_DEP = "^0.
|
|
2547
|
-
const NOMOS_FLUTTER_DEP = "^0.
|
|
2585
|
+
const NOMOS_CLIENT_DEP = "^0.69.0";
|
|
2586
|
+
const NOMOS_FLUTTER_DEP = "^0.68.0";
|
|
2548
2587
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in the Dart and Flutter
|
|
2549
2588
|
// package pubspecs — a release without this bump fails the suite, so tenants never
|
|
2550
2589
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -3282,7 +3321,7 @@ function removeGeneratedClientLawAssets(pkgDir: string): boolean {
|
|
|
3282
3321
|
function emitDartPackages(
|
|
3283
3322
|
modules: readonly DomainModule[],
|
|
3284
3323
|
dartOut: string,
|
|
3285
|
-
|
|
3324
|
+
law: CompiledLawIdentities,
|
|
3286
3325
|
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
3287
3326
|
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
3288
3327
|
packageInterface: Record<string, DomainInterface>,
|
|
@@ -3387,6 +3426,7 @@ function emitDartPackages(
|
|
|
3387
3426
|
FRAMEWORK_FILE,
|
|
3388
3427
|
generateDartDomain(shared.frameworkMod, {
|
|
3389
3428
|
additionalValueObjects: shared.frameworkMod.valueObjects ?? [],
|
|
3429
|
+
extraBrandNames: [...shared.sharedBrandNames],
|
|
3390
3430
|
})
|
|
3391
3431
|
);
|
|
3392
3432
|
}
|
|
@@ -3677,7 +3717,7 @@ function emitDartPackages(
|
|
|
3677
3717
|
? []
|
|
3678
3718
|
: [{ module, graph, paths }];
|
|
3679
3719
|
}),
|
|
3680
|
-
{
|
|
3720
|
+
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256, domainRequirements: law.domainRequirements }
|
|
3681
3721
|
);
|
|
3682
3722
|
const workspaceAccessReadImports = new Map<string, string>();
|
|
3683
3723
|
for (const module of operationProtoModules) {
|
|
@@ -3727,7 +3767,7 @@ function emitDartPackages(
|
|
|
3727
3767
|
const workspaceAccessReadImportUri = workspaceAccessReadImports.get(mod.name);
|
|
3728
3768
|
const makeClient = (imports: readonly string[]) =>
|
|
3729
3769
|
generateDartDomainClient(dd.modForDart, {
|
|
3730
|
-
domainHash,
|
|
3770
|
+
domainHash: law.unitSet,
|
|
3731
3771
|
callUsda: {
|
|
3732
3772
|
graph: lawGraphs.get(mod.name)!,
|
|
3733
3773
|
paths: lawPaths.get(mod.name)!,
|
|
@@ -3818,7 +3858,7 @@ function emitDartPackages(
|
|
|
3818
3858
|
invitationPolicies: (
|
|
3819
3859
|
dd.modForDart.applicationWorkspaceSharing ?? []
|
|
3820
3860
|
).map((policy) => ({
|
|
3821
|
-
domainHash,
|
|
3861
|
+
domainHash: law.unitSet,
|
|
3822
3862
|
query: policy.invitationLaw.pendingByRecipient.id,
|
|
3823
3863
|
redeem: policy.invitationLaw.redeem.id,
|
|
3824
3864
|
personField: policy.person,
|
|
@@ -3858,6 +3898,7 @@ function emitDartPackages(
|
|
|
3858
3898
|
`export 'package:${packages.types}/${genRel}/${businessSharedFile}';`,
|
|
3859
3899
|
`export 'package:nomos_client/src/workspace_open_progress.dart' show ApplicationWorkspaceOpenProgress;`,
|
|
3860
3900
|
`export 'package:nomos_client/src/write_progress.dart' show NomosWrite, NomosWriteProgress, NomosWritePhase;`,
|
|
3901
|
+
`export 'package:nomos_client/src/rows_watch.dart' show NomosRows, NomosRowProjection, NomosRowsProjectionStream;`,
|
|
3861
3902
|
`export 'package:nomos_types/nomos_types.dart' show CustodyError, CustodyPhase, CustodySource, NomosRecommendedAction;`,
|
|
3862
3903
|
...tenantTypesExportKeys
|
|
3863
3904
|
.map((file) => {
|
|
@@ -4201,6 +4242,7 @@ async function main(): Promise<void> {
|
|
|
4201
4242
|
"--preflight",
|
|
4202
4243
|
"--inspect-sqlite",
|
|
4203
4244
|
"--inspect-law",
|
|
4245
|
+
"--publishable",
|
|
4204
4246
|
]);
|
|
4205
4247
|
for (const flag of argv.filter((arg) => arg.startsWith("--"))) {
|
|
4206
4248
|
if (supportedFlags.has(flag)) continue;
|
|
@@ -4236,6 +4278,9 @@ async function main(): Promise<void> {
|
|
|
4236
4278
|
// `dart analyze` on the generated Dart package after emission and fails the compile on red.
|
|
4237
4279
|
const analyzeFlag =
|
|
4238
4280
|
argv.includes("--analyze") || process.env.NOMOS_ANALYZE === "1";
|
|
4281
|
+
// A PUBLISHABLE compile (architecture/domain_release_lifecycle.md, step 1) must start from the
|
|
4282
|
+
// baseline exported from released custody: it refuses without a pinned `nomos.baseline.usda`.
|
|
4283
|
+
const publishableFlag = argv.includes("--publishable");
|
|
4239
4284
|
const configArg = argv.find((a) => !a.startsWith("--")) ?? "nomos.project.ts";
|
|
4240
4285
|
const configPath = path.resolve(process.cwd(), configArg);
|
|
4241
4286
|
if (!existsSync(configPath)) fail(`config not found: ${configPath}`);
|
|
@@ -4320,6 +4365,39 @@ async function main(): Promise<void> {
|
|
|
4320
4365
|
"nomos.project.ts no longer accepts 'layered': every law closure is layered, with no alternate compile lane"
|
|
4321
4366
|
);
|
|
4322
4367
|
}
|
|
4368
|
+
// ── THE RELEASED BASELINE (CAP-660) ──────────────────────────────────────────────────────────
|
|
4369
|
+
// `nomos.project.ts` pins the baseline by content address. Verify the bytes are the pinned ones
|
|
4370
|
+
// and read it now, before any identity is touched; the import and the retention proof follow.
|
|
4371
|
+
const baselineRefused = (error: unknown): never => {
|
|
4372
|
+
if (error instanceof BaselineRefusal) fail(`[${error.code}] ${error.message}`);
|
|
4373
|
+
throw error;
|
|
4374
|
+
};
|
|
4375
|
+
let releasedBaseline: ReleasedBaseline | undefined;
|
|
4376
|
+
let releasedBaselineSha256: string | undefined;
|
|
4377
|
+
if (cfg.baseline === undefined) {
|
|
4378
|
+
if (publishableFlag) {
|
|
4379
|
+
fail(
|
|
4380
|
+
"[baseline-required] a publishable compile must name the released baseline it extends: " +
|
|
4381
|
+
`run \`githolon baseline export --units build/${cfg.name}.units\` (or --release <id>) against the release ` +
|
|
4382
|
+
"you are extending, commit nomos.baseline.usda, and pin it in nomos.project.ts as " +
|
|
4383
|
+
"baseline: { artifact: \"./nomos.baseline.usda\", sha256: \"<printed sha256>\" }"
|
|
4384
|
+
);
|
|
4385
|
+
}
|
|
4386
|
+
} else {
|
|
4387
|
+
const baselinePath = path.resolve(cfgDir, cfg.baseline.artifact);
|
|
4388
|
+
if (!existsSync(baselinePath)) {
|
|
4389
|
+
fail(`[baseline-unreadable] pinned baseline not found: ${baselinePath}`);
|
|
4390
|
+
}
|
|
4391
|
+
const baselineText = readFileSync(baselinePath, "utf8");
|
|
4392
|
+
try {
|
|
4393
|
+
verifyBaselinePin(baselineText, cfg.baseline);
|
|
4394
|
+
releasedBaseline = parseBaselineUsda(baselineText);
|
|
4395
|
+
} catch (error) {
|
|
4396
|
+
if (error instanceof BaselineRefusal) baselineRefused(error);
|
|
4397
|
+
fail(`[baseline-unreadable] ${cfg.baseline.artifact}: ${(error as Error).message}`);
|
|
4398
|
+
}
|
|
4399
|
+
releasedBaselineSha256 = cfg.baseline.sha256;
|
|
4400
|
+
}
|
|
4323
4401
|
let sourceTopologyDiagnostics: ReturnType<
|
|
4324
4402
|
typeof assertPackageFeatureTopology
|
|
4325
4403
|
> = [];
|
|
@@ -4391,6 +4469,7 @@ async function main(): Promise<void> {
|
|
|
4391
4469
|
if (cfg.rootPart !== undefined) {
|
|
4392
4470
|
applicationBirthPolicyDomains.push(APPLICATION_HOME_DOMAIN);
|
|
4393
4471
|
}
|
|
4472
|
+
const authoredDomainModules: Mod[] = [];
|
|
4394
4473
|
for (const domain of cfg.domains) {
|
|
4395
4474
|
let authored: Mod = {};
|
|
4396
4475
|
for (const rel of domain.modules) {
|
|
@@ -4416,10 +4495,32 @@ async function main(): Promise<void> {
|
|
|
4416
4495
|
}
|
|
4417
4496
|
}
|
|
4418
4497
|
const expanded = expandBusinessBirthExports(authored, domain.key);
|
|
4498
|
+
authoredDomainModules.push(authored);
|
|
4419
4499
|
if (directivesOf(expanded).some((dir) => dir.birthsChild === true)) {
|
|
4420
4500
|
applicationBirthPolicyDomains.push(domain.key);
|
|
4421
4501
|
}
|
|
4422
4502
|
}
|
|
4503
|
+
// A workspace name is fixed at birth, and the framework enforces it at the kernel: every field-keyed
|
|
4504
|
+
// birth's key is write-once (aggregate.ts BIRTH_KEY_WRITE_ONCE_CODE). Statically WARN at each source line
|
|
4505
|
+
// that writes a key outside the birth in a way that rule will refuse, or that keys another instance
|
|
4506
|
+
// (CAP-804; architecture/choosing_a_birth_key.md). Advisory only — the runtime rule is the guarantee.
|
|
4507
|
+
{
|
|
4508
|
+
const birthKeyWarnings = findBirthKeyWrites(
|
|
4509
|
+
authoredDomainModules,
|
|
4510
|
+
collectPackageSources(
|
|
4511
|
+
cfg.domains.flatMap((domain) => domain.modules.map((rel) => path.resolve(cfgDir, rel))),
|
|
4512
|
+
cfgDir
|
|
4513
|
+
),
|
|
4514
|
+
{ root: cfgDir }
|
|
4515
|
+
);
|
|
4516
|
+
if (birthKeyWarnings.length > 0) {
|
|
4517
|
+
console.warn(
|
|
4518
|
+
`nomos-compile: ${birthKeyWarnings.length} birth-key write warning(s)`
|
|
4519
|
+
);
|
|
4520
|
+
for (const line of formatBirthKeyWriteWarnings(birthKeyWarnings))
|
|
4521
|
+
console.warn(line);
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4423
4524
|
stage("domain discovery imports");
|
|
4424
4525
|
if (
|
|
4425
4526
|
cfg.application?.homeGenesis !== undefined &&
|
|
@@ -5539,15 +5640,6 @@ async function main(): Promise<void> {
|
|
|
5539
5640
|
finding.directiveId?.startsWith("nomos_internal_") === true ||
|
|
5540
5641
|
(finding.directiveId !== undefined &&
|
|
5541
5642
|
frameworkComposedDirectives.has(`${finding.domain}\0${finding.directiveId}`));
|
|
5542
|
-
// Self-description is a compiler-owned presentation projection, not executable law. Build it
|
|
5543
|
-
// once from the same composed modules and place it only in the separately routed describe plan;
|
|
5544
|
-
// exact offer/read plans must not carry OpenAPI generation and Zod JSON-Schema machinery.
|
|
5545
|
-
const runtimeOpenApiDocument = mergeOpenApiFragments(
|
|
5546
|
-
domainModules.map((module) =>
|
|
5547
|
-
generateOpenApiFragment(module, { includeFrameworkRoutes: true })
|
|
5548
|
-
),
|
|
5549
|
-
{ title: `${cfg.name} (nomos package)` }
|
|
5550
|
-
);
|
|
5551
5643
|
|
|
5552
5644
|
if (preflightFlag) {
|
|
5553
5645
|
const businessFindings = authorTimeFindings.filter(
|
|
@@ -5622,12 +5714,36 @@ async function main(): Promise<void> {
|
|
|
5622
5714
|
? parseIdentityUsda(readFileSync(lockPath, "utf8"))
|
|
5623
5715
|
: undefined;
|
|
5624
5716
|
const historicalFrontier = readHistoricalIdentityFrontier(lockPath);
|
|
5717
|
+
// Outside Git custody (a clean export, a CI checkout without history) the released baseline IS
|
|
5718
|
+
// the evolution frontier: it carries every released aggregate and field by sid, so a removal
|
|
5719
|
+
// without a declared retirement still refuses. It carries no value contracts, so it never
|
|
5720
|
+
// produces a false in-place refusal.
|
|
5625
5721
|
const historicalLock: CompilerIdentityModel | undefined =
|
|
5626
5722
|
historicalFrontier === undefined
|
|
5627
|
-
?
|
|
5723
|
+
? releasedBaseline?.continuity
|
|
5628
5724
|
: parseIdentityUsda(historicalFrontier.source);
|
|
5629
5725
|
const inferredRenames: { domain: string; renames: InferredRename[] }[] = [];
|
|
5630
5726
|
let nextIdentity = identityRegistryFromModel(priorLock);
|
|
5727
|
+
if (releasedBaseline !== undefined) {
|
|
5728
|
+
// Verify the ledger against released custody and import what it lacks, so a clean checkout
|
|
5729
|
+
// allocates the released sids and wire keys rather than fresh ones, and a diverged branch
|
|
5730
|
+
// refuses with the coordinate named (baseline_import.ts).
|
|
5731
|
+
try {
|
|
5732
|
+
const imported = importBaseline(
|
|
5733
|
+
nextIdentity,
|
|
5734
|
+
releasedBaseline,
|
|
5735
|
+
cfg.domains.flatMap((domain) => [domain.key, ...(domain.name === undefined ? [] : [domain.name])])
|
|
5736
|
+
);
|
|
5737
|
+
nextIdentity = imported.registry;
|
|
5738
|
+
console.log(
|
|
5739
|
+
`baseline: ${releasedBaseline.release === "none" ? "unreleased units" : `release ${releasedBaseline.release}`} ` +
|
|
5740
|
+
`(law ${releasedBaseline.unitSet}) — ${imported.verified} verified, ${imported.imported.length} identit${imported.imported.length === 1 ? "y" : "ies"} ` +
|
|
5741
|
+
`and ${imported.allocated.length} wire allocation(s) imported${imported.relabelled.length === 0 ? "" : `, ${imported.relabelled.length} released rename(s) carried`}`
|
|
5742
|
+
);
|
|
5743
|
+
} catch (error) {
|
|
5744
|
+
baselineRefused(error);
|
|
5745
|
+
}
|
|
5746
|
+
}
|
|
5631
5747
|
const typedLawGraphs = new Map<string, LawGraph>();
|
|
5632
5748
|
// The lock is project-wide, not package-local. Several package configs commonly live beside one
|
|
5633
5749
|
// application stage; compiling one must not erase the stable identity of domains owned by its siblings.
|
|
@@ -5837,6 +5953,18 @@ async function main(): Promise<void> {
|
|
|
5837
5953
|
return;
|
|
5838
5954
|
}
|
|
5839
5955
|
|
|
5956
|
+
// ── BASELINE RETENTION PROOF (CAP-660) ───────────────────────────────────────────
|
|
5957
|
+
// Every released identity still resolves to its released sid and every released wire key is still
|
|
5958
|
+
// the canonical allocation. Reconciliation never rewrites an allocation, so this holds by
|
|
5959
|
+
// construction; proving it here keeps "the candidate extends the release" a checked fact.
|
|
5960
|
+
if (releasedBaseline !== undefined) {
|
|
5961
|
+
try {
|
|
5962
|
+
assertBaselineRetained(nextIdentity, releasedBaseline);
|
|
5963
|
+
} catch (error) {
|
|
5964
|
+
baselineRefused(error);
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5840
5968
|
// ── ORDINARY-COMPILE EVOLUTION GATE ──────────────────────────────────────────────
|
|
5841
5969
|
// Agents reliably run `compile`; they do not reliably discover an optional migration command.
|
|
5842
5970
|
// Compare the candidate against the committed identity frontier here, after stable-id
|
|
@@ -5915,6 +6043,44 @@ async function main(): Promise<void> {
|
|
|
5915
6043
|
// giant formatting-only diff in an established lock.
|
|
5916
6044
|
writeFileSync(lockPath, serializeIdentityUsda(nextLock), "utf8");
|
|
5917
6045
|
|
|
6046
|
+
// USDA is rendered directly from the typed graph. The final closure writer below publishes these
|
|
6047
|
+
// exact texts under their logical paths; no parallel layer directory or JSON reconstruction exists.
|
|
6048
|
+
const v3Closure = [...typedLawGraphs.values()];
|
|
6049
|
+
const v3DomainAssets: EmittedLawClosureAsset[] = [];
|
|
6050
|
+
const v3DomainRoots: string[] = [];
|
|
6051
|
+
const v3LawPathByNode = new Map<LawGraph["nodes"][number], string>();
|
|
6052
|
+
const v3CompiledGraphs = new Map<LawGraph, ReturnType<typeof compileSparseLawGraphUsda>>();
|
|
6053
|
+
const typedDomainIdentityByName = new Map<string, string>();
|
|
6054
|
+
const typedLawPathsByName = new Map<string, ReadonlyMap<string, string>>();
|
|
6055
|
+
for (const [domain, graph] of typedLawGraphs) {
|
|
6056
|
+
const safeDomain = domain.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
6057
|
+
const logicalPath = `domains/${safeDomain}.usda`;
|
|
6058
|
+
const compiledLayer = compileSparseLawGraphUsda(
|
|
6059
|
+
graph,
|
|
6060
|
+
logicalPath,
|
|
6061
|
+
v3Closure
|
|
6062
|
+
);
|
|
6063
|
+
v3CompiledGraphs.set(graph, compiledLayer);
|
|
6064
|
+
const layerText = compiledLayer.text;
|
|
6065
|
+
const sha256 = sha256HexUtf8(layerText);
|
|
6066
|
+
v3DomainAssets.push({
|
|
6067
|
+
logicalPath,
|
|
6068
|
+
sha256,
|
|
6069
|
+
utf8: layerText,
|
|
6070
|
+
});
|
|
6071
|
+
const domainRoot = compiledLayer.paths.get(graph.domain.entity.id);
|
|
6072
|
+
if (domainRoot === undefined) {
|
|
6073
|
+
fail(`domain '${domain}' did not emit its canonical OpenUSD root path`);
|
|
6074
|
+
}
|
|
6075
|
+
v3DomainRoots.push(domainRoot);
|
|
6076
|
+
for (const node of graph.nodes) {
|
|
6077
|
+
const lawPath = compiledLayer.paths.get(node.entity.id);
|
|
6078
|
+
if (lawPath !== undefined) v3LawPathByNode.set(node, lawPath);
|
|
6079
|
+
}
|
|
6080
|
+
typedDomainIdentityByName.set(domain, sha256);
|
|
6081
|
+
typedLawPathsByName.set(domain, compiledLayer.paths);
|
|
6082
|
+
}
|
|
6083
|
+
|
|
5918
6084
|
// ── THE STRUCTURAL INTERFACE (#72) — directives (payload shapes) + aggregates (read
|
|
5919
6085
|
// shapes, sid-keyed), keyed by DOMAIN. The SAME object is (a) baked into the generated
|
|
5920
6086
|
// clients as their requirement and (b) staged on the deploy as the workspace's offer, so
|
|
@@ -5929,7 +6095,12 @@ async function main(): Promise<void> {
|
|
|
5929
6095
|
`compiler surface invariant: domain '${key}' has no typed USDA graph`
|
|
5930
6096
|
);
|
|
5931
6097
|
}
|
|
5932
|
-
|
|
6098
|
+
// Nested record members carry the allocation the generated codecs encode them under, which
|
|
6099
|
+
// follows the composed layer's canonical prim (CAP-681).
|
|
6100
|
+
const offeredInterface = domainInterfaceFromLawGraph(
|
|
6101
|
+
graph,
|
|
6102
|
+
typedLawPathsByName.get(mod.name)
|
|
6103
|
+
);
|
|
5933
6104
|
const di = publicClientInterface([mod], { [key]: offeredInterface })[key]!;
|
|
5934
6105
|
const graphRoutes = graph.nodes
|
|
5935
6106
|
.filter((node) => node.kind === "intent" && node.public)
|
|
@@ -6022,44 +6193,6 @@ async function main(): Promise<void> {
|
|
|
6022
6193
|
}
|
|
6023
6194
|
}
|
|
6024
6195
|
|
|
6025
|
-
// USDA is rendered directly from the typed graph. The final closure writer below publishes these
|
|
6026
|
-
// exact texts under their logical paths; no parallel layer directory or JSON reconstruction exists.
|
|
6027
|
-
const v3Closure = [...typedLawGraphs.values()];
|
|
6028
|
-
const v3DomainAssets: EmittedLawClosureAsset[] = [];
|
|
6029
|
-
const v3DomainRoots: string[] = [];
|
|
6030
|
-
const v3LawPathByNode = new Map<LawGraph["nodes"][number], string>();
|
|
6031
|
-
const v3CompiledGraphs = new Map<LawGraph, ReturnType<typeof compileSparseLawGraphUsda>>();
|
|
6032
|
-
const typedDomainIdentityByName = new Map<string, string>();
|
|
6033
|
-
const typedLawPathsByName = new Map<string, ReadonlyMap<string, string>>();
|
|
6034
|
-
for (const [domain, graph] of typedLawGraphs) {
|
|
6035
|
-
const safeDomain = domain.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
6036
|
-
const logicalPath = `domains/${safeDomain}.usda`;
|
|
6037
|
-
const compiledLayer = compileSparseLawGraphUsda(
|
|
6038
|
-
graph,
|
|
6039
|
-
logicalPath,
|
|
6040
|
-
v3Closure
|
|
6041
|
-
);
|
|
6042
|
-
v3CompiledGraphs.set(graph, compiledLayer);
|
|
6043
|
-
const layerText = compiledLayer.text;
|
|
6044
|
-
const sha256 = sha256HexUtf8(layerText);
|
|
6045
|
-
v3DomainAssets.push({
|
|
6046
|
-
logicalPath,
|
|
6047
|
-
sha256,
|
|
6048
|
-
utf8: layerText,
|
|
6049
|
-
});
|
|
6050
|
-
const domainRoot = compiledLayer.paths.get(graph.domain.entity.id);
|
|
6051
|
-
if (domainRoot === undefined) {
|
|
6052
|
-
fail(`domain '${domain}' did not emit its canonical OpenUSD root path`);
|
|
6053
|
-
}
|
|
6054
|
-
v3DomainRoots.push(domainRoot);
|
|
6055
|
-
for (const node of graph.nodes) {
|
|
6056
|
-
const lawPath = compiledLayer.paths.get(node.entity.id);
|
|
6057
|
-
if (lawPath !== undefined) v3LawPathByNode.set(node, lawPath);
|
|
6058
|
-
}
|
|
6059
|
-
typedDomainIdentityByName.set(domain, sha256);
|
|
6060
|
-
typedLawPathsByName.set(domain, compiledLayer.paths);
|
|
6061
|
-
}
|
|
6062
|
-
|
|
6063
6196
|
// Index the transient graph once. Both projections follow the same nominal edges, including
|
|
6064
6197
|
// transitive cross-domain dependencies. Per-command selection also follows reverse guard edges;
|
|
6065
6198
|
// the retained package command projection remains the compatibility consumer until the runtime
|
|
@@ -6607,7 +6740,6 @@ async function main(): Promise<void> {
|
|
|
6607
6740
|
const planEntrySource = (
|
|
6608
6741
|
domainKeys: readonly string[],
|
|
6609
6742
|
includeReports: boolean,
|
|
6610
|
-
includeDescribe: boolean,
|
|
6611
6743
|
sourceOverrides: ReadonlyMap<string, string> = new Map(),
|
|
6612
6744
|
includePreloads = true,
|
|
6613
6745
|
routingOverride?: Record<string, unknown>,
|
|
@@ -6659,12 +6791,6 @@ async function main(): Promise<void> {
|
|
|
6659
6791
|
...(!sharedRuntime && zodSeedNames.length > 0
|
|
6660
6792
|
? [` seeds: [${zodSeedNames.join(", ")}],`]
|
|
6661
6793
|
: []),
|
|
6662
|
-
...(includeDescribe
|
|
6663
|
-
? [` openapiDocument: ${JSON.stringify(runtimeOpenApiDocument)},`]
|
|
6664
|
-
: []),
|
|
6665
|
-
...(includeDescribe
|
|
6666
|
-
? [` packageTitle: ${JSON.stringify(`${cfg.name} (nomos package)`)},`]
|
|
6667
|
-
: []),
|
|
6668
6794
|
...workspaceEffects.config,
|
|
6669
6795
|
`});`,
|
|
6670
6796
|
...(includeMintInstalls
|
|
@@ -6841,7 +6967,6 @@ async function main(): Promise<void> {
|
|
|
6841
6967
|
const compilePlan = async (
|
|
6842
6968
|
domainKeys: readonly string[],
|
|
6843
6969
|
includeReports: boolean,
|
|
6844
|
-
includeDescribe: boolean,
|
|
6845
6970
|
options: {
|
|
6846
6971
|
readonly sourceOverrides?: ReadonlyMap<string, string>;
|
|
6847
6972
|
readonly sliceTargets?: readonly PlanSourceSliceTarget[];
|
|
@@ -6880,7 +7005,6 @@ async function main(): Promise<void> {
|
|
|
6880
7005
|
const signature = JSON.stringify({
|
|
6881
7006
|
domains: ordered,
|
|
6882
7007
|
reports: includeReports,
|
|
6883
|
-
describe: includeDescribe,
|
|
6884
7008
|
slice:
|
|
6885
7009
|
effectiveSliceTargets?.map((target) => [
|
|
6886
7010
|
target.modulePath,
|
|
@@ -6895,7 +7019,6 @@ async function main(): Promise<void> {
|
|
|
6895
7019
|
planEntrySource(
|
|
6896
7020
|
ordered,
|
|
6897
7021
|
includeReports,
|
|
6898
|
-
includeDescribe,
|
|
6899
7022
|
options.sourceOverrides,
|
|
6900
7023
|
options.includePreloads ?? options.sliceTargets === undefined,
|
|
6901
7024
|
options.routingOverride,
|
|
@@ -7035,14 +7158,9 @@ async function main(): Promise<void> {
|
|
|
7035
7158
|
const routePlan = async (
|
|
7036
7159
|
selector: string,
|
|
7037
7160
|
domainKeys: readonly string[],
|
|
7038
|
-
includeReports = false
|
|
7039
|
-
includeDescribe = false
|
|
7161
|
+
includeReports = false
|
|
7040
7162
|
): Promise<void> => {
|
|
7041
|
-
const asset = await compilePlan(
|
|
7042
|
-
domainKeys,
|
|
7043
|
-
includeReports,
|
|
7044
|
-
includeDescribe
|
|
7045
|
-
);
|
|
7163
|
+
const asset = await compilePlan(domainKeys, includeReports);
|
|
7046
7164
|
planRoutes.push({ selector, planSha256: asset.sha256 });
|
|
7047
7165
|
};
|
|
7048
7166
|
const routeAsset = (selector: string, asset: UsdPlanAsset): void => {
|
|
@@ -7086,7 +7204,7 @@ async function main(): Promise<void> {
|
|
|
7086
7204
|
// content hash, and emitted sorted by selector/hash), so compile them concurrently and bind
|
|
7087
7205
|
// routes afterwards in declaration order.
|
|
7088
7206
|
const domainPlans = await Promise.all(
|
|
7089
|
-
orderedDomainKeys.map((key) => compilePlan([key], false
|
|
7207
|
+
orderedDomainKeys.map((key) => compilePlan([key], false))
|
|
7090
7208
|
);
|
|
7091
7209
|
orderedDomainKeys.forEach((key, index) => {
|
|
7092
7210
|
const asset = domainPlans[index]!;
|
|
@@ -7158,7 +7276,7 @@ async function main(): Promise<void> {
|
|
|
7158
7276
|
const source = ` ${JSON.stringify(
|
|
7159
7277
|
BUSINESS_BIRTH_FRAMEWORK_PLAN_DOMAIN
|
|
7160
7278
|
)}: [${selectedSources.join(", ")}],`;
|
|
7161
|
-
frameworkPlan = compilePlan([domain], false,
|
|
7279
|
+
frameworkPlan = compilePlan([domain], false, {
|
|
7162
7280
|
sourceOverrides: new Map([[domain, source]]),
|
|
7163
7281
|
includePreloads: false,
|
|
7164
7282
|
cacheKey: "business-birth-framework",
|
|
@@ -7228,7 +7346,7 @@ async function main(): Promise<void> {
|
|
|
7228
7346
|
selectedModule,
|
|
7229
7347
|
...generated,
|
|
7230
7348
|
].join(", ")}],`;
|
|
7231
|
-
const asset = await compilePlan([domain], false,
|
|
7349
|
+
const asset = await compilePlan([domain], false, {
|
|
7232
7350
|
sourceOverrides: new Map([[domain, source]]),
|
|
7233
7351
|
sliceTargets: selected,
|
|
7234
7352
|
});
|
|
@@ -7386,7 +7504,7 @@ async function main(): Promise<void> {
|
|
|
7386
7504
|
)}: [${moduleExpression}],`;
|
|
7387
7505
|
workspaceInvariantPlans.push({
|
|
7388
7506
|
invariantIds: members.map(([id]) => id),
|
|
7389
|
-
plan: compilePlan([domain], false,
|
|
7507
|
+
plan: compilePlan([domain], false, {
|
|
7390
7508
|
sourceOverrides: new Map([[domain, domainSource]]),
|
|
7391
7509
|
sliceTargets: [...selectedByKey.values()],
|
|
7392
7510
|
cacheKey: `workspace-invariants:${directiveId}:${members
|
|
@@ -7403,9 +7521,11 @@ async function main(): Promise<void> {
|
|
|
7403
7521
|
}
|
|
7404
7522
|
}
|
|
7405
7523
|
stage("workspace invariant plans");
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7524
|
+
// No `describe` route: the kernel derives a workspace's description from its installed law
|
|
7525
|
+
// (rpc_describe renders it from the command contract and read projection), so a compiled
|
|
7526
|
+
// self-description plan over every domain was never executed, and it was the one composition
|
|
7527
|
+
// file a single-domain edit moved (CAP-658).
|
|
7528
|
+
const reportRoutes: Promise<void>[] = [];
|
|
7409
7529
|
for (const reportId of Object.keys(cfg.reports ?? {}))
|
|
7410
7530
|
reportRoutes.push(routePlan(`report:report:${reportId}`, [], true));
|
|
7411
7531
|
const routeTable = (
|
|
@@ -7447,7 +7567,7 @@ async function main(): Promise<void> {
|
|
|
7447
7567
|
}
|
|
7448
7568
|
}
|
|
7449
7569
|
await Promise.all(reportRoutes);
|
|
7450
|
-
stage("
|
|
7570
|
+
stage("report plans");
|
|
7451
7571
|
// Adaptive offer splitting deliberately compiles candidate parents before retaining their children.
|
|
7452
7572
|
// Only route-reachable content is custody; exploratory compiler work never becomes law bytes.
|
|
7453
7573
|
const routedPlanHashes = new Set(planRoutes.map((route) => route.planSha256));
|
|
@@ -7747,6 +7867,7 @@ async function main(): Promise<void> {
|
|
|
7747
7867
|
};
|
|
7748
7868
|
let lawClosure = emitLawClosure(
|
|
7749
7869
|
cfg.name,
|
|
7870
|
+
cfg.version === undefined ? undefined : lawVersionClaim(cfg.version),
|
|
7750
7871
|
domainModules.map((module) => module.domain ?? module.name),
|
|
7751
7872
|
runtimeDependencies,
|
|
7752
7873
|
v3DomainAssets,
|
|
@@ -7908,6 +8029,7 @@ async function main(): Promise<void> {
|
|
|
7908
8029
|
};
|
|
7909
8030
|
lawClosure = emitLawClosure(
|
|
7910
8031
|
cfg.name,
|
|
8032
|
+
cfg.version === undefined ? undefined : lawVersionClaim(cfg.version),
|
|
7911
8033
|
domainModules.map((module) => module.domain ?? module.name),
|
|
7912
8034
|
runtimeDependencies,
|
|
7913
8035
|
v3DomainAssets,
|
|
@@ -7934,8 +8056,10 @@ async function main(): Promise<void> {
|
|
|
7934
8056
|
if (probeFailure !== undefined) fail(probeFailure);
|
|
7935
8057
|
}
|
|
7936
8058
|
stage("boot probe (verdict)");
|
|
7937
|
-
// The
|
|
7938
|
-
//
|
|
8059
|
+
// The PACKAGE identity: this compiler's own closure of the package (root.usda, routes and its derived
|
|
8060
|
+
// finished goods included). It names the `.law.usdz` bytes and the package lane; it is NOT what a
|
|
8061
|
+
// unit-lane target serves (that target's kernel composes the units itself, CAP-773). The law
|
|
8062
|
+
// identity is the unit set identity below.
|
|
7939
8063
|
const domainHash = lawClosure.identity;
|
|
7940
8064
|
const rootAsset = lawClosure.assets.find(
|
|
7941
8065
|
(asset) => asset.logicalPath === lawClosure.rootLogicalPath
|
|
@@ -7949,11 +8073,18 @@ async function main(): Promise<void> {
|
|
|
7949
8073
|
.map((asset) => [`layers/${asset.logicalPath}`, asset.bytes] as const),
|
|
7950
8074
|
]);
|
|
7951
8075
|
writeFileSync(lawUsdzPath, lawUsdz);
|
|
7952
|
-
// The
|
|
8076
|
+
// The package closure's identity on its own line, for gates that check the `.law.usdz` bytes.
|
|
7953
8077
|
writeFileSync(path.join(outDir, `${cfg.name}.law.sha256`), `${domainHash}\n`, "utf8");
|
|
7954
8078
|
// D21: the same law, authored as per-domain units the kernel composes. Split from the closure just
|
|
7955
8079
|
// emitted (its bytes and identity are untouched), previewed for exact coverage, and written as plain
|
|
7956
8080
|
// trees: in custody each unit is a git tree, so git owns compression and deduplication.
|
|
8081
|
+
// THE LAW IDENTITY (CAP-773): the unit set identity of the units below, the kernel's own definition
|
|
8082
|
+
// (law_unit_set_identity.ts). Releases, generated clients and qualification name the law by it.
|
|
8083
|
+
let unitSetIdentity: string;
|
|
8084
|
+
// THE PER-DOMAIN REQUIREMENTS (CAP-666): each application domain's unit hash beside the identity of its own
|
|
8085
|
+
// compatibility requirement, derived from the units just split and the interfaces just emitted. Written into
|
|
8086
|
+
// no law or package (the era rule); the generated clients, the approved model and the inventory carry them.
|
|
8087
|
+
let domainRequirements: readonly DomainUnitRequirement[];
|
|
7957
8088
|
{
|
|
7958
8089
|
const lawUnits = (() => {
|
|
7959
8090
|
try {
|
|
@@ -7975,6 +8106,13 @@ async function main(): Promise<void> {
|
|
|
7975
8106
|
}
|
|
7976
8107
|
writeFileSync(path.join(unitPath, LAW_UNIT_MANIFEST), unit.manifest);
|
|
7977
8108
|
}
|
|
8109
|
+
unitSetIdentity = lawUnitSetIdentityWith(
|
|
8110
|
+
(bytes) => createHash("sha256").update(bytes).digest("hex"),
|
|
8111
|
+
lawUnits.map((unit) => ({ key: unit.key, unitHash: unit.hash }))
|
|
8112
|
+
);
|
|
8113
|
+
// The law identity on its own line, for publishers and gates that need it and nothing else.
|
|
8114
|
+
writeFileSync(path.join(outDir, `${cfg.name}.units.sha256`), `${unitSetIdentity}\n`, "utf8");
|
|
8115
|
+
domainRequirements = domainRequirementsOf(lawUnits, packageInterface, sha256HexUtf8);
|
|
7978
8116
|
}
|
|
7979
8117
|
const layeredRootPath = path.join(
|
|
7980
8118
|
lawClosureAssetsPath,
|
|
@@ -8133,6 +8271,7 @@ async function main(): Promise<void> {
|
|
|
8133
8271
|
package: cfg.name,
|
|
8134
8272
|
// Binds the summary to the published package asset consumed by an application stage.
|
|
8135
8273
|
sourceIdentity: composedUsdIdentity!,
|
|
8274
|
+
unitSetIdentity,
|
|
8136
8275
|
domainHash,
|
|
8137
8276
|
lawClosureIdentity: lawClosure.identity,
|
|
8138
8277
|
domains: presentationDomainModules.map((m) => ({
|
|
@@ -8168,7 +8307,10 @@ async function main(): Promise<void> {
|
|
|
8168
8307
|
|
|
8169
8308
|
const summaryTxt = [
|
|
8170
8309
|
`${cfg.name} — compiled Nomos domain package`,
|
|
8171
|
-
`law (
|
|
8310
|
+
`law (unit set): ${unitSetIdentity} # THE law identity: ${cfg.name}.units/, as releases, clients and qualification name it (${cfg.name}.units.sha256)`,
|
|
8311
|
+
`claimed version: ${cfg.version ?? "none"} # orders versions of law '${cfg.name}' (nomos.project.ts version); covered by the unit set identity`,
|
|
8312
|
+
`package closure: ${domainHash} # package — not what targets serve: this compiler's closure of ${cfg.name}.law.usdz (${cfg.name}.law.sha256)`,
|
|
8313
|
+
`served law: githolon domains status <ws> # each target's kernel composes the units into its own closure (it depends on that kernel's composer)`,
|
|
8172
8314
|
`law transport: ${path.basename(
|
|
8173
8315
|
lawUsdzPath
|
|
8174
8316
|
)} # lossless one-file USDZ envelope; not canonical custody`,
|
|
@@ -8190,6 +8332,11 @@ async function main(): Promise<void> {
|
|
|
8190
8332
|
d.counts.join(", ") || "—"
|
|
8191
8333
|
} sums: ${d.sums.join(", ") || "—"}`,
|
|
8192
8334
|
]),
|
|
8335
|
+
...(releasedBaseline === undefined
|
|
8336
|
+
? [`baseline: NONE # not a publishable build; githolon compile --publishable needs a pinned nomos.baseline.usda`]
|
|
8337
|
+
: [
|
|
8338
|
+
`baseline: ${releasedBaselineSha256} # extends ${releasedBaseline.release === "none" ? "unreleased units" : `release ${releasedBaseline.release}`}, law ${releasedBaseline.unitSet} (${releasedBaseline.source})`,
|
|
8339
|
+
]),
|
|
8193
8340
|
`deploy: githolon deploy <ws> --file ${cfg.name}.law.usdz`,
|
|
8194
8341
|
packageAssetPath !== undefined
|
|
8195
8342
|
? `package asset: ${path.basename(
|
|
@@ -8222,6 +8369,7 @@ async function main(): Promise<void> {
|
|
|
8222
8369
|
const provenance = buildProvenanceStatement({
|
|
8223
8370
|
packageName: cfg.name,
|
|
8224
8371
|
domainHash,
|
|
8372
|
+
unitSetIdentity,
|
|
8225
8373
|
artifacts: [
|
|
8226
8374
|
{ name: path.basename(lawUsdzPath) },
|
|
8227
8375
|
{
|
|
@@ -8245,6 +8393,16 @@ async function main(): Promise<void> {
|
|
|
8245
8393
|
id: "https://github.com/Captain-App/nomos2",
|
|
8246
8394
|
version: dslVersion,
|
|
8247
8395
|
},
|
|
8396
|
+
...(releasedBaseline === undefined || releasedBaselineSha256 === undefined
|
|
8397
|
+
? {}
|
|
8398
|
+
: {
|
|
8399
|
+
baseline: {
|
|
8400
|
+
sha256: releasedBaselineSha256,
|
|
8401
|
+
source: releasedBaseline.source,
|
|
8402
|
+
release: releasedBaseline.release,
|
|
8403
|
+
unitSet: releasedBaseline.unitSet,
|
|
8404
|
+
},
|
|
8405
|
+
}),
|
|
8248
8406
|
});
|
|
8249
8407
|
writeFileSync(
|
|
8250
8408
|
path.join(outDir, `${cfg.name}.provenance.json`),
|
|
@@ -8272,7 +8430,9 @@ async function main(): Promise<void> {
|
|
|
8272
8430
|
);
|
|
8273
8431
|
const clientOptions = {
|
|
8274
8432
|
packageName: cfg.name,
|
|
8275
|
-
|
|
8433
|
+
// THE LAW the generated clients name: the unit set (CAP-773), never the package closure.
|
|
8434
|
+
domainHash: unitSetIdentity,
|
|
8435
|
+
domainRequirements,
|
|
8276
8436
|
lawAssetName: `${cfg.name}.law.usdz`,
|
|
8277
8437
|
interface: packageInterface,
|
|
8278
8438
|
kernelContracts,
|
|
@@ -8380,10 +8540,9 @@ async function main(): Promise<void> {
|
|
|
8380
8540
|
writeKeyProofUsda(file: string, format: string, key: string): void;
|
|
8381
8541
|
};
|
|
8382
8542
|
const declarationProofFormat = "nomos.typescript-declaration-proof.v1";
|
|
8383
|
-
const normalizedClientSource = clientSource
|
|
8384
|
-
|
|
8385
|
-
"<nomos-
|
|
8386
|
-
);
|
|
8543
|
+
const normalizedClientSource = clientSource
|
|
8544
|
+
.replaceAll(unitSetIdentity, "<nomos-law-unit-set-identity>")
|
|
8545
|
+
.replaceAll(domainHash, "<nomos-package-identity>");
|
|
8387
8546
|
const declarationInputIdentity = createHash("sha256")
|
|
8388
8547
|
.update(`${declarationProofFormat}\0`)
|
|
8389
8548
|
.update(normalizedClientSource)
|
|
@@ -8863,7 +9022,7 @@ async function main(): Promise<void> {
|
|
|
8863
9022
|
const r = emitDartPackages(
|
|
8864
9023
|
presentationDomainModules,
|
|
8865
9024
|
dartOut,
|
|
8866
|
-
domainHash,
|
|
9025
|
+
{ unitSet: unitSetIdentity, packageSha256: domainHash, domainRequirements },
|
|
8867
9026
|
typedLawGraphs,
|
|
8868
9027
|
typedLawPathsByName,
|
|
8869
9028
|
packageInterface,
|
|
@@ -8891,7 +9050,7 @@ async function main(): Promise<void> {
|
|
|
8891
9050
|
dartFiles = emitDart(
|
|
8892
9051
|
presentationDomainModules,
|
|
8893
9052
|
dartOut,
|
|
8894
|
-
domainHash,
|
|
9053
|
+
{ unitSet: unitSetIdentity, packageSha256: domainHash, domainRequirements },
|
|
8895
9054
|
typedLawGraphs,
|
|
8896
9055
|
typedLawPathsByName,
|
|
8897
9056
|
packageInterface,
|
|
@@ -9274,10 +9433,12 @@ async function main(): Promise<void> {
|
|
|
9274
9433
|
// ── summary ──
|
|
9275
9434
|
const rel = (p: string) => path.relative(process.cwd(), p);
|
|
9276
9435
|
console.log(`nomos-compile: ${cfg.name}`);
|
|
9436
|
+
console.log(` law unit set ${unitSetIdentity} (${rel(path.join(outDir, `${cfg.name}.units`))})`);
|
|
9437
|
+
if (cfg.version !== undefined) console.log(` version ${cfg.name}@${cfg.version} (claimed; covered by the unit set identity)`);
|
|
9277
9438
|
console.log(
|
|
9278
|
-
`
|
|
9439
|
+
` package ${domainHash} — package — not what targets serve (${rel(lawUsdzPath)}, ${lawUsdz.byteLength} transport bytes)`
|
|
9279
9440
|
);
|
|
9280
|
-
console.log(`
|
|
9441
|
+
console.log(` served githolon domains status <ws> — each target's kernel composes the units into its own closure`);
|
|
9281
9442
|
console.log(
|
|
9282
9443
|
custodyPlacementDeclarations.length > 0
|
|
9283
9444
|
? ` placement ${rel(custodyPlacementDeclarationsPath)} (${
|
|
@@ -9506,6 +9667,7 @@ async function main(): Promise<void> {
|
|
|
9506
9667
|
dslDir: string;
|
|
9507
9668
|
configPath: string;
|
|
9508
9669
|
argumentIdentity: string;
|
|
9670
|
+
importedSources?: readonly string[];
|
|
9509
9671
|
}): unknown;
|
|
9510
9672
|
generatedOutputFiles(
|
|
9511
9673
|
outDir: string,
|
|
@@ -9525,6 +9687,11 @@ async function main(): Promise<void> {
|
|
|
9525
9687
|
dslDir: DSL_DIR,
|
|
9526
9688
|
configPath,
|
|
9527
9689
|
argumentIdentity: compileArgumentIdentity,
|
|
9690
|
+
importedSources: [
|
|
9691
|
+
...((globalThis as Record<symbol, unknown>)[
|
|
9692
|
+
Symbol.for("nomos.compile.importedSources")
|
|
9693
|
+
] as ReadonlySet<string> | undefined ?? []),
|
|
9694
|
+
],
|
|
9528
9695
|
});
|
|
9529
9696
|
const outputs = proof.generatedOutputFiles(outDir, [
|
|
9530
9697
|
lockPath,
|