@githolon/dsl 0.66.0 → 0.68.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/dart/CHANGELOG.md +14 -0
- package/dart/lib/src/webview_bridge.dart +71 -2
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +2 -2
- package/dart_types/CHANGELOG.md +14 -0
- package/dart_types/lib/nomos_types.dart +2 -0
- package/dart_types/lib/src/activity.dart +173 -0
- package/dart_types/lib/src/foreign_ref.dart +6 -0
- package/dart_types/lib/src/nomos_ref.dart +75 -0
- package/dart_types/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/src/activity.ts +197 -0
- package/src/codegen_dart.ts +168 -2
- package/src/codegen_dart_client.ts +97 -43
- package/src/codegen_ts.ts +215 -58
- package/src/compile_package_main.ts +28 -3
- package/src/directive.ts +28 -0
- package/src/index.ts +1 -0
|
@@ -56,6 +56,8 @@ import type { AggregateHandle } from "./aggregate.js";
|
|
|
56
56
|
import {
|
|
57
57
|
generateDartDomain,
|
|
58
58
|
generateDartContracts,
|
|
59
|
+
generateDartActivityRegistry,
|
|
60
|
+
collectActivityDescriptors,
|
|
59
61
|
type DartImport,
|
|
60
62
|
type DartRefImport,
|
|
61
63
|
type DomainModule,
|
|
@@ -428,6 +430,8 @@ const DART_SUPPORT_CORE_SRC = [
|
|
|
428
430
|
// The foreign-ref locator runtime (ForeignRef<T>/NomosForeignReader/…, t.foreignRef) — a generated read
|
|
429
431
|
// model with a `t.foreignRef` field references `ForeignRef<Target>` through the barrel, so it must vendor.
|
|
430
432
|
"foreign_ref.dart",
|
|
433
|
+
"activity.dart",
|
|
434
|
+
"nomos_ref.dart",
|
|
431
435
|
] as const;
|
|
432
436
|
// The RUNTIME support files, vendored from `nomos_client` (dsl/dart/lib/src): the async WebView
|
|
433
437
|
// bridge the generated `<name>.client.dart` drives, and the provider surface. Their
|
|
@@ -450,6 +454,10 @@ const FRAMEWORK_FILE = "nomos_framework";
|
|
|
450
454
|
/** The shared basename of the domain-contracts DTO file emitted once per package (domain_contracts.md). */
|
|
451
455
|
const CONTRACTS_FILE = "contracts";
|
|
452
456
|
|
|
457
|
+
/** The shared basename of the ACTIVITY REGISTRY file emitted once per package (activity_descriptors.md).
|
|
458
|
+
* Absent when no directive declares `.activity(...)` — an activity-free package emits no `activity_registry.dart`. */
|
|
459
|
+
const ACTIVITY_FILE = "activity_registry";
|
|
460
|
+
|
|
453
461
|
/** Collect every domain contract across the package's modules, deduped by id (later-wins). Sorted by id.
|
|
454
462
|
* Empty when no domain declares a contract (contract-free packages emit no `contracts.dart`). */
|
|
455
463
|
function collectPackageContracts(modules: readonly DomainModule[]): ContractHandle[] {
|
|
@@ -731,6 +739,14 @@ function emitDart(
|
|
|
731
739
|
if (packageContracts.length > 0) {
|
|
732
740
|
writeGenerated(CONTRACTS_FILE, generateDartContracts(packageContracts));
|
|
733
741
|
}
|
|
742
|
+
// 2a-ter. the shared ACTIVITY REGISTRY (`activity_registry.dart`) — the pure `renderActivity`, ONCE. Emitted
|
|
743
|
+
// iff a directive opts in via `.activity(...)` (activity-free packages stay byte-identical). Pure
|
|
744
|
+
// (nomos_types), so the client folds typed activity rows from the intent log with no runtime import.
|
|
745
|
+
const packageActivity = collectActivityDescriptors(modules);
|
|
746
|
+
const activityImportUri = packageActivity.length > 0 ? `${ACTIVITY_FILE}.dart` : undefined;
|
|
747
|
+
if (packageActivity.length > 0) {
|
|
748
|
+
writeGenerated(ACTIVITY_FILE, generateDartActivityRegistry(packageActivity));
|
|
749
|
+
}
|
|
734
750
|
// CROSS-DOMAIN `t.foreignRef` (auto import). A foreignRef field typed `ForeignRef<CatalogueListing>` +
|
|
735
751
|
// `CatalogueListing.fromJson` needs the TARGET aggregate's Dart class — which lives in the target DOMAIN's
|
|
736
752
|
// generated file. Within ONE package the compiler knows which domain owns each aggregate, so we auto-emit
|
|
@@ -794,6 +810,7 @@ function emitDart(
|
|
|
794
810
|
...(compat !== undefined ? { compat } : {}),
|
|
795
811
|
supportImport,
|
|
796
812
|
...(domainFrameworkImport !== undefined ? { frameworkImportUri: domainFrameworkImport } : {}),
|
|
813
|
+
...(packageActivity.length > 0 ? { emitActivity: true, ...(activityImportUri !== undefined ? { activityImportUri } : {}) } : {}),
|
|
797
814
|
});
|
|
798
815
|
const cp = path.join(genDir, `${mod.name}.client.dart`);
|
|
799
816
|
writeFileSync(cp, clientSrc, "utf8");
|
|
@@ -820,6 +837,7 @@ function emitDart(
|
|
|
820
837
|
: `export 'package:nomos_client/nomos_client.dart';`,
|
|
821
838
|
...(hasFrameworkSymbols ? [`export '${genRel}/${FRAMEWORK_FILE}.dart';`] : []),
|
|
822
839
|
...(contractsImportUri !== undefined ? [`export '${genRel}/${CONTRACTS_FILE}.dart';`] : []),
|
|
840
|
+
...(activityImportUri !== undefined ? [`export '${genRel}/${ACTIVITY_FILE}.dart';`] : []),
|
|
823
841
|
...modules.flatMap((m) => [
|
|
824
842
|
`export '${genRel}/${m.name}.dart';`,
|
|
825
843
|
`export '${genRel}/${m.name}.client.dart';`,
|
|
@@ -844,8 +862,10 @@ function emitDart(
|
|
|
844
862
|
/** The pure-core support import generated TYPES files carry in layered-packages mode. */
|
|
845
863
|
const DART_TYPES_IMPORT = `import 'package:nomos_types/nomos_types.dart';`;
|
|
846
864
|
/** Version constraints the scaffolded pubspecs pin — move together with the Dart packages' releases. */
|
|
847
|
-
|
|
848
|
-
const
|
|
865
|
+
// FLOOR = the release carrying every symbol generated code may reference (0.1.3: NomosRef).
|
|
866
|
+
const NOMOS_TYPES_DEP = "^0.1.3";
|
|
867
|
+
// FLOOR = the release carrying the bridge methods generated clients call (0.45.0: offerOutcome/NomosCreated.ref).
|
|
868
|
+
const NOMOS_CLIENT_DEP = "^0.45.0";
|
|
849
869
|
|
|
850
870
|
const isPubPackageName = (s: string): boolean => /^[a-z][a-z0-9_]*$/.test(s);
|
|
851
871
|
|
|
@@ -960,7 +980,7 @@ function emitDartPackages(
|
|
|
960
980
|
// field as the target aggregate's class, which lives in the target domain's file). A sibling types file is
|
|
961
981
|
// still PURE (no runtime/bridge surface — the purity gate exists to keep nomos_client out, not to isolate
|
|
962
982
|
// domain files from each other; Dart allows type-import cycles for mutual refs).
|
|
963
|
-
const siblingTypeFiles = new Set<string>([...modules.map((m) => `${m.name}.dart`), `${FRAMEWORK_FILE}.dart`, `${CONTRACTS_FILE}.dart`]);
|
|
983
|
+
const siblingTypeFiles = new Set<string>([...modules.map((m) => `${m.name}.dart`), `${FRAMEWORK_FILE}.dart`, `${CONTRACTS_FILE}.dart`, `${ACTIVITY_FILE}.dart`]);
|
|
964
984
|
const writeTypes = (fileBase: string, src: string): void => {
|
|
965
985
|
if (!src.includes(DART_PACKAGE_IMPORT)) {
|
|
966
986
|
fail(`generated Dart for '${fileBase}' does not carry the expected support import — codegen_dart header drifted`);
|
|
@@ -994,6 +1014,10 @@ function emitDartPackages(
|
|
|
994
1014
|
const packageContracts = collectPackageContracts(modules);
|
|
995
1015
|
const contractsImportUri = packageContracts.length > 0 ? `${CONTRACTS_FILE}.dart` : undefined;
|
|
996
1016
|
if (packageContracts.length > 0) writeTypes(CONTRACTS_FILE, generateDartContracts(packageContracts));
|
|
1017
|
+
// ACTIVITY REGISTRY (layered): the pure `renderActivity` in the TYPES package (nomos_types only). The
|
|
1018
|
+
// client resolves it through the types-package barrel (which re-exports every types file). Opt-in only.
|
|
1019
|
+
const packageActivity = collectActivityDescriptors(modules);
|
|
1020
|
+
if (packageActivity.length > 0) writeTypes(ACTIVITY_FILE, generateDartActivityRegistry(packageActivity));
|
|
997
1021
|
// CROSS-DOMAIN foreignRef (layered): map aggregate id → its domain's type file, so a foreignRef field's
|
|
998
1022
|
// target class resolves via a sibling import (the purity gate now permits sibling type files).
|
|
999
1023
|
const aggIdToTypeFile = new Map<string, string>();
|
|
@@ -1085,6 +1109,7 @@ function emitDartPackages(
|
|
|
1085
1109
|
...(compat !== undefined ? { compat } : {}),
|
|
1086
1110
|
supportImport: "package",
|
|
1087
1111
|
typesImportUri,
|
|
1112
|
+
...(packageActivity.length > 0 ? { emitActivity: true } : {}),
|
|
1088
1113
|
});
|
|
1089
1114
|
const cp = path.join(clientGen, `${mod.name}.client.dart`);
|
|
1090
1115
|
writeFileSync(cp, clientSrc, "utf8");
|
package/src/directive.ts
CHANGED
|
@@ -23,6 +23,7 @@ import type { Ports } from "./ctx.js";
|
|
|
23
23
|
import type { CertifiedReadDecl } from "./certified_read.js";
|
|
24
24
|
import type { RelationDecl } from "./relation.js";
|
|
25
25
|
import type { QueryDecl } from "./query.js";
|
|
26
|
+
import { normalizeActivity, type ActivityInput, type ActivityDescriptor } from "./activity.js";
|
|
26
27
|
import { BIRTH_METER_QUERIES } from "./birth_meter.js";
|
|
27
28
|
import {
|
|
28
29
|
isFromPayloadRef,
|
|
@@ -115,6 +116,15 @@ export interface Directive<P = unknown> {
|
|
|
115
116
|
* byte-identical in the canonical manifest to before `description` existed).
|
|
116
117
|
*/
|
|
117
118
|
readonly description?: string;
|
|
119
|
+
/**
|
|
120
|
+
* OPT-IN user-facing ACTIVITY metadata (`architecture/activity_descriptors.md`) — the kind/title/message
|
|
121
|
+
* template, refs, params, category/icon/severity a client uses to render a typed activity row from this
|
|
122
|
+
* directive's intents (no string-enricher). Set by `.activity({...})`; NON-LAW, additive (same class as
|
|
123
|
+
* `description` — a directive that never declares activity is byte-identical). Normalized + validated at
|
|
124
|
+
* author time. `undefined` ⇒ this directive contributes no activity row. (The setter is `.activity({...})`;
|
|
125
|
+
* this stored field is `activityDescriptor` to avoid a method/field name clash on `RequirableDirective`.)
|
|
126
|
+
*/
|
|
127
|
+
readonly activityDescriptor?: ActivityDescriptor;
|
|
118
128
|
/**
|
|
119
129
|
* NATIVE ZANZIBAR write-authz (P4): the RELATION the captured author must HOLD to author this
|
|
120
130
|
* directive, and the OBJECT it is checked on. The ONE gate runs `engine.check(schema, object,
|
|
@@ -414,6 +424,14 @@ export interface RequirableDirective<P> extends Directive<P> {
|
|
|
414
424
|
* calls this declares no prose (codegen falls back to a default derived from the id).
|
|
415
425
|
*/
|
|
416
426
|
doc(description: string): RequirableDirective<P>;
|
|
427
|
+
/**
|
|
428
|
+
* Declare OPT-IN user-facing ACTIVITY metadata (`architecture/activity_descriptors.md`) — a stable `kind`,
|
|
429
|
+
* a `{actor}`+params message template, navigation `refs`, display `params` (payload field paths), and
|
|
430
|
+
* category/icon/severity. Codegen emits a typed activity descriptor + `renderActivity` so a client folds
|
|
431
|
+
* typed activity rows from the intent log (no string-enricher). Validated at author time (unknown template
|
|
432
|
+
* var / missing payload field refuse). Non-law, additive; a directive that never calls it is byte-identical.
|
|
433
|
+
*/
|
|
434
|
+
activity(input: ActivityInput): RequirableDirective<P>;
|
|
417
435
|
/**
|
|
418
436
|
* Declare the directive's CertifiedReads (survival Constraint 5; `certified_read.md`
|
|
419
437
|
* §"Tenant authoring") — the profiled, named write-path reads its `decide()` consults, the
|
|
@@ -810,6 +828,16 @@ function makeRequirable<P>(base: Directive<P>): RequirableDirective<P> {
|
|
|
810
828
|
doc(description: string): RequirableDirective<P> {
|
|
811
829
|
return makeRequirable({ ...base, description });
|
|
812
830
|
},
|
|
831
|
+
activity(input: ActivityInput): RequirableDirective<P> {
|
|
832
|
+
// Normalize + validate against this directive's payload (unknown template var / missing payload field
|
|
833
|
+
// refuse here). "@created" refs are checked against the aggregates this directive CREATES (the primary
|
|
834
|
+
// .creates target + any .alsoCreates). Non-law, additive — stored like `description`.
|
|
835
|
+
const createdIds = [
|
|
836
|
+
...(base.marker === "creates" ? [base.aggregateId] : []),
|
|
837
|
+
...(base.secondaryOutputs ?? []).filter((o) => o.marker === "creates").map((o) => o.aggregateId),
|
|
838
|
+
];
|
|
839
|
+
return makeRequirable({ ...base, activityDescriptor: normalizeActivity(base.id, input, base.payloadSchema, createdIds) });
|
|
840
|
+
},
|
|
813
841
|
readsCertified(reads: Record<string, CertifiedReadDecl>): RequirableDirective<P> {
|
|
814
842
|
// Accumulate onto any prior declared CertifiedReads (a repeated local name's later decl
|
|
815
843
|
// wins) — additive, non-destructive. The local binding NAME (the key) is what `decide`
|
package/src/index.ts
CHANGED
|
@@ -136,6 +136,7 @@ export {
|
|
|
136
136
|
// surface). The dev never sees a "prim" — that is the GitHolon's internal OpenUSD IR.
|
|
137
137
|
export { create, existing, ensure, type AggregateRef } from "./authoring.js";
|
|
138
138
|
export { contract, isContractHandle, satisfiesContract, type ContractHandle, type ContractField, type ContractSatisfaction } from "./contract.js";
|
|
139
|
+
export { normalizeActivity, renderActivityTemplate, activityKey, type ActivityInput, type ActivityDescriptor, type ActivityRefInput, type ActivitySeverity } from "./activity.js";
|
|
139
140
|
// THE CAPTURED READ — a plan reads O(1) DSL queries via `read(query, args)`; the result is committed as
|
|
140
141
|
// the intent's read footprint (deterministic replay + stale-premise detection). The dev calls typed DSL
|
|
141
142
|
// queries; the library routes them here. The host capability is `nomos.read` (twin of `nomos.rng`).
|