@githolon/dsl 0.58.1 → 0.59.1
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 +3 -0
- package/dart/lib/nomos_client.dart +6 -14
- package/dart/lib/src/provider.dart +1 -1
- package/dart/lib/src/webview_bridge.dart +2 -175
- package/dart/lib/testing.dart +13 -0
- package/dart/pubspec.lock +7 -0
- package/dart/pubspec.yaml +5 -1
- package/dart/pubspec_overrides.yaml +7 -0
- package/dart_types/CHANGELOG.md +6 -0
- package/dart_types/LICENSE +45 -0
- package/dart_types/README.md +15 -0
- package/dart_types/lib/nomos_types.dart +29 -0
- package/dart_types/lib/src/error_info.dart +184 -0
- package/{dart → dart_types}/lib/src/errors.dart +1 -1
- package/dart_types/pubspec.lock +421 -0
- package/dart_types/pubspec.yaml +23 -0
- package/package.json +4 -1
- package/src/codegen_dart.ts +1 -1
- package/src/codegen_dart_client.ts +14 -4
- package/src/codegen_proof.ts +26 -19
- package/src/compile_package_main.ts +531 -110
- /package/{dart → dart_types}/lib/src/aggregate_meta.dart +0 -0
- /package/{dart → dart_types}/lib/src/driver.dart +0 -0
- /package/{dart → dart_types}/lib/src/null_slot.dart +0 -0
- /package/{dart → dart_types}/lib/src/offer.dart +0 -0
- /package/{dart → dart_types}/lib/src/schema_validation.dart +0 -0
- /package/{dart → dart_types}/lib/src/subscriptions.dart +0 -0
- /package/{dart → dart_types}/lib/src/wire.dart +0 -0
package/dart/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
## 0.38.0
|
|
2
|
+
- SPLIT: the pure data core (wire types, offer codec, NomosReads, aggregate meta, schema validation, error info) moved to the new `nomos_types` package; `nomos_client` depends on and re-exports it, so existing imports are unchanged. Frontend/UI code can now depend on `nomos_types` alone.
|
|
3
|
+
|
|
1
4
|
## 0.37.1
|
|
2
5
|
|
|
3
6
|
- Doc fix: `NomosBridge.attestedRead` docs now match the runtime — the call answers `{ entry: {queryId, result, attestation: …} }`; pass `result['entry']` as one `offerDirective` `attestations` element.
|
|
@@ -23,25 +23,17 @@
|
|
|
23
23
|
/// which re-exports this framework barrel PLUS every generated domain.
|
|
24
24
|
library;
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
export '
|
|
26
|
+
// THE PURE-DATA CORE — the hand-written kernel wire types, the `offer(intent)` codec,
|
|
27
|
+
// the tri-state `NomosSlot<T>`, `NomosReads`, schema validation, runtime aggregate
|
|
28
|
+
// metadata, the data-only error/trace types, and the typed diagnostics moved to the
|
|
29
|
+
// standalone `nomos_types` package (so generated per-domain TYPES files resolve against
|
|
30
|
+
// it alone). Re-exported here so this barrel's public API is unchanged for consumers.
|
|
31
|
+
export 'package:nomos_types/nomos_types.dart';
|
|
32
32
|
// homeNameOf(subject) — the canonical home-workspace name (parity with @githolon/client + the law side).
|
|
33
33
|
export 'src/home.dart';
|
|
34
|
-
export 'src/subscriptions.dart';
|
|
35
|
-
export 'src/schema_validation.dart';
|
|
36
|
-
// RUNTIME AGGREGATE METADATA — the generated per-domain registry's support types
|
|
37
|
-
// (lookup by aggregateType for generic surfaces: history UIs, op renderers, agents).
|
|
38
|
-
export 'src/aggregate_meta.dart';
|
|
39
34
|
// THE WEBVIEW BRIDGE (app-binding boundary) — the async Dart runtime that drives the REAL githolon running
|
|
40
35
|
// in a WebView, so the generated typed client never needs a `MemoryPersistence` fake.
|
|
41
36
|
export 'src/webview_bridge.dart';
|
|
42
|
-
// TYPED DIAGNOSTICS (co2 feedback req 7) — the fixed set of ways the home-birth ceremony can fail, each
|
|
43
|
-
// extending NomosBridgeError so existing handlers still catch them, named so the app can branch on `is`.
|
|
44
|
-
export 'src/errors.dart';
|
|
45
37
|
// The PROVIDER boundary (server-side capability-provider SDK runtime: TaskOutcome /
|
|
46
38
|
// TaskSuccess / TaskFailure / TaskResult / TaskProvider / HostClock). The symmetric twin
|
|
47
39
|
// of `offer.dart`; the generated per-task provider classes build on it.
|
|
@@ -31,7 +31,7 @@ library;
|
|
|
31
31
|
|
|
32
32
|
import 'dart:convert';
|
|
33
33
|
|
|
34
|
-
import '
|
|
34
|
+
import 'package:nomos_types/nomos_types.dart' show NomosIntent;
|
|
35
35
|
|
|
36
36
|
/// The typed OUTCOME a provider handler returns for one Obligation: success, failure, blocked,
|
|
37
37
|
/// or dead-lettered.
|
|
@@ -18,7 +18,8 @@ import 'dart:async';
|
|
|
18
18
|
import 'dart:convert';
|
|
19
19
|
import 'dart:math';
|
|
20
20
|
|
|
21
|
-
import '
|
|
21
|
+
import 'package:nomos_types/nomos_types.dart'
|
|
22
|
+
show nomosErrorFromInfo, NomosTraceContext, NomosErrorInfo;
|
|
22
23
|
|
|
23
24
|
/// The protocol version the runner and the bridge agree on (`webview-runner.mjs` `WEBVIEW_BRIDGE_VERSION`).
|
|
24
25
|
const int kWebviewBridgeVersion = 1;
|
|
@@ -31,180 +32,6 @@ abstract interface class BridgeTransport {
|
|
|
31
32
|
Stream<Map<String, Object?>> get messages;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
/// Trace/span context carried over the bridge as plain JSON. It is intentionally OpenTelemetry-shaped without
|
|
35
|
-
/// importing an OTel SDK: apps can map it to spans later, while Nomos stays dependency-light at the runtime edge.
|
|
36
|
-
class NomosTraceContext {
|
|
37
|
-
final String? traceId;
|
|
38
|
-
final String? spanId;
|
|
39
|
-
final String? parentSpanId;
|
|
40
|
-
final bool? sampled;
|
|
41
|
-
|
|
42
|
-
const NomosTraceContext({
|
|
43
|
-
this.traceId,
|
|
44
|
-
this.spanId,
|
|
45
|
-
this.parentSpanId,
|
|
46
|
-
this.sampled,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
factory NomosTraceContext.fromJson(Object? value) {
|
|
50
|
-
if (value is! Map) return const NomosTraceContext();
|
|
51
|
-
final m = value.cast<String, Object?>();
|
|
52
|
-
return NomosTraceContext(
|
|
53
|
-
traceId: m['traceId']?.toString(),
|
|
54
|
-
spanId: m['spanId']?.toString(),
|
|
55
|
-
parentSpanId: m['parentSpanId']?.toString(),
|
|
56
|
-
sampled: m['sampled'] is bool ? m['sampled'] as bool : null,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
Map<String, Object?> toJson() => {
|
|
61
|
-
if (traceId != null) 'traceId': traceId,
|
|
62
|
-
if (spanId != null) 'spanId': spanId,
|
|
63
|
-
if (parentSpanId != null) 'parentSpanId': parentSpanId,
|
|
64
|
-
if (sampled != null) 'sampled': sampled,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
bool get isEmpty =>
|
|
68
|
-
traceId == null &&
|
|
69
|
-
spanId == null &&
|
|
70
|
-
parentSpanId == null &&
|
|
71
|
-
sampled == null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/// Structured runtime error detail for the bridge boundary. Keep this data-only: it is safe to serialize, log,
|
|
75
|
-
/// persist, or later attach to an OpenTelemetry span without importing tracing into the core client package.
|
|
76
|
-
class NomosErrorInfo {
|
|
77
|
-
final String code;
|
|
78
|
-
final String message;
|
|
79
|
-
final String component;
|
|
80
|
-
final String? operation;
|
|
81
|
-
final String? workspace;
|
|
82
|
-
final String? domain;
|
|
83
|
-
final String? directiveId;
|
|
84
|
-
final NomosTraceContext trace;
|
|
85
|
-
final Map<String, Object?> attributes;
|
|
86
|
-
final NomosErrorInfo? cause;
|
|
87
|
-
|
|
88
|
-
const NomosErrorInfo({
|
|
89
|
-
required this.code,
|
|
90
|
-
required this.message,
|
|
91
|
-
this.component = 'nomos.client',
|
|
92
|
-
this.operation,
|
|
93
|
-
this.workspace,
|
|
94
|
-
this.domain,
|
|
95
|
-
this.directiveId,
|
|
96
|
-
this.trace = const NomosTraceContext(),
|
|
97
|
-
this.attributes = const {},
|
|
98
|
-
this.cause,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
factory NomosErrorInfo.legacy(
|
|
102
|
-
Object? message, {
|
|
103
|
-
String code = 'nomos.bridge.error',
|
|
104
|
-
String component = 'nomos.client',
|
|
105
|
-
String? operation,
|
|
106
|
-
NomosTraceContext trace = const NomosTraceContext(),
|
|
107
|
-
}) {
|
|
108
|
-
return NomosErrorInfo(
|
|
109
|
-
code: code,
|
|
110
|
-
message: (message ?? 'the githolon refused the request').toString(),
|
|
111
|
-
component: component,
|
|
112
|
-
operation: operation,
|
|
113
|
-
trace: trace,
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
factory NomosErrorInfo.fromJson(
|
|
118
|
-
Object? value, {
|
|
119
|
-
Object? fallbackMessage,
|
|
120
|
-
String? fallbackOperation,
|
|
121
|
-
NomosTraceContext fallbackTrace = const NomosTraceContext(),
|
|
122
|
-
}) {
|
|
123
|
-
if (value is! Map) {
|
|
124
|
-
return NomosErrorInfo.legacy(
|
|
125
|
-
fallbackMessage,
|
|
126
|
-
operation: fallbackOperation,
|
|
127
|
-
trace: fallbackTrace,
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
final m = value.cast<String, Object?>();
|
|
131
|
-
final trace = NomosTraceContext.fromJson(m['trace']);
|
|
132
|
-
return NomosErrorInfo(
|
|
133
|
-
code: (m['code'] ?? 'nomos.bridge.error').toString(),
|
|
134
|
-
message: (m['message'] ??
|
|
135
|
-
fallbackMessage ??
|
|
136
|
-
'the githolon refused the request')
|
|
137
|
-
.toString(),
|
|
138
|
-
component: (m['component'] ?? 'nomos.client').toString(),
|
|
139
|
-
operation: m['operation']?.toString() ?? fallbackOperation,
|
|
140
|
-
workspace: m['workspace']?.toString(),
|
|
141
|
-
domain: m['domain']?.toString(),
|
|
142
|
-
directiveId: m['directiveId']?.toString(),
|
|
143
|
-
trace: trace.isEmpty ? fallbackTrace : trace,
|
|
144
|
-
attributes:
|
|
145
|
-
((m['attributes'] as Map?)?.cast<String, Object?>()) ?? const {},
|
|
146
|
-
cause: m['cause'] == null
|
|
147
|
-
? null
|
|
148
|
-
: NomosErrorInfo.fromJson(m['cause'],
|
|
149
|
-
fallbackOperation: fallbackOperation),
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
factory NomosErrorInfo.fromBridgeMessage(
|
|
154
|
-
Map<String, Object?> message, {
|
|
155
|
-
String? fallbackOperation,
|
|
156
|
-
NomosTraceContext fallbackTrace = const NomosTraceContext(),
|
|
157
|
-
Object? fallbackMessage,
|
|
158
|
-
}) {
|
|
159
|
-
return NomosErrorInfo.fromJson(
|
|
160
|
-
message['errorInfo'],
|
|
161
|
-
fallbackMessage: message['error'] ?? fallbackMessage,
|
|
162
|
-
fallbackOperation: fallbackOperation,
|
|
163
|
-
fallbackTrace: fallbackTrace,
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
Map<String, Object?> toJson() => {
|
|
168
|
-
'code': code,
|
|
169
|
-
'message': message,
|
|
170
|
-
'component': component,
|
|
171
|
-
if (operation != null) 'operation': operation,
|
|
172
|
-
if (workspace != null) 'workspace': workspace,
|
|
173
|
-
if (domain != null) 'domain': domain,
|
|
174
|
-
if (directiveId != null) 'directiveId': directiveId,
|
|
175
|
-
if (!trace.isEmpty) 'trace': trace.toJson(),
|
|
176
|
-
if (attributes.isNotEmpty) 'attributes': attributes,
|
|
177
|
-
if (cause != null) 'cause': cause!.toJson(),
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/// Attribute map suitable for attaching to a future OTel span/event. The keys are stable and low-cardinality
|
|
181
|
-
/// where possible; high-cardinality values stay explicit (`workspace`, `domain`, directive) so apps can redact.
|
|
182
|
-
Map<String, Object?> toTelemetryAttributes() => {
|
|
183
|
-
'exception.type': code,
|
|
184
|
-
'exception.message': message,
|
|
185
|
-
'nomos.error.code': code,
|
|
186
|
-
'nomos.component': component,
|
|
187
|
-
if (operation != null) 'nomos.operation': operation,
|
|
188
|
-
if (workspace != null) 'nomos.workspace': workspace,
|
|
189
|
-
if (domain != null) 'nomos.domain': domain,
|
|
190
|
-
if (directiveId != null) 'nomos.directive_id': directiveId,
|
|
191
|
-
if (trace.traceId != null) 'trace_id': trace.traceId,
|
|
192
|
-
if (trace.spanId != null) 'span_id': trace.spanId,
|
|
193
|
-
...attributes,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/// A typed refusal surfaced from the githolon's gate (a law refusal, a drift, a malformed op). Carries the
|
|
198
|
-
/// human-first message verbatim plus structured detail for logging, UI mapping, and future OTel export.
|
|
199
|
-
class NomosBridgeError implements Exception {
|
|
200
|
-
final String message;
|
|
201
|
-
final NomosErrorInfo info;
|
|
202
|
-
NomosBridgeError(this.message, {NomosErrorInfo? info})
|
|
203
|
-
: info = info ?? NomosErrorInfo.legacy(message);
|
|
204
|
-
@override
|
|
205
|
-
String toString() => 'NomosBridgeError: $message';
|
|
206
|
-
}
|
|
207
|
-
|
|
208
35
|
/// Live byte-progress of a custody pack transfer (the big initial clone / heavy resync over `/pack`).
|
|
209
36
|
/// [total] is the host's REAL packed size from `Content-Length` (known before the first body byte — the
|
|
210
37
|
/// warm host packs into memory then sends), so [fraction] is a truthful 0→1 bar, never an estimate.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
2
|
+
// remotes are replaceable custody/transport, not truth.
|
|
3
|
+
//
|
|
4
|
+
/// The TEST-ONLY entrypoint (`package:nomos_client/testing.dart`) — the headless harness
|
|
5
|
+
/// (NomosTestHarness drives the REAL githolon under `dart test`, no WebView) and the
|
|
6
|
+
/// node-runner transport it rides. Depend on this ONLY from `dev_dependencies`-scoped
|
|
7
|
+
/// packages: it pulls `dart:io` and process management, which never belong in app code.
|
|
8
|
+
/// The layered-packages emit (`dart.packages.test`) re-exports this as the generated
|
|
9
|
+
/// test package's harness surface.
|
|
10
|
+
library;
|
|
11
|
+
|
|
12
|
+
export 'src/node_runner_transport.dart';
|
|
13
|
+
export 'src/test_harness.dart';
|
package/dart/pubspec.lock
CHANGED
|
@@ -185,6 +185,13 @@ packages:
|
|
|
185
185
|
url: "https://pub.dev"
|
|
186
186
|
source: hosted
|
|
187
187
|
version: "2.0.2"
|
|
188
|
+
nomos_types:
|
|
189
|
+
dependency: "direct main"
|
|
190
|
+
description:
|
|
191
|
+
path: "../dart_types"
|
|
192
|
+
relative: true
|
|
193
|
+
source: path
|
|
194
|
+
version: "0.1.0"
|
|
188
195
|
package_config:
|
|
189
196
|
dependency: transitive
|
|
190
197
|
description:
|
package/dart/pubspec.yaml
CHANGED
|
@@ -11,12 +11,16 @@ description: >-
|
|
|
11
11
|
Nomos 2 Dart frontend types — the hand-written kernel wire types plus the
|
|
12
12
|
code-generated per-domain aggregate + directive-payload types. (De)serializes
|
|
13
13
|
the EXACT serde JSON the Rust kernel + projection produce/consume.
|
|
14
|
-
version: 0.
|
|
14
|
+
version: 0.38.0
|
|
15
15
|
|
|
16
16
|
environment:
|
|
17
17
|
sdk: ^3.5.0
|
|
18
18
|
|
|
19
19
|
dependencies:
|
|
20
|
+
# The pure-data core (wire types, offer codec, NomosReads, schema validation, error
|
|
21
|
+
# info). nomos_client depends on and re-exports it, so existing imports are unchanged.
|
|
22
|
+
# For local monorepo dev, pubspec_overrides.yaml points this at ../dart_types.
|
|
23
|
+
nomos_types: ^0.1.0
|
|
20
24
|
json_schema: ^5.2.2
|
|
21
25
|
crypto: ^3.0.0
|
|
22
26
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# IN-REPO RESOLUTION: nomos_types lives in this monorepo (dsl/dart_types) and is not yet on
|
|
2
|
+
# pub.dev — this override makes `dart pub get` resolve it from source for everyone cloning the
|
|
3
|
+
# repo. Once nomos_types is published, consumers outside the repo resolve the hosted ^0.1.0;
|
|
4
|
+
# this file only affects in-repo development.
|
|
5
|
+
dependency_overrides:
|
|
6
|
+
nomos_types:
|
|
7
|
+
path: ../dart_types
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
## 0.1.0
|
|
2
|
+
- Initial release. The pure-data core split out of `nomos_client`: kernel wire types,
|
|
3
|
+
the offer codec, `NomosReads`, the tri-state `NomosSlot`, aggregate metadata, schema
|
|
4
|
+
validation, and the data-only error/trace types (`NomosBridgeError`, `NomosErrorInfo`,
|
|
5
|
+
`NomosTraceContext`) plus the typed diagnostics. No transport, no bridge, no runtime —
|
|
6
|
+
generated per-domain TYPES files depend on only this.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Nomos Pre-Release License (v1)
|
|
2
|
+
|
|
3
|
+
Copyright © 2026 Captain App Ltd. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This is a pre-release of Nomos. This license gives you what you need to BUILD
|
|
6
|
+
with it; we keep the rest for now.
|
|
7
|
+
|
|
8
|
+
## You may
|
|
9
|
+
|
|
10
|
+
- install and use these packages to author Nomos domains, compile them, and
|
|
11
|
+
deploy them to Nomos Cloud or any Nomos instance Captain App operates or
|
|
12
|
+
authorizes;
|
|
13
|
+
- build, run, and ship applications on top of them — including commercial ones;
|
|
14
|
+
- keep everything that's yours: code you write, and everything these tools
|
|
15
|
+
generate FOR you (scaffolds from `create-githolon` / `githolon generate`, generated
|
|
16
|
+
clients, compiled domain packages) carries NO restriction from us — it is
|
|
17
|
+
yours outright.
|
|
18
|
+
|
|
19
|
+
## You may not
|
|
20
|
+
|
|
21
|
+
- redistribute these packages or their source, in whole or in part, outside
|
|
22
|
+
your team;
|
|
23
|
+
- modify them or build derivative tools, SDKs, or runtimes from their source;
|
|
24
|
+
- offer the Nomos runtime, or anything materially similar, as a hosted service;
|
|
25
|
+
- reverse-engineer the holon wasm runtime.
|
|
26
|
+
|
|
27
|
+
## Data retention
|
|
28
|
+
|
|
29
|
+
This is a pre-release we are actively evaluating. Workspaces you retire stop
|
|
30
|
+
counting toward your quota but are NOT deleted: **we retain all workspace data
|
|
31
|
+
(ledgers, law, intents) and may examine it to evaluate how the product is
|
|
32
|
+
used.** Don't put anything in a pre-release workspace you wouldn't want the
|
|
33
|
+
builders to read. If you need something truly expunged, ask:
|
|
34
|
+
jack@captainapp.co.uk.
|
|
35
|
+
|
|
36
|
+
## The rest
|
|
37
|
+
|
|
38
|
+
Provided **as is**, with no warranty of any kind; to the maximum extent
|
|
39
|
+
permitted by law, Captain App Ltd accepts no liability arising from your use.
|
|
40
|
+
This license terminates automatically if you breach it.
|
|
41
|
+
|
|
42
|
+
Want the kernel source, broader rights, or to do something this doesn't cover?
|
|
43
|
+
**Ask: jack@captainapp.co.uk.** The plan is to open Nomos up gradually, with
|
|
44
|
+
the people actually using it — telling us what you're building is how that
|
|
45
|
+
happens faster.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# nomos_types
|
|
2
|
+
|
|
3
|
+
The pure data core for Nomos Dart frontends — kernel wire types, the offer codec,
|
|
4
|
+
the `NomosReads` typed-read seam, aggregate metadata, schema validation, and the
|
|
5
|
+
structured error surface. **No transport, no bridge, no runtime**: this package is
|
|
6
|
+
safe to depend on from UI code.
|
|
7
|
+
|
|
8
|
+
It is the foundation of the Nomos layered-packages emit (`dart.packages` in
|
|
9
|
+
`nomos-compile`): generated per-domain TYPES packages depend only on `nomos_types`,
|
|
10
|
+
while the effectful runtime rides `nomos_client` (which depends on and re-exports
|
|
11
|
+
this package). The layering line: generated types may flow to the UI; generated
|
|
12
|
+
clients/runtime may not.
|
|
13
|
+
|
|
14
|
+
Part of [Nomos](https://github.com/Captain-App/nomos2) — a local-first domain
|
|
15
|
+
runtime where every peer runs the same deterministic wasm holon.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
2
|
+
// remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
3
|
+
// wasm32-wasip1 artifact {kernel · projection · embedded QuickJS engine}.
|
|
4
|
+
// If a file isn't this / hosting this / authoring for this / proving this — it's gone.
|
|
5
|
+
|
|
6
|
+
/// Nomos 2 pure-data core — the hand-written kernel WIRE/data types with NO transport,
|
|
7
|
+
/// NO bridge, NO runtime, NO Flutter. Generated per-domain TYPES files depend on ONLY
|
|
8
|
+
/// this, so they resolve without pulling in sessions/workspace lifecycle. The
|
|
9
|
+
/// `nomos_client` package depends on and re-exports this barrel, so existing
|
|
10
|
+
/// `package:nomos_client/nomos_client.dart` imports are unchanged.
|
|
11
|
+
///
|
|
12
|
+
/// - The kernel WIRE types (`Value`, `Field`/`WireField`, `Hlc`, `Op`, `FieldOp`,
|
|
13
|
+
/// `Event`, `Schema`/`WireDriver`) — byte-compatible with serde_json.
|
|
14
|
+
/// - The ONE effectful write verb `offer(intent)` + the typed reactive read engine
|
|
15
|
+
/// `NomosReads`.
|
|
16
|
+
/// - The tri-state `NomosSlot<T>`, runtime aggregate metadata, schema validation, and
|
|
17
|
+
/// the data-only error/trace types (`NomosBridgeError`, `NomosErrorInfo`,
|
|
18
|
+
/// `NomosTraceContext`) plus the typed diagnostics.
|
|
19
|
+
library;
|
|
20
|
+
|
|
21
|
+
export 'src/wire.dart';
|
|
22
|
+
export 'src/driver.dart';
|
|
23
|
+
export 'src/offer.dart';
|
|
24
|
+
export 'src/null_slot.dart';
|
|
25
|
+
export 'src/subscriptions.dart';
|
|
26
|
+
export 'src/schema_validation.dart';
|
|
27
|
+
export 'src/aggregate_meta.dart';
|
|
28
|
+
export 'src/error_info.dart';
|
|
29
|
+
export 'src/errors.dart';
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
2
|
+
// remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
3
|
+
// wasm32-wasip1 artifact {kernel · projection · embedded QuickJS engine}.
|
|
4
|
+
// If a file isn't this / hosting this / authoring for this / proving this — it's gone.
|
|
5
|
+
|
|
6
|
+
/// Data-only error/trace types for the bridge boundary. These carry NO transport, NO
|
|
7
|
+
/// bridge, NO runtime — they are pure serializable value types, so they live in
|
|
8
|
+
/// `nomos_types` and are safe to depend on from generated types files + UI code. The
|
|
9
|
+
/// async [NomosBridge] runtime (in `nomos_client`'s `webview_bridge.dart`) builds on them.
|
|
10
|
+
library;
|
|
11
|
+
|
|
12
|
+
/// Trace/span context carried over the bridge as plain JSON. It is intentionally OpenTelemetry-shaped without
|
|
13
|
+
/// importing an OTel SDK: apps can map it to spans later, while Nomos stays dependency-light at the runtime edge.
|
|
14
|
+
class NomosTraceContext {
|
|
15
|
+
final String? traceId;
|
|
16
|
+
final String? spanId;
|
|
17
|
+
final String? parentSpanId;
|
|
18
|
+
final bool? sampled;
|
|
19
|
+
|
|
20
|
+
const NomosTraceContext({
|
|
21
|
+
this.traceId,
|
|
22
|
+
this.spanId,
|
|
23
|
+
this.parentSpanId,
|
|
24
|
+
this.sampled,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
factory NomosTraceContext.fromJson(Object? value) {
|
|
28
|
+
if (value is! Map) return const NomosTraceContext();
|
|
29
|
+
final m = value.cast<String, Object?>();
|
|
30
|
+
return NomosTraceContext(
|
|
31
|
+
traceId: m['traceId']?.toString(),
|
|
32
|
+
spanId: m['spanId']?.toString(),
|
|
33
|
+
parentSpanId: m['parentSpanId']?.toString(),
|
|
34
|
+
sampled: m['sampled'] is bool ? m['sampled'] as bool : null,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Map<String, Object?> toJson() => {
|
|
39
|
+
if (traceId != null) 'traceId': traceId,
|
|
40
|
+
if (spanId != null) 'spanId': spanId,
|
|
41
|
+
if (parentSpanId != null) 'parentSpanId': parentSpanId,
|
|
42
|
+
if (sampled != null) 'sampled': sampled,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
bool get isEmpty =>
|
|
46
|
+
traceId == null &&
|
|
47
|
+
spanId == null &&
|
|
48
|
+
parentSpanId == null &&
|
|
49
|
+
sampled == null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Structured runtime error detail for the bridge boundary. Keep this data-only: it is safe to serialize, log,
|
|
53
|
+
/// persist, or later attach to an OpenTelemetry span without importing tracing into the core client package.
|
|
54
|
+
class NomosErrorInfo {
|
|
55
|
+
final String code;
|
|
56
|
+
final String message;
|
|
57
|
+
final String component;
|
|
58
|
+
final String? operation;
|
|
59
|
+
final String? workspace;
|
|
60
|
+
final String? domain;
|
|
61
|
+
final String? directiveId;
|
|
62
|
+
final NomosTraceContext trace;
|
|
63
|
+
final Map<String, Object?> attributes;
|
|
64
|
+
final NomosErrorInfo? cause;
|
|
65
|
+
|
|
66
|
+
const NomosErrorInfo({
|
|
67
|
+
required this.code,
|
|
68
|
+
required this.message,
|
|
69
|
+
this.component = 'nomos.client',
|
|
70
|
+
this.operation,
|
|
71
|
+
this.workspace,
|
|
72
|
+
this.domain,
|
|
73
|
+
this.directiveId,
|
|
74
|
+
this.trace = const NomosTraceContext(),
|
|
75
|
+
this.attributes = const {},
|
|
76
|
+
this.cause,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
factory NomosErrorInfo.legacy(
|
|
80
|
+
Object? message, {
|
|
81
|
+
String code = 'nomos.bridge.error',
|
|
82
|
+
String component = 'nomos.client',
|
|
83
|
+
String? operation,
|
|
84
|
+
NomosTraceContext trace = const NomosTraceContext(),
|
|
85
|
+
}) {
|
|
86
|
+
return NomosErrorInfo(
|
|
87
|
+
code: code,
|
|
88
|
+
message: (message ?? 'the githolon refused the request').toString(),
|
|
89
|
+
component: component,
|
|
90
|
+
operation: operation,
|
|
91
|
+
trace: trace,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
factory NomosErrorInfo.fromJson(
|
|
96
|
+
Object? value, {
|
|
97
|
+
Object? fallbackMessage,
|
|
98
|
+
String? fallbackOperation,
|
|
99
|
+
NomosTraceContext fallbackTrace = const NomosTraceContext(),
|
|
100
|
+
}) {
|
|
101
|
+
if (value is! Map) {
|
|
102
|
+
return NomosErrorInfo.legacy(
|
|
103
|
+
fallbackMessage,
|
|
104
|
+
operation: fallbackOperation,
|
|
105
|
+
trace: fallbackTrace,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
final m = value.cast<String, Object?>();
|
|
109
|
+
final trace = NomosTraceContext.fromJson(m['trace']);
|
|
110
|
+
return NomosErrorInfo(
|
|
111
|
+
code: (m['code'] ?? 'nomos.bridge.error').toString(),
|
|
112
|
+
message: (m['message'] ??
|
|
113
|
+
fallbackMessage ??
|
|
114
|
+
'the githolon refused the request')
|
|
115
|
+
.toString(),
|
|
116
|
+
component: (m['component'] ?? 'nomos.client').toString(),
|
|
117
|
+
operation: m['operation']?.toString() ?? fallbackOperation,
|
|
118
|
+
workspace: m['workspace']?.toString(),
|
|
119
|
+
domain: m['domain']?.toString(),
|
|
120
|
+
directiveId: m['directiveId']?.toString(),
|
|
121
|
+
trace: trace.isEmpty ? fallbackTrace : trace,
|
|
122
|
+
attributes:
|
|
123
|
+
((m['attributes'] as Map?)?.cast<String, Object?>()) ?? const {},
|
|
124
|
+
cause: m['cause'] == null
|
|
125
|
+
? null
|
|
126
|
+
: NomosErrorInfo.fromJson(m['cause'],
|
|
127
|
+
fallbackOperation: fallbackOperation),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
factory NomosErrorInfo.fromBridgeMessage(
|
|
132
|
+
Map<String, Object?> message, {
|
|
133
|
+
String? fallbackOperation,
|
|
134
|
+
NomosTraceContext fallbackTrace = const NomosTraceContext(),
|
|
135
|
+
Object? fallbackMessage,
|
|
136
|
+
}) {
|
|
137
|
+
return NomosErrorInfo.fromJson(
|
|
138
|
+
message['errorInfo'],
|
|
139
|
+
fallbackMessage: message['error'] ?? fallbackMessage,
|
|
140
|
+
fallbackOperation: fallbackOperation,
|
|
141
|
+
fallbackTrace: fallbackTrace,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
Map<String, Object?> toJson() => {
|
|
146
|
+
'code': code,
|
|
147
|
+
'message': message,
|
|
148
|
+
'component': component,
|
|
149
|
+
if (operation != null) 'operation': operation,
|
|
150
|
+
if (workspace != null) 'workspace': workspace,
|
|
151
|
+
if (domain != null) 'domain': domain,
|
|
152
|
+
if (directiveId != null) 'directiveId': directiveId,
|
|
153
|
+
if (!trace.isEmpty) 'trace': trace.toJson(),
|
|
154
|
+
if (attributes.isNotEmpty) 'attributes': attributes,
|
|
155
|
+
if (cause != null) 'cause': cause!.toJson(),
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/// Attribute map suitable for attaching to a future OTel span/event. The keys are stable and low-cardinality
|
|
159
|
+
/// where possible; high-cardinality values stay explicit (`workspace`, `domain`, directive) so apps can redact.
|
|
160
|
+
Map<String, Object?> toTelemetryAttributes() => {
|
|
161
|
+
'exception.type': code,
|
|
162
|
+
'exception.message': message,
|
|
163
|
+
'nomos.error.code': code,
|
|
164
|
+
'nomos.component': component,
|
|
165
|
+
if (operation != null) 'nomos.operation': operation,
|
|
166
|
+
if (workspace != null) 'nomos.workspace': workspace,
|
|
167
|
+
if (domain != null) 'nomos.domain': domain,
|
|
168
|
+
if (directiveId != null) 'nomos.directive_id': directiveId,
|
|
169
|
+
if (trace.traceId != null) 'trace_id': trace.traceId,
|
|
170
|
+
if (trace.spanId != null) 'span_id': trace.spanId,
|
|
171
|
+
...attributes,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// A typed refusal surfaced from the githolon's gate (a law refusal, a drift, a malformed op). Carries the
|
|
176
|
+
/// human-first message verbatim plus structured detail for logging, UI mapping, and future OTel export.
|
|
177
|
+
class NomosBridgeError implements Exception {
|
|
178
|
+
final String message;
|
|
179
|
+
final NomosErrorInfo info;
|
|
180
|
+
NomosBridgeError(this.message, {NomosErrorInfo? info})
|
|
181
|
+
: info = info ?? NomosErrorInfo.legacy(message);
|
|
182
|
+
@override
|
|
183
|
+
String toString() => 'NomosBridgeError: $message';
|
|
184
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
/// All extend [NomosBridgeError] so existing `catch (NomosBridgeError)` handlers still catch them.
|
|
15
15
|
library;
|
|
16
16
|
|
|
17
|
-
import '
|
|
17
|
+
import 'error_info.dart' show NomosBridgeError, NomosErrorInfo;
|
|
18
18
|
|
|
19
19
|
/// Mint the MOST SPECIFIC typed error for a structured refusal — the one construction point the bridge
|
|
20
20
|
/// uses everywhere it surfaces an `errorInfo`. A `nomos.custody.*` code becomes a [CustodyError] (typed,
|