@githolon/dsl 0.100.4 → 0.100.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dart/CHANGELOG.md +6 -0
- package/dart/lib/src/test_harness.dart +146 -59
- package/dart/pubspec.yaml +1 -1
- package/dart/test/acquire_session_credentials_test.dart +1 -1
- package/dart/test/adv_realm_interference_test.dart +1 -1
- package/dart/test/cluster_attested_test.dart +1 -1
- package/dart/test/cluster_births_test.dart +1 -1
- package/dart/test/cluster_device_keyed_acceptance_test.dart +1 -1
- package/dart/test/cluster_local_autosync_test.dart +1 -1
- package/dart/test/cluster_scale_test.dart +1 -1
- package/dart/test/dlq_session_surface_test.dart +1 -1
- package/dart/test/first_app_gauntlet_test.dart +106 -87
- package/dart/test/local_sync_inert_test.dart +10 -5
- package/dart/test/parent_signer_recovery_test.dart +1 -1
- package/dart/test/sealing_client_test.dart +1 -1
- package/dart/test/session_bound_test.dart +1 -1
- package/dart/test/test_harness_test.dart +2 -2
- package/dart/test/vo_read_typing_test.dart +1 -1
- package/dart/test/watch_after_offer_stall_test.dart +1 -1
- package/package.json +1 -1
- package/src/birth_meter_ensure.ts +162 -18
- package/src/build_package.ts +52 -7
- package/src/business_birth.ts +31 -9
- package/src/codegen_dart_client.ts +11 -7
- package/src/compile_package_main.ts +17 -8
- package/src/framework/birth_meter.ts +82 -0
- package/src/index.ts +5 -0
- package/src/shape_compat.ts +14 -3
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// by CI, not by a tenant.
|
|
6
6
|
//
|
|
7
7
|
// Structure: ONE test, numbered legs, fail-fast — a failure names its leg, so CI output reads as
|
|
8
|
-
// a checklist.
|
|
9
|
-
//
|
|
8
|
+
// a checklist. Its first act uses the one-business-birth CO2 example: the same tenant source and
|
|
9
|
+
// generated client a real Flutter app consumes, never a harness-only birth recipe.
|
|
10
10
|
//
|
|
11
11
|
// Prereqs (fixtures compiled + a warm ~/.holon/runtime): locally the test SKIPS with the recipe
|
|
12
12
|
// when they are missing; in CI the job sets NOMOS_GAUNTLET_REQUIRED=1 so a missing prereq is a
|
|
@@ -14,24 +14,20 @@
|
|
|
14
14
|
@TestOn('vm')
|
|
15
15
|
library;
|
|
16
16
|
|
|
17
|
-
import 'dart:convert';
|
|
18
17
|
import 'dart:io';
|
|
19
18
|
|
|
20
|
-
import 'package:crypto/crypto.dart' show sha256;
|
|
21
|
-
|
|
22
19
|
import 'package:nomos_client/nomos_headless.dart';
|
|
23
20
|
import 'package:test/test.dart';
|
|
24
21
|
|
|
25
|
-
import '../../../
|
|
26
|
-
import '../../../bench/scale/fixtures/estate-birth/build/dart/src/generated/estate.client.dart'
|
|
27
|
-
show EstateClient, SeedEstateWorkspacePayload;
|
|
22
|
+
import '../../../examples/co2-birth/build/dart/src/generated/co2.client.dart';
|
|
28
23
|
|
|
29
24
|
String get _root => '${Directory.current.path}/../..';
|
|
30
25
|
String get _repoEntry => '$_root/cloud/web-client/runner/node-entry.ts';
|
|
31
|
-
String get _homeDeploy =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
String get _catDeploy =>
|
|
26
|
+
String get _homeDeploy => '$_root/examples/co2-birth/build/co2.deploy.json';
|
|
27
|
+
String get _docsDeploy =>
|
|
28
|
+
'$_root/bench/scale/fixtures/surfaced/build/surfaced.deploy.json';
|
|
29
|
+
String get _catDeploy =>
|
|
30
|
+
'$_root/bench/scale/fixtures/catalogue-src/build/cat.deploy.json';
|
|
35
31
|
String get _readerDeploy =>
|
|
36
32
|
'$_root/bench/scale/fixtures/catalogue-reader/build/estate.deploy.json';
|
|
37
33
|
String get _runtimeDir =>
|
|
@@ -42,9 +38,10 @@ const _owner = 'user:gauntlet-owner';
|
|
|
42
38
|
const _keyed = 'catalogue';
|
|
43
39
|
|
|
44
40
|
String? _missingPrereq() {
|
|
45
|
-
if (!File(_repoEntry).existsSync())
|
|
41
|
+
if (!File(_repoEntry).existsSync())
|
|
42
|
+
return 'in-repo runner not found at $_repoEntry';
|
|
46
43
|
final fixtures = {
|
|
47
|
-
_homeDeploy: '
|
|
44
|
+
_homeDeploy: 'examples/co2-birth',
|
|
48
45
|
_docsDeploy: 'bench/scale/fixtures/surfaced',
|
|
49
46
|
_catDeploy: 'bench/scale/fixtures/catalogue-src',
|
|
50
47
|
_readerDeploy: 'bench/scale/fixtures/catalogue-reader',
|
|
@@ -54,10 +51,10 @@ String? _missingPrereq() {
|
|
|
54
51
|
return 'missing fixture ${e.key} — compile it: (cd ${e.value} && node ../../../../dsl/compile_package.mjs)';
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync() ||
|
|
54
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
|
|
58
55
|
!File('$_runtimeDir/packages.json').existsSync()) {
|
|
59
|
-
return 'warm ~/.holon/runtime first (run any `githolon` command once, or
|
|
60
|
-
'/v1/runtime/holon.wasm + /v1/runtime/packages from the cloud)';
|
|
56
|
+
return 'warm ~/.holon/runtime first (run any `githolon` command once, or fetch '
|
|
57
|
+
'/v1/runtime/holon-testmint.wasm + /v1/runtime/packages from the cloud)';
|
|
61
58
|
}
|
|
62
59
|
return null;
|
|
63
60
|
}
|
|
@@ -74,18 +71,22 @@ Future<T> _leg<T>(String name, Future<T> Function() body) async {
|
|
|
74
71
|
print('✔ GAUNTLET $name (${sw.elapsedMilliseconds}ms)');
|
|
75
72
|
return r;
|
|
76
73
|
} catch (e, st) {
|
|
77
|
-
throw TestFailure(
|
|
74
|
+
throw TestFailure(
|
|
75
|
+
'GAUNTLET $name FAILED after ${sw.elapsedMilliseconds}ms:\n$e\n$st');
|
|
78
76
|
}
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
void main() {
|
|
82
|
-
test(
|
|
83
|
-
'
|
|
80
|
+
test(
|
|
81
|
+
'THE FIRST-FIVE-MINUTES GAUNTLET: harness → blessed shape → local posture → '
|
|
82
|
+
'acquire → reactive reads → attested read → diagnostics → disposal',
|
|
83
|
+
() async {
|
|
84
84
|
final required = Platform.environment['NOMOS_GAUNTLET_REQUIRED'] == '1';
|
|
85
85
|
final missing = _missingPrereq();
|
|
86
86
|
if (missing != null) {
|
|
87
87
|
if (required) {
|
|
88
|
-
fail(
|
|
88
|
+
fail(
|
|
89
|
+
'NOMOS_GAUNTLET_REQUIRED=1 but a prereq is missing — the CI job must provide it: '
|
|
89
90
|
'$missing');
|
|
90
91
|
}
|
|
91
92
|
markTestSkipped(missing);
|
|
@@ -95,7 +96,8 @@ void main() {
|
|
|
95
96
|
final diagnostics = <String>[];
|
|
96
97
|
|
|
97
98
|
// ── LEG 1: harness up — a 4-workspace cluster, one deviceKeyed, phase diagnostics on. ──
|
|
98
|
-
final harness = await _leg(
|
|
99
|
+
final harness = await _leg(
|
|
100
|
+
'leg 1: NomosTestHarness.cluster (4 ws, one deviceKeyed)', () async {
|
|
99
101
|
final h = await NomosTestHarness.cluster(
|
|
100
102
|
workspaces: {
|
|
101
103
|
'home': [_homeDeploy],
|
|
@@ -113,88 +115,93 @@ void main() {
|
|
|
113
115
|
// keyed 3b legs all log enter AND exit lines.
|
|
114
116
|
expect(diagnostics.any((l) => l.contains('offline law install')), isTrue,
|
|
115
117
|
reason: 'phase 1 install diagnostics must appear');
|
|
116
|
-
expect(
|
|
118
|
+
expect(
|
|
119
|
+
diagnostics
|
|
120
|
+
.any((l) => l.contains('runner ready') && l.contains('done')),
|
|
121
|
+
isTrue,
|
|
117
122
|
reason: 'the runner-ready phase must log its exit');
|
|
118
123
|
expect(diagnostics.any((l) => l.contains('3b: device keygen')), isTrue,
|
|
119
124
|
reason: 'the deviceKeyed keygen phase must log');
|
|
120
125
|
expect(
|
|
121
|
-
diagnostics.any(
|
|
122
|
-
|
|
126
|
+
diagnostics.any((l) =>
|
|
127
|
+
l.contains("3b: keyed reconnect of '$_keyed'") &&
|
|
128
|
+
l.contains('done')),
|
|
123
129
|
isTrue,
|
|
124
|
-
reason:
|
|
130
|
+
reason:
|
|
131
|
+
'the keyed reconnect phase must log its exit (the reported wedge)');
|
|
125
132
|
expect(h.sessions.toSet(), {'home', 'docs-ws', _keyed, 'reader'});
|
|
126
133
|
return h;
|
|
127
134
|
});
|
|
128
135
|
|
|
129
136
|
try {
|
|
130
|
-
// ── LEG 2: the blessed session-bound shape — mount → bind (preflight) →
|
|
131
|
-
// → follow(ref) → second client → typed read
|
|
137
|
+
// ── LEG 2: the blessed session-bound shape — mount → bind (preflight) → one business birth
|
|
138
|
+
// → follow(ref) → second client → typed read. Zero routing/security strings. ──
|
|
132
139
|
final home = harness.session('home');
|
|
133
|
-
final
|
|
134
|
-
'leg 2: blessed shape (bind →
|
|
140
|
+
final bornEstate = await _leg(
|
|
141
|
+
'leg 2: blessed shape (bind → business birth → follow → 2nd client → typed read)',
|
|
135
142
|
() async {
|
|
136
|
-
final homeClient = await
|
|
143
|
+
final homeClient = await Co2Client.bind(home, actor: _owner);
|
|
137
144
|
expect(homeClient.session!.workspace, home.workspace,
|
|
138
145
|
reason: 'inspectable session context');
|
|
139
|
-
final
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// era-0: the estate enrols the owner's device at birth (signer-ready) — the harness device.
|
|
146
|
-
ownerKeyHash: sha256.convert(base64Decode(harness.devicePublicKey(home.workspace)!)).toString(),
|
|
146
|
+
final ref = await homeClient.birth(
|
|
147
|
+
NomosBirthEstatePayload(
|
|
148
|
+
reference: 'E-001',
|
|
149
|
+
name: 'Foundry',
|
|
150
|
+
country: 'GB',
|
|
151
|
+
baselineTonnesCo2e: 4200,
|
|
147
152
|
),
|
|
148
153
|
);
|
|
149
|
-
expect(
|
|
150
|
-
|
|
151
|
-
expect(birth.born, hasLength(1));
|
|
152
|
-
expect(birth.birthOutcomes.first['status'], 'born');
|
|
154
|
+
expect(ref.workspace, startsWith('estate-'));
|
|
155
|
+
expect(ref.type, 'Estate');
|
|
153
156
|
|
|
154
|
-
final estateSession = await harness.bridge.follow(
|
|
155
|
-
|
|
157
|
+
final estateSession = await harness.bridge.follow(
|
|
158
|
+
ref,
|
|
159
|
+
authorSecret: harness.deviceSecret(home.workspace),
|
|
160
|
+
);
|
|
161
|
+
expect(estateSession.workspace, ref.workspace);
|
|
156
162
|
|
|
157
|
-
final estateClient = await
|
|
158
|
-
final rows = await estateClient.
|
|
159
|
-
expect(rows, hasLength(1),
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
bornAt: seeded.bornAt!,
|
|
165
|
-
));
|
|
166
|
-
expect(reseed.head, isNotEmpty, reason: 'a directive on the followed second client');
|
|
167
|
-
return estateSession;
|
|
163
|
+
final estateClient = await Co2Client.bind(estateSession, actor: _owner);
|
|
164
|
+
final rows = await estateClient.estateById(ref.id);
|
|
165
|
+
expect(rows, hasLength(1),
|
|
166
|
+
reason: 'the born business root reads back typed');
|
|
167
|
+
expect(rows.single.reference, 'E-001');
|
|
168
|
+
expect(rows.single.name, 'Foundry');
|
|
169
|
+
return (session: estateSession, ref: ref);
|
|
168
170
|
});
|
|
171
|
+
final estate = bornEstate.session;
|
|
169
172
|
|
|
170
173
|
// ── LEG 3: local posture — autoSync on a local-only session returns promptly and never
|
|
171
174
|
// monopolizes the plane; zero network fetch attempts (asserted again at the end). ──
|
|
172
|
-
await _leg(
|
|
175
|
+
await _leg(
|
|
176
|
+
'leg 3: local-only autoSync completes promptly, plane stays responsive',
|
|
173
177
|
() async {
|
|
174
178
|
await home.autoSync().timeout(const Duration(seconds: 10),
|
|
175
179
|
onTimeout: () => throw StateError(
|
|
176
180
|
'autoSync() on a local-only session did not return within 10s (the deadlock class)'));
|
|
177
181
|
// The plane is NOT blocked: a sibling session still answers.
|
|
178
|
-
final listed = await harness.bridge.listWorkspaces().timeout(
|
|
179
|
-
|
|
180
|
-
|
|
182
|
+
final listed = await harness.bridge.listWorkspaces().timeout(
|
|
183
|
+
const Duration(seconds: 10),
|
|
184
|
+
onTimeout: () => throw StateError(
|
|
185
|
+
'listWorkspaces() hung after a local-only autoSync'));
|
|
181
186
|
expect(listed.map((w) => w['session'].toString()).toSet(),
|
|
182
187
|
containsAll({'home', 'docs-ws', _keyed, 'reader'}));
|
|
183
188
|
await home.stopAutoSync().timeout(const Duration(seconds: 10),
|
|
184
|
-
onTimeout: () => throw StateError(
|
|
189
|
+
onTimeout: () => throw StateError(
|
|
190
|
+
'stopAutoSync() hung on a local-only session'));
|
|
185
191
|
});
|
|
186
192
|
|
|
187
193
|
// ── LEG 4: acquireSession — concurrent double-acquire single-flights to ONE handle; the
|
|
188
194
|
// credentials callback is NEVER invoked for a plane-known workspace. ──
|
|
189
|
-
await _leg(
|
|
195
|
+
await _leg(
|
|
196
|
+
'leg 4: acquireSession (concurrent, credential-free for a known workspace)',
|
|
190
197
|
() async {
|
|
191
198
|
final acquired = await Future.wait([
|
|
192
199
|
harness.bridge.acquireSession('reader',
|
|
193
|
-
ifAbsentCredentials: () async =>
|
|
194
|
-
|
|
200
|
+
ifAbsentCredentials: () async => fail(
|
|
201
|
+
'reader is on the plane — credentials must not be requested')),
|
|
195
202
|
harness.bridge.acquireSession('reader',
|
|
196
|
-
ifAbsentCredentials: () async =>
|
|
197
|
-
|
|
203
|
+
ifAbsentCredentials: () async => fail(
|
|
204
|
+
'reader is on the plane — credentials must not be requested')),
|
|
198
205
|
]);
|
|
199
206
|
expect(identical(acquired[0], acquired[1]), isTrue,
|
|
200
207
|
reason: 'a concurrent double-acquire yields ONE handle');
|
|
@@ -204,21 +211,22 @@ void main() {
|
|
|
204
211
|
|
|
205
212
|
// ── LEG 5: reactive reads on a SESSION — watchById / watch / watchPendingConflicts must
|
|
206
213
|
// all deliver a FIRST SNAPSHOT (the 0.48.x dead-delegation class). ──
|
|
207
|
-
await _leg('leg 5: session reactive reads emit their first snapshot',
|
|
208
|
-
|
|
214
|
+
await _leg('leg 5: session reactive reads emit their first snapshot',
|
|
215
|
+
() async {
|
|
216
|
+
final raw = await estate.queryById(bornEstate.ref.id);
|
|
209
217
|
final aggId = ((raw.single as Map)['id'] ?? '').toString();
|
|
210
218
|
expect(aggId, isNotEmpty);
|
|
211
|
-
final byId = await estate
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
onTimeout: () => throw StateError('watchById never emitted its first snapshot'));
|
|
219
|
+
final byId = await estate.watchById(aggId).first.timeout(
|
|
220
|
+
const Duration(seconds: 30),
|
|
221
|
+
onTimeout: () =>
|
|
222
|
+
throw StateError('watchById never emitted its first snapshot'));
|
|
216
223
|
expect(byId, hasLength(1));
|
|
217
224
|
final byQuery = await estate
|
|
218
|
-
.watch('
|
|
225
|
+
.watch('estatesByReference', {'reference': 'E-001'})
|
|
219
226
|
.first
|
|
220
227
|
.timeout(const Duration(seconds: 30),
|
|
221
|
-
onTimeout: () => throw StateError(
|
|
228
|
+
onTimeout: () => throw StateError(
|
|
229
|
+
'watch(query) never emitted its first snapshot'));
|
|
222
230
|
expect(byQuery, hasLength(1));
|
|
223
231
|
// The docs-ws session carries the Surfaced law — its pending-conflicts stream must emit a
|
|
224
232
|
// first snapshot (empty is correct; EMITTING at all is the regression under test).
|
|
@@ -234,10 +242,12 @@ void main() {
|
|
|
234
242
|
|
|
235
243
|
// ── LEG 6: the keyed lane end-to-end — an attested read served + SIGNED with the device
|
|
236
244
|
// key the 3b re-open installed. ──
|
|
237
|
-
await _leg('leg 6: attested read from the deviceKeyed workspace',
|
|
245
|
+
await _leg('leg 6: attested read from the deviceKeyed workspace',
|
|
246
|
+
() async {
|
|
238
247
|
final public = harness.devicePublicKey(_keyed);
|
|
239
248
|
expect(public, isNotNull);
|
|
240
|
-
expect(public, isNotEmpty,
|
|
249
|
+
expect(public, isNotEmpty,
|
|
250
|
+
reason: 'the 3b keygen public half rides the harness');
|
|
241
251
|
final cat = harness.session(_keyed);
|
|
242
252
|
final seeded = await cat.offerCreates(
|
|
243
253
|
domain: 'cat',
|
|
@@ -257,19 +267,23 @@ void main() {
|
|
|
257
267
|
args: {'listingId': 'L-1'},
|
|
258
268
|
);
|
|
259
269
|
final entry = (served['entry'] as Map).cast<String, Object?>();
|
|
260
|
-
final attestation =
|
|
270
|
+
final attestation =
|
|
271
|
+
(entry['attestation'] as Map).cast<String, Object?>();
|
|
261
272
|
expect((attestation['public_key'] ?? '').toString(), public,
|
|
262
273
|
reason: 'the read is signed by the re-opened session device key');
|
|
263
274
|
});
|
|
264
275
|
|
|
265
276
|
// ── LEG 7: harness diagnostics — assertDomainInstalled, resetWorkspaceCustody, and a
|
|
266
277
|
// mid-test seedWorkspaceFromDeployJson round-trip. ──
|
|
267
|
-
await _leg(
|
|
278
|
+
await _leg(
|
|
279
|
+
'leg 7: harness diagnostics (assertDomainInstalled / reset / seed)',
|
|
280
|
+
() async {
|
|
268
281
|
await harness.assertDomainInstalled(
|
|
269
|
-
workspace: estate.workspace, domain:
|
|
282
|
+
workspace: estate.workspace, domain: Co2Client.interface.domain);
|
|
270
283
|
// The negative arm names the active domains.
|
|
271
284
|
await expectLater(
|
|
272
|
-
harness.assertDomainInstalled(
|
|
285
|
+
harness.assertDomainInstalled(
|
|
286
|
+
workspace: 'docs-ws', domain: 'definitely-not-here'),
|
|
273
287
|
throwsA(isA<NomosTestHarnessException>()));
|
|
274
288
|
// Reset a workspace's local custody to its seed snapshot, then prove it still serves.
|
|
275
289
|
await harness.resetWorkspaceCustody('docs-ws');
|
|
@@ -278,23 +292,28 @@ void main() {
|
|
|
278
292
|
.watchPendingConflicts()
|
|
279
293
|
.first
|
|
280
294
|
.timeout(const Duration(seconds: 30),
|
|
281
|
-
onTimeout: () =>
|
|
282
|
-
|
|
283
|
-
expect(postReset, isEmpty,
|
|
295
|
+
onTimeout: () => throw StateError(
|
|
296
|
+
'the reset docs-ws session never served a read'));
|
|
297
|
+
expect(postReset, isEmpty,
|
|
298
|
+
reason: 'the reset workspace is back at its seed');
|
|
284
299
|
// Seed a brand-new workspace mid-test from a deploy.json and use it immediately.
|
|
285
300
|
final late = await harness.seedWorkspaceFromDeployJson(
|
|
286
301
|
workspace: 'late-ws', deployJsonPaths: [_docsDeploy]);
|
|
287
302
|
expect(late.workspace, 'late-ws');
|
|
288
|
-
await harness.assertDomainInstalled(
|
|
303
|
+
await harness.assertDomainInstalled(
|
|
304
|
+
workspace: 'late-ws', domain: 'docs');
|
|
289
305
|
});
|
|
290
306
|
|
|
291
307
|
// Local posture postscript (leg 3's zero-network promise, checked over the WHOLE run): no
|
|
292
308
|
// session on this plane ever attempted a network fetch.
|
|
293
309
|
final offending = diagnostics
|
|
294
|
-
.where((l) =>
|
|
310
|
+
.where((l) =>
|
|
311
|
+
l.contains('intent-offers') ||
|
|
312
|
+
l.contains('refusing network fetch'))
|
|
295
313
|
.toList();
|
|
296
314
|
expect(offending, isEmpty,
|
|
297
|
-
reason:
|
|
315
|
+
reason:
|
|
316
|
+
'local-only sessions must perform NO network work — saw:\n${offending.join('\n')}');
|
|
298
317
|
} finally {
|
|
299
318
|
// ── LEG 8: clean disposal within the deadline (a hung teardown is a failure, not a wedge). ──
|
|
300
319
|
await _leg('leg 8: harness disposal within the deadline', () async {
|
|
@@ -29,7 +29,7 @@ String? _missingPrereq() {
|
|
|
29
29
|
if (!File(_deployJson).existsSync()) {
|
|
30
30
|
return 'compile the fixture: (cd bench/scale/fixtures/estate-birth && node ../../../../dsl/compile_package.mjs)';
|
|
31
31
|
}
|
|
32
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync())
|
|
32
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync())
|
|
33
33
|
return 'warm ~/.holon/runtime first';
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
@@ -66,8 +66,10 @@ void main() {
|
|
|
66
66
|
);
|
|
67
67
|
expect(birth.born, hasLength(1));
|
|
68
68
|
|
|
69
|
-
// 3.
|
|
70
|
-
|
|
69
|
+
// 3. Infrastructure assertion: inspect Nomos's private birth record through the raw harness session.
|
|
70
|
+
// Generated tenant clients deliberately do not expose this framework query.
|
|
71
|
+
final before = await session
|
|
72
|
+
.query('birthRecordsByPrincipal', {'principal': _owner});
|
|
71
73
|
expect(before, hasLength(1),
|
|
72
74
|
reason: 'the offer must be readable BEFORE sync');
|
|
73
75
|
final statusBefore = await session.custodyStatus();
|
|
@@ -84,11 +86,14 @@ void main() {
|
|
|
84
86
|
expect(statusAfter.pendingLocalIntents, statusBefore.pendingLocalIntents,
|
|
85
87
|
reason:
|
|
86
88
|
'local-only sync must not consume/move pending local intents');
|
|
87
|
-
final after = await
|
|
89
|
+
final after = await session
|
|
90
|
+
.query('birthRecordsByPrincipal', {'principal': _owner});
|
|
88
91
|
expect(after, hasLength(1),
|
|
89
92
|
reason:
|
|
90
93
|
'local-only sync must be observationally inert — the row must still read');
|
|
91
|
-
|
|
94
|
+
final beforeData = ((before.single as Map)['data'] as Map);
|
|
95
|
+
final afterData = ((after.single as Map)['data'] as Map);
|
|
96
|
+
expect(afterData['principal'], beforeData['principal'],
|
|
92
97
|
reason: 'the SAME row, byte-for-byte semantics');
|
|
93
98
|
} finally {
|
|
94
99
|
await harness.dispose();
|
|
@@ -40,7 +40,7 @@ String? _missingPrereq() {
|
|
|
40
40
|
if (!File(_deploy).existsSync()) {
|
|
41
41
|
return 'compile the fixture: cd bench/scale/fixtures/estate-birth-signed && node ../../../../dsl/compile_package.mjs';
|
|
42
42
|
}
|
|
43
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync()) {
|
|
43
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync()) {
|
|
44
44
|
return 'warm ~/.holon/runtime first (run any `githolon` command once)';
|
|
45
45
|
}
|
|
46
46
|
return null;
|
|
@@ -34,7 +34,7 @@ String? _missingPrereq() {
|
|
|
34
34
|
if (!File(_deploy).existsSync() || !File(_lockfile).existsSync()) {
|
|
35
35
|
return 'missing encrypted-notes fixture — compile it: (cd cloud/web-client/test/fixtures/encrypted-notes && node ../../../../../dsl/compile_package.mjs)';
|
|
36
36
|
}
|
|
37
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync() ||
|
|
37
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
|
|
38
38
|
!File('$_runtimeDir/packages.json').existsSync()) {
|
|
39
39
|
return 'warm ~/.holon/runtime first (run any `githolon` command once)';
|
|
40
40
|
}
|
|
@@ -48,7 +48,7 @@ String? _missingPrereq() {
|
|
|
48
48
|
return 'compile the fixtures: (cd bench/scale/fixtures/estate-birth && node ../../../../dsl/compile_package.mjs); '
|
|
49
49
|
'(cd bench/scale/fixtures/surfaced && node ../../../../dsl/compile_package.mjs)';
|
|
50
50
|
}
|
|
51
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync() ||
|
|
51
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
|
|
52
52
|
!File('$_runtimeDir/packages.json').existsSync()) {
|
|
53
53
|
return 'warm ~/.holon/runtime first (run any `githolon` command once)';
|
|
54
54
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// the app UI uses, under `dart test` / `flutter test`, with no network.
|
|
5
5
|
//
|
|
6
6
|
// Prerequisites (skipped-with-reason when absent, so CI stays green either way): `node` on PATH; the
|
|
7
|
-
// in-repo runner; a warm `~/.holon/runtime` cache (holon.wasm + packages.json — one `githolon` run fills it);
|
|
7
|
+
// in-repo runner; a warm `~/.holon/runtime` cache (holon-testmint.wasm + packages.json — one `githolon` run fills it);
|
|
8
8
|
// and the compiled `examples/guestbook/build/guestbook.deploy.json` (`cd examples/guestbook && npx nomos-compile`).
|
|
9
9
|
@TestOn('vm')
|
|
10
10
|
library;
|
|
@@ -31,7 +31,7 @@ String? _missingPrereq() {
|
|
|
31
31
|
if (!File(_guestbookDeployJson).existsSync()) {
|
|
32
32
|
return 'compile the fixture first: cd examples/guestbook && npx nomos-compile';
|
|
33
33
|
}
|
|
34
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync() ||
|
|
34
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
|
|
35
35
|
!File('$_runtimeDir/packages.json').existsSync()) {
|
|
36
36
|
return 'warm ~/.holon/runtime first (run any `githolon` command once to cache the runtime)';
|
|
37
37
|
}
|
|
@@ -29,7 +29,7 @@ String? _missingPrereq() {
|
|
|
29
29
|
if (!File(_deployJson).existsSync()) {
|
|
30
30
|
return 'compile the fixture: cd bench/scale/fixtures/vo-read-typing && npx nomos-compile';
|
|
31
31
|
}
|
|
32
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync() ||
|
|
32
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
|
|
33
33
|
!File('$_runtimeDir/packages.json').existsSync()) {
|
|
34
34
|
return 'warm ~/.holon/runtime first (run any `githolon` command once)';
|
|
35
35
|
}
|
|
@@ -23,7 +23,7 @@ String? _missingPrereq() {
|
|
|
23
23
|
if (!File(_gbDeploy).existsSync()) {
|
|
24
24
|
return 'missing $_gbDeploy — compile it (cd examples/guestbook && npx nomos-compile)';
|
|
25
25
|
}
|
|
26
|
-
if (!File('$_runtimeDir/holon.wasm').existsSync() ||
|
|
26
|
+
if (!File('$_runtimeDir/holon-testmint.wasm').existsSync() ||
|
|
27
27
|
!File('$_runtimeDir/packages.json').existsSync()) {
|
|
28
28
|
return 'warm ~/.holon/runtime first (run any `githolon` command once)';
|
|
29
29
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@githolon/dsl",
|
|
3
|
-
"version": "0.100.
|
|
3
|
+
"version": "0.100.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|