@almadar/core 7.21.0 → 7.23.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.
@@ -1,4 +1,4 @@
1
- import { b6 as OrbitalDefinition, bh as OrbitalSchema } from './schema-DRDVNvPf.js';
1
+ import { b6 as OrbitalDefinition, bh as OrbitalSchema } from './schema-BVni4uNf.js';
2
2
 
3
3
  /**
4
4
  * Event Wiring
@@ -1,4 +1,4 @@
1
- import { a6 as EntityField, a9 as EntityPersistence, cX as TraitReference, c$ as TraitScope, a2 as Entity, br as Page, bh as OrbitalSchema, cE as Trait } from '../schema-DRDVNvPf.js';
1
+ import { a6 as EntityField, a9 as EntityPersistence, cX as TraitReference, c$ as TraitScope, a2 as Entity, br as Page, bh as OrbitalSchema, cE as Trait } from '../schema-BVni4uNf.js';
2
2
  import { S as SExpr } from '../expression-BVRFm0sV.js';
3
3
  import 'zod';
4
4
  import '@almadar/patterns';
@@ -281,6 +281,12 @@ interface FactoryTraitSignature {
281
281
  /** Config keys overridable via `traitOverrides.<name>.config.<key>`.
282
282
  * Read directly from the trait's `config` declaration block. */
283
283
  overridableConfigKeys: ReadonlyArray<string>;
284
+ /** Capability tags lifted directly from the source `.lolo` trait's
285
+ * header annotations. Free-form strings — the Phase 4 translator
286
+ * overlay matches rules to traits by exact set membership. Empty
287
+ * when the trait declared none. See `docs/Almadar_Domain_Language.md`
288
+ * Phase 3. */
289
+ capabilities: ReadonlyArray<string>;
284
290
  }
285
291
  /** One page the factory emits. The path is the factory default; the
286
292
  * projector may override via `params.pagePath` or `params.pages[].path`. */
@@ -466,6 +472,73 @@ interface PresentationNavItem {
466
472
  /** Optional icon key (consumer-resolved). */
467
473
  icon?: string;
468
474
  }
475
+ /**
476
+ * LLM-authored trait-level overrides keyed by trait name (matches
477
+ * `signature.traits[].name`). Each entry's `config` keys are
478
+ * validated against `signature.traits[i].overridableConfigKeys`;
479
+ * unknown trait names or unknown config keys emit typed warnings
480
+ * and are skipped. Mirrors the existing call-site override surface
481
+ * on `TraitReference` in `OrbitalSchema`.
482
+ */
483
+ type TraitOverlay = Readonly<Record<string, TraitOverlayEntry>>;
484
+ interface TraitOverlayEntry {
485
+ config?: Readonly<Record<string, FactoryParamValue>>;
486
+ linkedEntity?: string;
487
+ events?: Readonly<Record<string, string>>;
488
+ name?: string;
489
+ emitsScope?: 'internal' | 'external';
490
+ listens?: ReadonlyArray<TraitOverlayListener>;
491
+ }
492
+ interface TraitOverlayListener {
493
+ event: string;
494
+ source?: {
495
+ orbital?: string;
496
+ trait?: string;
497
+ };
498
+ }
499
+ /**
500
+ * Rules carry a free-form `capability: string` that the translator
501
+ * matches against `signature.traits[].capabilities` (source-tagged
502
+ * in `.lolo`, propagated via `@almadar/core@7.22.0`).
503
+ *
504
+ * NO closed enum on `capability` — atoms advertise capability
505
+ * strings in their `.lolo` headers, and the catalog grows the
506
+ * vocabulary organically. The agent emits whatever capability
507
+ * string the user's domain expresses; if no trait in the catalog
508
+ * advertises that capability, the translator emits a typed warning.
509
+ */
510
+ interface RuleOverlay {
511
+ rules: ReadonlyArray<DomainRuleOverlayEntry>;
512
+ /**
513
+ * Entity-level ownership signal. Until Phase 1.5 promotes
514
+ * `ownedBy` into `DomainEntity`, ownership rides here as a
515
+ * parallel typed channel. The translator threads it into the
516
+ * matched trait's `config.ownerField` (when the matched trait
517
+ * advertises that key in `overridableConfigKeys`).
518
+ */
519
+ ownership?: ReadonlyArray<OwnershipOverlayEntry>;
520
+ }
521
+ interface DomainRuleOverlayEntry {
522
+ id: string;
523
+ /** Free-form capability label, matched against
524
+ * `signature.traits[].capabilities` by exact set membership. */
525
+ capability: string;
526
+ description: string;
527
+ /** Entity names this rule binds to. Empty array = cross-cutting:
528
+ * the rule applies to every orbital the translator visits. */
529
+ appliesTo: ReadonlyArray<string>;
530
+ /** Optional role name (e.g. `"admin"`) when the rule is role-scoped. */
531
+ role?: string;
532
+ /** Optional extra config knobs threaded into the matched trait's
533
+ * `config`. Validated against the trait's `overridableConfigKeys`. */
534
+ config?: Readonly<Record<string, FactoryParamValue>>;
535
+ }
536
+ interface OwnershipOverlayEntry {
537
+ /** Entity name (matches `DomainEntity.name`). */
538
+ entity: string;
539
+ /** Field name on the entity that carries the owner identifier. */
540
+ ownerField: string;
541
+ }
469
542
 
