@rsconcept/domain 2.2.0 → 3.0.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.
Files changed (55) hide show
  1. package/dist/{diagnostics-Db1F7ruF.d.ts → diagnostics-DsEhmFh0.d.ts} +6 -4
  2. package/dist/{diagnostics-B1OfMra1.js → diagnostics-ndGYbvgh.js} +374 -15
  3. package/dist/diagnostics-ndGYbvgh.js.map +1 -0
  4. package/dist/index-DpiTybDB.d.ts +376 -0
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +2 -2
  7. package/dist/library/diagnostics.d.ts +1 -1
  8. package/dist/library/diagnostics.js +1 -1
  9. package/dist/library/index.d.ts +6 -5
  10. package/dist/library/index.js +1 -1
  11. package/dist/library/index.js.map +1 -1
  12. package/dist/library/oss-api.d.ts +1 -1
  13. package/dist/library/oss-api.js +1 -1
  14. package/dist/library/oss-api.js.map +1 -1
  15. package/dist/library/rsengine.d.ts +1 -1
  16. package/dist/library/rsengine.js +2 -2
  17. package/dist/library/rsform-api/index.d.ts +2 -146
  18. package/dist/library/rsform-api/index.js +2 -2
  19. package/dist/library/rsform.d.ts +2 -2
  20. package/dist/library/rsform.js.map +1 -1
  21. package/dist/library/rsmodel-api.d.ts +9 -4
  22. package/dist/library/rsmodel-api.js +7 -3
  23. package/dist/library/rsmodel-api.js.map +1 -1
  24. package/dist/library/rsmodel.d.ts +1 -1
  25. package/dist/library/structure-planner.d.ts +1 -1
  26. package/dist/library/structure-planner.js +2 -2
  27. package/dist/library/structure-planner.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/index.ts +1 -0
  30. package/src/library/diagnostics.ts +20 -9
  31. package/src/library/index.ts +1 -0
  32. package/src/library/oss-api.ts +5 -1
  33. package/src/library/rsform-api/alias.ts +60 -4
  34. package/src/library/rsform-api/attribution.ts +87 -0
  35. package/src/library/rsform-api/cst-type.ts +7 -5
  36. package/src/library/rsform-api/expression.ts +3 -3
  37. package/src/library/rsform-api/formal-graph.test.ts +2 -2
  38. package/src/library/rsform-api/formal-graph.ts +6 -10
  39. package/src/library/rsform-api/index.ts +38 -2
  40. package/src/library/rsform-api/semantic-relations.ts +4 -7
  41. package/src/library/rsform-api/stats.ts +6 -5
  42. package/src/library/rsform-api/structure.ts +12 -6
  43. package/src/library/rsform-api/substitution.ts +82 -0
  44. package/src/library/rsform-api/synthesis.test.ts +157 -0
  45. package/src/library/rsform-api/synthesis.ts +149 -6
  46. package/src/library/rsform-api/text-resolution.test.ts +84 -0
  47. package/src/library/rsform-api/text-resolution.ts +152 -0
  48. package/src/library/rsform-api/transforms.test.ts +161 -0
  49. package/src/library/rsform-api/transforms.ts +42 -0
  50. package/src/library/rsform-api/types.ts +102 -4
  51. package/src/library/rsform.ts +1 -1
  52. package/src/library/rsmodel-api.ts +10 -5
  53. package/src/library/structure-planner.ts +6 -2
  54. package/src/library/template-instantiation.ts +11 -9
  55. package/dist/diagnostics-B1OfMra1.js.map +0 -1
@@ -265,8 +265,10 @@ interface CstDiagnostic {
265
265
  /** Positional message arguments (per-code; homonyms/duplicates use `[aliases]`). */
266
266
  params?: readonly string[];
267
267
  }
268
- /** Whether a constituent has a schema/model diagnostic with the given code. */
269
- declare function hasCstDiagnostic(cst: Constituenta, code: RSDiagnosticCode): boolean;
268
+ /** Whether an item has a schema/model diagnostic with the given code. */
269
+ declare function hasCstDiagnostic(cst: {
270
+ diagnostics?: readonly CstDiagnostic[] | null;
271
+ }, code: RSDiagnosticCode): boolean;
270
272
  /**
271
273
  * Populate `diagnostics` on each constituent (homonyms, duplicates, metadata, type mismatch, cycles).
272
274
  *
@@ -297,5 +299,5 @@ declare function detectDependencyCycleDiagnostics(graph: Graph, resolveAlias: (i
297
299
  /** Map a model evaluation status to a compact diagnostic, or `null` when not an issue. */
