@shapeshift-labs/frontier-lang-compiler 0.2.103 → 0.2.105

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 (125) hide show
  1. package/README.md +14 -0
  2. package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
  3. package/dist/declarations/bidirectional-target-change.d.ts +10 -0
  4. package/dist/declarations/js-ts-safe-member-merge.d.ts +86 -0
  5. package/dist/declarations/js-ts-safe-merge.d.ts +131 -0
  6. package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
  7. package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
  8. package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
  9. package/dist/declarations/native-import-losses.d.ts +3 -0
  10. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
  11. package/dist/declarations/semantic-edit-script.d.ts +7 -4
  12. package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
  13. package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
  14. package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
  15. package/dist/declarations/semantic-transform-identity.d.ts +3 -0
  16. package/dist/declarations/source-preservation.d.ts +72 -0
  17. package/dist/declarations/universal-capability.d.ts +4 -0
  18. package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
  19. package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
  20. package/dist/declarations/universal-conversion-plan.d.ts +6 -1
  21. package/dist/declarations/universal-representation-coverage.d.ts +90 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +3 -0
  24. package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
  25. package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
  26. package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
  27. package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
  28. package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
  29. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
  30. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
  31. package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
  32. package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
  33. package/dist/internal/index-impl/diffNativeSymbols.js +3 -3
  34. package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
  35. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +43 -8
  36. package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
  37. package/dist/internal/index-impl/replaySemanticEditProjection.js +39 -19
  38. package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
  39. package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
  40. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
  41. package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
  42. package/dist/internal/index-impl/semanticEditProjectionRecord.js +29 -0
  43. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
  44. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
  45. package/dist/internal/index-impl/semanticEditScripts.js +4 -0
  46. package/dist/internal/index-impl/semanticEditSourceRanges.js +27 -0
  47. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
  48. package/dist/internal/index-impl/semanticPatchBundleAdmission.js +41 -7
  49. package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
  50. package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
  51. package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
  52. package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
  53. package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
  54. package/dist/js-ts-safe-member-merge-result.js +158 -0
  55. package/dist/js-ts-safe-member-merge.js +265 -0
  56. package/dist/js-ts-safe-merge-analyze.js +279 -0
  57. package/dist/js-ts-safe-merge-composed.js +170 -0
  58. package/dist/js-ts-safe-merge-constants.js +50 -0
  59. package/dist/js-ts-safe-merge-context.js +118 -0
  60. package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
  61. package/dist/js-ts-safe-merge-ledger.js +85 -0
  62. package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
  63. package/dist/js-ts-safe-merge-parse-statements.js +155 -0
  64. package/dist/js-ts-safe-merge-plan.js +190 -0
  65. package/dist/js-ts-safe-merge.js +175 -0
  66. package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
  67. package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
  68. package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
  69. package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
  70. package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
  71. package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
  72. package/dist/js-ts-semantic-merge-contracts.js +217 -0
  73. package/dist/js-ts-semantic-merge-member-containers.js +100 -0
  74. package/dist/js-ts-semantic-merge-member-keys.js +142 -0
  75. package/dist/js-ts-semantic-merge-member-segments.js +185 -0
  76. package/dist/js-ts-semantic-merge-member-source.js +82 -0
  77. package/dist/js-ts-semantic-merge-member-utils.js +18 -0
  78. package/dist/js-ts-semantic-merge-parse.js +16 -0
  79. package/dist/js-ts-semantic-merge.js +24 -0
  80. package/dist/lightweight-dependency-effects.js +51 -0
  81. package/dist/lightweight-dependency-language.js +12 -1
  82. package/dist/lightweight-dependency-relations.js +14 -27
  83. package/dist/native-region-scanner-core.js +33 -1
  84. package/dist/native-region-scanner-csharp.js +151 -0
  85. package/dist/native-region-scanner-dart.js +91 -0
  86. package/dist/native-region-scanner-dynamic.js +21 -151
  87. package/dist/native-region-scanner-functional.js +40 -13
  88. package/dist/native-region-scanner-java.js +97 -0
  89. package/dist/native-region-scanner-js-class.js +100 -0
  90. package/dist/native-region-scanner-js-helpers.js +28 -86
  91. package/dist/native-region-scanner-js-imports.js +121 -1
  92. package/dist/native-region-scanner-js-nested.js +96 -8
  93. package/dist/native-region-scanner-js-structure.js +27 -0
  94. package/dist/native-region-scanner-js-types.js +99 -0
  95. package/dist/native-region-scanner-js.js +70 -118
  96. package/dist/native-region-scanner-kotlin.js +94 -0
  97. package/dist/native-region-scanner-main.js +15 -181
  98. package/dist/native-region-scanner-php.js +80 -0
  99. package/dist/native-region-scanner-python.js +62 -0
  100. package/dist/native-region-scanner-ruby.js +72 -0
  101. package/dist/native-region-scanner-scala.js +91 -0
  102. package/dist/native-region-scanner-spans.js +74 -0
  103. package/dist/native-region-scanner-swift.js +155 -0
  104. package/dist/native-region-scanner.js +14 -10
  105. package/dist/native-source-ledger-helpers.js +195 -0
  106. package/dist/native-source-ledger.js +306 -0
  107. package/dist/native-source-preservation-scanner.js +4 -0
  108. package/dist/semantic-import-callsite-regions.js +136 -0
  109. package/dist/semantic-import-effect-regions.js +283 -0
  110. package/dist/semantic-import-regions.js +11 -2
  111. package/dist/semantic-import-sidecar-entry.js +16 -2
  112. package/dist/semantic-import-sidecar-types.d.ts +2 -0
  113. package/dist/semantic-sidecar-example.js +68 -0
  114. package/dist/universal-capability-matrix.js +23 -0
  115. package/dist/universal-conversion-artifact-query.js +79 -2
  116. package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
  117. package/dist/universal-conversion-artifact-summary.js +33 -1
  118. package/dist/universal-conversion-artifacts.js +13 -48
  119. package/dist/universal-conversion-plan-scoring.js +21 -1
  120. package/dist/universal-conversion-plan-summary.js +30 -0
  121. package/dist/universal-conversion-plan.js +25 -9
  122. package/dist/universal-conversion-route-metadata.js +96 -0
  123. package/dist/universal-conversion-route-operations.js +7 -0
  124. package/dist/universal-representation-coverage.js +193 -0
  125. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { uniqueStrings } from '../../native-import-utils.js';
2
+ import { summarizeSemanticSidecarQuality } from './semanticSidecarQuality.js';
2
3
 
