@almadar/core 10.9.0 → 10.11.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/dist/builders.d.ts +3 -3
- package/dist/builders.js +15 -5
- package/dist/builders.js.map +1 -1
- package/dist/{compose-behaviors-CNTCOsui.d.ts → compose-behaviors-D9bQEgqN.d.ts} +1 -1
- package/dist/factory/index.d.ts +60 -8
- package/dist/factory/index.js +67 -31
- package/dist/factory/index.js.map +1 -1
- package/dist/factory-runtime/index.d.ts +176 -0
- package/dist/factory-runtime/index.js +1727 -0
- package/dist/factory-runtime/index.js.map +1 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.js +68 -32
- package/dist/index.js.map +1 -1
- package/dist/{schema-DAc5czBW.d.ts → schema-CtOoanon.d.ts} +1 -1
- package/dist/{trait-CWjT0yBO.d.ts → trait-BB1dc5A_.d.ts} +12 -2
- package/dist/types/index.d.ts +318 -7
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/{types-CQvAbsEc.d.ts → types-COc0mLs1.d.ts} +5 -1
- package/package.json +6 -1
package/dist/factory/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { g as FactoryParamValue, c as FactoryConfigTier, b as FactoryConfigParam, F as FactoryCallSite, h as FactorySignature, R as RuleOverlay, p as RuleOverlayEntry, o as PresentationOverlay, q as TraitOverlay } from '../types-
|
|
2
|
-
export { a as FactoryCallSiteParams, d as FactoryEntitySignature, e as FactoryEventSignature, f as FactoryPageSignature, i as FactorySignatureCatalog, j as FactorySignatureEntityField, k as FactoryTraitSignature, m as JsonSchema, n as JsonSchemaType, J as JsonValue, O as OwnershipOverlayEntry, P as PresentationNavItem, S as SchemaFieldType, r as TraitOverlayEntry, s as TraitOverlayListener } from '../types-
|
|
3
|
-
import { g as EntityPersistence, f as EntityField, j as TraitReference } from '../trait-
|
|
1
|
+
import { g as FactoryParamValue, c as FactoryConfigTier, b as FactoryConfigParam, F as FactoryCallSite, h as FactorySignature, R as RuleOverlay, p as RuleOverlayEntry, o as PresentationOverlay, q as TraitOverlay } from '../types-COc0mLs1.js';
|
|
2
|
+
export { a as FactoryCallSiteParams, d as FactoryEntitySignature, e as FactoryEventSignature, f as FactoryPageSignature, i as FactorySignatureCatalog, j as FactorySignatureEntityField, k as FactoryTraitSignature, m as JsonSchema, n as JsonSchemaType, J as JsonValue, O as OwnershipOverlayEntry, P as PresentationNavItem, S as SchemaFieldType, r as TraitOverlayEntry, s as TraitOverlayListener } from '../types-COc0mLs1.js';
|
|
3
|
+
import { g as EntityPersistence, f as EntityField, j as TraitReference } from '../trait-BB1dc5A_.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../expression-BUIi9ezJ.js';
|
|
6
6
|
import '@almadar/patterns';
|
|
@@ -27,14 +27,32 @@ import '@almadar/patterns';
|
|
|
27
27
|
* + input widget keyed off `inputType` + `suggestedAnswers` (and, for
|
|
28
28
|
* structured types, `itemSchema` / `objectSchema`); the answer fills
|
|
29
29
|
* the matching `mutationTemplate`.
|
|
30
|
+
*
|
|
31
|
+
* ### Surfacing flag
|
|
32
|
+
* `advanced` is `true` for questions whose tier is NOT `domain` or
|
|
33
|
+
* `policy` (i.e. `infra`, `presentation`, untagged, or any non-canonical
|
|
34
|
+
* value). The UI collapses advanced questions under a disclosure panel;
|
|
35
|
+
* questions with `advanced` absent or `false` render inline.
|
|
36
|
+
*
|
|
37
|
+
* ### Entity-field multiselect
|
|
38
|
+
* When `inputType` is `'multiselect'` and `mutationTemplate.kind` is
|
|
39
|
+
* `'set-orbital-entity-fields'`, the answer is the subset of
|
|
40
|
+
* `suggestedAnswers` the user checked. The UI maps selected names back
|
|
41
|
+
* to `EntityField[]` via `fieldCandidates` (keyed by field name) before
|
|
42
|
+
* submitting to `answersToMutations`. `fieldDescriptions` carries each
|
|
43
|
+
* field's semantic description for the checkbox label.
|
|
30
44
|
*/
|
|
31
45
|
interface DomainQuestion {
|
|
32
46
|
/** Unique within a session. Keys the answer record. */
|
|
33
47
|
id: string;
|
|
34
48
|
/** Natural-language prompt shown to the user. */
|
|
35
49
|
question: string;
|
|
36
|
-
/**
|
|
37
|
-
|
|
50
|
+
/**
|
|
51
|
+
* One short sentence explaining WHY this question is being asked —
|
|
52
|
+
* distinct from `helpText`. Never set to the same string as `helpText`.
|
|
53
|
+
* Undefined when no distinct rationale exists.
|
|
54
|
+
*/
|
|
55
|
+
reason?: string;
|
|
38
56
|
/** Orbital this question scopes to (matches
|
|
39
57
|
* `FactoryCallSite.orbital`). */
|
|
40
58
|
orbitalName: string;
|
|
@@ -54,9 +72,14 @@ interface DomainQuestion {
|
|
|
54
72
|
* pre-fills the input, the user can confirm or override. */
|
|
55
73
|
defaultValue?: DomainQuestionAnswer;
|
|
56
74
|
/** Closed-enum or curated suggestions. Empty when the input is
|
|
57
|
-
* free-form.
|
|
75
|
+
* free-form. For entity-field multiselect this is the candidate
|
|
76
|
+
* field name list (see `fieldCandidates`). */
|
|
58
77
|
suggestedAnswers?: ReadonlyArray<string>;
|
|
59
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* How-to-answer caption shown under the input widget. Set from
|
|
80
|
+
* `FactoryConfigParam.description` (the knob's own authored caption).
|
|
81
|
+
* Never set to the same text as `reason`.
|
|
82
|
+
*/
|
|
60
83
|
helpText?: string;
|
|
61
84
|
/** Per-element schema for array-of-objects (`listOfObjects`) and
|
|
62
85
|
* free-form chip lists (`tagList`). Propagated from
|
|
@@ -70,6 +93,14 @@ interface DomainQuestion {
|
|
|
70
93
|
* `@tier` annotation — the studio treats undefined as
|
|
71
94
|
* `'presentation'`. */
|
|
72
95
|
tier?: FactoryConfigTier;
|
|
96
|
+
/**
|
|
97
|
+
* `true` when this question is NOT a primary domain/policy decision —
|
|
98
|
+
* i.e. `tier` is absent, `'infra'`, `'presentation'`, or any
|
|
99
|
+
* non-canonical value. The UI collapses advanced questions under a
|
|
100
|
+
* disclosure panel. Domain and policy questions always have
|
|
101
|
+
* `advanced` absent (falsy).
|
|
102
|
+
*/
|
|
103
|
+
advanced?: boolean;
|
|
73
104
|
/** Impact weight derived from `tier` (policy/domain high, infra medium,
|
|
74
105
|
* presentation low). Drives the studio's Confidence score — answering a
|
|
75
106
|
* high-weight question moves the needle more. */
|
|
@@ -78,6 +109,20 @@ interface DomainQuestion {
|
|
|
78
109
|
* (deterministic); the studio server may boost it by prompt relevance.
|
|
79
110
|
* Higher = surfaced earlier. */
|
|
80
111
|
priority?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Full `EntityField` candidates keyed by field name. Present only on
|
|
114
|
+
* entity-field multiselect questions (`inputType: 'multiselect'`,
|
|
115
|
+
* `mutationTemplate.kind: 'set-orbital-entity-fields'`). The UI maps
|
|
116
|
+
* the user's selected field names back to `EntityField[]` via this
|
|
117
|
+
* record before calling `answersToMutations`.
|
|
118
|
+
*/
|
|
119
|
+
fieldCandidates?: Readonly<Record<string, EntityField>>;
|
|
120
|
+
/**
|
|
121
|
+
* Human-readable description for each candidate field name. Keyed by
|
|
122
|
+
* field name (same keys as `fieldCandidates`). The UI shows this as
|
|
123
|
+
* the checkbox sublabel.
|
|
124
|
+
*/
|
|
125
|
+
fieldDescriptions?: Readonly<Record<string, string>>;
|
|
81
126
|
}
|
|
82
127
|
/**
|
|
83
128
|
* Narrow set of widget kinds the studio renders.
|
|
@@ -175,7 +220,14 @@ type DomainQuestionAnswers = Readonly<Record<string, DomainQuestionAnswer>>;
|
|
|
175
220
|
* @packageDocumentation
|
|
176
221
|
*/
|
|
177
222
|
|
|
178
|
-
declare function generateQuestions(plan: ReadonlyArray<FactoryCallSite>, catalog: ReadonlyArray<FactorySignature>, ruleOverlay?: RuleOverlay
|
|
223
|
+
declare function generateQuestions(plan: ReadonlyArray<FactoryCallSite>, catalog: ReadonlyArray<FactorySignature>, ruleOverlay?: RuleOverlay,
|
|
224
|
+
/**
|
|
225
|
+
* Optional user-authored prompt from the current session. Carried
|
|
226
|
+
* through so downstream consumers (route handlers, ranking passes)
|
|
227
|
+
* can re-order questions by relevance without re-generating. Does
|
|
228
|
+
* not affect the emitted set — only threading and ordering.
|
|
229
|
+
*/
|
|
230
|
+
_userPrompt?: string): DomainQuestion[];
|
|
179
231
|
/**
|
|
180
232
|
* Pick a widget for a config-key question from the param's typed
|
|
181
233
|
* declaration + its structural carriers. The type tag is lifted
|
package/dist/factory/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/factory/questions/generate.ts
|
|
2
|
-
function generateQuestions(plan, catalog, ruleOverlay) {
|
|
2
|
+
function generateQuestions(plan, catalog, ruleOverlay, _userPrompt) {
|
|
3
3
|
const out = [];
|
|
4
4
|
const ruleCapabilities = collectRuleCapabilities(ruleOverlay);
|
|
5
5
|
for (const call of plan) {
|
|
@@ -38,12 +38,14 @@ function buildConfigKeyQuestion(call, trait, param) {
|
|
|
38
38
|
const question = `${label}?`;
|
|
39
39
|
const callSiteOverride = callSiteOverrideValue(call, trait.name, param.key);
|
|
40
40
|
const effectiveDefault = callSiteOverride !== void 0 ? callSiteOverride : param.default;
|
|
41
|
-
const
|
|
41
|
+
const helpText = param.description;
|
|
42
|
+
const syntheticReason = `Customizes "${param.key}" on the ${trait.name} trait. ` + (effectiveDefault !== void 0 ? `Default: ${stringifyDefault(effectiveDefault)}.` : `No default \u2014 leave blank to inherit the factory's behavior.`);
|
|
43
|
+
const reason = helpText !== void 0 ? void 0 : syntheticReason;
|
|
44
|
+
const isAdvanced = !isPrimaryTier(param.tier);
|
|
42
45
|
const out = {
|
|
43
46
|
id: `${call.orbital}.${trait.name}.${param.key}`,
|
|
44
47
|
orbitalName: call.orbital,
|
|
45
48
|
question,
|
|
46
|
-
reason,
|
|
47
49
|
inputType: deriveInputType(param),
|
|
48
50
|
mutationTemplate: {
|
|
49
51
|
kind: "set-trait-override-config",
|
|
@@ -52,6 +54,12 @@ function buildConfigKeyQuestion(call, trait, param) {
|
|
|
52
54
|
configKey: param.key
|
|
53
55
|
}
|
|
54
56
|
};
|
|
57
|
+
if (reason !== void 0) {
|
|
58
|
+
out.reason = reason;
|
|
59
|
+
}
|
|
60
|
+
if (helpText !== void 0) {
|
|
61
|
+
out.helpText = helpText;
|
|
62
|
+
}
|
|
55
63
|
if (effectiveDefault !== void 0) {
|
|
56
64
|
out.defaultValue = effectiveDefault;
|
|
57
65
|
}
|
|
@@ -67,8 +75,8 @@ function buildConfigKeyQuestion(call, trait, param) {
|
|
|
67
75
|
if (param.tier) {
|
|
68
76
|
out.tier = param.tier;
|
|
69
77
|
}
|
|
70
|
-
if (
|
|
71
|
-
out.
|
|
78
|
+
if (isAdvanced) {
|
|
79
|
+
out.advanced = true;
|
|
72
80
|
}
|
|
73
81
|
const weight = tierWeight(param.tier);
|
|
74
82
|
out.weight = weight;
|
|
@@ -89,6 +97,9 @@ function tierWeight(tier) {
|
|
|
89
97
|
return 1;
|
|
90
98
|
}
|
|
91
99
|
}
|
|
100
|
+
function isPrimaryTier(tier) {
|
|
101
|
+
return tier === "domain" || tier === "policy";
|
|
102
|
+
}
|
|
92
103
|
function callSiteOverrideValue(call, traitName, configKey) {
|
|
93
104
|
const override = call.params.traitOverrides?.[traitName];
|
|
94
105
|
if (!override?.config) return void 0;
|
|
@@ -144,27 +155,42 @@ function entityFieldQuestions(call, signature) {
|
|
|
144
155
|
if (signature.entities.length === 0) return [];
|
|
145
156
|
const entity = signature.entities[0];
|
|
146
157
|
const entityName = call.params.entityName ?? entity.name;
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
kind: "set-orbital-entity-fields",
|
|
160
|
-
orbitalName: call.orbital
|
|
161
|
-
},
|
|
162
|
-
defaultValue: defaultFields,
|
|
163
|
-
tier: "domain",
|
|
164
|
-
weight,
|
|
165
|
-
priority: weight
|
|
158
|
+
const candidateFields = entity.fields.map(signatureFieldToEntityField);
|
|
159
|
+
const fieldCandidates = {};
|
|
160
|
+
const fieldDescriptions = {};
|
|
161
|
+
const candidateNames = [];
|
|
162
|
+
for (let i = 0; i < entity.fields.length; i++) {
|
|
163
|
+
const sig = entity.fields[i];
|
|
164
|
+
const ef = candidateFields[i];
|
|
165
|
+
const name = sig.name;
|
|
166
|
+
candidateNames.push(name);
|
|
167
|
+
fieldCandidates[name] = ef;
|
|
168
|
+
if (sig.description) {
|
|
169
|
+
fieldDescriptions[name] = sig.description;
|
|
166
170
|
}
|
|
167
|
-
|
|
171
|
+
}
|
|
172
|
+
const weight = tierWeight("domain");
|
|
173
|
+
const q = {
|
|
174
|
+
id: `${call.orbital}.__entityFields`,
|
|
175
|
+
orbitalName: call.orbital,
|
|
176
|
+
question: `Which fields should a ${entityName} have?`,
|
|
177
|
+
reason: `Defines the data model for ${entityName}. Pick the fields that matter for your use case.`,
|
|
178
|
+
inputType: "multiselect",
|
|
179
|
+
mutationTemplate: {
|
|
180
|
+
kind: "set-orbital-entity-fields",
|
|
181
|
+
orbitalName: call.orbital
|
|
182
|
+
},
|
|
183
|
+
suggestedAnswers: candidateNames,
|
|
184
|
+
defaultValue: candidateNames,
|
|
185
|
+
fieldCandidates,
|
|
186
|
+
tier: "domain",
|
|
187
|
+
weight,
|
|
188
|
+
priority: weight
|
|
189
|
+
};
|
|
190
|
+
if (Object.keys(fieldDescriptions).length > 0) {
|
|
191
|
+
q.fieldDescriptions = fieldDescriptions;
|
|
192
|
+
}
|
|
193
|
+
return [q];
|
|
168
194
|
}
|
|
169
195
|
function signatureFieldToEntityField(f) {
|
|
170
196
|
const base = {
|
|
@@ -187,8 +213,14 @@ function signatureFieldToEntityField(f) {
|
|
|
187
213
|
case "object":
|
|
188
214
|
return { ...base, type: "object" };
|
|
189
215
|
case "enum":
|
|
216
|
+
if (Array.isArray(f.values) && f.values.length > 0) {
|
|
217
|
+
return { ...base, type: "enum", values: f.values };
|
|
218
|
+
}
|
|
190
219
|
return { ...base, type: "string" };
|
|
191
220
|
case "relation":
|
|
221
|
+
if (f.relation !== void 0) {
|
|
222
|
+
return { ...base, type: "relation", relation: f.relation };
|
|
223
|
+
}
|
|
192
224
|
return { ...base, type: "string" };
|
|
193
225
|
default: {
|
|
194
226
|
f.type;
|
|
@@ -201,23 +233,26 @@ function capabilityQuestions(call, signature, ruleCapabilities) {
|
|
|
201
233
|
const seen = /* @__PURE__ */ new Set();
|
|
202
234
|
const out = [];
|
|
203
235
|
for (const trait of signature.traits) {
|
|
236
|
+
const policyKnobKeys = new Set(
|
|
237
|
+
trait.overridableConfigKeys.filter((p) => p.tier === "policy").map((p) => p.key)
|
|
238
|
+
);
|
|
204
239
|
for (const cap of trait.capabilities) {
|
|
205
240
|
if (seen.has(cap)) continue;
|
|
206
241
|
seen.add(cap);
|
|
207
242
|
if (ruleCapabilities.has(cap)) continue;
|
|
243
|
+
if (policyKnobKeys.has(cap)) continue;
|
|
208
244
|
out.push({
|
|
209
245
|
id: `${call.orbital}.capability.${cap}`,
|
|
210
246
|
orbitalName: call.orbital,
|
|
211
247
|
question: capabilityPrompt(cap, entityName),
|
|
212
|
-
|
|
248
|
+
helpText: capabilityHelp(cap, trait),
|
|
213
249
|
capability: cap,
|
|
214
|
-
inputType: "
|
|
250
|
+
inputType: "boolean",
|
|
215
251
|
mutationTemplate: {
|
|
216
252
|
kind: "set-rule",
|
|
217
253
|
capability: cap,
|
|
218
254
|
appliesTo: [entityName]
|
|
219
255
|
},
|
|
220
|
-
suggestedAnswers: ["yes", "skip"],
|
|
221
256
|
// Capabilities encode governance/policy decisions — high impact.
|
|
222
257
|
weight: 3,
|
|
223
258
|
priority: 3
|
|
@@ -227,10 +262,11 @@ function capabilityQuestions(call, signature, ruleCapabilities) {
|
|
|
227
262
|
return out;
|
|
228
263
|
}
|
|
229
264
|
function capabilityPrompt(capability, entity) {
|
|
230
|
-
|
|
265
|
+
const label = humanizeKey(capability);
|
|
266
|
+
return `Enable ${label} for ${entity}?`;
|
|
231
267
|
}
|
|
232
|
-
function
|
|
233
|
-
return `
|
|
268
|
+
function capabilityHelp(capability, trait) {
|
|
269
|
+
return `Turns on the "${capability}" behavior from the ${trait.name} trait. Say yes to wire a governance rule into the schema.`;
|
|
234
270
|
}
|
|
235
271
|
function findSignature(catalog, organism, orbital) {
|
|
236
272
|
return catalog.find((s) => s.organism === organism && s.orbital === orbital);
|