298
300
  declare function modelStatusCstDiagnostic(status: EvalStatus, cstType: CstType): CstDiagnostic | null;
299
301
  //#endregion
300
- export { RSFormStats as C, RSForm as S, TypeInfo as T, Attribution as _, detectDependencyCycleDiagnostics as a, CstStatus as b, modelStatusCstDiagnostic as c, DEFAULT_VALUE_TEXT as d, EvalStatus as f, ArgumentValue as g, TYPE_BASIC as h, assignSchemaDiagnostics as i, BasicBinding as l, RSModelStats as m, DiagnosticKind as n, formatDependencyCycle as o, RSModel as p, RSDiagnosticCode as r, hasCstDiagnostic as s, CstDiagnostic as t, BasicsContext as u, Constituenta as v, Substitution as w, CstType as x, CstClass as y };
301
- //# sourceMappingURL=diagnostics-Db1F7ruF.d.ts.map
302
+ export { RSFormStats as C, TypeInfo as E, RSForm as S, TermForm as T, Attribution as _, detectDependencyCycleDiagnostics as a, CstStatus as b, modelStatusCstDiagnostic as c, DEFAULT_VALUE_TEXT as d, EvalStatus as f, ArgumentValue as g, TYPE_BASIC as h, assignSchemaDiagnostics as i, BasicBinding as l, RSModelStats as m, DiagnosticKind as n, formatDependencyCycle as o, RSModel as p, RSDiagnosticCode as r, hasCstDiagnostic as s, CstDiagnostic as t, BasicsContext as u, Constituenta as v, Substitution as w, CstType as x, CstClass as y };
303
+ //# sourceMappingURL=diagnostics-DsEhmFh0.d.ts.map
@@ -1,14 +1,14 @@
1
1
  import { Graph } from "./graph/graph.js";
2
2
  import { TypeClass, TypeID, basic, bool, constant, isTypification } from "./rslang/semantic/typification.js";
3
3
  import { labelType } from "./rslang/labels.js";
4
- import { applyEntityReferenceMapping } from "./cctext/language-api.js";
4
+ import { applyEntityReferenceMapping, extractEntities, parseGrammemes, resolveTextReferences } from "./cctext/language-api.js";
5
5
  import { generateExpressionFromAst } from "./rslang/parser/expression-generator.js";
6
6
  import { applyAliasMapping, applyTypificationMapping, extractGlobals, isSimpleExpression, parseRSLangExpression, splitTemplateDefinition } from "./rslang/api.js";
7
+ import { CstClass, CstStatus, CstType } from "./library/rsform.js";
7
8
  import { RSErrorCode } from "./rslang/error.js";
8
9
  import { applyPath } from "./rslang/semantic/typification-api.js";
9
10
  import { ValueClass } from "./rslang/semantic/value-class.js";
10
11
  import "./rslang/index.js";
11
- import { CstClass, CstStatus, CstType } from "./library/rsform.js";
12
12
  import "./graph/index.js";
13
13
  import { EvalStatus } from "./library/rsmodel.js";
14
14
  //#region src/library/rsform-api/cst-type.ts
@@ -54,7 +54,7 @@ function inferClass(type, isTemplate = false) {
54
54
  if (isTemplate) return CstClass.TEMPLATE;
55
55
  return CST_TYPE_TO_CLASS[type];
56
56
  }
57
- /** Check if {@link Constituenta} is a template or a category. */
57
+ /** Check if item type is a template or a category. */
58
58
  function isTemplateCst(cst) {
59
59
  return cst.cst_type === CstType.FUNCTION || cst.cst_type === CstType.PREDICATE || cst.cst_type === CstType.STATEMENT;
60
60
  }
@@ -146,7 +146,7 @@ function typeClassForCstType(cstType) {
146
146
  case CstType.STATEMENT: return TypeClass.logic;
147
147
  }