3
4
  export function semanticEditRecordIndex(scripts, projections, replays, source = {}) {
4
5
  const operations = scripts.flatMap((script) => array(script.operations));
@@ -6,6 +7,8 @@ export function semanticEditRecordIndex(scripts, projections, replays, source =
6
7
  const replayEdits = replays.flatMap((replay) => array(replay.edits));
7
8
  const index = source.index ?? {};
8
9
  const summary = source.metadata?.semanticEditSummary ?? {};
10
+ const sidecarQuality = summarizeSemanticSidecarQuality([source, ...scripts, ...projections, ...replays]);
11
+ const priorSidecarQuality = summary.semanticSidecarQuality ?? {};
9
12
  return {
10
13
  semanticEditScriptIds: uniqueStrings([...strings(source.semanticEditScriptIds), ...strings(source.semanticEditScriptId), ...strings(index.semanticEditScriptIds), ...strings(summary.scriptIds), ...scripts.map((script) => script.id), ...replays.map((replay) => replay.scriptId)]),
11
14
  semanticEditProjectionIds: uniqueStrings([...strings(source.semanticEditProjectionIds), ...strings(source.semanticEditProjectionId), ...strings(index.semanticEditProjectionIds), ...strings(summary.projectionIds), ...projections.map((projection) => projection.id), ...replays.map((replay) => replay.projectionId)]),
@@ -15,8 +18,10 @@ export function semanticEditRecordIndex(scripts, projections, replays, source =
15
18
  semanticEditReplayEditCount: replayEdits.length,
16
19
  semanticEditReplayStatuses: uniqueStrings([...strings(source.semanticEditReplayStatuses), ...strings(index.semanticEditReplayStatuses), ...strings(summary.replayStatuses), ...replays.map((replay) => replay.status)]),
17
20
  semanticEditReplayActions: uniqueStrings([...strings(source.semanticEditReplayActions), ...strings(index.semanticEditReplayActions), ...strings(summary.replayActions), ...replays.map((replay) => replay.admission?.action)]),
21
+ semanticEditReplayReasonCodes: uniqueStrings([...strings(source.semanticEditReplayReasonCodes), ...strings(index.semanticEditReplayReasonCodes), ...strings(summary.replayReasonCodes), ...replays.flatMap(replayReasonCodes)]),
18
22
  semanticEditReplayCurrentHashes: uniqueStrings([...strings(source.semanticEditReplayCurrentHashes), ...strings(index.semanticEditReplayCurrentHashes), ...strings(summary.replayCurrentHashes), ...strings(summary.semanticEditReplayCurrentHashes), ...replays.map((replay) => replay.currentHash)]),
19
23
  semanticEditReplayOutputHashes: uniqueStrings([...strings(source.semanticEditReplayOutputHashes), ...strings(index.semanticEditReplayOutputHashes), ...strings(summary.replayOutputHashes), ...strings(summary.semanticEditReplayOutputHashes), ...replays.map((replay) => replay.outputHash)]),
24
+ sourceBackprojectionModes: uniqueStrings([...strings(source.sourceBackprojectionModes), ...strings(index.sourceBackprojectionModes), ...strings(summary.sourceBackprojectionModes), ...scripts.flatMap(scriptBackprojectionModes), ...projections.map((projection) => projection.metadata?.sourceBackprojectionMode), ...replays.map((replay) => replay.metadata?.sourceBackprojectionMode)]),
20
25
  semanticEditKeys: uniqueStrings([...strings(source.semanticEditKeys), ...strings(index.semanticEditKeys), ...strings(summary.semanticEditKeys), ...operations.map((operation) => operation.semanticKey), ...edits.map((edit) => edit.semanticKey), ...replayEdits.map((edit) => edit.semanticKey)]),
21
26
  semanticIdentityHashes: uniqueStrings([...strings(source.semanticIdentityHashes), ...strings(index.semanticIdentityHashes), ...strings(summary.semanticIdentityHashes), ...operations.map((operation) => operation.semanticIdentityHash), ...edits.map((edit) => edit.semanticIdentityHash), ...replayEdits.map((edit) => edit.semanticIdentityHash)]),
22
27
  sourceIdentityHashes: uniqueStrings([...strings(source.sourceIdentityHashes), ...strings(index.sourceIdentityHashes), ...strings(summary.sourceIdentityHashes), ...operations.map((operation) => operation.sourceIdentityHash), ...edits.map((edit) => edit.sourceIdentityHash), ...replayEdits.map((edit) => edit.sourceIdentityHash)]),
@@ -24,7 +29,15 @@ export function semanticEditRecordIndex(scripts, projections, replays, source =
24
29
  editContentHashes: uniqueStrings([...strings(source.editContentHashes), ...strings(index.editContentHashes), ...strings(summary.editContentHashes), ...edits.map((edit) => edit.editContentHash), ...replayEdits.map((edit) => edit.editContentHash)]),
25
30
  anchorKeys: uniqueStrings([...strings(source.anchorKeys), ...strings(index.anchorKeys), ...strings(summary.anchorKeys), ...operations.map((operation) => operation.anchor?.key), ...edits.map((edit) => edit.anchorKey), ...replayEdits.map((edit) => edit.anchorKey)]),
26
31
  conflictKeys: uniqueStrings([...strings(source.conflictKeys), ...strings(index.conflictKeys), ...strings(summary.conflictKeys), ...operations.map((operation) => operation.anchor?.conflictKey), ...edits.map((edit) => edit.conflictKey), ...replayEdits.map((edit) => edit.conflictKey)]),
27
- projectedSourcePaths: uniqueStrings([...strings(source.projectedSourcePaths), ...strings(index.projectedSourcePaths), ...strings(summary.projectedSourcePaths), ...projections.map((projection) => projection.sourcePath), ...edits.flatMap((edit) => [edit.sourcePath, edit.targetSourcePath]), ...replays.map((replay) => replay.sourcePath), ...replayEdits.map((edit) => edit.sourcePath)])
32
+ projectedSourcePaths: uniqueStrings([...strings(source.projectedSourcePaths), ...strings(index.projectedSourcePaths), ...strings(summary.projectedSourcePaths), ...projections.map((projection) => projection.sourcePath), ...edits.flatMap((edit) => [edit.sourcePath, edit.targetSourcePath]), ...replays.map((replay) => replay.sourcePath), ...replayEdits.map((edit) => edit.sourcePath)]),
33
+ semanticEditSidecarQualityRecords: maxCount(sidecarQuality.records, source.semanticEditSidecarQualityRecords, index.semanticEditSidecarQualityRecords, priorSidecarQuality.records),
34
+ semanticEditSidecarSymbolCount: maxCount(sidecarQuality.symbols, source.semanticEditSidecarSymbolCount, index.semanticEditSidecarSymbolCount, priorSidecarQuality.symbols),
35
+ semanticEditSidecarOwnershipRegionCount: maxCount(sidecarQuality.ownershipRegions, source.semanticEditSidecarOwnershipRegionCount, index.semanticEditSidecarOwnershipRegionCount, priorSidecarQuality.ownershipRegions),
36
+ semanticEditSidecarPatchHintCount: maxCount(sidecarQuality.patchHints, source.semanticEditSidecarPatchHintCount, index.semanticEditSidecarPatchHintCount, priorSidecarQuality.patchHints),
37
+ semanticEditSidecarWarningCount: maxCount(sidecarQuality.warnings, source.semanticEditSidecarWarningCount, index.semanticEditSidecarWarningCount, priorSidecarQuality.warnings),
38
+ semanticEditSidecarZeroRecordWarningCount: maxCount(sidecarQuality.zeroRecordWarnings, source.semanticEditSidecarZeroRecordWarningCount, index.semanticEditSidecarZeroRecordWarningCount, priorSidecarQuality.zeroRecordWarnings),
39
+ semanticEditSidecarWarningCodes: uniqueStrings([...strings(source.semanticEditSidecarWarningCodes), ...strings(index.semanticEditSidecarWarningCodes), ...strings(priorSidecarQuality.warningCodes), ...sidecarQuality.warningCodes]),
40
+ semanticEditSidecarZeroRecordWarningCodes: uniqueStrings([...strings(source.semanticEditSidecarZeroRecordWarningCodes), ...strings(index.semanticEditSidecarZeroRecordWarningCodes), ...strings(priorSidecarQuality.zeroRecordWarningCodes), ...sidecarQuality.zeroRecordWarningCodes])
28
41
  };
29
42
  }
30
43
 
@@ -36,8 +49,10 @@ export function semanticEditSummary(index) {
36
49
  replayIds: index.semanticEditReplayIds,
37
50
  replayStatuses: index.semanticEditReplayStatuses,
38
51
  replayActions: index.semanticEditReplayActions,
52
+ replayReasonCodes: index.semanticEditReplayReasonCodes,
39
53
  replayCurrentHashes: index.semanticEditReplayCurrentHashes,
40
54
  replayOutputHashes: index.semanticEditReplayOutputHashes,
55
+ sourceBackprojectionModes: index.sourceBackprojectionModes,
41
56
  semanticEditKeys: index.semanticEditKeys,
42
57
  semanticIdentityHashes: index.semanticIdentityHashes,
43
58
  sourceIdentityHashes: index.sourceIdentityHashes,
@@ -46,6 +61,16 @@ export function semanticEditSummary(index) {
46
61
  anchorKeys: index.anchorKeys,
47
62
  conflictKeys: index.conflictKeys,
48
63
  projectedSourcePaths: index.projectedSourcePaths,
64
+ semanticSidecarQuality: {
65
+ records: index.semanticEditSidecarQualityRecords,
66
+ symbols: index.semanticEditSidecarSymbolCount,
67
+ ownershipRegions: index.semanticEditSidecarOwnershipRegionCount,
68
+ patchHints: index.semanticEditSidecarPatchHintCount,
69
+ warnings: index.semanticEditSidecarWarningCount,
70
+ zeroRecordWarnings: index.semanticEditSidecarZeroRecordWarningCount,
71
+ warningCodes: index.semanticEditSidecarWarningCodes,
72
+ zeroRecordWarningCodes: index.semanticEditSidecarZeroRecordWarningCodes
73
+ },
49
74
  replayEditCount: index.semanticEditReplayEditCount
50
75
  });
51
76
  }
@@ -57,6 +82,27 @@ function replayOperationIds(replays) {
57
82
  ...array(replay.edits).map((edit) => edit.operationId)
58
83
  ]);
59
84
  }