470
543
  /**
471
544
  * Domain Language Tokens
@@ -995,7 +1068,7 @@ interface TranslationResult {
995
1068
  callSite: FactoryCallSite;
996
1069
  warnings: ReadonlyArray<TranslationWarning>;
997
1070
  }
998
- declare function translateDomainToParams(binding: TranslationBinding, signature: FactorySignature, presentation?: PresentationOverlay): TranslationResult;
1071
+ declare function translateDomainToParams(binding: TranslationBinding, signature: FactorySignature, presentation?: PresentationOverlay, ruleOverlay?: RuleOverlay, traitOverlay?: TraitOverlay, catalog?: ReadonlyArray<FactorySignature>): TranslationResult;
999
1072
 
1000
1073
  /**
1001
1074
  * Structural diff between two `FactoryCallSite[]` lists. Pure typed,
@@ -1323,4 +1396,4 @@ declare function generateDomainLanguageReference(): string;
1323
1396
  */
1324
1397
  declare function applyMutation(doc: DomainDocument, mut: DomainMutation): DomainDocument;
1325
1398
 
1326
- export { type ASTNode, type CallSiteDiff, type ComparisonCondition, type ComparisonOperator, type DomainBehavior, type DomainChunk, type DomainDocument, type DomainEffect, type DomainEntity, type DomainField, type DomainFieldDefault, type DomainFieldItems, type DomainFieldType, type DomainGuard, type DomainMutation, type DomainPage, type DomainPageAction, type DomainPageSection, type DomainRelationship, type DomainTick, type DomainToSchemaResult, type DomainTransition, EFFECT_REGISTRY, type EffectMapping, type EffectType, EntityPersistence, FIELD_TYPE_REGISTRY, type FactoryCallSite, type FactoryCallSiteParams, type FactoryEntitySignature, type FactoryPageSignature, type FactoryParamValue, type FactorySignature, type FactorySignatureCatalog, type FactorySignatureEntityField, type FactoryTraitSignature, type FieldCheckCondition, type FieldReference, type FieldTypeMapping, GUARD_REGISTRY, type GuardCondition, type GuardMapping, KEYWORDS, Lexer, type LogicalCondition, type LogicalOperator, MULTI_WORD_KEYWORDS, type MappingStore, type MergeResult, type ParseError, type ParseResult, type PresentationNavItem, type PresentationOverlay, type RelationshipType, type SchemaFieldType, type SchemaToDomainResult, type SectionMapping, type SourceLocation, type SourceRange, type Token, TokenType, TraitScope, type TranslationBinding, type TranslationResult, type TranslationWarning, type UserCheckCondition, applyMutation, applySectionUpdate, computeSchemaHash, convertDomainToSchema, convertEntitiesToDomain, convertPagesToDomain, convertSchemaToDomain, convertTraitsToDomain, createMappingStore, deleteSection, detectChanges, diffFactoryCalls, domainKeywordToSchemaType, findMapping, findMappingByPath, findMappingsByType, formatBehaviorToDomain, formatBehaviorToSchema, formatDomainGuardToSchema, formatEntityToDomain, formatEntityToSchema, formatGuardConditionToDomain, formatGuardToDomain, formatGuardToSchema, formatMergeSummary, formatPageToDomain, formatPageToSchema, formatSchemaEntityToDomain, formatSchemaGuardToDomain, formatSchemaPageToDomain, formatSchemaTraitToDomain, generateDomainLanguageReference, generateSectionId, getEffectMapping, getFieldTypeMapping, getGuardMapping, getRegisteredEffects, getRegisteredFieldTypes, getRegisteredGuards, getRegistryStats, getSchemaPath, hasSchemaChanged, isEffectRegistered, isFieldTypeRegistered, isGuardRegistered, mergeDomainChunks, parseBehavior, parseDomainEffect, parseDomainEffects, parseDomainGuard, parseEntity, parseGuard, parsePage, parseSectionId, removeMapping, resolveConflict, schemaEntityToDomainEntity, schemaPageToDomainPage, schemaTraitToDomainBehavior, schemaTypeToDomainKeyword, tokenize, translateDomainToParams, updateMappingRange, updateSchemaHash, upsertMapping, validateDomainChunk };
1399
+ export { type ASTNode, type CallSiteDiff, type ComparisonCondition, type ComparisonOperator, type DomainBehavior, type DomainChunk, type DomainDocument, type DomainEffect, type DomainEntity, type DomainField, type DomainFieldDefault, type DomainFieldItems, type DomainFieldType, type DomainGuard, type DomainMutation, type DomainPage, type DomainPageAction, type DomainPageSection, type DomainRelationship, type DomainRuleOverlayEntry, type DomainTick, type DomainToSchemaResult, type DomainTransition, EFFECT_REGISTRY, type EffectMapping, type EffectType, EntityPersistence, FIELD_TYPE_REGISTRY, type FactoryCallSite, type FactoryCallSiteParams, type FactoryEntitySignature, type FactoryPageSignature, type FactoryParamValue, type FactorySignature, type FactorySignatureCatalog, type FactorySignatureEntityField, type FactoryTraitSignature, type FieldCheckCondition, type FieldReference, type FieldTypeMapping, GUARD_REGISTRY, type GuardCondition, type GuardMapping, KEYWORDS, Lexer, type LogicalCondition, type LogicalOperator, MULTI_WORD_KEYWORDS, type MappingStore, type MergeResult, type OwnershipOverlayEntry, type ParseError, type ParseResult, type PresentationNavItem, type PresentationOverlay, type RelationshipType, type RuleOverlay, type SchemaFieldType, type SchemaToDomainResult, type SectionMapping, type SourceLocation, type SourceRange, type Token, TokenType, type TraitOverlay, type TraitOverlayEntry, type TraitOverlayListener, TraitScope, type TranslationBinding, type TranslationResult, type TranslationWarning, type UserCheckCondition, applyMutation, applySectionUpdate, computeSchemaHash, convertDomainToSchema, convertEntitiesToDomain, convertPagesToDomain, convertSchemaToDomain, convertTraitsToDomain, createMappingStore, deleteSection, detectChanges, diffFactoryCalls, domainKeywordToSchemaType, findMapping, findMappingByPath, findMappingsByType, formatBehaviorToDomain, formatBehaviorToSchema, formatDomainGuardToSchema, formatEntityToDomain, formatEntityToSchema, formatGuardConditionToDomain, formatGuardToDomain, formatGuardToSchema, formatMergeSummary, formatPageToDomain, formatPageToSchema, formatSchemaEntityToDomain, formatSchemaGuardToDomain, formatSchemaPageToDomain, formatSchemaTraitToDomain, generateDomainLanguageReference, generateSectionId, getEffectMapping, getFieldTypeMapping, getGuardMapping, getRegisteredEffects, getRegisteredFieldTypes, getRegisteredGuards, getRegistryStats, getSchemaPath, hasSchemaChanged, isEffectRegistered, isFieldTypeRegistered, isGuardRegistered, mergeDomainChunks, parseBehavior, parseDomainEffect, parseDomainEffects, parseDomainGuard, parseEntity, parseGuard, parsePage, parseSectionId, removeMapping, resolveConflict, schemaEntityToDomainEntity, schemaPageToDomainPage, schemaTraitToDomainBehavior, schemaTypeToDomainKeyword, tokenize, translateDomainToParams, updateMappingRange, updateSchemaHash, upsertMapping, validateDomainChunk };
@@ -3873,6 +3873,7 @@ var TraitSchema = z.object({
3873
3873
  description: z.string().optional(),
3874
3874
  description_visual_prompt: z.string().optional(),
3875
3875
  category: TraitCategorySchema.optional(),
3876
+ capabilities: z.array(z.string()).optional(),
3876
3877
  scope: TraitScopeSchema,
3877
3878
  linkedEntity: z.string().optional(),
3878
3879
  requiredFields: z.array(RequiredFieldSchema).optional(),
@@ -6429,7 +6430,7 @@ var UI_SLOTS2 = [
6429
6430
  ];
6430
6431
 
6431
6432
  // src/domain-language/sync/translate-domain-to-params.ts
6432
- function translateDomainToParams(binding, signature, presentation) {
6433
+ function translateDomainToParams(binding, signature, presentation, ruleOverlay, traitOverlay, catalog) {
6433
6434
  const warnings = [];
6434
6435
  const params = {};
6435
6436
  applyEntityName(binding.entity, signature, params);
@@ -6437,6 +6438,8 @@ function translateDomainToParams(binding, signature, presentation) {
6437
6438
  applyPersistence(binding.entity, signature, params, warnings);
6438
6439
  applyPagePaths(binding.pages ?? [], signature, params, warnings);
6439
6440
  applyPresentation(presentation, signature, params, warnings);
6441
+ applyTraitOverlay(traitOverlay, signature, params, warnings);
6442
+ applyRuleOverlay(ruleOverlay, signature, binding, catalog, params, warnings);
6440
6443
  return {
6441
6444
  callSite: {
6442
6445
  organism: signature.organism,
@@ -6525,6 +6528,165 @@ function applyPresentation(overlay, signature, params, warnings) {
6525
6528
  }
6526
6529
  };
6527
6530
  }
6531
+ function applyTraitOverlay(overlay, signature, params, warnings) {
6532
+ if (!overlay) return;
6533
+ const traitsByName = new Map(signature.traits.map((t) => [t.name, t]));
6534
+ for (const [traitName, entry] of Object.entries(overlay)) {
6535
+ const trait = traitsByName.get(traitName);
6536
+ if (!trait) {
6537
+ warnings.push({
6538
+ field: `traitOverlay.${traitName}`,
6539
+ reason: `factory signature has no trait named "${traitName}"`
6540
+ });
6541
+ continue;
6542
+ }
6543
+ mergeTraitOverride(traitName, entry, trait, params, warnings);
6544
+ }
6545
+ }
6546
+ function mergeTraitOverride(traitName, entry, trait, params, warnings) {
6547
+ const advertised = new Set(trait.overridableConfigKeys);
6548
+ const existing = params.traitOverrides?.[traitName] ?? {};
6549
+ const existingConfig = existing.config ?? {};
6550
+ const mergedConfig = { ...existingConfig };
6551
+ if (entry.config) {
6552
+ for (const [k, v] of Object.entries(entry.config)) {
6553
+ if (!advertised.has(k)) {
6554
+ warnings.push({
6555
+ field: `traitOverlay.${traitName}.config.${k}`,
6556
+ reason: `trait does not advertise config key "${k}" (overridableConfigKeys: [${trait.overridableConfigKeys.join(", ")}])`
6557
+ });
6558
+ continue;
6559
+ }
6560
+ mergedConfig[k] = v;
6561
+ }
6562
+ }
6563
+ const next = {
6564
+ ...existing,
6565
+ ...Object.keys(mergedConfig).length > 0 ? { config: mergedConfig } : {}
6566
+ };
6567
+ params.traitOverrides = {
6568
+ ...params.traitOverrides,
6569
+ [traitName]: next
6570
+ };
6571
+ }
6572
+ function applyRuleOverlay(overlay, signature, binding, catalog, params, warnings) {
6573
+ if (!overlay) return;
6574
+ for (const rule of overlay.rules) {
6575
+ if (!ruleAppliesToBinding(rule, binding)) continue;
6576
+ if (!catalog) {
6577
+ warnings.push({
6578
+ field: `ruleOverlay.rules.${rule.id}`,
6579
+ reason: "rule overlay supplied without a catalog \u2014 capability lookup requires one"
6580
+ });
6581
+ continue;
6582
+ }
6583
+ const match = findTraitByCapability(catalog, rule.capability);
6584
+ if (!match) {
6585
+ warnings.push({
6586
+ field: `ruleOverlay.rules.${rule.id}`,
6587
+ reason: `no trait in the catalog advertises capability "${rule.capability}"`
6588
+ });
6589
+ continue;
6590
+ }
6591
+ appendRuleExtraTrait(rule, match, binding, params);
6592
+ if (rule.config) {
6593
+ threadRuleConfig(rule, match.trait, params, warnings);
6594
+ }
6595
+ }
6596
+ if (overlay.ownership) {
6597
+ for (const entry of overlay.ownership) {
6598
+ if (entry.entity !== binding.entity.name) continue;
6599
+ applyOwnership(entry, params, signature, catalog, warnings);
6600
+ }
6601
+ }
6602
+ }
6603
+ function ruleAppliesToBinding(rule, binding) {
6604
+ if (rule.appliesTo.length === 0) return true;
6605
+ return rule.appliesTo.includes(binding.entity.name);
6606
+ }
6607
+ function findTraitByCapability(catalog, capability) {
6608
+ for (const sig of catalog) {
6609
+ for (const trait of sig.traits) {
6610
+ if (trait.capabilities.includes(capability)) {
6611
+ return { signature: sig, trait };
6612
+ }
6613
+ }
6614
+ }
6615
+ return void 0;
6616
+ }
6617
+ function appendRuleExtraTrait(rule, match, binding, params) {
6618
+ const fromPath = `std/behaviors/${match.signature.organism}`;
6619
+ const alias = organismToAlias(match.signature.organism);
6620
+ const ref2 = {
6621
+ from: fromPath,
6622
+ ref: `${alias}.traits.${match.trait.name}`,
6623
+ linkedEntity: binding.entity.name
6624
+ };
6625
+ const existing = params.extraTraits ?? [];
6626
+ params.extraTraits = [...existing, ref2];
6627
+ }
6628
+ function organismToAlias(organism) {
6629
+ const trimmed = organism.startsWith("std-") ? organism.slice(4) : organism;
6630
+ return trimmed.split("-").filter((s) => s.length > 0).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
6631
+ }
6632
+ function threadRuleConfig(rule, trait, params, warnings) {
6633
+ if (!rule.config) return;
6634
+ const advertised = new Set(trait.overridableConfigKeys);
6635
+ const existing = params.traitOverrides?.[trait.name] ?? {};
6636
+ const existingConfig = existing.config ?? {};
6637
+ const merged = { ...existingConfig };
6638
+ for (const [k, v] of Object.entries(rule.config)) {
6639
+ if (!advertised.has(k)) {
6640
+ warnings.push({
6641
+ field: `ruleOverlay.rules.${rule.id}.config.${k}`,
6642
+ reason: `trait "${trait.name}" does not advertise config key "${k}"`
6643
+ });
6644
+ continue;
6645
+ }
6646
+ merged[k] = v;
6647
+ }
6648
+ if (Object.keys(merged).length > 0) {
6649
+ params.traitOverrides = {
6650
+ ...params.traitOverrides,
6651
+ [trait.name]: { ...existing, config: merged }
6652
+ };
6653
+ }
6654
+ }
6655
+ function applyOwnership(entry, params, signature, catalog, warnings) {
6656
+ const local = signature.traits.find(
6657
+ (t) => t.overridableConfigKeys.includes("ownerField")
6658
+ );
6659
+ if (local) {
6660
+ writeOwnerField(local.name, entry.ownerField, params);
6661
+ return;
6662
+ }
6663
+ if (catalog) {
6664
+ for (const sig of catalog) {
6665
+ const trait = sig.traits.find(
6666
+ (t) => t.overridableConfigKeys.includes("ownerField")
6667
+ );
6668
+ if (trait) {
6669
+ writeOwnerField(trait.name, entry.ownerField, params);
6670
+ return;
6671
+ }
6672
+ }
6673
+ }
6674
+ warnings.push({
6675
+ field: `ruleOverlay.ownership.${entry.entity}`,
6676
+ reason: "no trait in the bound signature or catalog advertises an `ownerField` config knob"
6677
+ });
6678
+ }
6679
+ function writeOwnerField(traitName, ownerField, params) {
6680
+ const existing = params.traitOverrides?.[traitName] ?? {};
6681
+ const existingConfig = existing.config ?? {};
6682
+ params.traitOverrides = {
6683
+ ...params.traitOverrides,
6684
+ [traitName]: {
6685
+ ...existing,
6686
+ config: { ...existingConfig, ownerField }
6687
+ }
6688
+ };
6689
+ }
6528
6690
  function lowerField(f) {
6529
6691
  const schemaType = DOMAIN_TO_SCHEMA_FIELD_TYPE[f.fieldType];
6530
6692
  if (!schemaType) return void 0;