@githolon/dsl 0.102.5 → 0.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compile_package.mjs +43 -2
- package/compile_proof.d.mts +47 -0
- package/compile_proof.mjs +343 -0
- package/dart/CHANGELOG.md +7 -0
- package/dart/lib/src/dev_cloud.dart +8 -8
- package/dart/lib/src/nms_generated_runtime.dart +2 -0
- package/dart/lib/src/runner/node-entry.mjs +5504 -1236
- package/dart/lib/src/runner/offline-install.mjs +4578 -528
- package/dart/lib/src/test_harness.dart +206 -152
- package/dart/lib/src/webview_bridge.dart +196 -89
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +2 -2
- package/dart/test/acquire_session_credentials_test.dart +4 -3
- package/dart/test/adv_realm_interference_test.dart +7 -6
- package/dart/test/cloud_bound_topology_test.dart +3 -3
- package/dart/test/cluster_births_test.dart +4 -3
- package/dart/test/cluster_device_keyed_acceptance_test.dart +10 -16
- package/dart/test/cluster_local_autosync_test.dart +3 -2
- package/dart/test/cluster_scale_test.dart +3 -2
- package/dart/test/dlq_session_surface_test.dart +7 -6
- package/dart/test/first_app_gauntlet_test.dart +14 -21
- package/dart/test/fixtures/wedge/fake-install.mjs +1 -1
- package/dart/test/four_layer_nested_topology_test.dart +4 -4
- package/dart/test/harness_phase_timeout_test.dart +2 -2
- package/dart/test/local_sync_inert_test.dart +1 -1
- package/dart/test/parent_signer_recovery_test.dart +2 -2
- package/dart/test/sealing_client_test.dart +4 -3
- package/dart/test/session_bound_test.dart +8 -7
- package/dart/test/test_harness_test.dart +13 -12
- package/dart/test/vo_read_typing_test.dart +4 -3
- package/dart/test/watch_after_offer_stall_test.dart +4 -3
- package/dart/test/webview_bridge_test.dart +102 -5
- package/dart_types/CHANGELOG.md +5 -0
- package/dart_types/lib/nomos_types.dart +9 -0
- package/dart_types/lib/src/nomos_ref.dart +20 -0
- package/dart_types/lib/src/optional_ref.dart +85 -0
- package/dart_types/lib/src/sha256_digest.dart +41 -0
- package/dart_types/lib/src/versioned_nomos_ref.dart +81 -0
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/optional_ref_test.dart +44 -0
- package/dart_types/test/sha256_digest_test.dart +18 -0
- package/package.json +9 -5
- package/runtime/generated-application-host.js +5365 -1105
- package/src/aggregate.ts +18 -0
- package/src/application_composition.ts +6 -32
- package/src/attested_core.ts +6 -3
- package/src/birth_meter.ts +1 -0
- package/src/birth_meter_ensure.ts +28 -2
- package/src/births.ts +1 -1
- package/src/build_package.ts +162 -538
- package/src/business_birth.ts +19 -3
- package/src/canonical_json.ts +21 -0
- package/src/check_package_main.ts +73 -33
- package/src/clear_directive.ts +19 -8
- package/src/codegen_dart.ts +305 -22
- package/src/codegen_dart_application.ts +844 -292
- package/src/codegen_dart_client.ts +1084 -407
- package/src/codegen_dart_scenario.ts +12 -12
- package/src/codegen_proof.ts +169 -39
- package/src/codegen_provider_dart.ts +17 -1
- package/src/codegen_ts.ts +298 -106
- package/src/compat_manifest.ts +2 -2
- package/src/compat_package_main.ts +8 -12
- package/src/compile_package_main.ts +1858 -590
- package/src/compose.ts +1 -1
- package/src/directive.ts +208 -15
- package/src/engine_entry.ts +165 -111
- package/src/evolve_preview.ts +29 -69
- package/src/extremum.ts +1 -1
- package/src/fields.ts +183 -4
- package/src/flow_gate.ts +75 -2
- package/src/framework/application_home.ts +2 -0
- package/src/framework/auth_provider_law.ts +2 -2
- package/src/framework/birth_meter.ts +7 -19
- package/src/framework/bootstrap.ts +0 -2
- package/src/framework/business_corrections.ts +9 -5
- package/src/framework/domain_lifecycle.ts +15 -29
- package/src/framework/encryption_scope.ts +2 -1
- package/src/framework/framework_aggregates.ts +2 -0
- package/src/framework/genesis.ts +16 -14
- package/src/framework/home.ts +20 -14
- package/src/framework/owned_custody.ts +9 -3
- package/src/framework/platform_admin.ts +3 -3
- package/src/framework/relations.ts +21 -13
- package/src/framework/signing_identity.ts +45 -40
- package/src/framework/workspace_invariant.ts +245 -0
- package/src/framework/workspaces.ts +23 -29
- package/src/index.ts +36 -16
- package/src/intent.ts +178 -6
- package/src/law_check.ts +32 -11
- package/src/law_graph.ts +2902 -0
- package/src/law_graph_usda.ts +1799 -0
- package/src/law_identity.ts +435 -0
- package/src/law_value_type.ts +230 -0
- package/src/lsp_server.ts +58 -29
- package/src/ops.ts +7 -0
- package/src/package_config.ts +141 -0
- package/src/package_dependencies.ts +108 -0
- package/src/package_dependency_usage.ts +150 -0
- package/src/package_source_imports.ts +71 -0
- package/src/plan_source_slice.ts +335 -0
- package/src/point_guard.ts +192 -0
- package/src/precondition.ts +44 -9
- package/src/read_projection_namespace.ts +1 -1
- package/src/runtime_zod.ts +44 -0
- package/src/secondary_ensure.ts +67 -14
- package/src/shape_compat.ts +1 -1
- package/src/stable_id_identity_bridge.ts +149 -0
- package/src/stable_id_lockfile.ts +140 -6
- package/src/stable_ids.ts +1 -1
- package/src/stable_ids_for_module.ts +348 -0
- package/src/stable_ids_types.ts +1 -1
- package/src/sum.ts +1 -1
- package/src/usd_state.ts +1 -1
- package/src/usda_relationship_integrity.ts +66 -0
- package/src/usda_text.ts +18 -0
- package/src/usdz.ts +78 -0
- package/src/value_object.ts +95 -0
- package/src/wire.ts +19 -0
- package/src/wire_encode.ts +22 -0
- package/src/workspace_sharding.ts +52 -36
- package/src/workspace_sharing.ts +28 -4
- package/src/zod_introspection.ts +1 -1
- package/dart/test/cluster_attested_test.dart +0 -201
- package/src/compile_engine.ts +0 -595
- package/src/manifest.ts +0 -1476
- package/src/read_projection_composition.ts +0 -117
- package/src/read_projection_manifest.ts +0 -115
- package/src/relation_composition.ts +0 -286
- package/src/usd.ts +0 -1967
- package/src/usd_layers.ts +0 -1776
package/src/business_birth.ts
CHANGED
|
@@ -54,10 +54,16 @@ export const CURRENT_LAW_PREFIX = "nomos:current-law:";
|
|
|
54
54
|
|
|
55
55
|
export interface BusinessBirthMetadata {
|
|
56
56
|
readonly aggregateId: string;
|
|
57
|
+
/** Owning law domain for closure-safe cross-workspace intent linking. */
|
|
58
|
+
readonly domain: string;
|
|
57
59
|
readonly publicPayloadSchema: z.ZodObject<z.ZodRawShape>;
|
|
58
60
|
readonly rootId: string;
|
|
59
61
|
readonly namespace: string;
|
|
60
62
|
readonly keyField: string;
|
|
63
|
+
/** Exact child-genesis offer route prepared before the parent birth dispatch. */
|
|
64
|
+
readonly seedDirectiveId: string;
|
|
65
|
+
/** Compiler-owned child-genesis routes which may be appended after the business seed. */
|
|
66
|
+
readonly genesisDirectiveIds: readonly string[];
|
|
61
67
|
/** Private proof/lowering policy; omitted from every generated tenant payload. */
|
|
62
68
|
readonly founderRoles: readonly string[];
|
|
63
69
|
readonly founderScope: string;
|
|
@@ -69,6 +75,7 @@ export interface BusinessBirthDirective extends Directive<Record<string, unknown
|
|
|
69
75
|
|
|
70
76
|
type BusinessBirthInternalDirective<P = Record<string, unknown>> = Directive<P> & {
|
|
71
77
|
readonly businessBirthInternal: true;
|
|
78
|
+
readonly businessBirthSeed?: true;
|
|
72
79
|
};
|
|
73
80
|
|
|
74
81
|
function internalDirective<P>(d: Directive<P>): BusinessBirthInternalDirective<P> {
|
|
@@ -189,10 +196,12 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
189
196
|
}),
|
|
190
197
|
),
|
|
191
198
|
];
|
|
192
|
-
})
|
|
199
|
+
})
|
|
200
|
+
.alsoEnsures(RelationTuple);
|
|
193
201
|
const seed = {
|
|
194
202
|
...seedBase,
|
|
195
203
|
businessBirthInternal: true,
|
|
204
|
+
businessBirthSeed: true,
|
|
196
205
|
} as BusinessBirthInternalDirective;
|
|
197
206
|
|
|
198
207
|
const birthBase = directive(birthId)
|
|
@@ -228,7 +237,6 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
228
237
|
actor: founder,
|
|
229
238
|
payload: { domainHash: `${CURRENT_LAW_PREFIX}nomos` },
|
|
230
239
|
domainHash: `${CURRENT_LAW_PREFIX}nomos`,
|
|
231
|
-
domainPackageB64: "",
|
|
232
240
|
},
|
|
233
241
|
{
|
|
234
242
|
domain: "nomos",
|
|
@@ -236,7 +244,6 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
236
244
|
actor: founder,
|
|
237
245
|
payload: { domainHash: `${CURRENT_LAW_PREFIX}${domain}` },
|
|
238
246
|
domainHash: `${CURRENT_LAW_PREFIX}${domain}`,
|
|
239
|
-
domainPackageB64: "",
|
|
240
247
|
},
|
|
241
248
|
{
|
|
242
249
|
domain,
|
|
@@ -298,10 +305,19 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
298
305
|
|
|
299
306
|
const metadata: BusinessBirthMetadata = {
|
|
300
307
|
aggregateId: decl.aggregate.id,
|
|
308
|
+
domain,
|
|
301
309
|
publicPayloadSchema: publicSchema,
|
|
302
310
|
rootId,
|
|
303
311
|
namespace,
|
|
304
312
|
keyField: decl.keyField,
|
|
313
|
+
seedDirectiveId: seedId,
|
|
314
|
+
genesisDirectiveIds: [
|
|
315
|
+
"enrollSigner",
|
|
316
|
+
"seedAuthProvider",
|
|
317
|
+
"seedBirthAttestation",
|
|
318
|
+
"seedGenesis",
|
|
319
|
+
"nomosBirthRecordEnsure",
|
|
320
|
+
],
|
|
305
321
|
founderRoles: decl.founderRoles,
|
|
306
322
|
founderScope: decl.founderScope,
|
|
307
323
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic JSON for compiler-internal fingerprints whose model is already typed.
|
|
3
|
+
*
|
|
4
|
+
* This is a byte-stable serializer, not a law representation. Canonical Nomos law is
|
|
5
|
+
* typed USDA; callers use this only when a small derived compiler value (for example a
|
|
6
|
+
* generated client interface) needs a reproducible digest.
|
|
7
|
+
*/
|
|
8
|
+
function canonicalize(value: unknown): unknown {
|
|
9
|
+
if (Array.isArray(value)) return value.map(canonicalize);
|
|
10
|
+
if (value !== null && typeof value === "object") {
|
|
11
|
+
const object = value as Record<string, unknown>;
|
|
12
|
+
const sorted: Record<string, unknown> = {};
|
|
13
|
+
for (const key of Object.keys(object).sort()) sorted[key] = canonicalize(object[key]);
|
|
14
|
+
return sorted;
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function canonicalJson(value: unknown): string {
|
|
20
|
+
return JSON.stringify(canonicalize(value));
|
|
21
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* `githolon check` — the author-time gate as a standalone command
|
|
8
|
-
* (architecture/author_time_gate.md, slice 1). Loads `nomos.
|
|
8
|
+
* (architecture/author_time_gate.md, slice 1). Loads `nomos.project.ts`, composes each
|
|
9
9
|
* domain the SAME way `compile` does (`composeDomainModule` — the one owner of directive
|
|
10
10
|
* discovery), runs {@link checkDomainModules}, prints the unified report, and exits
|
|
11
11
|
* non-zero on any REFUSE-level finding. `compile` runs the same twins implicitly.
|
|
@@ -21,21 +21,26 @@ import { LawSourceMap } from "./law_source_map.js";
|
|
|
21
21
|
import {
|
|
22
22
|
currentEvolveLaw,
|
|
23
23
|
evolveDiff,
|
|
24
|
-
|
|
24
|
+
evolveLawFromInterface,
|
|
25
25
|
evolveLawFromLockfile,
|
|
26
26
|
type EvolveLaw,
|
|
27
27
|
type StableIdLockfile,
|
|
28
28
|
} from "./evolve_preview.js";
|
|
29
29
|
import { parseStableIdLockfile } from "./stable_id_lockfile.js";
|
|
30
|
+
import {
|
|
31
|
+
validateNomosPackageConfig,
|
|
32
|
+
type NomosPackageConfig,
|
|
33
|
+
} from "./package_config.js";
|
|
34
|
+
import { assertPublicPackageImports } from "./package_source_imports.js";
|
|
35
|
+
import { packageDependencyUsageFindings } from "./package_dependency_usage.js";
|
|
30
36
|
|
|
31
37
|
interface DomainConfig {
|
|
32
38
|
key: string;
|
|
33
39
|
name?: string;
|
|
34
40
|
modules: string[];
|
|
35
41
|
}
|
|
36
|
-
interface PackageConfig {
|
|
37
|
-
|
|
38
|
-
domains: DomainConfig[];
|
|
42
|
+
interface PackageConfig extends NomosPackageConfig {
|
|
43
|
+
readonly domains: readonly DomainConfig[];
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
function fail(msg: string): never {
|
|
@@ -44,7 +49,7 @@ function fail(msg: string): never {
|
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
/**
|
|
47
|
-
* Compose the package's domain modules from `nomos.
|
|
52
|
+
* Compose the package's domain modules from `nomos.project.ts` — the check-time subset of what
|
|
48
53
|
* `compile_package_main` does: import the config, import each domain's TS modules, and hand them to
|
|
49
54
|
* `composeDomainModule` (the shared composition primitive that discovers directives/aggregates and
|
|
50
55
|
* applies the secondary-ensure auto-declare). Returns the composed modules ready for the twins.
|
|
@@ -60,62 +65,84 @@ export async function loadComposedModules(configArg: string): Promise<DomainModu
|
|
|
60
65
|
*/
|
|
61
66
|
export async function loadComposedModulesWithSources(
|
|
62
67
|
configArg: string,
|
|
63
|
-
): Promise<{
|
|
68
|
+
): Promise<{
|
|
69
|
+
modules: DomainModule[];
|
|
70
|
+
domainFiles: Map<string, string[]>;
|
|
71
|
+
dependencyFindings: readonly Finding[];
|
|
72
|
+
}> {
|
|
64
73
|
const configPath = path.resolve(process.cwd(), configArg);
|
|
65
74
|
if (!existsSync(configPath)) fail(`config not found: ${configPath}`);
|
|
66
75
|
const cfgDir = path.dirname(configPath);
|
|
67
76
|
// Cache-bust the config import so a re-load (the LSP re-check) sees edits, not the first-import cache.
|
|
68
77
|
const cfgUrl = `${pathToFileURL(configPath).href}?t=${Date.now()}`;
|
|
69
78
|
const cfgModule = (await import(cfgUrl)) as { default?: PackageConfig };
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
79
|
+
let cfg: PackageConfig;
|
|
80
|
+
let runtimeDependencies: ReturnType<typeof validateNomosPackageConfig>["runtimeDependencies"];
|
|
81
|
+
try {
|
|
82
|
+
const validated = validateNomosPackageConfig(cfgModule.default);
|
|
83
|
+
cfg = validated.config as PackageConfig;
|
|
84
|
+
runtimeDependencies = validated.runtimeDependencies;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
fail(`package contract refused: ${(error as Error).message}`);
|
|
73
87
|
}
|
|
74
88
|
const composed: DomainModule[] = [];
|
|
75
89
|
const domainFiles = new Map<string, string[]>();
|
|
76
90
|
for (const d of cfg.domains) {
|
|
77
|
-
if (typeof d.key !== "string" || !Array.isArray(d.modules) || d.modules.length === 0) {
|
|
78
|
-
fail(`each domain needs { key, modules: [path, ...] }; got ${JSON.stringify(d)}`);
|
|
79
|
-
}
|
|
80
91
|
const mods: Mod[] = [];
|
|
81
92
|
const files: string[] = [];
|
|
82
93
|
for (const rel of d.modules) {
|
|
83
94
|
const abs = path.resolve(cfgDir, rel);
|
|
84
95
|
if (!existsSync(abs)) fail(`domain '${d.key}': module not found: ${abs}`);
|
|
85
96
|
files.push(abs);
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
assertPublicPackageImports(files);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
fail(`package import boundary refused: ${(error as Error).message}`);
|
|
102
|
+
}
|
|
103
|
+
for (const abs of files) {
|
|
86
104
|
// Cache-bust so a re-import (the LSP re-check after an edit) re-evaluates the edited module.
|
|
87
105
|
mods.push((await import(`${pathToFileURL(abs).href}?t=${Date.now()}`)) as Mod);
|
|
88
106
|
}
|
|
89
107
|
domainFiles.set(d.key, files);
|
|
90
108
|
composed.push(composeDomainModule({ name: d.name ?? d.key, domain: d.key, modules: mods }));
|
|
91
109
|
}
|
|
92
|
-
return {
|
|
110
|
+
return {
|
|
111
|
+
modules: composed,
|
|
112
|
+
domainFiles,
|
|
113
|
+
dependencyFindings: packageDependencyUsageFindings({
|
|
114
|
+
packageName: cfg.name,
|
|
115
|
+
exportedDomains: cfg.domains.map((domain) => domain.key),
|
|
116
|
+
runtimeDependencies,
|
|
117
|
+
modules: composed,
|
|
118
|
+
}),
|
|
119
|
+
};
|
|
93
120
|
}
|
|
94
121
|
|
|
95
122
|
/**
|
|
96
123
|
* Load the PRIOR law surface for `--against <path>` (the evolve preview's baseline). The supported
|
|
97
|
-
* prior is a
|
|
124
|
+
* prior is a diagnostic `build/<name>.interface.json`, a BUILD DIR / package dir containing one, or
|
|
98
125
|
* the committed `nomos.stable-ids.json` LOCKFILE (aggregate identity only — no directive payloads).
|
|
99
126
|
* A live `https://…` prior is NOT supported (the installed package's stable-ids aren't retrievable
|
|
100
|
-
* from GET /domains); point `--against` at the deployed
|
|
127
|
+
* from GET /domains); point `--against` at the deployed source's interface and lock sidecars instead.
|
|
101
128
|
*/
|
|
102
129
|
function loadPriorEvolveLaw(arg: string): { law: EvolveLaw; source: string; note?: string } {
|
|
103
130
|
if (/^https?:\/\//.test(arg)) {
|
|
104
131
|
fail(
|
|
105
132
|
`--against does not support a live URL (${arg}) — the installed package's #58 stable-ids are ` +
|
|
106
|
-
`not retrievable from GET /domains. Point --against at the deployed
|
|
133
|
+
`not retrievable from GET /domains. Point --against at the deployed source's build/<name>.interface.json.`,
|
|
107
134
|
);
|
|
108
135
|
}
|
|
109
136
|
const abs = path.resolve(process.cwd(), arg);
|
|
110
137
|
if (!existsSync(abs)) fail(`--against: prior not found: ${abs}`);
|
|
111
|
-
// Resolve a directory to
|
|
138
|
+
// Resolve a directory to its diagnostic interface or stable-id lockfile.
|
|
112
139
|
let file = abs;
|
|
113
140
|
if (statSync(abs).isDirectory()) {
|
|
114
|
-
const
|
|
141
|
+
const iface = findInterfaceJson(abs);
|
|
115
142
|
const lock = path.join(abs, "nomos.stable-ids.json");
|
|
116
|
-
if (
|
|
143
|
+
if (iface !== undefined) file = iface;
|
|
117
144
|
else if (existsSync(lock)) file = lock;
|
|
118
|
-
else fail(`--against: no *.
|
|
145
|
+
else fail(`--against: no *.interface.json or nomos.stable-ids.json under ${abs}`);
|
|
119
146
|
}
|
|
120
147
|
let parsed: unknown;
|
|
121
148
|
try {
|
|
@@ -123,22 +150,35 @@ function loadPriorEvolveLaw(arg: string): { law: EvolveLaw; source: string; note
|
|
|
123
150
|
} catch (e) {
|
|
124
151
|
fail(`--against: could not parse ${file}: ${(e as Error).message}`);
|
|
125
152
|
}
|
|
126
|
-
|
|
127
|
-
if (p.domains !== undefined && p.interface === undefined && p.packageUsda === undefined) {
|
|
153
|
+
if (path.basename(file) === "nomos.stable-ids.json") {
|
|
128
154
|
return {
|
|
129
155
|
law: evolveLawFromLockfile(parseStableIdLockfile(parsed)),
|
|
130
156
|
source: file,
|
|
131
|
-
note: `prior is a lockfile — aggregate/field identity is diffed, but directive payload changes
|
|
157
|
+
note: `prior is a lockfile — aggregate/field identity is diffed, but directive payload changes require the sibling interface sidecar.`,
|
|
132
158
|
};
|
|
133
159
|
}
|
|
134
|
-
|
|
160
|
+
const lockCandidates = [
|
|
161
|
+
path.join(path.dirname(file), "nomos.stable-ids.json"),
|
|
162
|
+
path.join(path.dirname(path.dirname(file)), "nomos.stable-ids.json"),
|
|
163
|
+
];
|
|
164
|
+
const lockFile = lockCandidates.find((candidate) => existsSync(candidate));
|
|
165
|
+
const lock = lockFile === undefined
|
|
166
|
+
? undefined
|
|
167
|
+
: parseStableIdLockfile(JSON.parse(readFileSync(lockFile, "utf8")));
|
|
168
|
+
return {
|
|
169
|
+
law: evolveLawFromInterface(parsed as Parameters<typeof evolveLawFromInterface>[0], lock),
|
|
170
|
+
source: lockFile === undefined ? file : `${file} + ${lockFile}`,
|
|
171
|
+
...(lockFile === undefined
|
|
172
|
+
? { note: `prior has no stable-id lock beside it — directive shapes are checked, but driver and contract evolution evidence is incomplete.` }
|
|
173
|
+
: {}),
|
|
174
|
+
};
|
|
135
175
|
}
|
|
136
176
|
|
|
137
|
-
/** Find a `*.
|
|
138
|
-
function
|
|
177
|
+
/** Find a compiler diagnostic `*.interface.json` directly or one level down in `build/`. */
|
|
178
|
+
function findInterfaceJson(dir: string): string | undefined {
|
|
139
179
|
const scan = (d: string): string | undefined => {
|
|
140
180
|
if (!existsSync(d)) return undefined;
|
|
141
|
-
const hit = readdirSync(d).find((f) => f.endsWith(".
|
|
181
|
+
const hit = readdirSync(d).find((f) => f.endsWith(".interface.json"));
|
|
142
182
|
return hit !== undefined ? path.join(d, hit) : undefined;
|
|
143
183
|
};
|
|
144
184
|
return scan(dir) ?? scan(path.join(dir, "build"));
|
|
@@ -162,7 +202,7 @@ async function main(): Promise<void> {
|
|
|
162
202
|
// positional — `prior.json` belongs to the flag, not the config slot).
|
|
163
203
|
const againstIdx = argv.findIndex((a) => a === "--against");
|
|
164
204
|
const positionals = argv.filter((a, i) => !a.startsWith("--") && i !== againstIdx + 1);
|
|
165
|
-
const configArg = positionals[0] ?? "nomos.
|
|
205
|
+
const configArg = positionals[0] ?? "nomos.project.ts";
|
|
166
206
|
const againstArg =
|
|
167
207
|
againstIdx >= 0
|
|
168
208
|
? argv[againstIdx + 1]
|
|
@@ -170,14 +210,14 @@ async function main(): Promise<void> {
|
|
|
170
210
|
|
|
171
211
|
const asJson = argv.includes("--json");
|
|
172
212
|
|
|
173
|
-
const { modules, domainFiles } = await loadComposedModulesWithSources(configArg);
|
|
174
|
-
const findings: Finding[] = [...checkDomainModules(modules)];
|
|
213
|
+
const { modules, domainFiles, dependencyFindings } = await loadComposedModulesWithSources(configArg);
|
|
214
|
+
const findings: Finding[] = [...dependencyFindings, ...checkDomainModules(modules)];
|
|
175
215
|
|
|
176
216
|
// ── EVOLVE PREVIEW (--against): diff the current build against a prior law + pre-fire the gate. ──
|
|
177
217
|
let evolveDispositions: Record<string, unknown> | undefined;
|
|
178
218
|
if (againstIdx >= 0 || againstArg !== undefined) {
|
|
179
219
|
if (againstArg === undefined || againstArg.startsWith("--")) {
|
|
180
|
-
fail(`--against needs a path: --against <build/<name>.
|
|
220
|
+
fail(`--against needs a path: --against <build/<name>.interface.json | build dir | nomos.stable-ids.json>`);
|
|
181
221
|
}
|
|
182
222
|
const lock = loadCwdLockfile(configArg);
|
|
183
223
|
if (lock === undefined && !asJson) {
|
|
@@ -224,7 +264,7 @@ async function main(): Promise<void> {
|
|
|
224
264
|
// The consolidated, pasteable dispositions the destructive evolves demand (per domain).
|
|
225
265
|
if (evolveDispositions !== undefined) {
|
|
226
266
|
console.log(
|
|
227
|
-
"\ngitholon check: to admit the destructive evolve,
|
|
267
|
+
"\ngitholon check: to admit the destructive evolve, include `dispositions` in the installation offer:",
|
|
228
268
|
);
|
|
229
269
|
console.log(JSON.stringify(evolveDispositions, null, 2));
|
|
230
270
|
}
|
package/src/clear_directive.ts
CHANGED
|
@@ -51,7 +51,12 @@ export function clearDirectiveId(aggregateId: string, field: string): string {
|
|
|
51
51
|
* needn't read it), plan = the one `clear` op. `.requires(relation)` iff the field declared
|
|
52
52
|
* `clearRequires`.
|
|
53
53
|
*/
|
|
54
|
-
export function makeClearDirective(
|
|
54
|
+
export function makeClearDirective(
|
|
55
|
+
agg: AggregateHandle,
|
|
56
|
+
field: string,
|
|
57
|
+
requires?: string,
|
|
58
|
+
object?: string,
|
|
59
|
+
): Directive<unknown> {
|
|
55
60
|
const payloadId = idOf(agg);
|
|
56
61
|
const built = directive(clearDirectiveId(agg.id, field))
|
|
57
62
|
.mutates(agg)
|
|
@@ -60,14 +65,20 @@ export function makeClearDirective(agg: AggregateHandle, field: string, requires
|
|
|
60
65
|
.doc(
|
|
61
66
|
`Explicitly clears the '${field}' field of a ${agg.id} (writes an explicit null — the declared clearable lane).`,
|
|
62
67
|
) as unknown as RequirableDirective<unknown>;
|
|
63
|
-
return requires !== undefined
|
|
68
|
+
return requires !== undefined
|
|
69
|
+
? built.requires(requires, object === undefined ? undefined : { object })
|
|
70
|
+
: built;
|
|
64
71
|
}
|
|
65
72
|
|
|
66
|
-
/** The clearable `(field, requires?)` entries of one aggregate handle. */
|
|
67
|
-
function clearableFieldsOf(agg: AggregateHandle): { field: string; requires?: string }[] {
|
|
68
|
-
const out: { field: string; requires?: string }[] = [];
|
|
73
|
+
/** The clearable `(field, requires?, object?)` entries of one aggregate handle. */
|
|
74
|
+
function clearableFieldsOf(agg: AggregateHandle): { field: string; requires?: string; object?: string }[] {
|
|
75
|
+
const out: { field: string; requires?: string; object?: string }[] = [];
|
|
69
76
|
for (const [name, f0] of Object.entries(agg.fields as Record<string, Field>)) {
|
|
70
|
-
if (f0.isClearable === true) out.push({
|
|
77
|
+
if (f0.isClearable === true) out.push({
|
|
78
|
+
field: name,
|
|
79
|
+
...(f0.clearRequires !== undefined ? { requires: f0.clearRequires } : {}),
|
|
80
|
+
...(f0.clearRequiresObject !== undefined ? { object: f0.clearRequiresObject } : {}),
|
|
81
|
+
});
|
|
71
82
|
}
|
|
72
83
|
return out;
|
|
73
84
|
}
|
|
@@ -94,10 +105,10 @@ export function withClearDirectives<M extends Record<string, unknown>>(mod: M):
|
|
|
94
105
|
|
|
95
106
|
const additions: Record<string, unknown> = {};
|
|
96
107
|
for (const agg of aggs) {
|
|
97
|
-
for (const { field, requires } of clearableFieldsOf(agg)) {
|
|
108
|
+
for (const { field, requires, object } of clearableFieldsOf(agg)) {
|
|
98
109
|
const id = clearDirectiveId(agg.id, field);
|
|
99
110
|
if (existingIds.has(id) || id in mod) continue;
|
|
100
|
-
additions[id] = makeClearDirective(agg, field, requires);
|
|
111
|
+
additions[id] = makeClearDirective(agg, field, requires, object);
|
|
101
112
|
existingIds.add(id);
|
|
102
113
|
}
|
|
103
114
|
}
|