85
+ function replayReasonCodes(replay) {
86
+ return [
87
+ ...array(replay.admission?.reasonCodes),
88
+ ...array(replay.summary?.reasonCodes),
89
+ ...array(replay.diagnostics).flatMap((diagnostic) => array(diagnostic.reasonCodes)),
90
+ ...array(replay.edits).flatMap((edit) => array(edit.reasonCodes))
91
+ ];
92
+ }
93
+ function scriptBackprojectionModes(script) {
94
+ return [
95
+ script.metadata?.sourceBackprojectionMode,
96
+ script.metadata?.sourceProjectionHint?.sourceBackprojectionMode,
97
+ ...array(script.operations).map((operation) => operation.metadata?.sourceBackprojection?.mode)
98
+ ];
99
+ }
100
+ function maxCount(...values) {
101
+ return Math.max(0, ...values.map((value) => {
102
+ const count = Number(value ?? 0);
103
+ return Number.isFinite(count) ? count : 0;
104
+ }));
105
+ }
60
106
  function array(value) { if (value === undefined || value === null) return []; return Array.isArray(value) ? value : [value]; }
61
107
  function strings(value) { return array(value).map((entry) => String(entry ?? '')).filter(Boolean); }
62
108
  function compactRecord(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0))); }
@@ -0,0 +1,40 @@
1
+ import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
2
+ import { spanOffsets } from './semanticEditSourceRanges.js';
3
+
4
+ export function explicitSourceReplacementEditForOperation(operation, identity, headSourceText, order) {
5
+ const backprojection = operation.metadata?.sourceBackprojection;
6
+ if (backprojection?.mode !== 'cross-language-explicit-source-replacement') return undefined;
7
+ const replacement = backprojection.sourceReplacementText;
8
+ const range = spanOffsets(headSourceText, backprojection.sourceEditSpan ?? operation.spans?.head ?? operation.spans?.base);
9
+ const anchorRange = spanOffsets(headSourceText, operation.anchor?.sourceSpan);
10
+ const reasons = [];
11
+ if (typeof replacement !== 'string') reasons.push(`source-replacement-text-missing:${operation.id}`);
12
+ if (!range) reasons.push(`head-span-not-resolvable:${operation.id}`);
13
+ if (reasons.length) return { ok: false, reasonCodes: reasons };
14
+ const current = headSourceText.slice(range.start, range.end);
15
+ const currentHash = hashSemanticValue(current);
16
+ const replacementHash = hashSemanticValue(replacement);
17
+ const expectedCurrentHash = backprojection.sourceEditTextHash ?? operation.hashes?.headTextHash ?? operation.hashes?.baseTextHash;
18
+ if (expectedCurrentHash && currentHash !== expectedCurrentHash) reasons.push(`head-span-hash-mismatch:${operation.id}`);
19
+ if (backprojection.sourceReplacementTextHash && replacementHash !== backprojection.sourceReplacementTextHash) {
20
+ reasons.push(`source-replacement-text-hash-mismatch:${operation.id}`);
21
+ }
22
+ if (reasons.length) return { ok: false, reasonCodes: reasons };
23
+ return {
24
+ ok: true,
25
+ value: {
26
+ operationId: operation.id,
27
+ order,
28
+ ...identity,
29
+ editKind: 'replace',
30
+ sourceRangeKind: 'cross-language-explicit-source-replacement',
31
+ start: range.start,
32
+ end: range.end,
33
+ headAnchorStart: anchorRange?.start,
34
+ headAnchorEnd: anchorRange?.end,
35
+ replacement,
36
+ replacementSpanText: replacement,
37
+ current
38
+ }
39
+ };
40
+ }
@@ -7,14 +7,16 @@ export function markCoveredSemanticEditOperations(operations, context) {
7
7
  worker: nativeImportSourceText(context.worker)
8
8
  };
