@githolon/dsl 0.113.4 → 0.114.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 +20 -0
- package/dart/lib/src/application_framework_calls.dart +9 -5
- 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/reception/dart_reception.dart +148 -11
- package/dart/lib/src/rows_watch.dart +390 -0
- package/dart/lib/src/runner/node-entry.mjs +2803 -690
- 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/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 +17 -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/test_peer_host_selection_test.dart +49 -0
- package/dart_types/CHANGELOG.md +15 -0
- package/dart_types/lib/src/approved_model.dart +22 -5
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +535 -1
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +65 -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 +359 -2
- 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 +20 -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/residency_desk.pb.dart +35 -0
- package/dart_types/pubspec.yaml +1 -1
- package/package.json +4 -2
- package/src/build_provenance.ts +7 -2
- package/src/codegen_dart_client.ts +21 -9
- package/src/codegen_dart_facade.ts +1 -0
- package/src/codegen_dart_framework_calls.ts +12 -9
- package/src/codegen_dart_scenario.ts +7 -0
- package/src/codegen_ts.ts +26 -24
- package/src/compile_package_main.ts +65 -61
- package/src/engine_entry.ts +4 -48
- package/src/law_unit_set_identity.ts +44 -0
- package/src/query/compile.ts +0 -0
- package/src/release_inspection.ts +24 -0
- package/src/release_publication.ts +298 -0
|
@@ -251,10 +251,6 @@ import {
|
|
|
251
251
|
tsClientFactoryName,
|
|
252
252
|
recursiveLazyTypes,
|
|
253
253
|
} from "./codegen_ts.js";
|
|
254
|
-
import {
|
|
255
|
-
generateOpenApiFragment,
|
|
256
|
-
mergeOpenApiFragments,
|
|
257
|
-
} from "./codegen_openapi.js";
|
|
258
254
|
import {
|
|
259
255
|
domainInterfaceFromLawGraph,
|
|
260
256
|
publicClientInterface,
|
|
@@ -269,6 +265,7 @@ import {
|
|
|
269
265
|
packageRoutesLayerUsda,
|
|
270
266
|
splitLawUnits,
|
|
271
267
|
} from "./law_units.js";
|
|
268
|
+
import { lawUnitSetIdentityWith } from "./law_unit_set_identity.js";
|
|
272
269
|
import { checkDomainModules, formatFindings, hasRefusal } from "./law_check.js";
|
|
273
270
|
import {
|
|
274
271
|
currentEvolveLaw,
|
|
@@ -2145,10 +2142,16 @@ function emitDartOperationProto(
|
|
|
2145
2142
|
return [protoPath, generatedBinding];
|
|
2146
2143
|
}
|
|
2147
2144
|
|
|
2145
|
+
/** The compiled law's identities (CAP-773): the unit set is the law; the package is the `.law.usdz` bytes. */
|
|
2146
|
+
interface CompiledLawIdentities {
|
|
2147
|
+
readonly unitSet: string;
|
|
2148
|
+
readonly packageSha256: string;
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2148
2151
|
function emitDart(
|
|
2149
2152
|
modules: readonly DomainModule[],
|
|
2150
2153
|
dartOut: string,
|
|
2151
|
-
|
|
2154
|
+
law: CompiledLawIdentities,
|
|
2152
2155
|
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
2153
2156
|
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
2154
2157
|
packageInterface: Record<string, DomainInterface> = {},
|
|
@@ -2224,7 +2227,7 @@ function emitDart(
|
|
|
2224
2227
|
? []
|
|
2225
2228
|
: [{ module, graph, paths }];
|
|
2226
2229
|
}),
|
|
2227
|
-
{
|
|
2230
|
+
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256 }
|
|
2228
2231
|
);
|
|
2229
2232
|
if (applicationFrameworkCallsSource !== undefined) {
|
|
2230
2233
|
const applicationFrameworkCallsPath = path.join(
|
|
@@ -2364,7 +2367,7 @@ function emitDart(
|
|
|
2364
2367
|
writeGenerated(mod.name, src);
|
|
2365
2368
|
|
|
2366
2369
|
const clientSrc = generateDartDomainClient(modForDart, {
|
|
2367
|
-
domainHash,
|
|
2370
|
+
domainHash: law.unitSet,
|
|
2368
2371
|
callUsda: {
|
|
2369
2372
|
graph: lawGraphs.get(mod.name)!,
|
|
2370
2373
|
paths: lawPaths.get(mod.name)!,
|
|
@@ -2539,12 +2542,12 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
2539
2542
|
* just the floor generated code needs — a lagging pin forces tenants into dependency_overrides. */
|
|
2540
2543
|
// 0.3.0: SurfacedValue<T>/SurfacedObservation/PendingConflictRow — generated Surfaced-field typing +
|
|
2541
2544
|
// the pendingConflicts read rows.
|
|
2542
|
-
const NOMOS_TYPES_DEP = "^0.
|
|
2545
|
+
const NOMOS_TYPES_DEP = "^0.13.0";
|
|
2543
2546
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
2544
2547
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
2545
2548
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
2546
|
-
const NOMOS_CLIENT_DEP = "^0.
|
|
2547
|
-
const NOMOS_FLUTTER_DEP = "^0.
|
|
2549
|
+
const NOMOS_CLIENT_DEP = "^0.68.0";
|
|
2550
|
+
const NOMOS_FLUTTER_DEP = "^0.67.0";
|
|
2548
2551
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in the Dart and Flutter
|
|
2549
2552
|
// package pubspecs — a release without this bump fails the suite, so tenants never
|
|
2550
2553
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -3282,7 +3285,7 @@ function removeGeneratedClientLawAssets(pkgDir: string): boolean {
|
|
|
3282
3285
|
function emitDartPackages(
|
|
3283
3286
|
modules: readonly DomainModule[],
|
|
3284
3287
|
dartOut: string,
|
|
3285
|
-
|
|
3288
|
+
law: CompiledLawIdentities,
|
|
3286
3289
|
lawGraphs: ReadonlyMap<string, LawGraph>,
|
|
3287
3290
|
lawPaths: ReadonlyMap<string, ReadonlyMap<string, string>>,
|
|
3288
3291
|
packageInterface: Record<string, DomainInterface>,
|
|
@@ -3677,7 +3680,7 @@ function emitDartPackages(
|
|
|
3677
3680
|
? []
|
|
3678
3681
|
: [{ module, graph, paths }];
|
|
3679
3682
|
}),
|
|
3680
|
-
{
|
|
3683
|
+
{ lawUnitSet: law.unitSet, lawPackageSha256: law.packageSha256 }
|
|
3681
3684
|
);
|
|
3682
3685
|
const workspaceAccessReadImports = new Map<string, string>();
|
|
3683
3686
|
for (const module of operationProtoModules) {
|
|
@@ -3727,7 +3730,7 @@ function emitDartPackages(
|
|
|
3727
3730
|
const workspaceAccessReadImportUri = workspaceAccessReadImports.get(mod.name);
|
|
3728
3731
|
const makeClient = (imports: readonly string[]) =>
|
|
3729
3732
|
generateDartDomainClient(dd.modForDart, {
|
|
3730
|
-
domainHash,
|
|
3733
|
+
domainHash: law.unitSet,
|
|
3731
3734
|
callUsda: {
|
|
3732
3735
|
graph: lawGraphs.get(mod.name)!,
|
|
3733
3736
|
paths: lawPaths.get(mod.name)!,
|
|
@@ -3818,7 +3821,7 @@ function emitDartPackages(
|
|
|
3818
3821
|
invitationPolicies: (
|
|
3819
3822
|
dd.modForDart.applicationWorkspaceSharing ?? []
|
|
3820
3823
|
).map((policy) => ({
|
|
3821
|
-
domainHash,
|
|
3824
|
+
domainHash: law.unitSet,
|
|
3822
3825
|
query: policy.invitationLaw.pendingByRecipient.id,
|
|
3823
3826
|
redeem: policy.invitationLaw.redeem.id,
|
|
3824
3827
|
personField: policy.person,
|
|
@@ -3858,6 +3861,7 @@ function emitDartPackages(
|
|
|
3858
3861
|
`export 'package:${packages.types}/${genRel}/${businessSharedFile}';`,
|
|
3859
3862
|
`export 'package:nomos_client/src/workspace_open_progress.dart' show ApplicationWorkspaceOpenProgress;`,
|
|
3860
3863
|
`export 'package:nomos_client/src/write_progress.dart' show NomosWrite, NomosWriteProgress, NomosWritePhase;`,
|
|
3864
|
+
`export 'package:nomos_client/src/rows_watch.dart' show NomosRows, NomosRowProjection, NomosRowsProjectionStream;`,
|
|
3861
3865
|
`export 'package:nomos_types/nomos_types.dart' show CustodyError, CustodyPhase, CustodySource, NomosRecommendedAction;`,
|
|
3862
3866
|
...tenantTypesExportKeys
|
|
3863
3867
|
.map((file) => {
|
|
@@ -5539,15 +5543,6 @@ async function main(): Promise<void> {
|
|
|
5539
5543
|
finding.directiveId?.startsWith("nomos_internal_") === true ||
|
|
5540
5544
|
(finding.directiveId !== undefined &&
|
|
5541
5545
|
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
5546
|
|
|
5552
5547
|
if (preflightFlag) {
|
|
5553
5548
|
const businessFindings = authorTimeFindings.filter(
|
|
@@ -6607,7 +6602,6 @@ async function main(): Promise<void> {
|
|
|
6607
6602
|
const planEntrySource = (
|
|
6608
6603
|
domainKeys: readonly string[],
|
|
6609
6604
|
includeReports: boolean,
|
|
6610
|
-
includeDescribe: boolean,
|
|
6611
6605
|
sourceOverrides: ReadonlyMap<string, string> = new Map(),
|
|
6612
6606
|
includePreloads = true,
|
|
6613
6607
|
routingOverride?: Record<string, unknown>,
|
|
@@ -6659,12 +6653,6 @@ async function main(): Promise<void> {
|
|
|
6659
6653
|
...(!sharedRuntime && zodSeedNames.length > 0
|
|
6660
6654
|
? [` seeds: [${zodSeedNames.join(", ")}],`]
|
|
6661
6655
|
: []),
|
|
6662
|
-
...(includeDescribe
|
|
6663
|
-
? [` openapiDocument: ${JSON.stringify(runtimeOpenApiDocument)},`]
|
|
6664
|
-
: []),
|
|
6665
|
-
...(includeDescribe
|
|
6666
|
-
? [` packageTitle: ${JSON.stringify(`${cfg.name} (nomos package)`)},`]
|
|
6667
|
-
: []),
|
|
6668
6656
|
...workspaceEffects.config,
|
|
6669
6657
|
`});`,
|
|
6670
6658
|
...(includeMintInstalls
|
|
@@ -6841,7 +6829,6 @@ async function main(): Promise<void> {
|
|
|
6841
6829
|
const compilePlan = async (
|
|
6842
6830
|
domainKeys: readonly string[],
|
|
6843
6831
|
includeReports: boolean,
|
|
6844
|
-
includeDescribe: boolean,
|
|
6845
6832
|
options: {
|
|
6846
6833
|
readonly sourceOverrides?: ReadonlyMap<string, string>;
|
|
6847
6834
|
readonly sliceTargets?: readonly PlanSourceSliceTarget[];
|
|
@@ -6880,7 +6867,6 @@ async function main(): Promise<void> {
|
|
|
6880
6867
|
const signature = JSON.stringify({
|
|
6881
6868
|
domains: ordered,
|
|
6882
6869
|
reports: includeReports,
|
|
6883
|
-
describe: includeDescribe,
|
|
6884
6870
|
slice:
|
|
6885
6871
|
effectiveSliceTargets?.map((target) => [
|
|
6886
6872
|
target.modulePath,
|
|
@@ -6895,7 +6881,6 @@ async function main(): Promise<void> {
|
|
|
6895
6881
|
planEntrySource(
|
|
6896
6882
|
ordered,
|
|
6897
6883
|
includeReports,
|
|
6898
|
-
includeDescribe,
|
|
6899
6884
|
options.sourceOverrides,
|
|
6900
6885
|
options.includePreloads ?? options.sliceTargets === undefined,
|
|
6901
6886
|
options.routingOverride,
|
|
@@ -7035,14 +7020,9 @@ async function main(): Promise<void> {
|
|
|
7035
7020
|
const routePlan = async (
|
|
7036
7021
|
selector: string,
|
|
7037
7022
|
domainKeys: readonly string[],
|
|
7038
|
-
includeReports = false
|
|
7039
|
-
includeDescribe = false
|
|
7023
|
+
includeReports = false
|
|
7040
7024
|
): Promise<void> => {
|
|
7041
|
-
const asset = await compilePlan(
|
|
7042
|
-
domainKeys,
|
|
7043
|
-
includeReports,
|
|
7044
|
-
includeDescribe
|
|
7045
|
-
);
|
|
7025
|
+
const asset = await compilePlan(domainKeys, includeReports);
|
|
7046
7026
|
planRoutes.push({ selector, planSha256: asset.sha256 });
|
|
7047
7027
|
};
|
|
7048
7028
|
const routeAsset = (selector: string, asset: UsdPlanAsset): void => {
|
|
@@ -7086,7 +7066,7 @@ async function main(): Promise<void> {
|
|
|
7086
7066
|
// content hash, and emitted sorted by selector/hash), so compile them concurrently and bind
|
|
7087
7067
|
// routes afterwards in declaration order.
|
|
7088
7068
|
const domainPlans = await Promise.all(
|
|
7089
|
-
orderedDomainKeys.map((key) => compilePlan([key], false
|
|
7069
|
+
orderedDomainKeys.map((key) => compilePlan([key], false))
|
|
7090
7070
|
);
|
|
7091
7071
|
orderedDomainKeys.forEach((key, index) => {
|
|
7092
7072
|
const asset = domainPlans[index]!;
|
|
@@ -7158,7 +7138,7 @@ async function main(): Promise<void> {
|
|
|
7158
7138
|
const source = ` ${JSON.stringify(
|
|
7159
7139
|
BUSINESS_BIRTH_FRAMEWORK_PLAN_DOMAIN
|
|
7160
7140
|
)}: [${selectedSources.join(", ")}],`;
|
|
7161
|
-
frameworkPlan = compilePlan([domain], false,
|
|
7141
|
+
frameworkPlan = compilePlan([domain], false, {
|
|
7162
7142
|
sourceOverrides: new Map([[domain, source]]),
|
|
7163
7143
|
includePreloads: false,
|
|
7164
7144
|
cacheKey: "business-birth-framework",
|
|
@@ -7228,7 +7208,7 @@ async function main(): Promise<void> {
|
|
|
7228
7208
|
selectedModule,
|
|
7229
7209
|
...generated,
|
|
7230
7210
|
].join(", ")}],`;
|
|
7231
|
-
const asset = await compilePlan([domain], false,
|
|
7211
|
+
const asset = await compilePlan([domain], false, {
|
|
7232
7212
|
sourceOverrides: new Map([[domain, source]]),
|
|
7233
7213
|
sliceTargets: selected,
|
|
7234
7214
|
});
|
|
@@ -7386,7 +7366,7 @@ async function main(): Promise<void> {
|
|
|
7386
7366
|
)}: [${moduleExpression}],`;
|
|
7387
7367
|
workspaceInvariantPlans.push({
|
|
7388
7368
|
invariantIds: members.map(([id]) => id),
|
|
7389
|
-
plan: compilePlan([domain], false,
|
|
7369
|
+
plan: compilePlan([domain], false, {
|
|
7390
7370
|
sourceOverrides: new Map([[domain, domainSource]]),
|
|
7391
7371
|
sliceTargets: [...selectedByKey.values()],
|
|
7392
7372
|
cacheKey: `workspace-invariants:${directiveId}:${members
|
|
@@ -7403,9 +7383,11 @@ async function main(): Promise<void> {
|
|
|
7403
7383
|
}
|
|
7404
7384
|
}
|
|
7405
7385
|
stage("workspace invariant plans");
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7386
|
+
// No `describe` route: the kernel derives a workspace's description from its installed law
|
|
7387
|
+
// (rpc_describe renders it from the command contract and read projection), so a compiled
|
|
7388
|
+
// self-description plan over every domain was never executed, and it was the one composition
|
|
7389
|
+
// file a single-domain edit moved (CAP-658).
|
|
7390
|
+
const reportRoutes: Promise<void>[] = [];
|
|
7409
7391
|
for (const reportId of Object.keys(cfg.reports ?? {}))
|
|
7410
7392
|
reportRoutes.push(routePlan(`report:report:${reportId}`, [], true));
|
|
7411
7393
|
const routeTable = (
|
|
@@ -7447,7 +7429,7 @@ async function main(): Promise<void> {
|
|
|
7447
7429
|
}
|
|
7448
7430
|
}
|
|
7449
7431
|
await Promise.all(reportRoutes);
|
|
7450
|
-
stage("
|
|
7432
|
+
stage("report plans");
|
|
7451
7433
|
// Adaptive offer splitting deliberately compiles candidate parents before retaining their children.
|
|
7452
7434
|
// Only route-reachable content is custody; exploratory compiler work never becomes law bytes.
|
|
7453
7435
|
const routedPlanHashes = new Set(planRoutes.map((route) => route.planSha256));
|
|
@@ -7934,8 +7916,10 @@ async function main(): Promise<void> {
|
|
|
7934
7916
|
if (probeFailure !== undefined) fail(probeFailure);
|
|
7935
7917
|
}
|
|
7936
7918
|
stage("boot probe (verdict)");
|
|
7937
|
-
// The
|
|
7938
|
-
//
|
|
7919
|
+
// The PACKAGE identity: this compiler's own closure of the package (root.usda, routes and its derived
|
|
7920
|
+
// finished goods included). It names the `.law.usdz` bytes and the package lane; it is NOT what a
|
|
7921
|
+
// unit-lane target serves (that target's kernel composes the units itself, CAP-773). The law
|
|
7922
|
+
// identity is the unit set identity below.
|
|
7939
7923
|
const domainHash = lawClosure.identity;
|
|
7940
7924
|
const rootAsset = lawClosure.assets.find(
|
|
7941
7925
|
(asset) => asset.logicalPath === lawClosure.rootLogicalPath
|
|
@@ -7949,11 +7933,14 @@ async function main(): Promise<void> {
|
|
|
7949
7933
|
.map((asset) => [`layers/${asset.logicalPath}`, asset.bytes] as const),
|
|
7950
7934
|
]);
|
|
7951
7935
|
writeFileSync(lawUsdzPath, lawUsdz);
|
|
7952
|
-
// The
|
|
7936
|
+
// The package closure's identity on its own line, for gates that check the `.law.usdz` bytes.
|
|
7953
7937
|
writeFileSync(path.join(outDir, `${cfg.name}.law.sha256`), `${domainHash}\n`, "utf8");
|
|
7954
7938
|
// D21: the same law, authored as per-domain units the kernel composes. Split from the closure just
|
|
7955
7939
|
// emitted (its bytes and identity are untouched), previewed for exact coverage, and written as plain
|
|
7956
7940
|
// trees: in custody each unit is a git tree, so git owns compression and deduplication.
|
|
7941
|
+
// THE LAW IDENTITY (CAP-773): the unit set identity of the units below, the kernel's own definition
|
|
7942
|
+
// (law_unit_set_identity.ts). Releases, generated clients and qualification name the law by it.
|
|
7943
|
+
let unitSetIdentity: string;
|
|
7957
7944
|
{
|
|
7958
7945
|
const lawUnits = (() => {
|
|
7959
7946
|
try {
|
|
@@ -7975,6 +7962,12 @@ async function main(): Promise<void> {
|
|
|
7975
7962
|
}
|
|
7976
7963
|
writeFileSync(path.join(unitPath, LAW_UNIT_MANIFEST), unit.manifest);
|
|
7977
7964
|
}
|
|
7965
|
+
unitSetIdentity = lawUnitSetIdentityWith(
|
|
7966
|
+
(bytes) => createHash("sha256").update(bytes).digest("hex"),
|
|
7967
|
+
lawUnits.map((unit) => ({ key: unit.key, unitHash: unit.hash }))
|
|
7968
|
+
);
|
|
7969
|
+
// The law identity on its own line, for publishers and gates that need it and nothing else.
|
|
7970
|
+
writeFileSync(path.join(outDir, `${cfg.name}.units.sha256`), `${unitSetIdentity}\n`, "utf8");
|
|
7978
7971
|
}
|
|
7979
7972
|
const layeredRootPath = path.join(
|
|
7980
7973
|
lawClosureAssetsPath,
|
|
@@ -8133,6 +8126,7 @@ async function main(): Promise<void> {
|
|
|
8133
8126
|
package: cfg.name,
|
|
8134
8127
|
// Binds the summary to the published package asset consumed by an application stage.
|
|
8135
8128
|
sourceIdentity: composedUsdIdentity!,
|
|
8129
|
+
unitSetIdentity,
|
|
8136
8130
|
domainHash,
|
|
8137
8131
|
lawClosureIdentity: lawClosure.identity,
|
|
8138
8132
|
domains: presentationDomainModules.map((m) => ({
|
|
@@ -8168,7 +8162,9 @@ async function main(): Promise<void> {
|
|
|
8168
8162
|
|
|
8169
8163
|
const summaryTxt = [
|
|
8170
8164
|
`${cfg.name} — compiled Nomos domain package`,
|
|
8171
|
-
`law (
|
|
8165
|
+
`law (unit set): ${unitSetIdentity} # THE law identity: ${cfg.name}.units/, as releases, clients and qualification name it (${cfg.name}.units.sha256)`,
|
|
8166
|
+
`package closure: ${domainHash} # package — not what targets serve: this compiler's closure of ${cfg.name}.law.usdz (${cfg.name}.law.sha256)`,
|
|
8167
|
+
`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
8168
|
`law transport: ${path.basename(
|
|
8173
8169
|
lawUsdzPath
|
|
8174
8170
|
)} # lossless one-file USDZ envelope; not canonical custody`,
|
|
@@ -8222,6 +8218,7 @@ async function main(): Promise<void> {
|
|
|
8222
8218
|
const provenance = buildProvenanceStatement({
|
|
8223
8219
|
packageName: cfg.name,
|
|
8224
8220
|
domainHash,
|
|
8221
|
+
unitSetIdentity,
|
|
8225
8222
|
artifacts: [
|
|
8226
8223
|
{ name: path.basename(lawUsdzPath) },
|
|
8227
8224
|
{
|
|
@@ -8272,7 +8269,8 @@ async function main(): Promise<void> {
|
|
|
8272
8269
|
);
|
|
8273
8270
|
const clientOptions = {
|
|
8274
8271
|
packageName: cfg.name,
|
|
8275
|
-
|
|
8272
|
+
// THE LAW the generated clients name: the unit set (CAP-773), never the package closure.
|
|
8273
|
+
domainHash: unitSetIdentity,
|
|
8276
8274
|
lawAssetName: `${cfg.name}.law.usdz`,
|
|
8277
8275
|
interface: packageInterface,
|
|
8278
8276
|
kernelContracts,
|
|
@@ -8380,10 +8378,9 @@ async function main(): Promise<void> {
|
|
|
8380
8378
|
writeKeyProofUsda(file: string, format: string, key: string): void;
|
|
8381
8379
|
};
|
|
8382
8380
|
const declarationProofFormat = "nomos.typescript-declaration-proof.v1";
|
|
8383
|
-
const normalizedClientSource = clientSource
|
|
8384
|
-
|
|
8385
|
-
"<nomos-
|
|
8386
|
-
);
|
|
8381
|
+
const normalizedClientSource = clientSource
|
|
8382
|
+
.replaceAll(unitSetIdentity, "<nomos-law-unit-set-identity>")
|
|
8383
|
+
.replaceAll(domainHash, "<nomos-package-identity>");
|
|
8387
8384
|
const declarationInputIdentity = createHash("sha256")
|
|
8388
8385
|
.update(`${declarationProofFormat}\0`)
|
|
8389
8386
|
.update(normalizedClientSource)
|
|
@@ -8863,7 +8860,7 @@ async function main(): Promise<void> {
|
|
|
8863
8860
|
const r = emitDartPackages(
|
|
8864
8861
|
presentationDomainModules,
|
|
8865
8862
|
dartOut,
|
|
8866
|
-
domainHash,
|
|
8863
|
+
{ unitSet: unitSetIdentity, packageSha256: domainHash },
|
|
8867
8864
|
typedLawGraphs,
|
|
8868
8865
|
typedLawPathsByName,
|
|
8869
8866
|
packageInterface,
|
|
@@ -8891,7 +8888,7 @@ async function main(): Promise<void> {
|
|
|
8891
8888
|
dartFiles = emitDart(
|
|
8892
8889
|
presentationDomainModules,
|
|
8893
8890
|
dartOut,
|
|
8894
|
-
domainHash,
|
|
8891
|
+
{ unitSet: unitSetIdentity, packageSha256: domainHash },
|
|
8895
8892
|
typedLawGraphs,
|
|
8896
8893
|
typedLawPathsByName,
|
|
8897
8894
|
packageInterface,
|
|
@@ -9274,10 +9271,11 @@ async function main(): Promise<void> {
|
|
|
9274
9271
|
// ── summary ──
|
|
9275
9272
|
const rel = (p: string) => path.relative(process.cwd(), p);
|
|
9276
9273
|
console.log(`nomos-compile: ${cfg.name}`);
|
|
9274
|
+
console.log(` law unit set ${unitSetIdentity} (${rel(path.join(outDir, `${cfg.name}.units`))})`);
|
|
9277
9275
|
console.log(
|
|
9278
|
-
`
|
|
9276
|
+
` package ${domainHash} — package — not what targets serve (${rel(lawUsdzPath)}, ${lawUsdz.byteLength} transport bytes)`
|
|
9279
9277
|
);
|
|
9280
|
-
console.log(`
|
|
9278
|
+
console.log(` served githolon domains status <ws> — each target's kernel composes the units into its own closure`);
|
|
9281
9279
|
console.log(
|
|
9282
9280
|
custodyPlacementDeclarations.length > 0
|
|
9283
9281
|
? ` placement ${rel(custodyPlacementDeclarationsPath)} (${
|
|
@@ -9506,6 +9504,7 @@ async function main(): Promise<void> {
|
|
|
9506
9504
|
dslDir: string;
|
|
9507
9505
|
configPath: string;
|
|
9508
9506
|
argumentIdentity: string;
|
|
9507
|
+
importedSources?: readonly string[];
|
|
9509
9508
|
}): unknown;
|
|
9510
9509
|
generatedOutputFiles(
|
|
9511
9510
|
outDir: string,
|
|
@@ -9525,6 +9524,11 @@ async function main(): Promise<void> {
|
|
|
9525
9524
|
dslDir: DSL_DIR,
|
|
9526
9525
|
configPath,
|
|
9527
9526
|
argumentIdentity: compileArgumentIdentity,
|
|
9527
|
+
importedSources: [
|
|
9528
|
+
...((globalThis as Record<symbol, unknown>)[
|
|
9529
|
+
Symbol.for("nomos.compile.importedSources")
|
|
9530
|
+
] as ReadonlySet<string> | undefined ?? []),
|
|
9531
|
+
],
|
|
9528
9532
|
});
|
|
9529
9533
|
const outputs = proof.generatedOutputFiles(outDir, [
|
|
9530
9534
|
lockPath,
|
package/src/engine_entry.ts
CHANGED
|
@@ -73,7 +73,6 @@ import {
|
|
|
73
73
|
nomosSourceFrontierEnsure,
|
|
74
74
|
withAttestedReadExports,
|
|
75
75
|
} from "./attested.js";
|
|
76
|
-
import type { OpenApiDoc } from "./codegen_openapi.js";
|
|
77
76
|
import type { Directive } from "./directive.js";
|
|
78
77
|
import type { AggregateHandle, AggregateInvariantFn, AggregateInvariantVerdict } from "./aggregate.js";
|
|
79
78
|
import type { Ports } from "./ctx.js";
|
|
@@ -178,18 +177,6 @@ export interface EngineEntryConfig {
|
|
|
178
177
|
* `sideEffects: false` (a bare side-effect import would be tree-shaken away).
|
|
179
178
|
*/
|
|
180
179
|
readonly seeds?: readonly unknown[];
|
|
181
|
-
/**
|
|
182
|
-
* Compiler-derived self-description. It is a presentation projection held inside the separately
|
|
183
|
-
* routed `describe` plan, never executable law IR. Ordinary offer/read plans omit it completely,
|
|
184
|
-
* so OpenAPI/JSON-Schema generation cannot sit on their parse or readiness flame path.
|
|
185
|
-
*/
|
|
186
|
-
readonly openapiDocument?: OpenApiDoc;
|
|
187
|
-
/**
|
|
188
|
-
* The package's OpenAPI document title (the compiler's `"<name> (nomos package)"`). Baked into
|
|
189
|
-
* the lump so `describe` reproduces the compiler's public description byte-for-byte without
|
|
190
|
-
* the kernel knowing the package name. The kernel MAY override it (the workspace-level title).
|
|
191
|
-
*/
|
|
192
|
-
readonly packageTitle?: string;
|
|
193
180
|
/** Compiler-generated nominal encoders keyed by the exact target Directive singleton. Source law
|
|
194
181
|
* can name a target by type, while the runtime emits only canonical USDA. */
|
|
195
182
|
readonly workspaceEffectTargets?: readonly {
|
|
@@ -297,7 +284,7 @@ function mergeModules(mods: readonly DomainModuleExports[], domain: string): Dom
|
|
|
297
284
|
// without per-piece re-exports (capability_exports.ts).
|
|
298
285
|
// METERED BIRTH: a `.births()`-declaring domain gains the birth-meter structural exports
|
|
299
286
|
// (the sanctioning `nomosBirthRecordEnsure` + the meter aggregates) at this same seam, so
|
|
300
|
-
// the registry
|
|
287
|
+
// the registry sees the exact surface the composed manifest carries.
|
|
301
288
|
// ROLE SUGAR: lift every `role(...).emit()` into its grant/revoke/seed directives at the SAME
|
|
302
289
|
// engine merge point so the registry dispatches them (the compiler saw them via the same expander).
|
|
303
290
|
return expandRoleExports(
|
|
@@ -650,8 +637,6 @@ export interface RegisteredEngine {
|
|
|
650
637
|
prepareDomain(domain: string): { complete: boolean; initialized: number; total: number };
|
|
651
638
|
/** Compiler/tooling probe: force one domain and prove an exact routed offer is registered. */
|
|
652
639
|
hasDirective(domain: string, directiveId: string): boolean;
|
|
653
|
-
/** The G1 self-describe verb: the lump's own merged OpenAPI, derived from its modules. */
|
|
654
|
-
describe(opts?: { lawHash?: string; title?: string }): OpenApiDoc;
|
|
655
640
|
}
|
|
656
641
|
|
|
657
642
|
/**
|
|
@@ -1155,42 +1140,13 @@ export function registerEngine(config: EngineEntryConfig): RegisteredEngine {
|
|
|
1155
1140
|
};
|
|
1156
1141
|
}
|
|
1157
1142
|
|
|
1158
|
-
/**
|
|
1159
|
-
* THE SELF-DESCRIBE VERB (G1) — the lump's OWN OpenAPI, derived from the SAME modules it
|
|
1160
|
-
* dispatches. The kernel selects the content-addressed describe plan from the native USD
|
|
1161
|
-
* package in custody, so the workspace's API surface is a pure,
|
|
1162
|
-
* deterministic function of installed law — NOT a host-staged blob. Its public `paths` reproduce
|
|
1163
|
-
* the public description the compiler derived; describe also carries a private, law-derived
|
|
1164
|
-
* framework routing manifest which the host consumes internally and never publishes.
|
|
1165
|
-
* `opts.lawHash`/`opts.title` are injected by the kernel at describe-time (the version stamp +
|
|
1166
|
-
* package title), matching the compiler's `domainHash`/`"<name> (nomos package)"`.
|
|
1167
|
-
*/
|
|
1168
|
-
function describe(opts?: { lawHash?: string; title?: string }): OpenApiDoc {
|
|
1169
|
-
const document = config.openapiDocument;
|
|
1170
|
-
if (document === undefined) {
|
|
1171
|
-
throw new Error("engine describe: selected plan has no compiled OpenAPI projection");
|
|
1172
|
-
}
|
|
1173
|
-
const lawHash = opts?.lawHash;
|
|
1174
|
-
const title = opts?.title ?? config.packageTitle ?? document.info["title"];
|
|
1175
|
-
const priorInfo = document.info;
|
|
1176
|
-
const info: Record<string, unknown> = {
|
|
1177
|
-
...priorInfo,
|
|
1178
|
-
...(title === undefined ? {} : { title }),
|
|
1179
|
-
version: lawHash === undefined ? (priorInfo["version"] ?? "0") : lawHash.slice(0, 12),
|
|
1180
|
-
};
|
|
1181
|
-
if (lawHash === undefined) delete info["x-nomos-law-hash"];
|
|
1182
|
-
else info["x-nomos-law-hash"] = lawHash;
|
|
1183
|
-
return { ...document, info };
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
1143
|
// The engine evals the bundle as a classic script and FREEZES globalThis before
|
|
1187
|
-
// dispatch — assign all entries NOW, at top-level eval. `describe`
|
|
1188
|
-
//
|
|
1144
|
+
// dispatch — assign all entries NOW, at top-level eval. There is no `describe` entry: the
|
|
1145
|
+
// kernel derives a workspace's description from its installed law (CAP-658).
|
|
1189
1146
|
(globalThis as { plan?: unknown }).plan = plan;
|
|
1190
1147
|
(globalThis as { planReport?: unknown }).planReport = planReport;
|
|
1191
1148
|
(globalThis as { __nomosPrepareDomain?: unknown }).__nomosPrepareDomain = prepareDomain;
|
|
1192
1149
|
(globalThis as { __nomosHasDirective?: unknown }).__nomosHasDirective = hasDirective;
|
|
1193
|
-
(globalThis as { describe?: unknown }).describe = describe;
|
|
1194
1150
|
|
|
1195
|
-
return { plan, planReport, prepareDomain, hasDirective
|
|
1151
|
+
return { plan, planReport, prepareDomain, hasDirective } as RegisteredEngine;
|
|
1196
1152
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// THE LAW IDENTITY (CAP-773, architecture/law_units_format.md "Identities").
|
|
2
|
+
//
|
|
3
|
+
// A law is a set of content-addressed units (framework, composition, one per domain). Its identity is the unit set
|
|
4
|
+
// identity: sha256("nomos-law-unit-set-identity-v1\0" { key "\0" unitHash "\0" }*), units sorted by key in byte
|
|
5
|
+
// order. It names exactly which units the set holds and nothing about how a kernel composes them, so publishers,
|
|
6
|
+
// generated clients, the console and qualification all name law by it, and every kernel agrees on it whatever its
|
|
7
|
+
// composer version. The kernel's definition is `law_unit_set_identity` (kernel/src/law_units.rs); the two are bound
|
|
8
|
+
// by one vector (law_unit_set_identity.test.ts, law_units.rs tests) and by a compiled fixture the real kernel composes
|
|
9
|
+
// (kernel/tests/compiled_law_units.rs).
|
|
10
|
+
//
|
|
11
|
+
// Not the law identity: the realised closure a target's kernel composes from the set (it also depends on the
|
|
12
|
+
// kernel's OpenUSD pin and composer version), the compiler's package closure (`build/<name>.law.sha256`), and the
|
|
13
|
+
// kernel's composition identity (the set record's `setIdentity`, which binds the set to one composer).
|
|
14
|
+
//
|
|
15
|
+
// Dependency-free and synchronous over the bytes: each runtime hashes the preimage with its own sha256 (node:crypto
|
|
16
|
+
// in the compiler, WebCrypto in the console and CLI, the Peer Office's own digest on a device).
|
|
17
|
+
|
|
18
|
+
export const LAW_UNIT_SET_IDENTITY_TAG = "nomos-law-unit-set-identity-v1";
|
|
19
|
+
|
|
20
|
+
export interface LawUnitSetMember {
|
|
21
|
+
readonly key: string;
|
|
22
|
+
readonly unitHash: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const HEX64 = /^[0-9a-f]{64}$/;
|
|
26
|
+
const byteOrder = (left: string, right: string): number => (left < right ? -1 : left > right ? 1 : 0);
|
|
27
|
+
|
|
28
|
+
/** The exact bytes the unit set identity hashes. Refuses a duplicate key or a unit hash that is not a sha256. */
|
|
29
|
+
export function lawUnitSetIdentityPreimage(units: readonly LawUnitSetMember[]): Uint8Array {
|
|
30
|
+
const sorted = [...units].sort((left, right) => byteOrder(left.key, right.key));
|
|
31
|
+
const parts = [`${LAW_UNIT_SET_IDENTITY_TAG}\0`];
|
|
32
|
+
sorted.forEach((unit, index) => {
|
|
33
|
+
if (unit.key.length === 0 || unit.key.includes("\0")) throw new Error(`law unit key ${JSON.stringify(unit.key)} is not a unit key`);
|
|
34
|
+
if (index > 0 && sorted[index - 1]!.key === unit.key) throw new Error(`law unit ${unit.key} appears twice in one set`);
|
|
35
|
+
if (!HEX64.test(unit.unitHash)) throw new Error(`law unit ${unit.key} names ${JSON.stringify(unit.unitHash)}, not a unit hash`);
|
|
36
|
+
parts.push(unit.key, "\0", unit.unitHash, "\0");
|
|
37
|
+
});
|
|
38
|
+
return new TextEncoder().encode(parts.join(""));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The unit set identity, hashed with the caller's synchronous sha256 (lowercase hex out). */
|
|
42
|
+
export function lawUnitSetIdentityWith(sha256Hex: (bytes: Uint8Array) => string, units: readonly LawUnitSetMember[]): string {
|
|
43
|
+
return sha256Hex(lawUnitSetIdentityPreimage(units));
|
|
44
|
+
}
|
package/src/query/compile.ts
CHANGED
|
Binary file
|
|
@@ -145,3 +145,27 @@ export function inspectReleaseBaseline(input: { identity: string; units: string;
|
|
|
145
145
|
'Unobserved declarations may be out of package scope or structurally interned; absence is not a compatibility refusal.',
|
|
146
146
|
'Consumer compatibility, state evolution and publication provenance are not certified by this report.'] };
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* A compiled `build/<name>.units` directory as a release candidate and the bytes to upload: every unit
|
|
151
|
+
* verified by `readInspectionUnits` (digests, canonical manifest, unit hash), every file named by digest.
|
|
152
|
+
* The console verifies the same bytes again on publication (release_publication.ts `verifyRelease`).
|
|
153
|
+
*/
|
|
154
|
+
export function releaseCandidateFromUnits(directory: string, series: string, predecessor: string): {
|
|
155
|
+
candidate: { series: string; predecessor: string; units: { key: string; unitHash: string; files: { path: string; sha256: string; size: number }[] }[] };
|
|
156
|
+
blobs: Map<string, Uint8Array>;
|
|
157
|
+
} {
|
|
158
|
+
const blobs = new Map<string, Uint8Array>();
|
|
159
|
+
const units = readInspectionUnits(directory).map((unit) => {
|
|
160
|
+
const files = [...unit.assets.map((asset) => ({ path: asset.logicalPath, bytes: asset.bytes })),
|
|
161
|
+
{ path: 'unit.usda', bytes: unit.manifest }]
|
|
162
|
+
.sort((l, r) => (l.path < r.path ? -1 : l.path > r.path ? 1 : 0))
|
|
163
|
+
.map(({ path: filePath, bytes }) => {
|
|
164
|
+
const sha256 = sha(bytes);
|
|
165
|
+
blobs.set(sha256, new Uint8Array(bytes));
|
|
166
|
+
return { path: filePath, sha256, size: bytes.byteLength };
|
|
167
|
+
});
|
|
168
|
+
return { key: unit.key, unitHash: unit.hash, files };
|
|
169
|
+
}).sort((l, r) => (l.key < r.key ? -1 : l.key > r.key ? 1 : 0));
|
|
170
|
+
return { candidate: { series, predecessor, units }, blobs };
|
|
171
|
+
}
|