@shapeshift-labs/frontier-lang-compiler 0.2.66 → 0.2.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/bench/smoke.mjs +15 -1
- package/bench/universal-fixture-suite.mjs +183 -0
- package/dist/declarations/native-project-admission.d.ts +115 -0
- package/dist/declarations/roundtrip-audit.d.ts +177 -0
- package/dist/declarations/roundtrip.d.ts +2 -53
- package/dist/declarations/semantic-history-records.d.ts +277 -0
- package/dist/declarations/semantic-history.d.ts +45 -92
- package/dist/declarations/semantic-slice-admission.d.ts +111 -0
- package/dist/declarations/semantic-slice.d.ts +36 -1
- package/dist/declarations/universal-conversion-plan.d.ts +59 -0
- package/dist/declarations/universal-runtime-capabilities.d.ts +171 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/index-impl/createNativeRoundtripEvidence.js +54 -49
- package/dist/internal/index-impl/createSemanticSlice.js +1 -1
- package/dist/internal/index-impl/createSemanticSliceAdmissionRecord.js +10 -1
- package/dist/internal/index-impl/expandSemanticSliceSelection.js +0 -1
- package/dist/internal/index-impl/nativeRoundtripAudit.js +217 -0
- package/dist/internal/index-impl/projectImportAdmissionImportEvidence.js +160 -0
- package/dist/internal/index-impl/projectImportAdmissionLanguageSummaries.js +247 -0
- package/dist/internal/index-impl/projectImportAdmissionRanks.js +52 -0
- package/dist/internal/index-impl/projectImportAdmissionSummaries.js +46 -111
- package/dist/internal/index-impl/projectImportAdmissionTasks.js +239 -0
- package/dist/internal/index-impl/semanticHistoryRecordNormalizers.js +151 -0
- package/dist/internal/index-impl/semanticHistoryRecordOverlaps.js +113 -0
- package/dist/internal/index-impl/semanticHistoryRecords.js +210 -149
- package/dist/internal/index-impl/semanticSliceAdmissionSurface.js +142 -0
- package/dist/internal/index-impl/semanticSliceExpectationAssertions.js +100 -0
- package/dist/internal/index-impl/semanticSliceExpectationRecords.js +75 -0
- package/dist/internal/index-impl/semanticSliceExpectedAssertions.js +5 -2
- package/dist/internal/index-impl/testSemanticSlice.js +4 -1
- package/dist/language-adapter-package-contracts.js +12 -57
- package/dist/language-adapter-package-rows.js +116 -0
- package/dist/universal-conversion-plan-summary.js +42 -0
- package/dist/universal-conversion-plan.js +46 -40
- package/dist/universal-runtime-capabilities.js +92 -0
- package/dist/universal-runtime-host-selectors.js +192 -0
- package/dist/universal-runtime-profiles.js +109 -0
- package/dist/universal-runtime-route-records.js +162 -0
- package/examples/js-frontier-rust-workbench-client.mjs +58 -1
- package/examples/js-frontier-rust-workbench-convert.mjs +161 -0
- package/examples/js-frontier-rust-workbench-route-styles.mjs +126 -0
- package/examples/js-frontier-rust-workbench-route.mjs +190 -0
- package/examples/js-frontier-rust-workbench-styles.mjs +3 -38
- package/examples/js-frontier-rust-workbench.mjs +22 -128
- package/package.json +1 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import{uniqueStrings as uniqueRawStrings}from'../../native-import-utils.js';
|
|
2
|
+
|
|
3
|
+
export function querySemanticHistoryRecordOverlaps(records,options={}){
|
|
4
|
+
const list=array(records).filter(Boolean);
|
|
5
|
+
const overlaps=[];
|
|
6
|
+
for(let leftIndex=0;leftIndex<list.length;leftIndex+=1){
|
|
7
|
+
for(let rightIndex=leftIndex+1;rightIndex<list.length;rightIndex+=1){
|
|
8
|
+
const overlap=semanticHistoryOverlap(list[leftIndex],list[rightIndex],options);
|
|
9
|
+
if(overlap.overlapKinds.length||overlap.conflictReasons.length)overlaps.push(overlap);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return overlaps.sort((left,right)=>Number(right.conflict)-Number(left.conflict)||left.leftId.localeCompare(right.leftId)||left.rightId.localeCompare(right.rightId));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function semanticHistoryRecordsOverlap(left,right,options={}){
|
|
16
|
+
return semanticHistoryOverlap(left,right,options).overlapKinds.length>0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function semanticHistoryRecordsConflict(left,right,options={}){
|
|
20
|
+
return semanticHistoryOverlap(left,right,options).conflict;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function semanticHistoryOverlap(left,right,options){
|
|
24
|
+
const leftIndex=historyIndex(left);
|
|
25
|
+
const rightIndex=historyIndex(right);
|
|
26
|
+
const overlap=compactRecord({
|
|
27
|
+
ownership:intersect(leftIndex.ownershipKeys,rightIndex.ownershipKeys),
|
|
28
|
+
'conflict-key':intersect(leftIndex.conflictKeys,rightIndex.conflictKeys),
|
|
29
|
+
source:intersect(leftIndex.sourceIds,rightIndex.sourceIds),
|
|
30
|
+
'source-path':options.includeSourcePaths===false?[]:intersect(leftIndex.sourcePaths,rightIndex.sourcePaths),
|
|
31
|
+
import:intersect(leftIndex.importIds,rightIndex.importIds),
|
|
32
|
+
'semantic-candidate':intersect(leftIndex.semanticCandidateIds,rightIndex.semanticCandidateIds),
|
|
33
|
+
'semantic-claim':options.includeClaims?intersect(leftIndex.semanticClaimIds,rightIndex.semanticClaimIds):[],
|
|
34
|
+
'claim-hash':options.includeClaims?intersect(leftIndex.semanticClaimHashes,rightIndex.semanticClaimHashes):[],
|
|
35
|
+
evidence:options.includeEvidence?intersect(leftIndex.evidenceIds,rightIndex.evidenceIds):[],
|
|
36
|
+
proof:options.includeProofs?intersect(leftIndex.proofIds,rightIndex.proofIds):[],
|
|
37
|
+
replay:options.includeReplay?intersect(leftIndex.replayIds,rightIndex.replayIds):[],
|
|
38
|
+
patch:options.includePatches?intersect(leftIndex.patchIds,rightIndex.patchIds):[],
|
|
39
|
+
'merge-decision':options.includeMergeDecisions?intersect(leftIndex.mergeDecisionIds,rightIndex.mergeDecisionIds):[],
|
|
40
|
+
actor:options.includeActors?intersect(leftIndex.actorIds,rightIndex.actorIds):[],
|
|
41
|
+
'record-source':options.includeRecordSources?intersect(leftIndex.recordSourceIds,rightIndex.recordSourceIds):[],
|
|
42
|
+
'base-hash':options.includeBaseHashes?intersect(leftIndex.baseHashes,rightIndex.baseHashes):[],
|
|
43
|
+
'target-hash':options.includeTargetHashes?intersect(leftIndex.targetHashes,rightIndex.targetHashes):[]
|
|
44
|
+
});
|
|
45
|
+
const overlapKinds=Object.keys(overlap);
|
|
46
|
+
const semanticOverlap=Boolean(overlap.ownership?.length||overlap['conflict-key']?.length||overlap.source?.length||overlap['source-path']?.length||overlap.import?.length);
|
|
47
|
+
const conflictReasons=uniqueStrings([
|
|
48
|
+
overlap.ownership?.length?'ownership-overlap':undefined,
|
|
49
|
+
overlap['conflict-key']?.length?'semantic-conflict-key-overlap':undefined,
|
|
50
|
+
semanticOverlap&&disjointNonEmpty(leftIndex.baseHashes,rightIndex.baseHashes)?'base-hash-mismatch':undefined,
|
|
51
|
+
(overlap.ownership?.length||overlap['conflict-key']?.length)&&disjointNonEmpty(leftIndex.targetHashes,rightIndex.targetHashes)?'target-hash-mismatch':undefined,
|
|
52
|
+
semanticOverlap&&(blockedAdmission(left)||blockedAdmission(right))?'admission-blocked':undefined,
|
|
53
|
+
semanticOverlap&&(rejectedReview(left)||rejectedReview(right))?'reviewer-rejected':undefined,
|
|
54
|
+
options.conflictOnSourcePath&&overlap['source-path']?.length?'source-path-overlap':undefined
|
|
55
|
+
]);
|
|
56
|
+
return{
|
|
57
|
+
schema:'frontier.lang.semanticHistoryOverlap.v1',
|
|
58
|
+
leftId:String(left?.id??'left'),
|
|
59
|
+
rightId:String(right?.id??'right'),
|
|
60
|
+
overlap,
|
|
61
|
+
overlapKinds,
|
|
62
|
+
conflict:conflictReasons.length>0,
|
|
63
|
+
conflictReasons,
|
|
64
|
+
admission:{left:left?.admission?.status,right:right?.admission?.status},
|
|
65
|
+
reviewer:{left:left?.reviewer?.status,right:right?.reviewer?.status}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function historyIndex(record){
|
|
70
|
+
const acceptedFacts=record?.acceptedFacts??[];
|
|
71
|
+
const rejectedTheories=record?.rejectedTheories??[];
|
|
72
|
+
const importedParserEvidence=record?.importedParserEvidence??[];
|
|
73
|
+
const proofAttempts=record?.proofAttempts??[];
|
|
74
|
+
const patchAncestry=record?.patchAncestry??[];
|
|
75
|
+
const mergeDecisions=record?.mergeDecisions??[];
|
|
76
|
+
return record?.index??{
|
|
77
|
+
baseHashes:uniqueStrings([record?.baseHash]),
|
|
78
|
+
targetHashes:uniqueStrings([record?.targetHash]),
|
|
79
|
+
sourceIds:uniqueStrings(record?.sourceIds),
|
|
80
|
+
importIds:uniqueStrings(record?.importIds),
|
|
81
|
+
sourcePaths:uniqueStrings([record?.sourcePath,...(record?.sources??[]).map((source)=>source.sourcePath)]),
|
|
82
|
+
sourceHashes:uniqueStrings((record?.sources??[]).map((source)=>source.sourceHash)),
|
|
83
|
+
actorIds:uniqueStrings([record?.actor?.id,...acceptedFacts.map((claim)=>claim.actor?.id),...rejectedTheories.map((claim)=>claim.actor?.id),...importedParserEvidence.map((entry)=>entry.actor?.id),...proofAttempts.map((entry)=>entry.actor?.id),...patchAncestry.map((entry)=>entry.actor?.id),...mergeDecisions.map((entry)=>entry.actor?.id)]),
|
|
84
|
+
recordSourceIds:uniqueStrings([record?.recordSource?.id,record?.recordSource?.sourceId,...acceptedFacts.flatMap((claim)=>[claim.recordSource?.id,claim.recordSource?.sourceId]),...rejectedTheories.flatMap((claim)=>[claim.recordSource?.id,claim.recordSource?.sourceId]),...importedParserEvidence.flatMap((entry)=>[entry.recordSource?.id,entry.recordSource?.sourceId]),...proofAttempts.flatMap((entry)=>[entry.recordSource?.id,entry.recordSource?.sourceId]),...patchAncestry.flatMap((entry)=>[entry.recordSource?.id,entry.recordSource?.sourceId]),...mergeDecisions.flatMap((entry)=>[entry.recordSource?.id,entry.recordSource?.sourceId])]),
|
|
85
|
+
ownershipKeys:uniqueStrings((record?.ownershipRegions??[]).map((region)=>region.key)),
|
|
86
|
+
semanticCandidateIds:uniqueStrings((record?.semanticCandidates??[]).map((candidate)=>candidate.id)),
|
|
87
|
+
semanticClaimIds:uniqueStrings([...acceptedFacts.map((claim)=>claim.id),...rejectedTheories.map((claim)=>claim.id)]),
|
|
88
|
+
semanticClaimHashes:uniqueStrings([...acceptedFacts.map((claim)=>claim.hash),...rejectedTheories.map((claim)=>claim.hash)]),
|
|
89
|
+
acceptedFactIds:uniqueStrings(acceptedFacts.map((claim)=>claim.id)),
|
|
90
|
+
rejectedTheoryIds:uniqueStrings(rejectedTheories.map((claim)=>claim.id)),
|
|
91
|
+
conflictKeys:uniqueStrings([...(record?.semanticCandidates??[]).flatMap((candidate)=>candidate.conflictKeys??[]),...acceptedFacts.flatMap((claim)=>claim.conflictKeys??[]),...rejectedTheories.flatMap((claim)=>claim.conflictKeys??[]),...patchAncestry.flatMap((patch)=>patch.conflictKeys??[]),...mergeDecisions.flatMap((decision)=>decision.conflictKeys??[])]),
|
|
92
|
+
evidenceIds:uniqueStrings([...(record?.evidenceIds??[]),...acceptedFacts.flatMap((claim)=>claim.evidenceIds??[]),...rejectedTheories.flatMap((claim)=>claim.evidenceIds??[]),...importedParserEvidence.flatMap((entry)=>[entry.evidenceId,...(entry.evidenceIds??[])]),...proofAttempts.flatMap((entry)=>entry.evidenceIds??[]),...mergeDecisions.flatMap((entry)=>entry.evidenceIds??[])]),
|
|
93
|
+
importedParserEvidenceIds:uniqueStrings(importedParserEvidence.map((entry)=>entry.id)),
|
|
94
|
+
importedParserEvidenceHashes:uniqueStrings(importedParserEvidence.map((entry)=>entry.hash)),
|
|
95
|
+
proofIds:uniqueStrings([...(record?.proofIds??[]),...acceptedFacts.flatMap((claim)=>claim.proofIds??[]),...rejectedTheories.flatMap((claim)=>claim.proofIds??[]),...proofAttempts.flatMap((entry)=>[entry.proofId,...(entry.proofIds??[])]),...mergeDecisions.flatMap((entry)=>entry.proofIds??[])]),
|
|
96
|
+
proofAttemptIds:uniqueStrings(proofAttempts.map((entry)=>entry.id)),
|
|
97
|
+
proofAttemptHashes:uniqueStrings(proofAttempts.map((entry)=>entry.hash)),
|
|
98
|
+
replayIds:uniqueStrings([...(record?.replayLinks??[]).map((link)=>link.id),...(record?.semanticCandidates??[]).flatMap((candidate)=>candidate.replayIds??[]),...acceptedFacts.flatMap((claim)=>claim.replayIds??[]),...rejectedTheories.flatMap((claim)=>claim.replayIds??[]),...proofAttempts.flatMap((entry)=>entry.replayIds??[])]),
|
|
99
|
+
patchIds:uniqueStrings([...(record?.semanticCandidates??[]).map((candidate)=>candidate.patchId),...patchAncestry.flatMap((entry)=>[entry.patchId,...(entry.parentPatchIds??[]),...(entry.ancestorPatchIds??[])]),...mergeDecisions.flatMap((entry)=>entry.patchIds??[])]),
|
|
100
|
+
patchHashes:uniqueStrings(patchAncestry.flatMap((entry)=>[entry.hash,...(entry.parentHashes??[]),...(entry.ancestorHashes??[])])),
|
|
101
|
+
mergeDecisionIds:uniqueStrings(mergeDecisions.map((entry)=>entry.id)),
|
|
102
|
+
mergeDecisionHashes:uniqueStrings(mergeDecisions.map((entry)=>entry.hash))
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function blockedAdmission(record){return ['blocked','rejected'].includes(String(record?.admission?.status??''));}
|
|
107
|
+
function rejectedReview(record){return ['rejected','changes-requested'].includes(String(record?.reviewer?.status??''));}
|
|
108
|
+
function intersect(left,right){const rightSet=new Set(right??[]);return uniqueStrings((left??[]).filter((value)=>rightSet.has(value)));}
|
|
109
|
+
function disjointNonEmpty(left,right){return Boolean(left?.length&&right?.length&&intersect(left,right).length===0);}
|
|
110
|
+
|
|
111
|
+
function array(value){if(value===undefined||value===null)return[];return Array.isArray(value)?value:[value];}
|
|
112
|
+
function uniqueStrings(values){return uniqueRawStrings((values??[]).filter((entry)=>entry!==undefined&&entry!==null&&String(entry)!==''));}
|
|
113
|
+
function compactRecord(value){return Object.fromEntries(Object.entries(value??{}).filter(([,entry])=>entry!==undefined&&(!Array.isArray(entry)||entry.length>0)));}
|
|
@@ -1,182 +1,263 @@
|
|
|
1
|
+
import{hashSemanticValue}from'@shapeshift-labs/frontier-lang-kernel';
|
|
1
2
|
import{ idFragment, maxSemanticMergeReadiness, normalizeSemanticMergeReadiness, uniqueStrings as uniqueRawStrings }from'../../native-import-utils.js';
|
|
3
|
+
import{normalizeOwnershipRegions,normalizeSemanticCandidates,normalizeSemanticClaims,normalizeSources,semanticClaimsByStatus}from'./semanticHistoryRecordNormalizers.js';
|
|
2
4
|
|
|
3
5
|
export const SemanticHistoryAdmissionStatuses=Object.freeze(['proposed','queued','admitted','needs-review','blocked','rejected']);
|
|
4
6
|
export const SemanticHistoryReviewerStatuses=Object.freeze(['unreviewed','approved','changes-requested','reviewed','rejected']);
|
|
5
|
-
export const SemanticHistoryOverlapKinds=Object.freeze(['ownership','conflict-key','source','source-path','import','semantic-candidate','evidence','proof','replay','base-hash','target-hash']);
|
|
7
|
+
export const SemanticHistoryOverlapKinds=Object.freeze(['ownership','conflict-key','source','source-path','import','semantic-candidate','semantic-claim','claim-hash','evidence','proof','replay','patch','merge-decision','actor','record-source','base-hash','target-hash']);
|
|
6
8
|
export const SemanticHistoryConflictReasons=Object.freeze(['ownership-overlap','semantic-conflict-key-overlap','base-hash-mismatch','target-hash-mismatch','admission-blocked','reviewer-rejected','source-path-overlap']);
|
|
7
9
|
|
|
8
10
|
export function createSemanticHistoryRecord(input={},options={}){
|
|
9
11
|
const imported=input.importResult??input.imported;
|
|
12
|
+
const actor=normalizeActor(input.actor??options.actor??compactRecord({id:input.actorId??options.actorId,kind:input.actorKind??options.actorKind,role:input.actorRole??options.actorRole,runId:input.runId??options.runId,lane:input.lane??options.lane,taskId:input.taskId??options.taskId}));
|
|
13
|
+
const recordSource=normalizeRecordSource(input.recordSource??input.historySource??options.recordSource??options.historySource,compactRecord({...input,...options}));
|
|
10
14
|
const sources=normalizeSources(input,imported);
|
|
11
15
|
const ownershipRegions=normalizeOwnershipRegions([...(array(input.ownershipRegions)),...(array(input.changedRegions)),...(array(input.changeSet?.changedRegions)),...(array(imported?.ownershipRegions))]);
|
|
12
16
|
const semanticCandidates=normalizeSemanticCandidates([...(array(input.semanticCandidates)),...(array(input.mergeCandidates)),...(array(input.mergeCandidate)),...(array(input.changeSet?.mergeCandidate)),...(array(imported?.mergeCandidates))]);
|
|
13
17
|
const replayLinks=normalizeReplayLinks(input.replayLinks??input.replay);
|
|
14
18
|
const baseHash=firstString(input.baseHash,input.beforeHash,...sources.map((source)=>source.baseHash),...semanticCandidates.map((candidate)=>candidate.baseHash));
|
|
15
19
|
const targetHash=firstString(input.targetHash,input.afterHash,...sources.map((source)=>source.targetHash),...semanticCandidates.map((candidate)=>candidate.targetHash));
|
|
16
|
-
const
|
|
17
|
-
const
|
|
20
|
+
const sourceContext={actor,recordSource,language:input.language??imported?.language??sources.find((source)=>source.language)?.language,sourcePath:input.sourcePath??imported?.sourcePath??sources.find((source)=>source.sourcePath)?.sourcePath,sourceHash:input.sourceHash??imported?.sourceHash??sources.find((source)=>source.sourceHash)?.sourceHash,baseHash,targetHash};
|
|
21
|
+
const acceptedFacts=normalizeSemanticClaims([
|
|
22
|
+
...(array(input.acceptedFacts)),
|
|
23
|
+
...(array(input.acceptedSemanticClaims)),
|
|
24
|
+
...semanticClaimsByStatus(input,'accepted')
|
|
25
|
+
],{...sourceContext,status:'accepted',claimKind:'fact',prefix:'semantic_fact'});
|
|
26
|
+
const rejectedTheories=normalizeSemanticClaims([
|
|
27
|
+
...(array(input.rejectedTheories)),
|
|
28
|
+
...(array(input.rejectedSemanticClaims)),
|
|
29
|
+
...semanticClaimsByStatus(input,'rejected')
|
|
30
|
+
],{...sourceContext,status:'rejected',claimKind:'theory',prefix:'semantic_theory'});
|
|
31
|
+
const importedParserEvidence=normalizeImportedParserEvidence([
|
|
32
|
+
...(array(input.importedParserEvidence)),
|
|
33
|
+
...(array(input.parserEvidence)),
|
|
34
|
+
...(array(imported?.parserEvidence))
|
|
35
|
+
],sourceContext);
|
|
36
|
+
const proofAttempts=normalizeProofAttempts([...(array(input.proofAttempts)),...(array(input.proofs))],sourceContext);
|
|
37
|
+
const patchAncestry=normalizePatchAncestry(input.patchAncestry??input.patchAncestors??input.ancestry,sourceContext);
|
|
38
|
+
const mergeDecisions=normalizeMergeDecisions(input.mergeDecisions??input.decisions,sourceContext);
|
|
39
|
+
const semanticClaimIds=uniqueStrings([...acceptedFacts.map((claim)=>claim.id),...rejectedTheories.map((claim)=>claim.id)]);
|
|
40
|
+
const semanticClaimHashes=uniqueStrings([...acceptedFacts.map((claim)=>claim.hash),...rejectedTheories.map((claim)=>claim.hash)]);
|
|
41
|
+
const evidenceIds=uniqueStrings([...(strings(input.evidenceIds)),...(array(input.evidence)).map((record)=>record?.id),...(array(imported?.evidence)).map((record)=>record?.id),...semanticCandidates.flatMap((candidate)=>candidate.evidenceIds),...acceptedFacts.flatMap((claim)=>claim.evidenceIds),...rejectedTheories.flatMap((claim)=>claim.evidenceIds),...importedParserEvidence.flatMap((record)=>[record.evidenceId,...array(record.evidenceIds)]),...proofAttempts.flatMap((record)=>record.evidenceIds),...mergeDecisions.flatMap((decision)=>decision.evidenceIds),...(strings(input.reviewer?.evidenceIds)),...(strings(input.admission?.evidenceIds))]);
|
|
42
|
+
const proofIds=uniqueStrings([...(strings(input.proofIds)),...(array(input.proofs)).map((record)=>record?.id),...semanticCandidates.flatMap((candidate)=>candidate.proofIds),...acceptedFacts.flatMap((claim)=>claim.proofIds),...rejectedTheories.flatMap((claim)=>claim.proofIds),...proofAttempts.flatMap((record)=>[record.proofId,...array(record.proofIds)]),...mergeDecisions.flatMap((decision)=>decision.proofIds)]);
|
|
18
43
|
const sourceIds=uniqueStrings([input.sourceId,...strings(input.sourceIds),...sources.map((source)=>source.id)]);
|
|
19
44
|
const importIds=uniqueStrings([input.importId,input.importResultId,imported?.id,...strings(input.importIds),...sources.map((source)=>source.importId),...semanticCandidates.map((candidate)=>candidate.importResultId)]);
|
|
20
45
|
const sourcePaths=uniqueStrings([input.sourcePath,imported?.sourcePath,...sources.map((source)=>source.sourcePath),...ownershipRegions.map((region)=>region.sourcePath),...semanticCandidates.map((candidate)=>candidate.sourcePath)]);
|
|
21
46
|
const sourceHashes=uniqueStrings([input.sourceHash,imported?.sourceHash,...sources.map((source)=>source.sourceHash),...ownershipRegions.map((region)=>region.sourceHash)]);
|
|
22
|
-
const conflictKeys=uniqueStrings([...(strings(input.conflictKeys)),...semanticCandidates.flatMap((candidate)=>candidate.conflictKeys)]);
|
|
47
|
+
const conflictKeys=uniqueStrings([...(strings(input.conflictKeys)),...semanticCandidates.flatMap((candidate)=>candidate.conflictKeys),...acceptedFacts.flatMap((claim)=>claim.conflictKeys),...rejectedTheories.flatMap((claim)=>claim.conflictKeys),...patchAncestry.flatMap((patch)=>patch.conflictKeys),...mergeDecisions.flatMap((decision)=>decision.conflictKeys)]);
|
|
23
48
|
const reviewer=normalizeReviewer(input.reviewer);
|
|
24
49
|
const admission=normalizeAdmission(input.admission,semanticCandidates,reviewer);
|
|
25
|
-
|
|
50
|
+
const actorIds=uniqueStrings([actor?.id,actor?.actorId,...acceptedFacts.map((claim)=>claim.actor?.id),...rejectedTheories.map((claim)=>claim.actor?.id),...importedParserEvidence.map((record)=>record.actor?.id),...proofAttempts.map((record)=>record.actor?.id),...patchAncestry.map((record)=>record.actor?.id),...mergeDecisions.map((record)=>record.actor?.id)]);
|
|
51
|
+
const recordSourceIds=uniqueStrings([recordSource?.id,recordSource?.sourceId,...acceptedFacts.flatMap((claim)=>[claim.recordSource?.id,claim.recordSource?.sourceId]),...rejectedTheories.flatMap((claim)=>[claim.recordSource?.id,claim.recordSource?.sourceId]),...importedParserEvidence.flatMap((record)=>[record.recordSource?.id,record.recordSource?.sourceId]),...proofAttempts.flatMap((record)=>[record.recordSource?.id,record.recordSource?.sourceId]),...patchAncestry.flatMap((record)=>[record.recordSource?.id,record.recordSource?.sourceId]),...mergeDecisions.flatMap((record)=>[record.recordSource?.id,record.recordSource?.sourceId])]);
|
|
52
|
+
const patchIds=uniqueStrings([...semanticCandidates.map((candidate)=>candidate.patchId),...patchAncestry.flatMap((patch)=>[patch.patchId,...array(patch.parentPatchIds),...array(patch.ancestorPatchIds)]),...mergeDecisions.flatMap((decision)=>decision.patchIds)]);
|
|
53
|
+
const mergeDecisionIds=uniqueStrings(mergeDecisions.map((decision)=>decision.id));
|
|
54
|
+
const index={
|
|
55
|
+
baseHashes:uniqueStrings([baseHash,...sources.map((source)=>source.baseHash),...semanticCandidates.map((candidate)=>candidate.baseHash),...patchAncestry.map((patch)=>patch.baseHash)]),
|
|
56
|
+
targetHashes:uniqueStrings([targetHash,...sources.map((source)=>source.targetHash),...semanticCandidates.map((candidate)=>candidate.targetHash),...patchAncestry.map((patch)=>patch.targetHash)]),
|
|
57
|
+
sourceIds,
|
|
58
|
+
importIds,
|
|
59
|
+
sourcePaths,
|
|
60
|
+
sourceHashes,
|
|
61
|
+
actorIds,
|
|
62
|
+
recordSourceIds,
|
|
63
|
+
ownershipKeys:uniqueStrings([...ownershipRegions.map((region)=>region.key),...semanticCandidates.flatMap((candidate)=>candidate.ownershipKeys)]),
|
|
64
|
+
semanticCandidateIds:uniqueStrings(semanticCandidates.map((candidate)=>candidate.id)),
|
|
65
|
+
semanticClaimIds,
|
|
66
|
+
semanticClaimHashes,
|
|
67
|
+
acceptedFactIds:uniqueStrings(acceptedFacts.map((claim)=>claim.id)),
|
|
68
|
+
rejectedTheoryIds:uniqueStrings(rejectedTheories.map((claim)=>claim.id)),
|
|
69
|
+
conflictKeys,
|
|
70
|
+
evidenceIds,
|
|
71
|
+
importedParserEvidenceIds:uniqueStrings(importedParserEvidence.map((record)=>record.id)),
|
|
72
|
+
importedParserEvidenceHashes:uniqueStrings(importedParserEvidence.map((record)=>record.hash)),
|
|
73
|
+
proofIds,
|
|
74
|
+
proofAttemptIds:uniqueStrings(proofAttempts.map((record)=>record.id)),
|
|
75
|
+
proofAttemptHashes:uniqueStrings(proofAttempts.map((record)=>record.hash)),
|
|
76
|
+
replayIds:uniqueStrings([...replayLinks.map((link)=>link.id),...semanticCandidates.flatMap((candidate)=>candidate.replayIds),...acceptedFacts.flatMap((claim)=>claim.replayIds),...rejectedTheories.flatMap((claim)=>claim.replayIds),...proofAttempts.flatMap((record)=>record.replayIds)]),
|
|
77
|
+
patchIds,
|
|
78
|
+
patchHashes:uniqueStrings(patchAncestry.flatMap((patch)=>[patch.hash,...array(patch.parentHashes),...array(patch.ancestorHashes)])),
|
|
79
|
+
mergeDecisionIds,
|
|
80
|
+
mergeDecisionHashes:uniqueStrings(mergeDecisions.map((decision)=>decision.hash))
|
|
81
|
+
};
|
|
82
|
+
const recordCore={
|
|
26
83
|
kind:'frontier.lang.semanticHistoryRecord',
|
|
27
84
|
version:1,
|
|
28
|
-
id:input.id??options.id??`semantic_history_${idFragment(firstString(sourcePaths[0],importIds[0],sourceIds[0],'record'))}`,
|
|
29
|
-
createdAt:input.createdAt??options.createdAt??Date.now(),
|
|
30
85
|
baseHash,
|
|
31
86
|
targetHash,
|
|
32
|
-
language:
|
|
33
|
-
sourcePath:
|
|
87
|
+
language:sourceContext.language,
|
|
88
|
+
sourcePath:sourceContext.sourcePath??sourcePaths[0],
|
|
89
|
+
actor,
|
|
90
|
+
recordSource,
|
|
34
91
|
sourceIds,
|
|
35
92
|
importIds,
|
|
36
93
|
sources,
|
|
37
94
|
ownershipRegions,
|
|
38
95
|
semanticCandidates,
|
|
96
|
+
acceptedFacts,
|
|
97
|
+
rejectedTheories,
|
|
98
|
+
importedParserEvidence,
|
|
99
|
+
proofAttempts,
|
|
100
|
+
patchAncestry,
|
|
101
|
+
mergeDecisions,
|
|
39
102
|
evidenceIds,
|
|
40
103
|
proofIds,
|
|
41
104
|
reviewer,
|
|
42
105
|
admission,
|
|
43
106
|
replayLinks,
|
|
44
|
-
index
|
|
45
|
-
baseHashes:uniqueStrings([baseHash,...sources.map((source)=>source.baseHash),...semanticCandidates.map((candidate)=>candidate.baseHash)]),
|
|
46
|
-
targetHashes:uniqueStrings([targetHash,...sources.map((source)=>source.targetHash),...semanticCandidates.map((candidate)=>candidate.targetHash)]),
|
|
47
|
-
sourceIds,
|
|
48
|
-
importIds,
|
|
49
|
-
sourcePaths,
|
|
50
|
-
sourceHashes,
|
|
51
|
-
ownershipKeys:uniqueStrings([...ownershipRegions.map((region)=>region.key),...semanticCandidates.flatMap((candidate)=>candidate.ownershipKeys)]),
|
|
52
|
-
semanticCandidateIds:uniqueStrings(semanticCandidates.map((candidate)=>candidate.id)),
|
|
53
|
-
conflictKeys,
|
|
54
|
-
evidenceIds,
|
|
55
|
-
proofIds,
|
|
56
|
-
replayIds:uniqueStrings(replayLinks.map((link)=>link.id))
|
|
57
|
-
},
|
|
107
|
+
index,
|
|
58
108
|
metadata:compactRecord(input.metadata)
|
|
59
109
|
};
|
|
110
|
+
const hash=hashSemanticValue(recordCore);
|
|
111
|
+
const stableId=`semantic_history_${idFragment(hash)}`;
|
|
112
|
+
return{
|
|
113
|
+
...recordCore,
|
|
114
|
+
id:input.id??options.id??stableId,
|
|
115
|
+
stableId,
|
|
116
|
+
hash,
|
|
117
|
+
createdAt:input.createdAt??options.createdAt??Date.now()
|
|
118
|
+
};
|
|
60
119
|
}
|
|
61
120
|
|
|
62
|
-
export
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
121
|
+
export{querySemanticHistoryRecordOverlaps,semanticHistoryRecordsConflict,semanticHistoryRecordsOverlap}from'./semanticHistoryRecordOverlaps.js';
|
|
122
|
+
|
|
123
|
+
function normalizeImportedParserEvidence(records,defaults){
|
|
124
|
+
return records.filter(Boolean).map((record,index)=>{
|
|
125
|
+
const source=typeof record==='string'?{evidenceId:record}:record;
|
|
126
|
+
const normalized=compactRecord({
|
|
127
|
+
kind:'frontier.lang.semanticHistoryImportedParserEvidence',
|
|
128
|
+
version:1,
|
|
129
|
+
evidenceId:firstString(source.evidenceId,source.id),
|
|
130
|
+
importId:source.importId??source.importResultId??defaults.importId,
|
|
131
|
+
parserId:source.parserId??source.parser??source.adapterId,
|
|
132
|
+
parserKind:source.parserKind??source.kind,
|
|
133
|
+
language:source.language??defaults.language,
|
|
134
|
+
sourcePath:source.sourcePath??defaults.sourcePath,
|
|
135
|
+
sourceHash:source.sourceHash??source.hash??defaults.sourceHash,
|
|
136
|
+
astHash:source.astHash??source.nativeAstHash,
|
|
137
|
+
semanticIndexHash:source.semanticIndexHash,
|
|
138
|
+
status:source.status??'unknown',
|
|
139
|
+
evidenceIds:uniqueStrings([source.evidenceId,source.id,...strings(source.evidenceIds)]),
|
|
140
|
+
replayIds:uniqueStrings(source.replayIds),
|
|
141
|
+
actor:normalizeActor(source.actor)??defaults.actor,
|
|
142
|
+
recordSource:normalizeRecordSource(source.recordSource??source.historySource??defaults.recordSource,defaults),
|
|
143
|
+
metadata:source.metadata
|
|
144
|
+
});
|
|
145
|
+
return withStableSubrecordIdentity('imported_parser_evidence',normalized,source,index);
|
|
146
|
+
});
|
|
72
147
|
}
|
|
73
148
|
|
|
74
|
-
|
|
75
|
-
return
|
|
149
|
+
function normalizeProofAttempts(records,defaults){
|
|
150
|
+
return records.filter(Boolean).map((record,index)=>{
|
|
151
|
+
const source=typeof record==='string'?{proofId:record}:record;
|
|
152
|
+
const normalized=compactRecord({
|
|
153
|
+
kind:'frontier.lang.semanticHistoryProofAttempt',
|
|
154
|
+
version:1,
|
|
155
|
+
proofId:firstString(source.proofId,source.id),
|
|
156
|
+
proofKind:source.proofKind??source.kind,
|
|
157
|
+
status:source.status??'unknown',
|
|
158
|
+
proverId:source.proverId??source.prover,
|
|
159
|
+
claimIds:uniqueStrings(source.claimIds),
|
|
160
|
+
evidenceIds:uniqueStrings(source.evidenceIds),
|
|
161
|
+
proofIds:uniqueStrings(source.proofIds),
|
|
162
|
+
replayIds:uniqueStrings(source.replayIds),
|
|
163
|
+
command:source.command,
|
|
164
|
+
resultHash:source.resultHash??source.proofHash,
|
|
165
|
+
actor:normalizeActor(source.actor)??defaults.actor,
|
|
166
|
+
recordSource:normalizeRecordSource(source.recordSource??source.historySource??defaults.recordSource,defaults),
|
|
167
|
+
metadata:source.metadata
|
|
168
|
+
});
|
|
169
|
+
return withStableSubrecordIdentity('proof_attempt',normalized,source,index);
|
|
170
|
+
});
|
|
76
171
|
}
|
|
77
172
|
|
|
78
|
-
|
|
79
|
-
return
|
|
173
|
+
function normalizePatchAncestry(records,defaults){
|
|
174
|
+
return array(records).filter(Boolean).map((record,index)=>{
|
|
175
|
+
const source=typeof record==='string'?{patchId:record}:record;
|
|
176
|
+
const normalized=compactRecord({
|
|
177
|
+
kind:'frontier.lang.semanticHistoryPatchAncestry',
|
|
178
|
+
version:1,
|
|
179
|
+
patchId:firstString(source.patchId,source.id),
|
|
180
|
+
parentPatchIds:uniqueStrings([...(strings(source.parentPatchIds)),...(strings(source.parents))]),
|
|
181
|
+
ancestorPatchIds:uniqueStrings([...(strings(source.ancestorPatchIds)),...(strings(source.ancestors))]),
|
|
182
|
+
baseHash:source.baseHash??defaults.baseHash,
|
|
183
|
+
targetHash:source.targetHash??defaults.targetHash,
|
|
184
|
+
parentHashes:uniqueStrings(source.parentHashes),
|
|
185
|
+
ancestorHashes:uniqueStrings(source.ancestorHashes),
|
|
186
|
+
conflictKeys:uniqueStrings(source.conflictKeys),
|
|
187
|
+
actor:normalizeActor(source.actor)??defaults.actor,
|
|
188
|
+
recordSource:normalizeRecordSource(source.recordSource??source.historySource??defaults.recordSource,defaults),
|
|
189
|
+
metadata:source.metadata
|
|
190
|
+
});
|
|
191
|
+
return withStableSubrecordIdentity('patch_ancestry',normalized,source,index);
|
|
192
|
+
});
|
|
80
193
|
}
|
|
81
194
|
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
195
|
+
function normalizeMergeDecisions(records,defaults){
|
|
196
|
+
return array(records).filter(Boolean).map((record,index)=>{
|
|
197
|
+
const source=typeof record==='string'?{decision:record}:record;
|
|
198
|
+
const normalized=compactRecord({
|
|
199
|
+
kind:'frontier.lang.semanticHistoryMergeDecision',
|
|
200
|
+
version:1,
|
|
201
|
+
decision:source.decision??source.status,
|
|
202
|
+
status:source.status??source.decision,
|
|
203
|
+
decidedAt:source.decidedAt,
|
|
204
|
+
claimIds:uniqueStrings(source.claimIds),
|
|
205
|
+
acceptedClaimIds:uniqueStrings(source.acceptedClaimIds),
|
|
206
|
+
rejectedClaimIds:uniqueStrings(source.rejectedClaimIds),
|
|
207
|
+
patchIds:uniqueStrings([...(strings(source.patchIds)),source.patchId]),
|
|
208
|
+
conflictKeys:uniqueStrings(source.conflictKeys),
|
|
209
|
+
evidenceIds:uniqueStrings(source.evidenceIds),
|
|
210
|
+
proofIds:uniqueStrings(source.proofIds),
|
|
211
|
+
reasonCodes:uniqueStrings(source.reasonCodes),
|
|
212
|
+
actor:normalizeActor(source.actor)??defaults.actor,
|
|
213
|
+
recordSource:normalizeRecordSource(source.recordSource??source.historySource??defaults.recordSource,defaults),
|
|
214
|
+
metadata:source.metadata
|
|
215
|
+
});
|
|
216
|
+
return withStableSubrecordIdentity('merge_decision',normalized,source,index);
|
|
97
217
|
});
|
|
98
|
-
const overlapKinds=Object.keys(overlap);
|
|
99
|
-
const semanticOverlap=Boolean(overlap.ownership?.length||overlap['conflict-key']?.length||overlap.source?.length||overlap['source-path']?.length||overlap.import?.length);
|
|
100
|
-
const conflictReasons=uniqueStrings([
|
|
101
|
-
overlap.ownership?.length?'ownership-overlap':undefined,
|
|
102
|
-
overlap['conflict-key']?.length?'semantic-conflict-key-overlap':undefined,
|
|
103
|
-
semanticOverlap&&disjointNonEmpty(leftIndex.baseHashes,rightIndex.baseHashes)?'base-hash-mismatch':undefined,
|
|
104
|
-
(overlap.ownership?.length||overlap['conflict-key']?.length)&&disjointNonEmpty(leftIndex.targetHashes,rightIndex.targetHashes)?'target-hash-mismatch':undefined,
|
|
105
|
-
semanticOverlap&&(blockedAdmission(left)||blockedAdmission(right))?'admission-blocked':undefined,
|
|
106
|
-
semanticOverlap&&(rejectedReview(left)||rejectedReview(right))?'reviewer-rejected':undefined,
|
|
107
|
-
options.conflictOnSourcePath&&overlap['source-path']?.length?'source-path-overlap':undefined
|
|
108
|
-
]);
|
|
109
|
-
return{
|
|
110
|
-
schema:'frontier.lang.semanticHistoryOverlap.v1',
|
|
111
|
-
leftId:String(left?.id??'left'),
|
|
112
|
-
rightId:String(right?.id??'right'),
|
|
113
|
-
overlap,
|
|
114
|
-
overlapKinds,
|
|
115
|
-
conflict:conflictReasons.length>0,
|
|
116
|
-
conflictReasons,
|
|
117
|
-
admission:{left:left?.admission?.status,right:right?.admission?.status},
|
|
118
|
-
reviewer:{left:left?.reviewer?.status,right:right?.reviewer?.status}
|
|
119
|
-
};
|
|
120
218
|
}
|
|
121
219
|
|
|
122
|
-
function
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
importId:source?.importId??source?.importResultId??(source?.kind==='frontier.lang.importResult'?source.id:undefined),
|
|
130
|
-
language:source?.language??input.language,
|
|
131
|
-
sourcePath:source?.sourcePath??source?.path??input.sourcePath,
|
|
132
|
-
sourceHash:source?.sourceHash??source?.hash,
|
|
133
|
-
baseHash:source?.baseHash??source?.beforeHash??input.baseHash??input.beforeHash,
|
|
134
|
-
targetHash:source?.targetHash??source?.afterHash??input.targetHash??input.afterHash,
|
|
135
|
-
metadata:source?.metadata,
|
|
136
|
-
ordinal:index
|
|
137
|
-
})).filter((source)=>source.id||source.importId||source.sourcePath||source.sourceHash||source.baseHash||source.targetHash);
|
|
220
|
+
function withStableSubrecordIdentity(prefix,record,source,index){
|
|
221
|
+
const hash=source.hash??hashSemanticValue(record);
|
|
222
|
+
return{
|
|
223
|
+
...record,
|
|
224
|
+
id:source.id??`${prefix}_${idFragment(firstString(record.subject,record.evidenceId,record.proofId,record.patchId,record.decision,hash,index+1))}`,
|
|
225
|
+
hash
|
|
226
|
+
};
|
|
138
227
|
}
|
|
139
228
|
|
|
140
|
-
function
|
|
141
|
-
const
|
|
142
|
-
const normalized=
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
sourcePath:region?.sourcePath,
|
|
154
|
-
sourceHash:region?.sourceHash,
|
|
155
|
-
symbolId:region?.symbolId,
|
|
156
|
-
symbolName:region?.symbolName??region?.name,
|
|
157
|
-
sourceSpan:region?.sourceSpan??region?.span,
|
|
158
|
-
metadata:region?.metadata
|
|
159
|
-
}));
|
|
160
|
-
}
|
|
161
|
-
return normalized;
|
|
229
|
+
function normalizeActor(value){
|
|
230
|
+
const actor=typeof value==='string'?{id:value}:value;
|
|
231
|
+
const normalized=compactRecord({
|
|
232
|
+
id:actor?.id??actor?.actorId,
|
|
233
|
+
kind:actor?.kind??actor?.actorKind??actor?.type,
|
|
234
|
+
role:actor?.role,
|
|
235
|
+
displayName:actor?.displayName??actor?.name,
|
|
236
|
+
runId:actor?.runId,
|
|
237
|
+
lane:actor?.lane,
|
|
238
|
+
taskId:actor?.taskId,
|
|
239
|
+
metadata:actor?.metadata
|
|
240
|
+
});
|
|
241
|
+
return nonEmptyRecord(normalized);
|
|
162
242
|
}
|
|
163
243
|
|
|
164
|
-
function
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
metadata:
|
|
179
|
-
})
|
|
244
|
+
function normalizeRecordSource(value,context={}){
|
|
245
|
+
const source=typeof value==='string'?{id:value}:value;
|
|
246
|
+
const normalized=compactRecord({
|
|
247
|
+
id:source?.id??source?.sourceId??context.recordSourceId??context.historySourceId,
|
|
248
|
+
sourceId:source?.sourceId??source?.id??context.recordSourceId??context.historySourceId,
|
|
249
|
+
sourceKind:source?.sourceKind??source?.kind??source?.type,
|
|
250
|
+
sourcePath:source?.sourcePath??source?.path,
|
|
251
|
+
sourceHash:source?.sourceHash??source?.hash,
|
|
252
|
+
href:source?.href??source?.url,
|
|
253
|
+
importId:source?.importId??context.importId??context.importResultId,
|
|
254
|
+
runId:source?.runId??context.runId,
|
|
255
|
+
jobId:source?.jobId??context.jobId,
|
|
256
|
+
lane:source?.lane??context.lane,
|
|
257
|
+
taskId:source?.taskId??context.taskId,
|
|
258
|
+
metadata:source?.metadata
|
|
259
|
+
});
|
|
260
|
+
return nonEmptyRecord(normalized);
|
|
180
261
|
}
|
|
181
262
|
|
|
182
263
|
function normalizeReplayLinks(value){
|
|
@@ -205,29 +286,9 @@ function normalizeAdmission(admission,candidates,reviewer){
|
|
|
205
286
|
return compactRecord({status:admission?.status??'proposed',readiness,admittedAt:admission?.admittedAt,reviewerId:admission?.reviewerId??reviewer.reviewerId,reasonCodes:uniqueStrings(admission?.reasonCodes),evidenceIds:uniqueStrings(admission?.evidenceIds),metadata:admission?.metadata});
|
|
206
287
|
}
|
|
207
288
|
|
|
208
|
-
function historyIndex(record){
|
|
209
|
-
return record?.index??{
|
|
210
|
-
baseHashes:uniqueStrings([record?.baseHash]),
|
|
211
|
-
targetHashes:uniqueStrings([record?.targetHash]),
|
|
212
|
-
sourceIds:uniqueStrings(record?.sourceIds),
|
|
213
|
-
importIds:uniqueStrings(record?.importIds),
|
|
214
|
-
sourcePaths:uniqueStrings([record?.sourcePath,...(record?.sources??[]).map((source)=>source.sourcePath)]),
|
|
215
|
-
sourceHashes:uniqueStrings((record?.sources??[]).map((source)=>source.sourceHash)),
|
|
216
|
-
ownershipKeys:uniqueStrings((record?.ownershipRegions??[]).map((region)=>region.key)),
|
|
217
|
-
semanticCandidateIds:uniqueStrings((record?.semanticCandidates??[]).map((candidate)=>candidate.id)),
|
|
218
|
-
conflictKeys:uniqueStrings((record?.semanticCandidates??[]).flatMap((candidate)=>candidate.conflictKeys??[])),
|
|
219
|
-
evidenceIds:uniqueStrings(record?.evidenceIds),
|
|
220
|
-
proofIds:uniqueStrings(record?.proofIds),
|
|
221
|
-
replayIds:uniqueStrings((record?.replayLinks??[]).map((link)=>link.id))
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function blockedAdmission(record){return ['blocked','rejected'].includes(String(record?.admission?.status??''));}
|
|
226
|
-
function rejectedReview(record){return ['rejected','changes-requested'].includes(String(record?.reviewer?.status??''));}
|
|
227
|
-
function intersect(left,right){const rightSet=new Set(right??[]);return uniqueStrings((left??[]).filter((value)=>rightSet.has(value)));}
|
|
228
|
-
function disjointNonEmpty(left,right){return Boolean(left?.length&&right?.length&&intersect(left,right).length===0);}
|
|
229
289
|
function array(value){if(value===undefined||value===null)return[];return Array.isArray(value)?value:[value];}
|
|
230
290
|
function strings(value){return array(value).map((entry)=>String(entry??'')).filter(Boolean);}
|
|
231
291
|
function uniqueStrings(values){return uniqueRawStrings((values??[]).filter((entry)=>entry!==undefined&&entry!==null&&String(entry)!==''));}
|
|
232
292
|
function firstString(...values){return values.map((value)=>value===undefined||value===null?'':String(value)).find(Boolean);}
|
|
233
293
|
function compactRecord(value){return Object.fromEntries(Object.entries(value??{}).filter(([,entry])=>entry!==undefined&&(!Array.isArray(entry)||entry.length>0)));}
|
|
294
|
+
function nonEmptyRecord(value){return Object.keys(value??{}).length?value:undefined;}
|