9
9
  return (operations ?? []).map((operation) => {
10
- const coveredBy = coveredByChildOperations(operation, operations, sourceText);
10
+ const childCoverage = coveredByChildOperations(operation, operations, sourceText);
11
+ const parentCoverage = childCoverage.length ? [] : coveredByParentOperations(operation, operations, sourceText);
12
+ const coveredBy = childCoverage.length ? childCoverage : parentCoverage;
11
13
  if (!coveredBy.length) return operation;
12
14
  return {
13
15
  ...operation,
14
16
  status: 'covered',
15
17
  readiness: 'ready',
16
18
  confidence: Math.max(operation.confidence ?? 0, 0.82),
17
- reasonCodes: uniqueStrings([...(operation.reasonCodes ?? []), 'container-covered-by-child-edits']),
19
+ reasonCodes: uniqueStrings([...(operation.reasonCodes ?? []), coverageReason(childCoverage)]),
18
20
  evidenceIds: uniqueStrings(operation.evidenceIds ?? []),
19
21
  metadata: {
20
22
  ...(operation.metadata ?? {}),
@@ -24,6 +26,10 @@ export function markCoveredSemanticEditOperations(operations, context) {
24
26
  });
25
27
  }
26
28
 
29
+ function coverageReason(childCoverage) {
30
+ return childCoverage.length ? 'container-covered-by-child-edits' : 'child-covered-by-container-edit';
31
+ }
32
+
27
33
  function coveredByChildOperations(container, operations, sourceText) {
28
34
  if (!isCoverableContainer(container)) return [];
29
35
  const containerBase = spanOffsets(sourceText.base, container.spans?.base);
@@ -43,7 +49,31 @@ function isCoverableContainer(operation) {
43
49
  if (operation.changeKind !== 'modified') return false;
44
50
  if (!operation.spans?.base || !operation.spans?.worker) return false;
45
51
  const kind = String(operation.anchor?.regionKind ?? operation.regionKind ?? '');
46
- return kind === 'type' || kind === 'config' || kind === 'content' || kind === 'route' || kind === 'property';
52
+ return ['type', 'config', 'content', 'route', 'property', 'controlFlow', 'effect', 'mutation'].includes(kind);
53
+ }
54
+
55
+ function coveredByParentOperations(child, operations, sourceText) {
56
+ if (child.changeKind !== 'added' && child.changeKind !== 'removed') return [];
57
+ if (!isSemanticFactRegion(child)) return [];
58
+ const side = child.changeKind === 'removed' ? 'base' : 'worker';
59
+ const childRange = spanOffsets(sourceText[side], child.spans?.[side]);
60
+ if (!childRange) return [];
61
+ return (operations ?? []).filter((parent) => parent.id !== child.id
62
+ && parent.changeKind === child.changeKind
63
+ && ['portable', 'already-applied'].includes(parent.status)
64
+ && parent.anchor?.regionKind === 'body'
65
+ && sameSourcePath(parent, child)
66
+ && contained(childRange, spanOffsets(sourceText[side], parent.spans?.[side])));
67
+ }
68
+
69
+ function isSemanticFactRegion(operation) {
70
+ return ['controlFlow', 'effect', 'mutation', 'call'].includes(String(operation.anchor?.regionKind ?? ''));
71
+ }
72
+
73
+ function sameSourcePath(left, right) {
74
+ const leftPath = left.anchor?.sourcePath ?? left.insertion?.sourcePath;
75
+ const rightPath = right.anchor?.sourcePath ?? right.insertion?.sourcePath;
76
+ return !leftPath || !rightPath || leftPath === rightPath;
47
77
  }
48
78
 
49
79
  function childEdit(operation, sourceText, containerBase) {
@@ -6,6 +6,7 @@ export function projectionEditRecord(edit) {
6
6
  const replacementTextHash = hashSemanticValue(edit.replacement);
7
7
  const replacementSpanText = edit.replacementSpanText ?? edit.replacement;
8
8
  const identity = semanticEditIdentityFields(edit);
9
+ const sourceIdentity = sourceIdentityAnchorFields(edit);
9
10
  return compactRecord({
10
11
  operationId: edit.operationId,
11
12
  status: edit.alreadyApplied ? 'already-applied' : 'applied',
@@ -26,9 +27,14 @@ export function projectionEditRecord(edit) {
26
27
  symbolName: edit.symbolName,
27
28
  symbolKind: edit.symbolKind,
28
29
  ...identity,
30
+ ...sourceIdentity,
29
31
  operationContentHash: edit.operationContentHash,
30
32
  editContentHash: hashSemanticValue(compactRecord({
31
33
  semanticIdentityHash: identity.semanticIdentityHash,
34
+ sourceIdentityHash: identity.sourceIdentityHash,
35
+ sourceIdentityStatus: sourceIdentity.sourceIdentityStatus,
36
+ sourceIdentityAnchorKey: sourceIdentity.sourceIdentityAnchorKey,
37
+ targetIdentityAnchorKey: sourceIdentity.targetIdentityAnchorKey,
32
38
  sourceRangeKind: edit.sourceRangeKind,
33
39
  deletedTextHash,
34
40
  replacementTextHash,
@@ -48,6 +54,7 @@ export function projectionEditRecord(edit) {
48
54
  replacementBytes: edit.replacement.length,
49
55
  deletedTextHash,
50
56
  replacementTextHash,
57
+ deletedText: deletedTextForEdit(edit),
51
58
  deletedTextLineEndingStableHash: lineEndingStableTextHash(edit.current),
52
59
  replacementTextLineEndingStableHash: lineEndingStableTextHash(edit.replacement),
53
60
  anchorDeletedTextHash: edit.anchorDeletedTextHash,
@@ -63,6 +70,28 @@ export function projectionEditRecord(edit) {
63
70
  });
64
71
  }
65
72
 
73
+ function deletedTextForEdit(edit) {
74
+ return edit.sourceRangeKind === 'cross-language-explicit-source-replacement' ? edit.current : undefined;
75
+ }
76
+
77
+ function sourceIdentityAnchorFields(edit) {
78
+ const sourceIdentityAnchorKey = edit.sourceIdentityAnchorKey ?? edit.anchorKey;
79
+ const targetIdentityAnchorKey = edit.targetIdentityAnchorKey ?? edit.targetAnchorKey ?? sourceIdentityAnchorKey;
80
+ const sourceIdentitySourcePath = edit.sourceIdentitySourcePath ?? edit.originalSourcePath ?? edit.sourcePath;
81
+ const targetIdentitySourcePath = edit.targetIdentitySourcePath ?? edit.targetSourcePath ?? edit.sourcePath;
82
+ const moved = Boolean(
83
+ (sourceIdentityAnchorKey && targetIdentityAnchorKey && sourceIdentityAnchorKey !== targetIdentityAnchorKey)
84
+ || (sourceIdentitySourcePath && targetIdentitySourcePath && sourceIdentitySourcePath !== targetIdentitySourcePath)
85
+ );
86
+ return compactRecord({
87
+ sourceIdentityStatus: edit.sourceIdentityStatus ?? (moved ? 'moved-source' : 'same-source'),
88
+ sourceIdentityAnchorKey,
89
+ targetIdentityAnchorKey,
90
+ sourceIdentitySourcePath,
91
+ targetIdentitySourcePath
92
+ });
93
+ }
94
+
66
95
  function lineEndingStableTextHash(value) {
67
96
  const normalized = lineEndingStableText(value);
68
97
  return normalized === undefined ? undefined : hashSemanticValue(normalized);
@@ -8,6 +8,7 @@ export function replayEditDiagnostics(edit, status, range, reasonCodes, sourceTe
8
8
  status,
9
9
  operationId: edit.operationId,
10
10
  sourcePath: edit.targetSourcePath ?? edit.sourcePath,
11
+ ...sourceIdentityDiagnosticContext(edit),
11
12
  symbolName: edit.targetSymbolName ?? edit.symbolName,
12
13
  symbolKind: edit.targetSymbolKind ?? edit.symbolKind,
13
14
  editKind: edit.editKind,
@@ -64,6 +65,7 @@ function appendOverlapDiagnostic(overlapDiagnostics, edit, code, operationIds) {
64
65
  status: 'conflict',
65
66
  operationId: edit.operationId,
66
67
  sourcePath: edit.sourcePath,
68
+ ...sourceIdentityDiagnosticContext(edit),
67
69
  symbolName: edit.symbolName,
68
70
  symbolKind: edit.symbolKind,
69
71
  editKind: edit.editKind,
@@ -93,6 +95,18 @@ function replayDiagnostic(code, context) {
93
95
  status: context.status,
94
96
  operationId: context.operationId,
95
97
  sourcePath: context.sourcePath,
98
+ originalSourcePath: context.originalSourcePath,
99
+ targetSourcePath: context.targetSourcePath,
100
+ anchorKey: context.anchorKey,
101
+ targetAnchorKey: context.targetAnchorKey,
102
+ sourceIdentityStatus: context.sourceIdentityStatus,
103
+ sourceIdentityAnchorKey: context.sourceIdentityAnchorKey,
104
+ targetIdentityAnchorKey: context.targetIdentityAnchorKey,
105
+ sourceIdentitySourcePath: context.sourceIdentitySourcePath,
106
+ targetIdentitySourcePath: context.targetIdentitySourcePath,
107
+ semanticIdentityHash: context.semanticIdentityHash,
108
+ sourceIdentityHash: context.sourceIdentityHash,
109
+ editContentHash: context.editContentHash,
96
110
  symbolName: context.symbolName,
97
111
  symbolKind: context.symbolKind,
98
112
  editKind: context.editKind,
@@ -105,6 +119,31 @@ function replayDiagnostic(code, context) {
105
119
  });
106
120
  }
107
121
 
122
+ function sourceIdentityDiagnosticContext(edit) {
123
+ const sourceIdentityAnchorKey = edit.sourceIdentityAnchorKey ?? edit.anchorKey;
124
+ const targetIdentityAnchorKey = edit.targetIdentityAnchorKey ?? edit.targetAnchorKey ?? sourceIdentityAnchorKey;
125
+ const sourceIdentitySourcePath = edit.sourceIdentitySourcePath ?? edit.originalSourcePath ?? edit.sourcePath;
126
+ const targetIdentitySourcePath = edit.targetIdentitySourcePath ?? edit.targetSourcePath ?? edit.sourcePath;
127
+ const moved = Boolean(
128
+ (sourceIdentityAnchorKey && targetIdentityAnchorKey && sourceIdentityAnchorKey !== targetIdentityAnchorKey)
129
+ || (sourceIdentitySourcePath && targetIdentitySourcePath && sourceIdentitySourcePath !== targetIdentitySourcePath)
130
+ );
131
+ return compactRecord({
132
+ originalSourcePath: edit.originalSourcePath,
133
+ targetSourcePath: edit.targetSourcePath,
134
+ anchorKey: edit.anchorKey,
135
+ targetAnchorKey: edit.targetAnchorKey,
136
+ sourceIdentityStatus: edit.sourceIdentityStatus ?? (moved ? 'moved-source' : 'same-source'),
137
+ sourceIdentityAnchorKey,
138
+ targetIdentityAnchorKey,
139
+ sourceIdentitySourcePath,
140
+ targetIdentitySourcePath,
141
+ semanticIdentityHash: edit.semanticIdentityHash,
142
+ sourceIdentityHash: edit.sourceIdentityHash,
143
+ editContentHash: edit.editContentHash
144
+ });
145
+ }
146
+
108
147
  function replayDiagnosticCategory(code, status) {
109
148
  if (code.includes('overlap')) return 'overlap';
110
149
  if (code.startsWith('missing-current-source') || code.startsWith('missing-head-source') || code.startsWith('missing-worker-source')) return 'missing-source';
@@ -0,0 +1,85 @@
1
+ export function explicitSourceReplacementReplayRange(edit, symbolRange, sourceText) {
2
+ if (edit.sourceRangeKind !== 'cross-language-explicit-source-replacement' || !symbolRange || typeof sourceText !== 'string') {
3
+ return undefined;
4
+ }
5
+ const deleted = uniqueTextRange(sourceText, symbolRange, edit.deletedText, 'deleted-text');
6
+ if (deleted.status === 'matched') return deleted;
7
+ const replacement = uniqueTextRange(sourceText, symbolRange, edit.replacementText, 'replacement-text');
8
+ if (replacement.status === 'matched') return replacement;
9
+ const relative = relativeAnchorRange(edit, symbolRange);
10
+ return {
11
+ ...relative,
12
+ conflictReasonCodes: [deleted.reasonCode, replacement.reasonCode].filter(Boolean)
13
+ };
14
+ }
15
+
16
+ function uniqueTextRange(sourceText, symbolRange, needle, label) {
17
+ if (typeof needle !== 'string' || needle.length === 0) {
18
+ return { status: 'missing', reasonCode: `current-symbol-explicit-source-replacement-${label}-missing` };
19
+ }
20
+ const symbolText = sourceText.slice(symbolRange.start, symbolRange.end);
21
+ const matches = [];
22
+ for (let index = symbolText.indexOf(needle); index >= 0; index = symbolText.indexOf(needle, index + 1)) {
23
+ const start = symbolRange.start + index;
24
+ if (isCodeOffset(sourceText, start)) matches.push(start);
25
+ }
26
+ if (matches.length !== 1) {
27
+ return { status: matches.length ? 'ambiguous' : 'missing', reasonCode: `current-symbol-explicit-source-replacement-${label}-${matches.length ? 'ambiguous' : 'missing'}` };
28
+ }
29
+ const first = matches[0] - symbolRange.start;
30
+ return {
31
+ status: 'matched',
32
+ range: { start: symbolRange.start + first, end: symbolRange.start + first + needle.length },
33
+ reasonCode: `current-symbol-explicit-source-replacement-${label}`
34
+ };
35
+ }
36
+
37
+ function isCodeOffset(sourceText, offset) {
38
+ let state = 'code';
39
+ for (let index = 0; index < offset; index += 1) {
40
+ const char = sourceText[index];
41
+ const next = sourceText[index + 1];
42
+ if (state === 'line-comment') {
43
+ if (char === '\n' || char === '\r') state = 'code';
44
+ continue;
45
+ }
46
+ if (state === 'block-comment') {
47
+ if (char === '*' && next === '/') {
48
+ index += 1;
49
+ state = 'code';
50
+ }
51
+ continue;
52
+ }
53
+ if (state === 'single' || state === 'double' || state === 'template') {
54
+ if (char === '\\') {
55
+ index += 1;
56
+ continue;
57
+ }
58
+ if ((state === 'single' && char === "'") || (state === 'double' && char === '"') || (state === 'template' && char === '`')) state = 'code';
59
+ continue;
60
+ }
61
+ if (char === '/' && next === '/') {
62
+ index += 1;
63
+ state = 'line-comment';
64
+ } else if (char === '#') {
65
+ state = 'line-comment';
66
+ } else if (char === '/' && next === '*') {
67
+ index += 1;
68
+ state = 'block-comment';
69
+ } else if (char === "'") state = 'single';
70
+ else if (char === '"') state = 'double';
71
+ else if (char === '`') state = 'template';
72
+ }
73
+ return state === 'code';
74
+ }
75
+
76
+ function relativeAnchorRange(edit, symbolRange) {
77
+ if (!Number.isFinite(edit.headAnchorStart) || !Number.isFinite(edit.headAnchorEnd)) return undefined;
78
+ if (!Number.isFinite(edit.headStart) || !Number.isFinite(edit.headEnd)) return undefined;
79
+ const offset = edit.headStart - edit.headAnchorStart;
80
+ const length = edit.headEnd - edit.headStart;
81
+ if (offset < 0 || length < 0) return undefined;
82
+ const range = { start: symbolRange.start + offset, end: symbolRange.start + offset + length };
83
+ if (range.start < symbolRange.start || range.end > symbolRange.end) return undefined;
84
+ return { range, reasonCode: 'current-symbol-explicit-source-replacement-relative-offset' };
85
+ }
@@ -226,6 +226,10 @@ function semanticEditOperationKind(region) {
226
226
  if (kind === 'import') return `${prefix}Import`;
227
227
  if (kind === 'type') return `${prefix}TypeDeclaration`;
228
228
  if (kind === 'property') return `${prefix}Property`;
229
+ if (kind === 'call') return `${prefix}Callsite`;
230
+ if (kind === 'controlFlow') return `${prefix}ControlFlow`;
231
+ if (kind === 'effect') return `${prefix}Effect`;
232
+ if (kind === 'mutation') return `${prefix}Mutation`;
229
233
  return `${prefix}Region`;
230
234
  }
231
235
 
@@ -1,5 +1,7 @@
1
1
  import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
2
2
 
3
+ const nestedBodyCoveredKinds = new Set(['export', 'call', 'controlFlow', 'effect', 'mutation']);
4
+
3
5
  export function projectionCoveredContainerOperationIds(operations, workerSourceText) {
4
6
  if (typeof workerSourceText !== 'string') return new Set();
5
7
  const result = new Set();
@@ -7,6 +9,9 @@ export function projectionCoveredContainerOperationIds(operations, workerSourceT
7
9
  if (!isProjectionCoverableContainer(operation)) continue;
8
10
  if (workerContainerCoveredByInsertedChildren(operation, operations, workerSourceText)) result.add(operation.id);
9
11
  }
12
+ for (const operation of operations ?? []) {
13
+ if (operationCoveredByBody(operation, operations, workerSourceText)) result.add(operation.id);
14
+ }
10
15
  return result;
11
16
  }
12
17
 
@@ -111,6 +116,28 @@ function workerContainerCoveredByInsertedChildren(container, operations, workerS
111
116
  return hashSemanticValue(stripped) === container.hashes.baseTextHash;
112
117
  }
113
118
 
119
+ function operationCoveredByBody(operation, operations, workerSourceText) {
120
+ const kind = operation.anchor?.regionKind;
121
+ if (!nestedBodyCoveredKinds.has(kind)) return false;
122
+ if (!['added', 'modified'].includes(operation.changeKind)) return false;
123
+ const range = spanOffsets(workerSourceText, operation.spans?.worker);
124
+ if (!range) return false;
125
+ return (operations ?? []).some((candidate) => (
126
+ candidate.id !== operation.id
127
+ && ['portable', 'already-applied'].includes(candidate.status)
128
+ && candidate.anchor?.regionKind === 'body'
129
+ && (kind !== 'export' || candidate.anchor?.symbolName === operation.anchor?.symbolName)
130
+ && sameOperationSourcePath(candidate, operation)
131
+ && containedRange(range, spanOffsets(workerSourceText, candidate.spans?.worker))
132
+ ));
133
+ }
134
+
135
+ function sameOperationSourcePath(left, right) {
136
+ const leftPath = left.anchor?.sourcePath ?? left.insertion?.sourcePath;
137
+ const rightPath = right.anchor?.sourcePath ?? right.insertion?.sourcePath;
138
+ return !leftPath || !rightPath || leftPath === rightPath;
139
+ }
140
+
114
141
  function containedRange(inner, outer) {
115
142
  return Boolean(inner && outer && outer.start <= inner.start && inner.end <= outer.end);
116
143
  }
@@ -35,6 +35,7 @@ export function semanticIndexFromNativeDeclarations(declarations, input, options
35
35
  signatureHash: hashSemanticValue([input.language, declaration.nativeNode.kind, declaration.name, declaration.nativeNode.fields ?? {}]),
36
36
  definitionSpan: declaration.nativeNode.span,
37
37
  metadata: {
38
+ ...declaration.nativeNode.metadata,
38
39
  ownershipRegionId: ownershipRegion.id,
39
40
  ownershipRegionKey: ownershipRegion.key,
40
41
  ownershipRegionKind: ownershipRegion.regionKind
@@ -7,18 +7,20 @@ export function createSemanticPatchBundleAdmission(input = {}, context = {}) {
7
7
  );
8
8
  const evidenceAdmission = autoMergeEvidenceAdmission(context, { transformAdmission, semanticEditAdmission });
9
9
  const fallbackReadiness = fallbackAdmissionReadiness(transformAdmission, semanticEditAdmission, evidenceAdmission, context.readiness);
10
- const inputReadiness = normalizeSemanticMergeReadiness(input.readiness ?? fallbackReadiness) ?? input.readiness ?? fallbackReadiness;
11
- const readiness = hasPositiveApplyAction(transformAdmission, semanticEditAdmission) && evidenceAdmission.action !== 'admit'
10
+ const requestedReadiness = normalizeSemanticMergeReadiness(input.readiness) ?? input.readiness;
11
+ const inputReadiness = fallbackReadiness === 'blocked' ? 'blocked' : requestedReadiness ?? fallbackReadiness;
12
+ const positiveApply = !hasSkipReadyAction(semanticEditAdmission) && hasPositiveApplyAction(transformAdmission, semanticEditAdmission);
13
+ const readiness = positiveApply && evidenceAdmission.action !== 'admit'
12
14
  ? evidenceAdmission.readiness
13
15
  : inputReadiness;
14
16
  const computedStatus = admissionStatusForReadiness(readiness, transformAdmission, semanticEditAdmission, evidenceAdmission);
15
- const status = input.status === 'admitted' && computedStatus !== 'admitted' ? computedStatus : input.status ?? computedStatus;
17
+ const status = safePatchBundleStatus(input.status, computedStatus);
16
18
  const computedAutoApplyCandidate = status === 'admitted' &&
17
- hasPositiveApplyAction(transformAdmission, semanticEditAdmission) &&
19
+ positiveApply &&
18
20
  evidenceAdmission.action === 'admit';
19
21
  const autoApplyCandidate = input.autoApplyCandidate === true ? computedAutoApplyCandidate : input.autoApplyCandidate ?? computedAutoApplyCandidate;
20
22
  const admittedWithoutPositiveProof = status === 'admitted' &&
21
- hasPositiveApplyAction(transformAdmission, semanticEditAdmission) &&
23
+ positiveApply &&
22
24
  evidenceAdmission.action !== 'admit';
23
25
  return compactRecord({
24
26
  status,
@@ -72,10 +74,15 @@ function semanticTransformAdmission(context) {
72
74
  transformKeys: strings(index.semanticTransformKeys),
73
75
  contentHashes: strings(index.semanticTransformContentHashes),
74
76
  projectionIdentityHashes: strings(index.projectionIdentityHashes),
77
+ baseHashes: strings(index.transformBaseHashes),
78
+ targetHashes: strings(index.transformTargetHashes),
75
79
  sourceLanguages: strings(index.transformSourceLanguages),
76
80
  targetLanguages: strings(index.transformTargetLanguages),
77
81
  sourcePaths: strings(index.transformSourcePaths),
78
82
  targetPaths: strings(index.transformTargetPaths),
83
+ sourceMapIds: strings(index.transformSourceMapIds),
84
+ sourceMapLinkIds: strings(index.transformSourceMapLinkIds),
85
+ sourceMapMappingIds: strings(index.transformSourceMapMappingIds),
79
86
  evidenceIds: strings(index.semanticTransformEvidenceIds)
80
87
  });
81
88
  }
@@ -108,8 +115,12 @@ function autoMergeEvidenceAdmission(context, admissions) {
108
115
  ...array(context.source?.semanticPatch?.evidence),
109
116
  ...array(context.mergeCandidate?.evidence)
110
117
  ]);
111
- const positiveApply = hasPositiveApplyAttempt(admissions.transformAdmission, admissions.semanticEditAdmission);
112
- if (!positiveApply) return { status: 'none', action: 'none', readiness: 'needs-review', reasonCodes: [], evidenceIds: evidenceIds(evidence) };
118
+ const skipReady = hasSkipReadyAction(admissions.semanticEditAdmission);
119
+ const positiveApply = !skipReady &&
120
+ hasPositiveApplyAttempt(admissions.transformAdmission, admissions.semanticEditAdmission);
121
+ if (!positiveApply) return skipReady
122
+ ? skipEvidenceAdmission(evidence)
123
+ : { status: 'none', action: 'none', readiness: 'needs-review', reasonCodes: [], evidenceIds: evidenceIds(evidence) };
113
124
  const summary = summarizeAutoMergeEvidence(evidence);
114
125
  const blocked = summary.failed > 0 || summary.conflict > 0;
115
126
  const ready = !blocked && summary.stale === 0 && summary.passed > 0;
@@ -127,6 +138,23 @@ function autoMergeEvidenceAdmission(context, admissions) {
127
138
  });
128
139
  }
129
140
 
141
+ function skipEvidenceAdmission(evidence) {
142
+ const summary = summarizeAutoMergeEvidence(evidence);
143
+ const blocked = summary.failed > 0 || summary.conflict > 0;
144
+ const status = blocked ? 'blocked' : summary.stale > 0 ? 'stale' : summary.passed > 0 ? 'ready' : 'none';
145
+ return compactRecord({
146
+ status,
147
+ action: blocked ? 'block' : status === 'stale' ? 'rerun-semantic-import' : status === 'ready' ? 'skip' : 'none',
148
+ readiness: blocked ? 'blocked' : status === 'ready' ? 'ready' : 'needs-review',
149
+ reasonCodes: status === 'none' ? [] : autoMergeEvidenceReasonCodes(summary, status),
150
+ evidenceIds: summary.evidenceIds,
151
+ passed: summary.passed,
152
+ failed: summary.failed,
153
+ conflict: summary.conflict,
154
+ stale: summary.stale
155
+ });
156
+ }
157
+
130
158
  function summarizeAutoMergeEvidence(evidence) {
131
159
  const testLike = evidence.filter(isAutoMergeTestEvidence);
132
160
  const failed = testLike.filter((record) => evidenceStatus(record, ['failed', 'failure', 'error', 'blocked', 'rejected']));
@@ -167,6 +195,12 @@ function admissionStatusForReadiness(readiness, transformAdmission, semanticEdit
167
195
  return readiness === 'needs-review' ? 'needs-review' : 'proposed';
168
196
  }
169
197
 
198
+ function safePatchBundleStatus(requested, computed) {
199
+ if (computed === 'blocked' && requested !== 'rejected') return 'blocked';
200
+ if (requested === 'admitted' && computed !== 'admitted') return computed;
201
+ return requested ?? computed;
202
+ }
203
+
170
204
  function hasAdmissibleReadyAction(transformAdmission, semanticEditAdmission, evidenceAdmission) {
171
205
  return hasSkipReadyAction(semanticEditAdmission) ||
172
206
  (hasPositiveApplyAction(transformAdmission, semanticEditAdmission) && evidenceAdmission.action === 'admit');
@@ -141,11 +141,13 @@ function recordIndex(parts){
141
141
  semanticEditReplayIds:editIndex.semanticEditReplayIds,
142
142
  semanticEditReplayStatuses:editIndex.semanticEditReplayStatuses,
143
143
  semanticEditReplayActions:editIndex.semanticEditReplayActions,
144
+ semanticEditReplayReasonCodes:editIndex.semanticEditReplayReasonCodes,
144
145
  semanticEditAdmissionStatuses:uniqueStrings([editAdmission.status]),
145
146
  semanticEditAdmissionActions:uniqueStrings([editAdmission.action]),
146
147
  semanticEditAdmissionReadinesses:uniqueStrings([editAdmission.readiness]),
147
148
  semanticEditReplayCurrentHashes:editIndex.semanticEditReplayCurrentHashes,
148
149
  semanticEditReplayOutputHashes:editIndex.semanticEditReplayOutputHashes,
150
+ sourceBackprojectionModes:editIndex.sourceBackprojectionModes,
149
151
  semanticEditKeys:editIndex.semanticEditKeys,
150
152
  semanticIdentityHashes:editIndex.semanticIdentityHashes,
151
153
  sourceIdentityHashes:editIndex.sourceIdentityHashes,
@@ -156,12 +158,18 @@ function recordIndex(parts){
156
158
  semanticTransformIdentityHashes:semanticTransformIndex.semanticTransformIdentityHashes,
157
159
  semanticTransformContentHashes:semanticTransformIndex.semanticTransformContentHashes,
158
160
  projectionIdentityHashes:semanticTransformIndex.projectionIdentityHashes,
161
+ transformBaseHashes:semanticTransformIndex.transformBaseHashes,
162
+ transformTargetHashes:semanticTransformIndex.transformTargetHashes,
159
163
  semanticTransformReadinesses:semanticTransformIndex.semanticTransformReadinesses,
160
164
  semanticTransformEvidenceIds:semanticTransformIndex.semanticTransformEvidenceIds,
161
165
  transformSourceLanguages:semanticTransformIndex.transformSourceLanguages,
162
166
  transformTargetLanguages:semanticTransformIndex.transformTargetLanguages,
163
167
  transformSourcePaths:semanticTransformIndex.transformSourcePaths,
164
168
  transformTargetPaths:semanticTransformIndex.transformTargetPaths,
169
+ transformCrossLanguages:semanticTransformIndex.transformCrossLanguages,
170
+ transformSourceMapIds:semanticTransformIndex.transformSourceMapIds,
171
+ transformSourceMapLinkIds:semanticTransformIndex.transformSourceMapLinkIds,
172
+ transformSourceMapMappingIds:semanticTransformIndex.transformSourceMapMappingIds,
165
173
  targetPortabilityStatuses:uniqueStrings([parts.targetPortability?.status]),
166
174
  targetPortabilityActions:uniqueStrings([parts.targetPortability?.action]),
167
175
  targetPortabilityReasonCodes:uniqueStrings(parts.targetPortability?.reasonCodes),
@@ -202,11 +210,13 @@ function matchesRecord(record,query){
202
210
  &&matchAny(queryValues(query.semanticEditReplayId,query.semanticEditReplayIds),index.semanticEditReplayIds)
203
211
  &&matchAny(queryValues(query.semanticEditReplayStatus,query.semanticEditReplayStatuses),index.semanticEditReplayStatuses)
204
212
  &&matchAny(queryValues(query.semanticEditReplayAction,query.semanticEditReplayActions),index.semanticEditReplayActions)
213
+ &&matchAny(queryValues(query.semanticEditReplayReasonCode,query.semanticEditReplayReasonCodes),index.semanticEditReplayReasonCodes)
205
214
  &&matchAny(queryValues(query.semanticEditAdmissionStatus,query.semanticEditAdmissionStatuses),index.semanticEditAdmissionStatuses)
206
215
  &&matchAny(queryValues(query.semanticEditAdmissionAction,query.semanticEditAdmissionActions),index.semanticEditAdmissionActions)
207
216
  &&matchAny(queryValues(query.semanticEditAdmissionReadiness,query.semanticEditAdmissionReadinesses),index.semanticEditAdmissionReadinesses)
208
217
  &&matchAny(queryValues(query.semanticEditReplayCurrentHash,query.semanticEditReplayCurrentHashes),index.semanticEditReplayCurrentHashes)
209
218
  &&matchAny(queryValues(query.semanticEditReplayOutputHash,query.semanticEditReplayOutputHashes),index.semanticEditReplayOutputHashes)
219
+ &&matchAny(queryValues(query.sourceBackprojectionMode,query.sourceBackprojectionModes),index.sourceBackprojectionModes)
210
220
  &&matchAny(queryValues(query.semanticEditKey,query.semanticEditKeys),index.semanticEditKeys)
211
221
  &&matchAny(queryValues(query.semanticIdentityHash,query.semanticIdentityHashes),index.semanticIdentityHashes)
212
222
  &&matchAny(queryValues(query.sourceIdentityHash,query.sourceIdentityHashes),index.sourceIdentityHashes)
@@ -217,12 +227,18 @@ function matchesRecord(record,query){
217
227
  &&matchAny(queryValues(query.semanticTransformIdentityHash,query.semanticTransformIdentityHashes),index.semanticTransformIdentityHashes)
218
228
  &&matchAny(queryValues(query.semanticTransformContentHash,query.semanticTransformContentHashes),index.semanticTransformContentHashes)
219
229
  &&matchAny(queryValues(query.projectionIdentityHash,query.projectionIdentityHashes),index.projectionIdentityHashes)
230
+ &&matchAny(queryValues(query.transformBaseHash,query.transformBaseHashes),index.transformBaseHashes)
231
+ &&matchAny(queryValues(query.transformTargetHash,query.transformTargetHashes),index.transformTargetHashes)
220
232
  &&matchAny(queryValues(query.semanticTransformReadiness,query.semanticTransformReadinesses),index.semanticTransformReadinesses)
221
233
  &&matchAny(queryValues(query.semanticTransformEvidenceId,query.semanticTransformEvidenceIds),index.semanticTransformEvidenceIds)
222
234
  &&matchAny(queryValues(query.transformSourceLanguage,query.transformSourceLanguages),index.transformSourceLanguages)
223
235
  &&matchAny(queryValues(query.transformTargetLanguage,query.transformTargetLanguages),index.transformTargetLanguages)
224
236
  &&matchAny(queryValues(query.transformSourcePath,query.transformSourcePaths),index.transformSourcePaths)
225
237
  &&matchAny(queryValues(query.transformTargetPath,query.transformTargetPaths),index.transformTargetPaths)
238
+ &&matchAny(queryValues(query.transformCrossLanguage,query.transformCrossLanguages),index.transformCrossLanguages)
239
+ &&matchAny(queryValues(query.transformSourceMapId,query.transformSourceMapIds),index.transformSourceMapIds)
240
+ &&matchAny(queryValues(query.transformSourceMapLinkId,query.transformSourceMapLinkIds),index.transformSourceMapLinkIds)
241
+ &&matchAny(queryValues(query.transformSourceMapMappingId,query.transformSourceMapMappingIds),index.transformSourceMapMappingIds)
226
242
  &&matchAny(queryValues(query.targetPortabilityStatus,query.targetPortabilityStatuses),index.targetPortabilityStatuses)
227
243
  &&matchAny(queryValues(query.targetPortabilityAction,query.targetPortabilityActions),index.targetPortabilityActions)
228
244
  &&matchAny(queryValues(query.targetPortabilityReasonCode,query.targetPortabilityReasonCodes),index.targetPortabilityReasonCodes)