148
148
  }
149
- /** Evaluate if {@link Constituenta} can be used produce structure. */
149
+ /** Evaluate if an item can be used to produce structure. */
150
150
  function canProduceStructure(cst) {
151
151
  switch (cst.cst_type) {
152
152
  case CstType.NOMINAL:
@@ -222,6 +222,45 @@ function applyMappingToConstituents(items, mapping, changeAliases) {
222
222
  cst.definition_raw = applyEntityReferenceMapping(cst.definition_raw, mapping);
223
223
  }
224
224
  }
225
+ /** Highest numeric alias suffix for {@link type} among {@link items} (0 when none). */
226
+ function maxAliasIndex(items, type) {
227
+ const prefix = getCstTypePrefix(type);
228
+ return items.reduce((max, cst) => {
229
+ if (cst.cst_type !== type) return max;
230
+ const index = Number(cst.alias.slice(prefix.length));
231
+ return Number.isFinite(index) ? Math.max(max, index) : max;
232
+ }, 0);
233
+ }
234
+ /**
235
+ * Build alias → new-alias mapping that renumbers each type sequentially in list order.
236
+ * Matches backend {@code RSFormCached.reset_aliases}.
237
+ */
238
+ function buildSequentialAliasMapping(items) {
239
+ const counts = {};
240
+ for (const value of Object.values(CstType)) counts[value] = 1;
241
+ const mapping = {};
242
+ for (const cst of items) {
243
+ const alias = `${getCstTypePrefix(cst.cst_type)}${counts[cst.cst_type]}`;
244
+ counts[cst.cst_type] += 1;
245
+ if (cst.alias !== alias) mapping[cst.alias] = alias;
246
+ }
247
+ return mapping;
248
+ }
249
+ /**
250
+ * Allocate fresh aliases for {@link source} constituents being imported into a non-empty receiver.
251
+ * Returns an empty mapping when the receiver has no items (aliases kept as-is).
252
+ */
253
+ function allocateImportAliases(receiver, source) {
254
+ if (receiver.length === 0) return {};
255
+ const counts = {};
256
+ for (const value of Object.values(CstType)) counts[value] = maxAliasIndex(receiver, value);
257
+ const mapping = {};
258
+ for (const cst of source) {
259
+ counts[cst.cst_type] += 1;
260
+ mapping[cst.alias] = `${getCstTypePrefix(cst.cst_type)}${counts[cst.cst_type]}`;
261
+ }
262
+ return mapping;
263
+ }
225
264
  /** Remove alias from expression. */
226
265
  function removeAliasReference(expression, alias) {
227
266
  const escaped = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -333,6 +372,66 @@ function resolveDependencyCycleText(schema, graph, currentId, missingId) {
333
372
  return null;
334
373
  }
335
374
  //#endregion
375
+ //#region src/library/rsform-api/attribution.ts
376
+ function attributionKey(attr) {
377
+ return `${attr.container}:${attr.attribute}`;
378
+ }
379
+ /**
380
+ * Remap attributions when constituents are substituted (original → replacement).
381
+ * Drops self-loops and duplicates. Matches sandbox / backend substitute attribution rewrite.
382
+ */
383
+ function remapAttributionsUnderSubstitution(attributions, origToSub) {
384
+ const result = [];
385
+ const seen = /* @__PURE__ */ new Set();
386
+ for (const attr of attributions) {
387
+ if (!origToSub.has(attr.container) && !origToSub.has(attr.attribute)) {
388
+ const key = attributionKey(attr);
389
+ if (!seen.has(key)) {
390
+ seen.add(key);
391
+ result.push({ ...attr });
392
+ }
393
+ continue;
394
+ }
395
+ const container = origToSub.get(attr.container) ?? attr.container;
396
+ const attribute = origToSub.get(attr.attribute) ?? attr.attribute;
397
+ if (container === attribute) continue;
398
+ const key = `${container}:${attribute}`;
399
+ if (seen.has(key)) continue;
400
+ seen.add(key);
401
+ result.push({
402
+ container,
403
+ attribute
404
+ });
405
+ }
406
+ return result;
407
+ }
408
+ /**
409
+ * Copy attributions whose both endpoints are in {@link sourceIdSet}, remapping ids via {@link idMap}.
410
+ * Appends onto a clone of {@link existing} with dedupe. Used by schema embedding / insert.
411
+ */
412
+ function importAttributions(sourceAttributions, sourceIdSet, idMap, existing = []) {
413
+ const result = existing.map((attr) => ({ ...attr }));
414
+ const seen = new Set(result.map(attributionKey));
415
+ for (const attr of sourceAttributions) {
416
+ if (!sourceIdSet.has(attr.container) || !sourceIdSet.has(attr.attribute)) continue;
417
+ const container = idMap[attr.container];
418
+ const attribute = idMap[attr.attribute];
419
+ if (container === void 0 || attribute === void 0 || container === attribute) continue;
420
+ const key = `${container}:${attribute}`;
421
+ if (seen.has(key)) continue;
422
+ seen.add(key);
423
+ result.push({
424
+ container,
425
+ attribute
426
+ });
427
+ }
428
+ return result;
429
+ }
430
+ /** Drop attributions that reference any id in {@link deletedIds}. */
431
+ function filterAttributions(attributions, deletedIds) {
432
+ return attributions.filter((attr) => !deletedIds.has(attr.container) && !deletedIds.has(attr.attribute));
433
+ }
434
+ //#endregion
336
435
  //#region src/library/rsform-api/expression.ts
337
436
  /** Infers the status of an expression based on parsing and value information. */
338
437
  function inferStatus(parse, value) {
@@ -367,7 +466,7 @@ function inferTemplate(expression) {
367
466
  const match = expression.match(/R\d+/g);
368
467
  return (match && match?.length > 0) ?? false;
369
468
  }
370
- /** Apply filter based on start {@link Constituenta} type. */
469
+ /** Apply filter based on start item type within an ordered list. */
371
470
  function applyFilterCategory(start, items) {
372
471
  const startIndex = items.indexOf(start);
373
472
  if (startIndex === -1) return [];
@@ -551,7 +650,7 @@ function kernelPriority(items, graph, parentOf) {
551
650
  /**
552
651
  * Schema-level statistics and issue flags.
553
652
  */
554
- /** Checks if {@link Constituenta} is a schema issue. */
653
+ /** Checks if an item is a schema issue. */
555
654
  function isSchemaIssue(cst) {
556
655
  return (cst.diagnostics?.length ?? 0) > 0 || cst.status === CstStatus.INCORRECT || cst.status === CstStatus.INCALCULABLE;
557
656
  }
@@ -674,7 +773,7 @@ function inferNewSpawnPosition(schema, targetId) {
674
773
  for (const cst of schema.items) if (cst.spawner === targetId) last = cst.id;
675
774
  return last ?? targetId;
676
775
  }
677
- /** Finds {@link Constituenta} by structure path. */
776
+ /** Finds schema item by absolute structure path under `targetId`. */
678
777
  function findCstByStructure(schema, target, path) {
679
778
  const byId = schema.cstByID ?? new Map(schema.items.map((item) => [item.id, item]));
680
779
  for (const cst of schema.items) {
@@ -684,7 +783,7 @@ function findCstByStructure(schema, target, path) {
684
783
  }
685
784
  return null;
686
785
  }
687
- /** Retrieves name for piece of target {@link Constituenta} structure. */
786
+ /** Retrieves name for piece of target structure. */
688
787
  function getStructureName(schema, target, path) {
689
788
  const representation = findCstByStructure(schema, target, path);
690
789
  if (representation) return `${representation.alias}: ${representation.term_resolved}`;
@@ -714,16 +813,276 @@ function resolveAbsoluteSpawnerPath(cst, targetId, byId) {
714
813
  return null;
715
814
  }
716
815
  //#endregion
816
+ //#region src/library/rsform-api/substitution.ts
817
+ /**
818
+ * Apply constituenta substitutions: remap attributions, drop originals, rewrite aliases in survivors.
819
+ * Does not resolve texts — call {@link resolveAllConstituentTexts} afterwards.
820
+ */
821
+ function applyConstituentSubstitutions(items, attributions, substitutions) {
822
+ if (substitutions.length === 0) return {
823
+ items: [...items],
824
+ attributions: attributions.map((attr) => ({ ...attr })),
825
+ deletedIds: /* @__PURE__ */ new Set(),
826
+ replacementIds: []
827
+ };
828
+ const byId = new Map(items.map((cst) => [cst.id, cst]));
829
+ const mapping = {};
830
+ const deletedIds = /* @__PURE__ */ new Set();
831
+ const origToSub = /* @__PURE__ */ new Map();
832
+ const replacementIds = [];
833
+ for (const { original, substitution } of substitutions) {
834
+ const originalCst = byId.get(original);
835
+ const substitutionCst = byId.get(substitution);
836
+ if (!originalCst || !substitutionCst) throw new Error(`applyConstituentSubstitutions: unknown constituenta ${original} -> ${substitution}`);
837
+ mapping[originalCst.alias] = substitutionCst.alias;
838
+ deletedIds.add(original);
839
+ origToSub.set(original, substitution);
840
+ replacementIds.push(substitution);
841
+ }
842
+ const nextItems = items.filter((cst) => !deletedIds.has(cst.id));
843
+ applyMappingToConstituents(nextItems, mapping, false);
844
+ return {
845
+ items: nextItems,
846
+ attributions: remapAttributionsUnderSubstitution(attributions, origToSub),
847
+ deletedIds,
848
+ replacementIds
849
+ };
850
+ }
851
+ /**
852
+ * Remap substitution endpoints after source constituents were inserted under new ids.
853
+ * If {@link original} was imported, map it; otherwise map {@link substitution}.
854
+ */
855
+ function remapSubstitutionsAfterImport(substitutions, sourceIdSet, idMap) {
856
+ return substitutions.map((sub) => {
857
+ if (sourceIdSet.has(sub.original)) return {
858
+ original: idMap[sub.original],
859
+ substitution: sub.substitution
860
+ };
861
+ return {
862
+ original: sub.original,
863
+ substitution: idMap[sub.substitution]
864
+ };
865
+ });
866
+ }
867
+ //#endregion
868
+ //#region src/library/rsform-api/text-resolution.ts
869
+ /** Build term-reference graph: referenced constituent → dependent (backend {@code graph_term}). */
870
+ function buildTermReferenceGraph(items) {
871
+ return buildReferenceGraph(items, "term_raw");
872
+ }
873
+ /** Build definition-reference graph: referenced constituent → dependent (backend {@code graph_text}). */
874
+ function buildDefinitionReferenceGraph(items) {
875
+ return buildReferenceGraph(items, "definition_raw");
876
+ }
877
+ /** Resolve all term and definition texts in topological order. Mutates items in place. */
878
+ function resolveAllConstituentTexts(items) {
879
+ const graphTerm = buildTermReferenceGraph(items);
880
+ const idToItem = new Map(items.map((item) => [item.id, item]));
881
+ const context = buildTermContext(items);
882
+ for (const id of graphTerm.topologicalOrder()) {
883
+ const row = idToItem.get(id);
884
+ if (!row) continue;
885
+ const resolved = resolveTextReferences(row.term_raw, context);
886
+ if (resolved !== row.term_resolved) {
887
+ row.term_resolved = resolved;
888
+ row.term_forms = [];
889
+ context[row.alias] = {
890
+ nominal: row.term_resolved,
891
+ forms: []
892
+ };
893
+ }
894
+ }
895
+ for (const row of items) row.definition_resolved = resolveTextReferences(row.definition_raw, context);
896
+ }
897
+ /**
898
+ * Resolve texts after a single constituent change, cascading dependents when the term changed.
899
+ * Mutates items in place.
900
+ */
901
+ function resolveConstituentTextChange(items, targetID, options) {
902
+ const idToItem = new Map(items.map((item) => [item.id, item]));
903
+ const target = idToItem.get(targetID);
904
+ if (!target) throw new Error(`resolveConstituentTextChange: unknown target ${targetID}`);
905
+ const context = buildTermContext(items);
906
+ if (options.termRawChanged) {
907
+ target.term_resolved = resolveTextReferences(target.term_raw, context);
908
+ if (options.clearTargetForms) target.term_forms = [];
909
+ context[target.alias] = toContextItem(target);
910
+ } else if (options.termChanged) context[target.alias] = toContextItem(target);
911
+ if (options.definitionRawChanged && !options.termChanged) target.definition_resolved = resolveTextReferences(target.definition_raw, context);
912
+ if (!options.termChanged) return;
913
+ const graphTerm = buildTermReferenceGraph(items);
914
+ const graphText = buildDefinitionReferenceGraph(items);
915
+ const expansion = graphTerm.expandAllOutputs([targetID]);
916
+ const expansionSet = new Set(expansion);
917
+ for (const id of graphTerm.topologicalOrder()) {
918
+ if (!expansionSet.has(id)) continue;
919
+ const expanded = idToItem.get(id);
920
+ if (!expanded) continue;
921
+ const resolved = resolveTextReferences(expanded.term_raw, context);
922
+ if (resolved !== expanded.term_resolved) {
923
+ expanded.term_resolved = resolved;
924
+ expanded.term_forms = [];
925
+ context[expanded.alias] = {
926
+ nominal: expanded.term_resolved,
927
+ forms: []
928
+ };
929
+ }
930
+ }
931
+ const updateDefs = /* @__PURE__ */ new Set([
932
+ targetID,
933
+ ...expansion,
934
+ ...graphText.expandAllOutputs([targetID, ...expansion])
935
+ ]);
936
+ for (const item of items) if (updateDefs.has(item.id)) item.definition_resolved = resolveTextReferences(item.definition_raw, context);
937
+ }
938
+ function buildReferenceGraph(items, field) {
939
+ const graph = new Graph();
940
+ const idByAlias = new Map(items.map((row) => [row.alias, row.id]));
941
+ for (const row of items) graph.addNode(row.id);
942
+ for (const row of items) for (const entity of extractEntities(row[field])) {
943
+ const source = idByAlias.get(entity);
944
+ if (source !== void 0) graph.addEdge(source, row.id);
945
+ }
946
+ return graph;
947
+ }
948
+ function buildTermContext(items) {
949
+ const context = {};
950
+ for (const row of items) context[row.alias] = toContextItem(row);
951
+ return context;
952
+ }
953
+ function toContextItem(row) {
954
+ return {
955
+ nominal: row.term_resolved,
956
+ forms: row.term_forms.map((form) => ({
957
+ text: form.text,
958
+ grams: parseGrammemes(form.tags)
959
+ }))
960
+ };
961
+ }
962
+ //#endregion
717
963
  //#region src/library/rsform-api/synthesis.ts
718
- /** Sorts library items relevant for InlineSynthesis with specified {@link RSForm}. */
964
+ /**
965
+ * Embed {@link InlineSynthesisInput.sourceItems} into the receiver and apply substitutions.
966
+ * Resolves term/definition entity references on the result.
967
+ * Does not mutate inputs.
968
+ */
969
+ function inlineSynthesis(input) {
970
+ const sourceItems = input.sourceItems;
971
+ if (sourceItems.length === 0) return {
972
+ items: input.receiverItems.map((item) => structuredClone(item)),
973
+ attributions: (input.receiverAttributions ?? []).map((attr) => ({ ...attr })),
974
+ nextId: input.nextId,
975
+ idMap: {},
976
+ aliasMapping: {},
977
+ deletedIds: /* @__PURE__ */ new Set(),
978
+ insertedIds: [],
979
+ replacementIds: []
980
+ };
981
+ const receiverItems = input.receiverItems.map((item) => structuredClone(item));
982
+ let attributions = (input.receiverAttributions ?? []).map((attr) => ({ ...attr }));
983
+ const aliasMapping = allocateImportAliases(receiverItems, sourceItems);
984
+ const idMap = {};
985
+ const inserted = [];
986
+ const sourceIdSet = new Set(sourceItems.map((cst) => cst.id));
987
+ let nextId = input.nextId;
988
+ for (const cst of sourceItems) {
989
+ const newId = nextId;
990
+ nextId += 1;
991
+ idMap[cst.id] = newId;
992
+ const cloned = structuredClone(cst);
993
+ cloned.id = newId;
994
+ if (Object.keys(aliasMapping).length > 0) {
995
+ cloned.alias = aliasMapping[cst.alias];
996
+ applyMappingToConstituents([cloned], aliasMapping, false);
997
+ }
998
+ inserted.push(cloned);
999
+ }
1000
+ attributions = importAttributions(input.sourceAttributions ?? [], sourceIdSet, idMap, attributions);
1001
+ const items = receiverItems.concat(inserted);
1002
+ resolveAllConstituentTexts(items);
1003
+ const substitutions = input.substitutions ?? [];
1004
+ if (substitutions.length === 0) return {
1005
+ items,
1006
+ attributions,
1007
+ nextId,
1008
+ idMap,
1009
+ aliasMapping,
1010
+ deletedIds: /* @__PURE__ */ new Set(),
1011
+ insertedIds: inserted.map((cst) => cst.id),
1012
+ replacementIds: []
1013
+ };
1014
+ const remapped = remapSubstitutionsAfterImport(substitutions, sourceIdSet, idMap);
1015
+ const substituted = applyConstituentSubstitutions(items, attributions, remapped);
1016
+ resolveAllConstituentTexts(substituted.items);
1017
+ return {
1018
+ items: substituted.items,
1019
+ attributions: substituted.attributions,
1020
+ nextId,
1021
+ idMap,
1022
+ aliasMapping,
1023
+ deletedIds: substituted.deletedIds,
1024
+ insertedIds: inserted.map((cst) => cst.id),
1025
+ replacementIds: substituted.replacementIds
1026
+ };
1027
+ }
1028
+ /** Sorts library items relevant for schema embedding with specified {@link RSForm}. */
719
1029
  function sortItemsForInlineSynthesis(receiver, items) {
720
1030
  const result = items.filter((item) => item.location === receiver.location);
721
- for (const item of items) if (item.visible && item.owner === receiver.owner && !result.includes(item)) result.push(item);
722
- for (const item of items) if (item.visible && !result.includes(item)) result.push(item);
723
- for (const item of items) if (!result.includes(item)) result.push(item);
1031
+ const included = new Set(result);
1032
+ for (const item of items) if (item.visible && item.owner === receiver.owner && !included.has(item)) {
1033
+ result.push(item);
1034
+ included.add(item);
1035
+ }
1036
+ for (const item of items) if (item.visible && !included.has(item)) {
1037
+ result.push(item);
1038
+ included.add(item);
1039
+ }
1040
+ for (const item of items) if (!included.has(item)) {
1041
+ result.push(item);
1042
+ included.add(item);
1043
+ }
724
1044
  return result;
725
1045
  }
726
1046
  //#endregion
1047
+ //#region src/library/rsform-api/transforms.ts
1048
+ /**
1049
+ * Pure constituenta list transforms: reorder, move, insert position.
1050
+ */
1051
+ /** Rebuild an item list following {@link orderedIds}. Throws if an id is missing. */
1052
+ function reorderItemsByIds(items, orderedIds) {
1053
+ const byId = new Map(items.map((item) => [item.id, item]));
1054
+ return orderedIds.map((id) => {
1055
+ const item = byId.get(id);
1056
+ if (!item) throw new Error(`reorderItemsByIds: missing id ${id}`);
1057
+ return item;
1058
+ });
1059
+ }
1060
+ /**
1061
+ * Move a subset of ids within an ordered id list.
1062
+ * {@link moveTo} is clamped to `[0, rest.length]` (index among non-moving items).
1063
+ */
1064
+ function moveIdsInOrder(ids, moving, moveTo) {
1065
+ const movingSet = new Set(moving);
1066
+ const rest = ids.filter((id) => !movingSet.has(id));
1067
+ const movingItems = ids.filter((id) => movingSet.has(id));
1068
+ const clamped = Math.max(0, Math.min(moveTo, rest.length));
1069
+ return [
1070
+ ...rest.slice(0, clamped),
1071
+ ...movingItems,
1072
+ ...rest.slice(clamped)
1073
+ ];
1074
+ }
1075
+ /** Insert {@link item} after {@link insertAfter}, or append when null/undefined/missing. Mutates {@link items}. */
1076
+ function insertItemAfter(items, item, insertAfter) {
1077
+ if (insertAfter === null || insertAfter === void 0) {
1078
+ items.push(item);
1079
+ return;
1080
+ }
1081
+ const idx = items.findIndex((row) => row.id === insertAfter);
1082
+ const insertAt = idx === -1 ? items.length : idx + 1;
1083
+ items.splice(insertAt, 0, item);
1084
+ }
1085
+ //#endregion
727
1086
  //#region src/library/diagnostics.ts
728
1087
  /** Origin of a diagnostic. */
729
1088
  const DiagnosticKind = {
@@ -744,7 +1103,7 @@ const RSDiagnosticCode = {
744
1103
  modelInvalidData: 35090,
745
1104
  modelEvalFail: 35091
746
1105
  };
747
- /** Whether a constituent has a schema/model diagnostic with the given code. */
1106
+ /** Whether an item has a schema/model diagnostic with the given code. */
748
1107
  function hasCstDiagnostic(cst, code) {
749
1108
  return cst.diagnostics?.some((item) => item.code === code) ?? false;
750
1109
  }
@@ -891,6 +1250,6 @@ function modelStatusToCode(status, cstType) {
891
1250
  }
892
1251
  }
893
1252
  //#endregion
894
- export { canProduceStructure as A, applyMappingToConstituents as C, validateAliasFormat as D, removeAliasReference as E, isBasicConcept as F, isFunctional as I, isLogical as L, guessCstType as M, inferClass as N, validateNewAlias as O, isBaseSet as P, isTemplateCst as R, addAliasReference as S, generateAlias as T, inferTemplate as _, formatDependencyCycle as a, getAnalysisFor as b, sortItemsForInlineSynthesis as c, inferNewSpawnPosition as d, calculateSchemaStats as f, inferStatus as g, applyFilterCategory as h, detectDependencyCycleDiagnostics as i, getCstTypePrefix as j, canHaveManualTypification as k, findCstByStructure as l, restoreConstituentOrder as m, RSDiagnosticCode as n, hasCstDiagnostic as o, isSchemaIssue as p, assignSchemaDiagnostics as r, modelStatusCstDiagnostic as s, DiagnosticKind as t, getStructureName as u, inferTemplatedType as v, argumentValuesToMapping as w, refineAnalysisForDependencyCycles as x, normalizeExpression as y, typeClassForCstType as z };
1253
+ export { isFunctional as $, normalizeExpression as A, buildSequentialAliasMapping as B, isSchemaIssue as C, inferStatus as D, applyFilterCategory as E, refineAnalysisForDependencyCycles as F, validateNewAlias as G, maxAliasIndex as H, addAliasReference as I, getCstTypePrefix as J, canHaveManualTypification as K, allocateImportAliases as L, importAttributions as M, remapAttributionsUnderSubstitution as N, inferTemplate as O, getAnalysisFor as P, isBasicConcept as Q, applyMappingToConstituents as R, calculateSchemaStats as S, restoreConstituentOrder as T, removeAliasReference as U, generateAlias as V, validateAliasFormat as W, inferClass as X, guessCstType as Y, isBaseSet as Z, applyConstituentSubstitutions as _, formatDependencyCycle as a, getStructureName as b, insertItemAfter as c, inlineSynthesis as d, isLogical as et, sortItemsForInlineSynthesis as f, resolveConstituentTextChange as g, resolveAllConstituentTexts as h, detectDependencyCycleDiagnostics as i, filterAttributions as j, inferTemplatedType as k, moveIdsInOrder as l, buildTermReferenceGraph as m, RSDiagnosticCode as n, typeClassForCstType as nt, hasCstDiagnostic as o, buildDefinitionReferenceGraph as p, canProduceStructure as q, assignSchemaDiagnostics as r, modelStatusCstDiagnostic as s, DiagnosticKind as t, isTemplateCst as tt, reorderItemsByIds as u, remapSubstitutionsAfterImport as v, buildFormalDependencyGraph as w, inferNewSpawnPosition as x, findCstByStructure as y, argumentValuesToMapping as z };
895
1254
 
896
- //# sourceMappingURL=diagnostics-B1OfMra1.js.map
1255
+ //# sourceMappingURL=diagnostics-ndGYbvgh.js.map