@githolon/dsl 0.117.0 → 0.119.9
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_proof.mjs +16 -0
- package/dart/CHANGELOG.md +45 -0
- package/dart/lib/src/application_status.dart +58 -2
- package/dart/lib/src/peer_application_streams.dart +7 -1
- package/dart/lib/src/reception/dart_reception.dart +92 -12
- package/dart/lib/src/reception/reception_session.dart +10 -2
- package/dart/lib/src/replica_readiness.dart +200 -50
- package/dart/lib/src/runner/node-entry.mjs +2480 -1021
- package/dart/lib/src/sync_status_projection.dart +346 -4
- package/dart/lib/src/sync_status_reducer.dart +44 -0
- package/dart/lib/src/test_harness.dart +1 -0
- package/dart/lib/src/typed_watch_registry.dart +67 -7
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +2 -2
- package/dart/test/copy_repair_status_test.dart +238 -0
- package/dart/test/reads_never_wait_test.dart +387 -0
- package/dart/test/replica_readiness_test.dart +223 -109
- package/dart/test/sync_status_reducer_test.dart +39 -0
- package/dart/test/typed_watch_registry_test.dart +69 -0
- package/dart/test/unshared_work_status_test.dart +269 -0
- package/dart_types/CHANGELOG.md +18 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +320 -85
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +57 -1
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +14 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +25 -1
- package/dart_types/lib/src/runtime_outcome.dart +17 -0
- package/dart_types/pubspec.yaml +1 -1
- package/package.json +6 -2
- package/src/codegen_ts.ts +7 -8
- package/src/compile_package_main.ts +11 -4
- package/src/reception_template.ts +4 -3
- package/src/reception_unit_artifact.ts +105 -0
- package/src/reception_unit_artifact_contract.ts +220 -0
- package/src/reception_unit_context.ts +47 -0
- package/src/reception_unit_source.ts +205 -0
|
@@ -8334,6 +8334,7 @@ class LiveFrontier extends $pb.GeneratedMessage {
|
|
|
8334
8334
|
$core.String? outcomesDigest,
|
|
8335
8335
|
$core.Iterable<RetainedRef>? outcomes,
|
|
8336
8336
|
$core.String? sealed,
|
|
8337
|
+
$core.Iterable<$core.String>? heldTrees,
|
|
8337
8338
|
}) {
|
|
8338
8339
|
final result = create();
|
|
8339
8340
|
if (head != null) result.head = head;
|
|
@@ -8344,6 +8345,7 @@ class LiveFrontier extends $pb.GeneratedMessage {
|
|
|
8344
8345
|
if (outcomesDigest != null) result.outcomesDigest = outcomesDigest;
|
|
8345
8346
|
if (outcomes != null) result.outcomes.addAll(outcomes);
|
|
8346
8347
|
if (sealed != null) result.sealed = sealed;
|
|
8348
|
+
if (heldTrees != null) result.heldTrees.addAll(heldTrees);
|
|
8347
8349
|
return result;
|
|
8348
8350
|
}
|
|
8349
8351
|
|
|
@@ -8370,6 +8372,7 @@ class LiveFrontier extends $pb.GeneratedMessage {
|
|
|
8370
8372
|
..pPM<RetainedRef>(6, _omitFieldNames ? '' : 'outcomes',
|
|
8371
8373
|
subBuilder: RetainedRef.create)
|
|
8372
8374
|
..aOS(7, _omitFieldNames ? '' : 'sealed')
|
|
8375
|
+
..pPS(8, _omitFieldNames ? '' : 'heldTrees')
|
|
8373
8376
|
..hasRequiredFields = false;
|
|
8374
8377
|
|
|
8375
8378
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
|
@@ -8448,6 +8451,13 @@ class LiveFrontier extends $pb.GeneratedMessage {
|
|
|
8448
8451
|
$core.bool hasSealed() => $_has(6);
|
|
8449
8452
|
@$pb.TagNumber(7)
|
|
8450
8453
|
void clearSealed() => $_clearField(7);
|
|
8454
|
+
|
|
8455
|
+
/// Law-closure trees this copy already holds in some workspace on its own peer (CAP-901), at most
|
|
8456
|
+
/// 16. The peer may leave every object reachable from a named tree out of a checkpoint it offers
|
|
8457
|
+
/// (LiveCheckpointOffer.omitted_trees); the copy supplies them from its own custody before it verifies
|
|
8458
|
+
/// the checkpoint, or asks again naming none. A copy that names none gets the whole checkpoint.
|
|
8459
|
+
@$pb.TagNumber(8)
|
|
8460
|
+
$pb.PbList<$core.String> get heldTrees => $_getList(7);
|
|
8451
8461
|
}
|
|
8452
8462
|
|
|
8453
8463
|
/// Start or resume a checkpoint. A resume names the checkpoint (`head`, `pack_id`) and the bytes it
|
|
@@ -8460,12 +8470,14 @@ class LiveCheckpointRequest extends $pb.GeneratedMessage {
|
|
|
8460
8470
|
$core.String? packId,
|
|
8461
8471
|
$fixnum.Int64? offset,
|
|
8462
8472
|
$core.int? windowChunks,
|
|
8473
|
+
$core.Iterable<$core.String>? heldTrees,
|
|
8463
8474
|
}) {
|
|
8464
8475
|
final result = create();
|
|
8465
8476
|
if (head != null) result.head = head;
|
|
8466
8477
|
if (packId != null) result.packId = packId;
|
|
8467
8478
|
if (offset != null) result.offset = offset;
|
|
8468
8479
|
if (windowChunks != null) result.windowChunks = windowChunks;
|
|
8480
|
+
if (heldTrees != null) result.heldTrees.addAll(heldTrees);
|
|
8469
8481
|
return result;
|
|
8470
8482
|
}
|
|
8471
8483
|
|
|
@@ -8489,6 +8501,7 @@ class LiveCheckpointRequest extends $pb.GeneratedMessage {
|
|
|
8489
8501
|
defaultOrMaker: $fixnum.Int64.ZERO)
|
|
8490
8502
|
..aI(4, _omitFieldNames ? '' : 'windowChunks',
|
|
8491
8503
|
fieldType: $pb.PbFieldType.OU3)
|
|
8504
|
+
..pPS(5, _omitFieldNames ? '' : 'heldTrees')
|
|
8492
8505
|
..hasRequiredFields = false;
|
|
8493
8506
|
|
|
8494
8507
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
|
@@ -8546,6 +8559,11 @@ class LiveCheckpointRequest extends $pb.GeneratedMessage {
|
|
|
8546
8559
|
$core.bool hasWindowChunks() => $_has(3);
|
|
8547
8560
|
@$pb.TagNumber(4)
|
|
8548
8561
|
void clearWindowChunks() => $_clearField(4);
|
|
8562
|
+
|
|
8563
|
+
/// As in LiveFrontier: trees the copy holds and the checkpoint may leave out. A resume names the same
|
|
8564
|
+
/// trees it named when the checkpoint was offered (they are part of the checkpoint's identity).
|
|
8565
|
+
@$pb.TagNumber(5)
|
|
8566
|
+
$pb.PbList<$core.String> get heldTrees => $_getList(4);
|
|
8549
8567
|
}
|
|
8550
8568
|
|
|
8551
8569
|
/// The checkpoint the peer will send: the frontier state at H (H's commit and state tree, and the
|
|
@@ -8564,6 +8582,8 @@ class LiveCheckpointOffer extends $pb.GeneratedMessage {
|
|
|
8564
8582
|
$core.String? requestId,
|
|
8565
8583
|
$core.String? sealed,
|
|
8566
8584
|
$core.String? main,
|
|
8585
|
+
$core.Iterable<$core.String>? omittedTrees,
|
|
8586
|
+
$core.Iterable<$core.String>? sharedTrees,
|
|
8567
8587
|
}) {
|
|
8568
8588
|
final result = create();
|
|
8569
8589
|
if (head != null) result.head = head;
|
|
@@ -8577,6 +8597,8 @@ class LiveCheckpointOffer extends $pb.GeneratedMessage {
|
|
|
8577
8597
|
if (requestId != null) result.requestId = requestId;
|
|
8578
8598
|
if (sealed != null) result.sealed = sealed;
|
|
8579
8599
|
if (main != null) result.main = main;
|
|
8600
|
+
if (omittedTrees != null) result.omittedTrees.addAll(omittedTrees);
|
|
8601
|
+
if (sharedTrees != null) result.sharedTrees.addAll(sharedTrees);
|
|
8580
8602
|
return result;
|
|
8581
8603
|
}
|
|
8582
8604
|
|
|
@@ -8609,6 +8631,8 @@ class LiveCheckpointOffer extends $pb.GeneratedMessage {
|
|
|
8609
8631
|
..aOS(10, _omitFieldNames ? '' : 'requestId')
|
|
8610
8632
|
..aOS(11, _omitFieldNames ? '' : 'sealed')
|
|
8611
8633
|
..aOS(12, _omitFieldNames ? '' : 'main')
|
|
8634
|
+
..pPS(13, _omitFieldNames ? '' : 'omittedTrees')
|
|
8635
|
+
..pPS(14, _omitFieldNames ? '' : 'sharedTrees')
|
|
8612
8636
|
..hasRequiredFields = false;
|
|
8613
8637
|
|
|
8614
8638
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
|
@@ -8725,6 +8749,16 @@ class LiveCheckpointOffer extends $pb.GeneratedMessage {
|
|
|
8725
8749
|
$core.bool hasMain() => $_has(10);
|
|
8726
8750
|
@$pb.TagNumber(12)
|
|
8727
8751
|
void clearMain() => $_clearField(12);
|
|
8752
|
+
|
|
8753
|
+
/// The held trees (named by the copy's ask) whose reachable objects this pack leaves out (CAP-901):
|
|
8754
|
+
/// the copy supplies them from its own custody before it verifies the checkpoint.
|
|
8755
|
+
@$pb.TagNumber(13)
|
|
8756
|
+
$pb.PbList<$core.String> get omittedTrees => $_getList(11);
|
|
8757
|
+
|
|
8758
|
+
/// The law-closure trees this checkpoint carries (its `state/law-units` tree): a copy that holds one
|
|
8759
|
+
/// in another workspace may name it in its next ask and receive a checkpoint without it.
|
|
8760
|
+
@$pb.TagNumber(14)
|
|
8761
|
+
$pb.PbList<$core.String> get sharedTrees => $_getList(12);
|
|
8728
8762
|
}
|
|
8729
8763
|
|
|
8730
8764
|
/// One chunk of a checkpoint, or (with `request_id`) of a history slice.
|
|
@@ -9646,6 +9680,7 @@ class PeerStreamReceipt extends $pb.GeneratedMessage {
|
|
|
9646
9680
|
$core.String? sealed,
|
|
9647
9681
|
$core.String? stagedPackFile,
|
|
9648
9682
|
$core.String? main,
|
|
9683
|
+
$core.Iterable<$core.String>? omittedTrees,
|
|
9649
9684
|
}) {
|
|
9650
9685
|
final result = create();
|
|
9651
9686
|
if (pack != null) result.pack = pack;
|
|
@@ -9656,6 +9691,7 @@ class PeerStreamReceipt extends $pb.GeneratedMessage {
|
|
|
9656
9691
|
if (sealed != null) result.sealed = sealed;
|
|
9657
9692
|
if (stagedPackFile != null) result.stagedPackFile = stagedPackFile;
|
|
9658
9693
|
if (main != null) result.main = main;
|
|
9694
|
+
if (omittedTrees != null) result.omittedTrees.addAll(omittedTrees);
|
|
9659
9695
|
return result;
|
|
9660
9696
|
}
|
|
9661
9697
|
|
|
@@ -9694,6 +9730,7 @@ class PeerStreamReceipt extends $pb.GeneratedMessage {
|
|
|
9694
9730
|
..aOS(6, _omitFieldNames ? '' : 'sealed')
|
|
9695
9731
|
..aOS(7, _omitFieldNames ? '' : 'stagedPackFile')
|
|
9696
9732
|
..aOS(8, _omitFieldNames ? '' : 'main')
|
|
9733
|
+
..pPS(9, _omitFieldNames ? '' : 'omittedTrees')
|
|
9697
9734
|
..hasRequiredFields = false;
|
|
9698
9735
|
|
|
9699
9736
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
|
@@ -9801,6 +9838,11 @@ class PeerStreamReceipt extends $pb.GeneratedMessage {
|
|
|
9801
9838
|
$core.bool hasMain() => $_has(7);
|
|
9802
9839
|
@$pb.TagNumber(8)
|
|
9803
9840
|
void clearMain() => $_clearField(8);
|
|
9841
|
+
|
|
9842
|
+
/// With a checkpoint: the trees its pack leaves out (LiveCheckpointOffer.omitted_trees), which the
|
|
9843
|
+
/// copy supplies from its own custody before the import verifies it.
|
|
9844
|
+
@$pb.TagNumber(9)
|
|
9845
|
+
$pb.PbList<$core.String> get omittedTrees => $_getList(8);
|
|
9804
9846
|
}
|
|
9805
9847
|
|
|
9806
9848
|
enum PeerSocketEffect_Operation { openUrl, send, close, notSet }
|
|
@@ -10348,8 +10390,18 @@ class LiveLinkClosure extends $pb.GeneratedMessage {
|
|
|
10348
10390
|
void clearUnansweredBatches() => $_clearField(12);
|
|
10349
10391
|
}
|
|
10350
10392
|
|
|
10393
|
+
/// The peer observed a socket receipt. `rung_workspaces` names each workspace whose upstream rang
|
|
10394
|
+
/// for a main this copy does not hold while the receipt was handled: its follow round is now due, and
|
|
10395
|
+
/// it is news a person is waiting for. A native shell starts that round at once rather than after the
|
|
10396
|
+
/// foreground's quiet window, still behind interactive requests already queued.
|
|
10351
10397
|
class PeerSocketObserved extends $pb.GeneratedMessage {
|
|
10352
|
-
factory PeerSocketObserved(
|
|
10398
|
+
factory PeerSocketObserved({
|
|
10399
|
+
$core.Iterable<$core.String>? rungWorkspaces,
|
|
10400
|
+
}) {
|
|
10401
|
+
final result = create();
|
|
10402
|
+
if (rungWorkspaces != null) result.rungWorkspaces.addAll(rungWorkspaces);
|
|
10403
|
+
return result;
|
|
10404
|
+
}
|
|
10353
10405
|
|
|
10354
10406
|
PeerSocketObserved._();
|
|
10355
10407
|
|
|
@@ -10365,6 +10417,7 @@ class PeerSocketObserved extends $pb.GeneratedMessage {
|
|
|
10365
10417
|
package:
|
|
10366
10418
|
const $pb.PackageName(_omitMessageNames ? '' : 'nomos.runtime.v2'),
|
|
10367
10419
|
createEmptyInstance: create)
|
|
10420
|
+
..pPS(1, _omitFieldNames ? '' : 'rungWorkspaces')
|
|
10368
10421
|
..hasRequiredFields = false;
|
|
10369
10422
|
|
|
10370
10423
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
|
@@ -10385,6 +10438,9 @@ class PeerSocketObserved extends $pb.GeneratedMessage {
|
|
|
10385
10438
|
static PeerSocketObserved getDefault() => _defaultInstance ??=
|
|
10386
10439
|
$pb.GeneratedMessage.$_defaultFor<PeerSocketObserved>(create);
|
|
10387
10440
|
static PeerSocketObserved? _defaultInstance;
|
|
10441
|
+
|
|
10442
|
+
@$pb.TagNumber(1)
|
|
10443
|
+
$pb.PbList<$core.String> get rungWorkspaces => $_getList(0);
|
|
10388
10444
|
}
|
|
10389
10445
|
|
|
10390
10446
|
class ExportLiveOffersRequest extends $pb.GeneratedMessage {
|
|
@@ -127,10 +127,12 @@ class LocalReadPending extends $pb.GeneratedMessage {
|
|
|
127
127
|
factory LocalReadPending({
|
|
128
128
|
$core.String? workId,
|
|
129
129
|
$core.int? resumeAfterMillis,
|
|
130
|
+
$core.String? heldReason,
|
|
130
131
|
}) {
|
|
131
132
|
final result = create();
|
|
132
133
|
if (workId != null) result.workId = workId;
|
|
133
134
|
if (resumeAfterMillis != null) result.resumeAfterMillis = resumeAfterMillis;
|
|
135
|
+
if (heldReason != null) result.heldReason = heldReason;
|
|
134
136
|
return result;
|
|
135
137
|
}
|
|
136
138
|
|
|
@@ -151,6 +153,7 @@ class LocalReadPending extends $pb.GeneratedMessage {
|
|
|
151
153
|
..aOS(1, _omitFieldNames ? '' : 'workId')
|
|
152
154
|
..aI(2, _omitFieldNames ? '' : 'resumeAfterMillis',
|
|
153
155
|
fieldType: $pb.PbFieldType.OU3)
|
|
156
|
+
..aOS(3, _omitFieldNames ? '' : 'heldReason')
|
|
154
157
|
..hasRequiredFields = false;
|
|
155
158
|
|
|
156
159
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
|
@@ -189,6 +192,17 @@ class LocalReadPending extends $pb.GeneratedMessage {
|
|
|
189
192
|
$core.bool hasResumeAfterMillis() => $_has(1);
|
|
190
193
|
@$pb.TagNumber(2)
|
|
191
194
|
void clearResumeAfterMillis() => $_clearField(2);
|
|
195
|
+
|
|
196
|
+
/// CAP-900: why the kernel holds this read (ReadIndexPending.last_ready_absent), so the shell's
|
|
197
|
+
/// log names it. Diagnostic text only: shells never branch on it.
|
|
198
|
+
@$pb.TagNumber(3)
|
|
199
|
+
$core.String get heldReason => $_getSZ(2);
|
|
200
|
+
@$pb.TagNumber(3)
|
|
201
|
+
set heldReason($core.String value) => $_setString(2, value);
|
|
202
|
+
@$pb.TagNumber(3)
|
|
203
|
+
$core.bool hasHeldReason() => $_has(2);
|
|
204
|
+
@$pb.TagNumber(3)
|
|
205
|
+
void clearHeldReason() => $_clearField(3);
|
|
192
206
|
}
|
|
193
207
|
|
|
194
208
|
/// An exact custody frontier advanced through a write entrance which is not
|
|
@@ -100,6 +100,28 @@ class RuntimeUnavailableReason extends $pb.ProtobufEnum {
|
|
|
100
100
|
RuntimeUnavailableReason._(
|
|
101
101
|
7, _omitEnumNames ? '' : 'RUNTIME_UNAVAILABLE_REASON_PEER_BUSY');
|
|
102
102
|
|
|
103
|
+
/// CAP-891: this peer's only ready read index for the workspace was built under the law its head
|
|
104
|
+
/// has since replaced. The application's decoders belong to the new law, so no rows are served
|
|
105
|
+
/// from it; read maintenance is building the index under the new law. Retryable: render
|
|
106
|
+
/// "updating", never an empty result and never a decode failure (CO2-APP-209).
|
|
107
|
+
static const RuntimeUnavailableReason
|
|
108
|
+
RUNTIME_UNAVAILABLE_REASON_READ_INDEX_REFRESHING_SUCCESSOR_LAW =
|
|
109
|
+
RuntimeUnavailableReason._(
|
|
110
|
+
8,
|
|
111
|
+
_omitEnumNames
|
|
112
|
+
? ''
|
|
113
|
+
: 'RUNTIME_UNAVAILABLE_REASON_READ_INDEX_REFRESHING_SUCCESSOR_LAW');
|
|
114
|
+
|
|
115
|
+
/// This workspace has never been on this device: its placement keeps a local copy here and that
|
|
116
|
+
/// copy's first download (Replica Follow) is under way. Answered at once, to a read and to a
|
|
117
|
+
/// write alike; nothing is admitted against an absent base. Retryable, and ONE-TIME per workspace
|
|
118
|
+
/// per device: once the first download lands the copy persists across kills, updates and reboots,
|
|
119
|
+
/// and writes go against it as normal (Jack, 11 Oct 2026). Distinct from LOCAL_REPLICA_NOT_READY,
|
|
120
|
+
/// which also names a copy that is here but unreadable (being refetched or awaiting a drop).
|
|
121
|
+
static const RuntimeUnavailableReason
|
|
122
|
+
RUNTIME_UNAVAILABLE_REASON_FIRST_DOWNLOAD = RuntimeUnavailableReason._(
|
|
123
|
+
9, _omitEnumNames ? '' : 'RUNTIME_UNAVAILABLE_REASON_FIRST_DOWNLOAD');
|
|
124
|
+
|
|
103
125
|
static const $core.List<RuntimeUnavailableReason> values =
|
|
104
126
|
<RuntimeUnavailableReason>[
|
|
105
127
|
RUNTIME_UNAVAILABLE_REASON_UNSPECIFIED,
|
|
@@ -110,10 +132,12 @@ class RuntimeUnavailableReason extends $pb.ProtobufEnum {
|
|
|
110
132
|
RUNTIME_UNAVAILABLE_REASON_CREDENTIAL_UNAVAILABLE,
|
|
111
133
|
RUNTIME_UNAVAILABLE_REASON_WORKSPACE_OPENING,
|
|
112
134
|
RUNTIME_UNAVAILABLE_REASON_PEER_BUSY,
|
|
135
|
+
RUNTIME_UNAVAILABLE_REASON_READ_INDEX_REFRESHING_SUCCESSOR_LAW,
|
|
136
|
+
RUNTIME_UNAVAILABLE_REASON_FIRST_DOWNLOAD,
|
|
113
137
|
];
|
|
114
138
|
|
|
115
139
|
static final $core.List<RuntimeUnavailableReason?> _byValue =
|
|
116
|
-
$pb.ProtobufEnum.$_initByValueList(values,
|
|
140
|
+
$pb.ProtobufEnum.$_initByValueList(values, 9);
|
|
117
141
|
static RuntimeUnavailableReason? valueOf($core.int value) =>
|
|
118
142
|
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
|
119
143
|
|
|
@@ -17,6 +17,18 @@ enum NomosUnavailableReason {
|
|
|
17
17
|
localReplicaNotReady,
|
|
18
18
|
credentialUnavailable,
|
|
19
19
|
workspaceOpening,
|
|
20
|
+
|
|
21
|
+
/// The workspace's only ready read index was built under a law its head has since replaced,
|
|
22
|
+
/// and it is being rebuilt under the new law (CAP-891). This application decodes the head's
|
|
23
|
+
/// law only (no reception for the predecessor closure, CAP-884), so no rows are served from
|
|
24
|
+
/// it. A wait like [localReplicaNotReady], never a result and never a failure (CAP-900).
|
|
25
|
+
readIndexRefreshing,
|
|
26
|
+
|
|
27
|
+
/// This workspace has never been on this device and its first download is under way. A read
|
|
28
|
+
/// answers empty and a write is refused, at once; nothing is admitted against an absent base.
|
|
29
|
+
/// ONE-TIME per workspace per device: the landed copy persists (CAP-907). Distinct from
|
|
30
|
+
/// [localReplicaNotReady], which also names a copy here that is unreadable (Jack, 11 Oct 2026).
|
|
31
|
+
firstDownload,
|
|
20
32
|
unknown,
|
|
21
33
|
}
|
|
22
34
|
|
|
@@ -57,6 +69,11 @@ final class NomosUnavailable implements Exception {
|
|
|
57
69
|
NomosUnavailableReason.credentialUnavailable,
|
|
58
70
|
RuntimeUnavailableReason.RUNTIME_UNAVAILABLE_REASON_WORKSPACE_OPENING =>
|
|
59
71
|
NomosUnavailableReason.workspaceOpening,
|
|
72
|
+
RuntimeUnavailableReason
|
|
73
|
+
.RUNTIME_UNAVAILABLE_REASON_READ_INDEX_REFRESHING_SUCCESSOR_LAW =>
|
|
74
|
+
NomosUnavailableReason.readIndexRefreshing,
|
|
75
|
+
RuntimeUnavailableReason.RUNTIME_UNAVAILABLE_REASON_FIRST_DOWNLOAD =>
|
|
76
|
+
NomosUnavailableReason.firstDownload,
|
|
60
77
|
_ => NomosUnavailableReason.unknown,
|
|
61
78
|
},
|
|
62
79
|
workspace: unavailable.workspace,
|
package/dart_types/pubspec.yaml
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
Pure kernel wire/data types for Nomos Dart frontends — no transport, no bridge,
|
|
10
10
|
no runtime. Typed protobuf and USDA boundary values plus the offer codec,
|
|
11
11
|
reactive read engine, schema validation, and data-only error/trace types.
|
|
12
|
-
version: 0.15.
|
|
12
|
+
version: 0.15.2
|
|
13
13
|
|
|
14
14
|
environment:
|
|
15
15
|
sdk: ^3.5.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@githolon/dsl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.119.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
"./workspace-sharding": "./src/workspace_sharding.ts",
|
|
35
35
|
"./reception-artifact": "./src/reception_artifact.ts",
|
|
36
36
|
"./reception-artifact-contract": "./src/reception_artifact_contract.ts",
|
|
37
|
+
"./reception-unit-artifact": "./src/reception_unit_artifact.ts",
|
|
38
|
+
"./reception-unit-artifact-contract": "./src/reception_unit_artifact_contract.ts",
|
|
39
|
+
"./reception-unit-source": "./src/reception_unit_source.ts",
|
|
37
40
|
"./build-package": "./src/build_package.ts",
|
|
38
41
|
"./codegen-dart": "./src/codegen_dart.ts",
|
|
39
42
|
"./codegen-dot": "./src/codegen_dot.ts",
|
|
@@ -79,10 +82,11 @@
|
|
|
79
82
|
"test": "vitest run"
|
|
80
83
|
},
|
|
81
84
|
"dependencies": {
|
|
82
|
-
"@githolon/runtime": "^0.
|
|
85
|
+
"@githolon/runtime": "^0.119.9",
|
|
83
86
|
"@bufbuild/protobuf": "^2.13.0",
|
|
84
87
|
"@bufbuild/protoc-gen-es": "^2.13.0",
|
|
85
88
|
"esbuild": "0.24.2",
|
|
89
|
+
"fflate": "0.8.2",
|
|
86
90
|
"tsx": "^4.19.2",
|
|
87
91
|
"typescript": "^5.6.3",
|
|
88
92
|
"vscode-languageserver": "^9.0.1",
|
package/src/codegen_ts.ts
CHANGED
|
@@ -4765,6 +4765,7 @@ function generateTsClientBody(
|
|
|
4765
4765
|
d as unknown as {
|
|
4766
4766
|
businessBirth?: {
|
|
4767
4767
|
aggregateId: string;
|
|
4768
|
+
domain: string;
|
|
4768
4769
|
publicPayloadSchema: z.ZodTypeAny;
|
|
4769
4770
|
rootId: string;
|
|
4770
4771
|
namespace: string;
|
|
@@ -4789,17 +4790,15 @@ function generateTsClientBody(
|
|
|
4789
4790
|
businessBirth === undefined
|
|
4790
4791
|
? undefined
|
|
4791
4792
|
: (() => {
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4793
|
+
if (typeof businessBirth.domain !== "string" || businessBirth.domain.length === 0) {
|
|
4794
|
+
throw new Error(`codegen: business birth '${domain}/${d.id}' has no declared owning domain`);
|
|
4795
|
+
}
|
|
4796
|
+
const owners = (aggregateOwners.get(businessBirth.aggregateId) ?? [])
|
|
4797
|
+
.filter(owner => owner === businessBirth.domain);
|
|
4797
4798
|
if (owners.length !== 1) {
|
|
4798
4799
|
throw new Error(
|
|
4799
4800
|
`codegen: business birth '${domain}/${d.id}' must target one generated domain owning ` +
|
|
4800
|
-
`'${businessBirth.aggregateId}', found ${
|
|
4801
|
-
owners.length === 0 ? "none" : owners.join(", ")
|
|
4802
|
-
}`
|
|
4801
|
+
`'${businessBirth.domain}/${businessBirth.aggregateId}', found ${owners.length}`
|
|
4803
4802
|
);
|
|
4804
4803
|
}
|
|
4805
4804
|
return owners[0]!;
|
|
@@ -265,6 +265,7 @@ import {
|
|
|
265
265
|
import { proofLegsIndex } from "./codegen_proof.js";
|
|
266
266
|
import { usdzPack } from "./usdz.js";
|
|
267
267
|
import { compilerReceptionOperations, bundleCompilerReceptionFactory, compressCompilerReceptionTemplate } from "./reception_template.js";
|
|
268
|
+
import { ReceptionUnitContextIndex } from "./reception_unit_context.js";
|
|
268
269
|
import { embedReceptionTemplate, appendReceptionDomainOpinion, RECEPTION_CLOSURE_TOKEN } from "./reception_artifact_contract.js";
|
|
269
270
|
import {
|
|
270
271
|
LAW_UNIT_MANIFEST,
|
|
@@ -2586,12 +2587,12 @@ const dartTypesImportFor = (generatedSource: string): string => {
|
|
|
2586
2587
|
* just the floor generated code needs — a lagging pin forces tenants into dependency_overrides. */
|
|
2587
2588
|
// 0.3.0: SurfacedValue<T>/SurfacedObservation/PendingConflictRow — generated Surfaced-field typing +
|
|
2588
2589
|
// the pendingConflicts read rows.
|
|
2589
|
-
const NOMOS_TYPES_DEP = "^0.15.
|
|
2590
|
+
const NOMOS_TYPES_DEP = "^0.15.2";
|
|
2590
2591
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
2591
2592
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
2592
2593
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
2593
|
-
const NOMOS_CLIENT_DEP = "^0.70.
|
|
2594
|
-
const NOMOS_FLUTTER_DEP = "^0.
|
|
2594
|
+
const NOMOS_CLIENT_DEP = "^0.70.10";
|
|
2595
|
+
const NOMOS_FLUTTER_DEP = "^0.69.0";
|
|
2595
2596
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in the Dart and Flutter
|
|
2596
2597
|
// package pubspecs — a release without this bump fails the suite, so tenants never
|
|
2597
2598
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -7893,6 +7894,11 @@ async function main(): Promise<void> {
|
|
|
7893
7894
|
// Complete compiler-produced Reception metadata belongs to the domain unit.
|
|
7894
7895
|
// The realised closure is not known until the target kernel composes its installed
|
|
7895
7896
|
// set; its token is bound only by the server generator, outside law identity.
|
|
7897
|
+
const receptionUnitContexts = new ReceptionUnitContextIndex(domainModules.map(module => {
|
|
7898
|
+
const graph = typedLawGraphs.get(module.name);
|
|
7899
|
+
if (!graph) fail(`Reception unit context has no graph for '${module.name}'`);
|
|
7900
|
+
return { module, graph };
|
|
7901
|
+
}), lawDependencies, v3LawPathByNode);
|
|
7896
7902
|
for (const module of presentationDomainModules) {
|
|
7897
7903
|
const graph = typedLawGraphs.get(module.name);
|
|
7898
7904
|
const paths = typedLawPathsByName.get(module.name);
|
|
@@ -7912,7 +7918,8 @@ async function main(): Promise<void> {
|
|
|
7912
7918
|
const binding = readFileSync(path.join(scratch, "operation_payloads_pb.ts"), "utf8");
|
|
7913
7919
|
const source = generateTsClient([module], {
|
|
7914
7920
|
packageName: module.name, domainHash: RECEPTION_CLOSURE_TOKEN,
|
|
7915
|
-
interface: { [domain]: packageInterface[domain]! },
|
|
7921
|
+
interface: { [domain]: packageInterface[domain]! },
|
|
7922
|
+
kernelContracts: receptionUnitContexts.forGraph(graph).kernelContracts,
|
|
7916
7923
|
homeDomain: domain, exportHolonFactory: true, callUsda: [{ graph, paths }],
|
|
7917
7924
|
factoryOnly: { composition: presentationDomainModules },
|
|
7918
7925
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { build, version as esbuildVersion } from "esbuild";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import { gzipSync } from "
|
|
4
|
+
import { gzipSync } from "fflate";
|
|
5
5
|
/** Compiler-only inventory of the generated stateless business methods. */
|
|
6
6
|
import type { DomainModule } from "./codegen_dart.js";
|
|
7
7
|
import type { LawGraph } from "./law_graph.js";
|
|
@@ -12,10 +12,11 @@ import type { ReceptionTemplate } from "./reception_artifact_contract.js";
|
|
|
12
12
|
import { isFrameworkAggregate, isFrameworkQuery } from "./framework/framework_aggregates.js";
|
|
13
13
|
|
|
14
14
|
/** Keep source completeness without multiplying opaque metadata in semantic USD.
|
|
15
|
-
*
|
|
15
|
+
* The pinned pure-JS compressor, fixed memory level and zero timestamp keep law bytes independent
|
|
16
|
+
* of the host's zlib version. Do not substitute native gzip for this encoder. */
|
|
16
17
|
export function compressCompilerReceptionTemplate(template: ReceptionTemplate): ReceptionTemplate {
|
|
17
18
|
const bytes = Buffer.from(JSON.stringify([template.factorySource, template.clientSource, template.operationBinding, template.operationProto]));
|
|
18
|
-
return { ...template, sourceEnvelope: { gzipBase64: gzipSync(bytes, { level: 9 }).toString("base64"), decodedBytes: bytes.byteLength } };
|
|
19
|
+
return { ...template, sourceEnvelope: { gzipBase64: Buffer.from(gzipSync(bytes, { level: 9, mem: 8, mtime: 0 })).toString("base64"), decodedBytes: bytes.byteLength } };
|
|
19
20
|
}
|
|
20
21
|
const queryMember = (value: string) => {
|
|
21
22
|
const camel = value.replace(/[_\s-]+(\w)/g, (_match, letter: string) => letter.toUpperCase());
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** Pure additive prototype; no production activation, source transformation or law evaluation.
|
|
2
|
+
* Unit associations must be authenticated upstream. A cached module receives closure context
|
|
3
|
+
* only through a fresh host-verified binding; the Office still judges the requested operation. */
|
|
4
|
+
import { RECEPTION_CLOSURE_TOKEN, RECEPTION_SOURCE_BYTES_LIMIT } from "./reception_artifact_contract.js";
|
|
5
|
+
import {
|
|
6
|
+
assertUnitReceptionRecord, snapshotUnitReceptionValue, canonicalReceptionOperations, closureReceptionOperations, closureReceptionManifestIdentity,
|
|
7
|
+
receptionSha256, unitReceptionArtifactIdentity, unitReceptionUnavailable, validateUnitReceptionIdentity,
|
|
8
|
+
verifyClosureReceptionManifest, verifyUnitReceptionArtifact, verifyUnitReceptionManifest,
|
|
9
|
+
UNIT_RECEPTION_ARTIFACT_FORMAT, CLOSURE_RECEPTION_MANIFEST_FORMAT,
|
|
10
|
+
type UnitReceptionInput, type UnitReceptionArtifact, type UnitReceptionManifest,
|
|
11
|
+
type ClosureReceptionManifestInput, type ClosureReceptionManifest,
|
|
12
|
+
} from "./reception_unit_artifact_contract.js";
|
|
13
|
+
export * from "./reception_unit_artifact_contract.js";
|
|
14
|
+
|
|
15
|
+
export async function generateUnitReceptionArtifact(input: UnitReceptionInput): Promise<UnitReceptionArtifact> {
|
|
16
|
+
input = snapshotUnitReceptionValue(input);
|
|
17
|
+
assertUnitReceptionRecord(input, ["unitKey", "unitHash", "domain", "generator", "runtimeContract", "template"]);
|
|
18
|
+
validateUnitReceptionIdentity(input);
|
|
19
|
+
const template = input.template;
|
|
20
|
+
if (!template || template.domain !== input.domain || !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(template.factory)) unitReceptionUnavailable("unit Reception template domain/factory mismatch");
|
|
21
|
+
let bytes = 0;
|
|
22
|
+
for (const [source, hash] of [[template.factorySource, template.factorySha256], [template.clientSource, template.sourceSha256],
|
|
23
|
+
[template.operationBinding, template.bindingSha256], [template.operationProto, template.protoSha256]]) {
|
|
24
|
+
if (typeof source !== "string" || !source) unitReceptionUnavailable("incomplete unit Reception template");
|
|
25
|
+
if (source.length > RECEPTION_SOURCE_BYTES_LIMIT) unitReceptionUnavailable("unit Reception source budget exceeded");
|
|
26
|
+
bytes += new TextEncoder().encode(source).byteLength;
|
|
27
|
+
if (bytes > RECEPTION_SOURCE_BYTES_LIMIT) unitReceptionUnavailable("unit Reception source budget exceeded");
|
|
28
|
+
if (typeof hash !== "string" || !/^[0-9a-f]{64}$/.test(hash) || await receptionSha256(source) !== hash) unitReceptionUnavailable("unit Reception template digest mismatch");
|
|
29
|
+
}
|
|
30
|
+
const literal = JSON.stringify(RECEPTION_CLOSURE_TOKEN);
|
|
31
|
+
if (!template.factorySource.includes(literal) || !template.clientSource.includes(literal)) unitReceptionUnavailable("unit Reception template has no closure binding");
|
|
32
|
+
const operations = canonicalReceptionOperations(template.operations);
|
|
33
|
+
const description = { unitKey: input.unitKey, unitHash: input.unitHash, domain: input.domain,
|
|
34
|
+
generator: input.generator, runtimeContract: input.runtimeContract, factory: template.factory, operations };
|
|
35
|
+
// This is a lexical expression substituted once into compiler-produced code, not an eval or
|
|
36
|
+
// per-closure module rewrite. Each call gets a separate factory and closure variable.
|
|
37
|
+
const source = [
|
|
38
|
+
'import { WorkerEntrypoint } from "cloudflare:workers";',
|
|
39
|
+
`const description = ${JSON.stringify(description)};`,
|
|
40
|
+
`description.operations = Object.freeze(description.operations.map(operation => Object.freeze(operation))); Object.freeze(description);`,
|
|
41
|
+
`const operations = Object.freeze(Object.fromEntries(description.operations.map(operation => [operation.member, Object.freeze(operation)])));`,
|
|
42
|
+
`function bindFactory(__nomosBoundClosure) { ${template.factorySource.replaceAll(literal, "__nomosBoundClosure")} return __NOMOS_RECEPTION_FACET__.${template.factory}; }`,
|
|
43
|
+
`function serialiseResult(value, depth = 0, seen = new Set()) {`,
|
|
44
|
+
` const unavailable = () => { const error = new Error("Generated result cannot cross the hosted JSON contract"); error.code = "nomos.reception.result.unavailable"; throw error; };`,
|
|
45
|
+
` if (depth > 64) return unavailable();`,
|
|
46
|
+
` if (value === undefined) return { $nomos: "absent" };`,
|
|
47
|
+
` if (value === null || typeof value === "string" || typeof value === "boolean") return value;`,
|
|
48
|
+
` if (typeof value === "number") { if (!Number.isFinite(value)) return unavailable(); return value; }`,
|
|
49
|
+
` if (typeof value === "bigint") return { $nomos: "integer", decimal: value.toString() };`,
|
|
50
|
+
` if (value instanceof Uint8Array) { let binary = ""; for (const byte of value) binary += String.fromCharCode(byte); return { $nomos: "bytes", base64: btoa(binary) }; }`,
|
|
51
|
+
` if (value instanceof Date) { if (!Number.isFinite(value.getTime())) return unavailable(); return { $nomos: "timestamp", iso: value.toISOString() }; }`,
|
|
52
|
+
` if (typeof value !== "object" || seen.has(value)) return unavailable();`,
|
|
53
|
+
` seen.add(value); try {`,
|
|
54
|
+
` if (Array.isArray(value)) return value.map(item => serialiseResult(item, depth + 1, seen));`,
|
|
55
|
+
` const prototype = Object.getPrototypeOf(value); if (prototype !== Object.prototype && prototype !== null) return unavailable();`,
|
|
56
|
+
` const output = {}; for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) { if (descriptor.get || descriptor.set) return unavailable(); Object.defineProperty(output, key, { value: serialiseResult(descriptor.value, depth + 1, seen), enumerable: true }); } return output;`,
|
|
57
|
+
` } finally { seen.delete(value); }`,
|
|
58
|
+
`}`,
|
|
59
|
+
`export default class UnitReception extends WorkerEntrypoint {`,
|
|
60
|
+
` describe() { return description; }`,
|
|
61
|
+
` async invoke(call, office, binding) {`,
|
|
62
|
+
` if (!call || !binding || call.domain !== description.domain || binding.domain !== description.domain || binding.unitKey !== description.unitKey || binding.unitHash !== description.unitHash || call.member !== binding.member || call.closure !== binding.closure || !/^[0-9a-f]{64}$/.test(binding.closure)) throw new Error("unit Reception invocation binding mismatch");`,
|
|
63
|
+
` if (typeof call.workspace !== "string" || !call.workspace || typeof call.principal !== "string" || !call.principal || !Array.isArray(call.args)) throw new Error("invalid unit Reception invocation");`,
|
|
64
|
+
` if (!Object.hasOwn(operations, call.member)) throw new Error("unit Reception member is absent");`,
|
|
65
|
+
` const selected = operations[call.member]; if (binding.kind !== selected.kind || binding.selector !== selected.selector) throw new Error("unit Reception operation binding mismatch");`,
|
|
66
|
+
` const scoped = { workspace: call.workspace, principal: call.principal, offerCall: (...args) => office.offerCall(...args),`,
|
|
67
|
+
` __nomosQuery: (...args) => office.__nomosQuery(...args), __nomosQueryUsda: (...args) => office.__nomosQueryUsda(...args),`,
|
|
68
|
+
` __nomosQueryByIdUsda: (...args) => office.__nomosQueryByIdUsda(...args), __nomosQueryByTypeUsda: (...args) => office.__nomosQueryByTypeUsda(...args),`,
|
|
69
|
+
` __nomosQueryPage: (...args) => office.__nomosQueryPage(...args), __nomosQueryPageUsda: (...args) => office.__nomosQueryPageUsda(...args),`,
|
|
70
|
+
` prepareDomain: (domain, closure) => { if (domain !== description.domain || closure !== binding.closure) throw new Error("unit Reception closure binding escaped its call"); } };`,
|
|
71
|
+
` const client = bindFactory(binding.closure)(scoped);`,
|
|
72
|
+
` const path = call.member.split("."); let parent = client;`,
|
|
73
|
+
` for (const part of path.slice(0, -1)) { if (!part || part.startsWith("__") || ["constructor", "prototype"].includes(part) || !Object.hasOwn(parent, part)) throw new Error("unit Reception business member is absent"); parent = parent[part]; if (!parent || typeof parent !== "object") throw new Error("unit Reception business member is absent"); }`,
|
|
74
|
+
` const member = path.at(-1); if (!member || member.startsWith("watch") || member.startsWith("__") || ["constructor", "prototype"].includes(member) || !Object.hasOwn(parent, member) || typeof parent[member] !== "function") throw new Error("unit Reception business member is absent");`,
|
|
75
|
+
` const args = [...call.args];`,
|
|
76
|
+
` if (selected.kind === "byId" && typeof args[0] === "string" && typeof parent.fromAddress === "function") args[0] = parent.fromAddress(args[0]);`,
|
|
77
|
+
` return serialiseResult(await parent[member](...args));`,
|
|
78
|
+
` }`,
|
|
79
|
+
`}`, "",
|
|
80
|
+
].join("\n");
|
|
81
|
+
const content: Omit<UnitReceptionManifest, "artifactId"> = { format: UNIT_RECEPTION_ARTIFACT_FORMAT,
|
|
82
|
+
unitKey: input.unitKey, unitHash: input.unitHash, domain: input.domain, generator: input.generator,
|
|
83
|
+
runtimeContract: input.runtimeContract, entrypoint: "reception-unit.mjs", moduleSha256: await receptionSha256(source),
|
|
84
|
+
factory: template.factory, factorySha256: template.factorySha256, sourceSha256: template.sourceSha256,
|
|
85
|
+
bindingSha256: template.bindingSha256, protoSha256: template.protoSha256, operations };
|
|
86
|
+
const artifact: UnitReceptionArtifact = { manifest: { ...content, artifactId: await unitReceptionArtifactIdentity(content) }, moduleSource: source };
|
|
87
|
+
await verifyUnitReceptionArtifact(artifact, input);
|
|
88
|
+
return snapshotUnitReceptionValue(artifact);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function generateClosureReceptionManifest(input: ClosureReceptionManifestInput): Promise<ClosureReceptionManifest> {
|
|
92
|
+
input = snapshotUnitReceptionValue(input);
|
|
93
|
+
assertUnitReceptionRecord(input, ["closure", "generator", "runtimeContract", "units", "domains"]);
|
|
94
|
+
if (!Array.isArray(input.domains) || input.domains.length === 0 || new Set(input.domains).size !== input.domains.length) unitReceptionUnavailable("invalid authoritative Reception domain coverage");
|
|
95
|
+
if (!Array.isArray(input.units) || input.units.length === 0) unitReceptionUnavailable("invalid closure Reception units");
|
|
96
|
+
for (const unit of input.units) await verifyUnitReceptionManifest(unit);
|
|
97
|
+
const units = input.units.map((unit: UnitReceptionManifest) => ({ ...unit, operations: unit.operations.map(operation => ({ ...operation })) }))
|
|
98
|
+
.sort((a, b) => a.unitKey < b.unitKey ? -1 : a.unitKey > b.unitKey ? 1 : 0);
|
|
99
|
+
if (input.domains.length !== units.length || units.some(unit => !input.domains.includes(unit.domain))) unitReceptionUnavailable("closure Reception domain membership is incomplete");
|
|
100
|
+
const content = { format: CLOSURE_RECEPTION_MANIFEST_FORMAT, closure: input.closure,
|
|
101
|
+
generator: input.generator, runtimeContract: input.runtimeContract, units, operations: closureReceptionOperations(units) } as const;
|
|
102
|
+
const manifest = { ...content, manifestId: await closureReceptionManifestIdentity(content) };
|
|
103
|
+
await verifyClosureReceptionManifest(manifest, input);
|
|
104
|
+
return snapshotUnitReceptionValue(manifest);
|
|
105
|
+
}
|