@shapeshift-labs/frontier-lang-compiler 0.2.164 → 0.2.165

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 CHANGED
@@ -547,6 +547,15 @@ Current JS/TS semantic-merge status matrix:
547
547
 
548
548
  | Surface | Status | Current evidence |
549
549
  | --- | --- | --- |
550
+ | Source-text merge candidate | baseline | Project admission records the conservative concrete source merge candidate before semantic proof rows run. `sourceTextMergeCandidateStatus`, `sourceTextMergeCandidateFiles`, `sourceTextMergeBlockedFiles`, `sourceTextMergeOutputFiles`, `source-text-merge-candidate` evidence, and the `confidence.admissionMatrixAudit` `source-text-merge-candidate` surface make the baseline machine-checkable. Failed source-text candidates block before semantic admission; this row is not a semantic-equivalence or browser-runtime claim. |
551
+ | HTML parser/source evidence | bounded-evidence | HTML project files are counted separately through `htmlFiles`, `htmlMergedFiles`, `htmlBlockedFiles`, parser evidence counters, and `html-parser-source-evidence` matrix proof statuses. Current evidence is parser/source-span bounded around parse5-style source locations, parser-backed spans, and fail-closed parser evidence failures; it does not claim browser DOM, hydration, or render equivalence. |
552
+ | CSS parser/source evidence | bounded-evidence | CSS project files are counted separately through `cssFiles`, `cssMergedFiles`, `cssBlockedFiles`, parser evidence counters, and `css-parser-source-evidence` matrix proof statuses. Current evidence is parser/source-span bounded around PostCSS-style rule/declaration spans, raw trivia hashes, parse-error blockers, and source preservation; it does not claim cascade or browser runtime equivalence. |
553
+ | HTML identity evidence | bounded-evidence | HTML identity proof uses `htmlIdentityEvidenceFiles`, explicit/path identity residual counters, duplicate identity counters, runtime/framework boundary counters, `htmlProofGapBlockedFiles`, and the `html-identity-evidence` proof status. Parser-backed stable identity can support later structural admission, while duplicate identity, runtime boundaries, framework boundaries, or missing proof gaps stay review/blocking evidence. |
554
+ | CSS selector target evidence | bounded-evidence | CSS selector target proof uses `cssSelectorTargetEvidenceFiles`, selector target graph/specificity/move counters, selector conflict/rebase counters, and the `css-selector-target-evidence` proof status. Target evidence remains bounded to parser-backed selector/target/rebase facts and does not claim cascade or browser runtime equivalence. |
555
+ | HTML structural merge admission | partial | HTML structural admission uses `html-structural-merge` proof statuses plus parser and identity evidence. It can admit bounded structural source merges when files merge cleanly and required identity/parser evidence is present; blocked files route to `admit-html-structural-merge` and browser/runtime proof remains a separate row. |
556
+ | CSS cascade merge admission | partial | CSS cascade admission uses `css-cascade-merge` proof statuses plus parser, selector, scoped cascade, dependency, and CSS Module use-site evidence. It remains partial: generated class maps, bundler transform identity, source-map proof, scoped cascade proof, dependency proof, and dynamic use sites stay fail-closed when absent. |
557
+ | CSS dependency graph evidence | bounded-evidence | CSS dependency graph proof uses `cssDependencySurfaceFiles`, `cssDependencyGraphEvidenceFiles`, missing-proof/blocker counters, and the `css-dependency-graph` proof status for custom property, `var()` fallback, animation, font, and asset dependency surfaces. It is absent when no dependency surface is present and does not claim cascade/browser equivalence. |
558
+ | HTML/CSS browser runtime proof | bounded-evidence | HTML/CSS browser proof is an explicit separate row tracked by `htmlCssBrowserRuntimeProofs`, the `html-css-browser-runtime-proof` surface, and the `browser-runtime-proof` proof status. Structural source merges keep browser/render/cascade equivalence claims false unless a bounded browser proof bundle is attached; missing proof routes to `prove-html-css-browser-runtime`. |
550
559
  | Parser/source-span/trivia evidence | Partial | Source preservation, source hashes, runtime directive-prologue entries, directives, comments/trivia summaries, project `sourceFileRecords` / `sourceSpanRecords`, protected-span hashes, shebang file-entrypoint directive ownership anchors, `sourceMappingURL` and `sourceURL` generated-boundary source-map spans, deterministic source-map generated-boundary ownership keys from supplied exact source/generated spans and hashes, generated-boundary position conflict evidence, deterministic ownership anchors, source-span/trivia ownership blockers, exact parser-trivia ownership records for directive prologues plus leading/trailing comments and JSDoc/block-comment spans when parser evidence matches the source hash, TypeScript `SourceFile` compiler-scanner exact token/trivia source-preservation evidence for JS/TS/JSX/TSX imports, ESTree/Babel parser token/comment range evidence when the supplied AST covers every non-whitespace byte of the current source, fail-closed scanner/ledger spoof blockers, source-span delta conflicts, parser roundtrip proof records, failed source-span roundtrip proof admission blockers, project-merge stage parser-trivia evidence from supplied parser-backed imports for base/worker/head/output, metadata-only exactness blockers for scanner fallbacks, and fixture corpus checks. Parser-backed exactness also requires contiguous current-source token/comment/trivia coverage with no gaps, overlaps, truncation, or text mismatches; truncated coverage blocks exact token/comment ownership. Adapters without token/comment ranges remain approximate/caller evidence, not exact parser trivia. |
551
560
  | Scope/use-def graph | Partial | Lightweight lexical scope/use-def scans, destructuring alias binding records, object/array/nested/rest/default-initializer parameter binding evidence for function and arrow parameters, default import alias reads through re-export chains when a stable default-export local binding is observed, fail-closed `lexical-scope-import-alias-target-unresolved` records when an alias target cannot be tied to a lexical binding, namespace import dot and literal/static-template computed member-read evidence, blocked evidence for ambiguous computed namespace reads and namespace member writes, `this`/`super` receiver member read/write evidence including computed string and static-template members, optional chaining markers, and TypeScript checker-backed receiver-member reference proof for full `this`/`super` access spans including private identifiers, template-literal interpolation live-reference records with expression hashes plus tagged-template site/tag root/member metadata, caller-supplied ESTree/scope-manager structural evidence normalization, closure-capture depth/owner/reference hashes, binding-level closure capture hashes, project `scopeBindingRecords` / `scopeReferenceRecords`, public owner use hashes, public scope-use and reference-site delta conflicts with alias target route/use-hash evidence, TypeScript compiler reference relations when a checker is supplied, exact compiler reference-site proof hashes on scope reference records, fail-closed `typescript-compiler-reference-site-ambiguous`, `typescript-compiler-reference-lexical-binding-mismatch`, and `typescript-compiler-reference-import-alias-target-mismatch` records when compiler alias evidence cannot be reconciled with the lexical route or re-export/import target, and dependency-sensitive fixture coverage. Full whole-program binding/control-flow resolution is still caller/compiler-evidence bounded. |
552
561
  | Module/export/import graph | Partial | Project graph stages, module resolution, runtime-neutral package manifest conversion from in-memory `package.json` objects/text, duplicate workspace-root package-name ambiguity diagnostics and fail-closed `package-workspace-root-ambiguous-missing` edges with `packageWorkspaceRoots` evidence, package exports/imports including wildcard package export key/target evidence, fail-closed package `imports` condition misses, runtime-ambiguous `import`/`require` condition blockers, caller-supplied package type runtime-condition evidence for `.js`/`.ts` package exports/imports, caller-supplied package environment-condition evidence such as `browser`, fail-closed `package-export-environment-ambiguous-missing` / `package-import-environment-ambiguous-missing` blockers with condition candidates when environment targets such as `browser` and `node` diverge without explicit evidence, and fail-closed host-runtime ambiguity blockers for non-resolver host package specifiers with divergent `import`/`require` targets, re-export identities including static TypeScript-style CommonJS bare and `tslib_1.__...` member-form `__exportStar(require("./dep"), exports)` fanout and `__createBinding(exports, require("./dep"), "name", "alias")` named re-export fanout, same-document CommonJS require-alias getter re-export identities for descriptor `get: function () { return dep.name; }`, named descriptor `get: function getName() { return dep.name; }`, shorthand `get() { return dep.name; }`, and block-bodied arrow `get: () => { return dep.name; }`, TypeScript-style CommonJS bare and `tslib_1.__...` member-form `__importDefault(require("./dep"))` and `__importStar(require("./dep"))` helper import edges, CommonJS `module.exports` default-import interop when no direct `default` export exists, literal computed CommonJS export properties such as `exports["default"]`, static `module.exports = { named }`, `Object.assign(exports, { named })`, `Object.defineProperty(exports, "named", { value/get })`, and `Object.defineProperties(exports, { named: { value/get } })` export maps in lightweight and AST-backed imports, ESTree/Babel no-expression `TemplateLiteral` normalization for CommonJS `require`, computed export keys, descriptor export specifiers, dynamic `import()`, CommonJS helper re-export specifiers, and host dependency specifiers while expression-bearing templates stay unresolved, TypeScript compiler no-substitution dynamic import and host dependency template evidence, `exports.__esModule` marker filtering, import-target deltas for head-introduced CommonJS export assignments, namespace/ambient module/global augmentation/export-assignment static shape records with proof hashes and no runtime-equivalence claim, fail-closed namespace/export-assignment shape delta conflicts, non-literal dynamic `import()` pseudo-specifiers with expression kind/text/hash evidence and fail-closed resolution evidence, static `new URL(specifier, import.meta.url)`, `Worker`, `SharedWorker`, `serviceWorker.register`, worklet `addModule`, `importScripts`, `import.meta.resolve`, and `require.resolve` host dependency edges with expression hashes and no runtime-resolution claim, dynamic host dependency targets emitted as `<host-dependency>` with expression hashes, `hostDependencyStaticSpecifierEvidence: false`, and proof-required unresolved evidence, import-attribute/import-assertion normalized key/value/count/hash evidence on static imports, dynamic imports, and re-exports, import-attribute delta conflicts, output graph unresolved-module conflicts that preserve edge-level fail-closed package, host, dynamic import, and import-attribute value evidence, and output graph resolved-module missing-export conflicts that preserve edge-level package and import-attribute evidence. Host filesystem/package graph crawling, namespace runtime evaluation, ambient/global compatibility, and CommonJS runtime interop equivalence remain out of the root API. |
@@ -62,12 +62,14 @@ export interface JsTsProjectMergeProofEvidenceSummary {
62
62
  readonly failed: number;
63
63
  readonly skipped: number;
64
64
  readonly unknown: number;
65
+ readonly levelStatuses: Readonly<Record<string, JsTsProjectMergeProofEvidenceRecordStatus>>;
65
66
  readonly evidenceLevels: readonly JsTsProjectMergeProofLevel[];
66
67
  readonly passedLevels: readonly JsTsProjectMergeProofLevel[];
67
68
  readonly failedLevels: readonly JsTsProjectMergeProofLevel[];
68
69
  readonly skippedLevels: readonly JsTsProjectMergeProofLevel[];
69
70
  readonly unknownLevels: readonly JsTsProjectMergeProofLevel[];
70
71
  readonly missingLevels: readonly JsTsProjectMergeProofLevel[];
72
+ readonly missingSignals: readonly string[];
71
73
  readonly unsupportedSurfaceEvidenceCount?: number;
72
74
  readonly unsupportedSurfaceKinds?: readonly string[];
73
75
  readonly unsupportedSurfaceReasonCodes?: readonly string[];
@@ -82,6 +84,7 @@ export interface JsTsProjectMergeProofEvidenceSummary {
82
84
  readonly nextMissingEvidence?: JsTsProjectMergeProofMissingEvidence;
83
85
  readonly semanticEquivalenceLevel: 'semantic-equivalence-unknown' | string;
84
86
  readonly semanticEquivalenceClaim: boolean;
87
+ readonly semanticEquivalenceUnknown: boolean;
85
88
  readonly evidenceOnly: true;
86
89
  readonly proofClaims: number;
87
90
  }
@@ -102,6 +105,7 @@ export interface JsTsProjectMergeProofEvidence {
102
105
  readonly evidenceOnly?: true;
103
106
  readonly proofClaims?: number;
104
107
  readonly missingLevels?: readonly JsTsProjectMergeProofLevel[];
108
+ readonly missingSignals?: readonly string[];
105
109
  readonly nextMissingEvidence?: JsTsProjectMergeProofMissingEvidence;
106
110
  readonly autoMergeClaim?: false;
107
111
  readonly semanticEquivalenceClaim?: boolean;
@@ -1,16 +1,21 @@
1
1
  import type { JsTsProjectMergeProofLevel } from './js-ts-project-merge-proof-levels.js';
2
2
  import type { JsTsProjectSafeMergeMissingEvidenceTelemetry } from './js-ts-project-merge-confidence.js';
3
3
 
4
+ export type JsTsProjectSourceTextMergeCandidateStatus = 'passed' | 'failed' | 'absent' | string;
5
+ export type JsTsProjectMergeSummaryProofStatus = 'passed' | 'failed' | 'skipped' | 'unknown' | 'missing' | 'absent' | string;
6
+
4
7
  export interface JsTsProjectSafeMergeSummary {
5
8
  readonly files: number; readonly mergedFiles: number; readonly blockedFiles: number; readonly outputFiles: number;
9
+ readonly sourceTextMergeCandidateFiles: number; readonly sourceTextMergeBlockedFiles: number; readonly sourceTextMergeOutputFiles: number; readonly sourceTextMergeCandidateStatus: JsTsProjectSourceTextMergeCandidateStatus;
6
10
  readonly htmlFiles:number; readonly cssFiles:number; readonly htmlCssFiles:number; readonly htmlMergedFiles:number; readonly cssMergedFiles:number; readonly htmlCssMergedFiles:number; readonly htmlBlockedFiles:number; readonly cssBlockedFiles:number; readonly htmlCssBlockedFiles:number; readonly htmlCssBrowserRuntimeProofs:number;
7
11
  readonly htmlParserEvidenceFiles:number; readonly cssParserEvidenceFiles:number; readonly htmlCssParserEvidenceFiles:number; readonly htmlParserEvidenceFailedFiles:number; readonly cssParserEvidenceFailedFiles:number; readonly htmlCssParserEvidenceFailedFiles:number;
8
- readonly htmlIdentityEvidenceFiles:number; readonly cssSelectorTargetEvidenceFiles:number; readonly htmlCssStructuralTargetEvidenceFiles:number; readonly htmlIdentityEvidenceFailedFiles:number; readonly cssSelectorTargetConflictFiles:number; readonly htmlCssStructuralTargetEvidenceFailedFiles:number; readonly cssSelectorTargetRebasedFiles:number;
9
- readonly projectGraphConflicts: number; readonly projectGraphDeltaEvidenceIncluded: number; readonly outputProjectGraphConflicts:number; readonly projectGraphCssModuleUseSiteConflicts:number; readonly projectGraphDeltaConflicts: number; readonly projectGraphLimitConflicts: number; readonly projectGraphPublicContractConflicts: number; readonly projectGraphSourceSpanConflicts: number;
12
+ readonly htmlIdentityEvidenceFiles:number; readonly cssSelectorTargetEvidenceFiles:number; readonly htmlCssStructuralTargetEvidenceFiles:number; readonly cssSelectorTargetGraphEvidenceFiles:number; readonly cssSelectorSpecificityEvidenceFiles:number; readonly cssSelectorTargetMoveFiles:number; readonly htmlExplicitIdentityEvidenceFiles:number; readonly htmlPathOnlyIdentityResidualFiles:number; readonly htmlDuplicateIdentityEvidenceFiles:number; readonly htmlDuplicateIdentityKeys:number; readonly htmlRuntimeBoundaryEvidenceFiles:number; readonly htmlFrameworkBoundaryEvidenceFiles:number; readonly htmlProofGapBlockedFiles:number; readonly htmlIdentityEvidenceFailedFiles:number; readonly cssSelectorTargetConflictFiles:number; readonly htmlCssStructuralTargetEvidenceFailedFiles:number; readonly cssSelectorTargetRebasedFiles:number;
13
+ readonly cssScopedCascadeFiles:number; readonly cssScopedCascadeEvidenceFiles:number; readonly cssScopedCascadeBlockedFiles:number; readonly cssDependencySurfaceFiles:number; readonly cssDependencyGraphEvidenceFiles:number; readonly cssDependencyGraphMissingProofFiles:number; readonly cssDependencyGraphBlockedFiles:number;
14
+ readonly projectGraphConflicts: number; readonly projectGraphDeltaEvidenceIncluded: number; readonly projectGraphEvidenceIncluded: number; readonly outputProjectGraphConflicts:number; readonly projectGraphCssModuleUseSiteConflicts:number; readonly projectGraphDeltaConflicts: number; readonly projectGraphCssModuleUseSiteBlockers:number; readonly projectGraphLimitConflicts: number; readonly projectGraphCssModuleUseSiteGraphs:number; readonly projectGraphCssModuleUseSites:number; readonly projectGraphCssModuleImportBindings:number; readonly projectGraphPublicContractConflicts: number; readonly projectGraphSourceSpanConflicts: number;
10
15
  readonly projectGraphCompilerTypeConflicts: number; readonly projectGraphRuntimeRegionConflicts: number; readonly projectGraphScopeUseDefConflicts: number; readonly projectGraphJsxPropConflicts: number; readonly projectGraphJsxRenderRiskConflicts: number; readonly projectGraphReExportIdentityConflicts: number; readonly projectGraphModuleDeclarationShapeConflicts: number; readonly projectGraphExportAssignmentShapeConflicts: number;
11
16
  readonly projectGraphImportAttributeConflicts: number; readonly projectGraphImportTargetConflicts: number; readonly outputDiagnostics: number; readonly outputDiagnosticConflicts: number; readonly outputDiagnosticErrors: number; readonly outputDiagnosticWarnings: number; readonly outputDeclarations: number; readonly outputDeclarationBytes: number; readonly outputDeclarationConflicts: number; readonly outputDeclarationDiagnosticErrors: number; readonly outputQualityGates: number; readonly outputQualityGateConflicts: number;
12
- readonly proofEvidenceRecords: number; readonly proofEvidencePassed: number; readonly proofEvidenceFailed: number; readonly proofEvidenceSkipped: number; readonly proofEvidenceUnknown: number; readonly proofEvidenceMissing: number; readonly proofEvidenceMissingLevels: readonly JsTsProjectMergeProofLevel[]; readonly semanticEquivalenceLevel: 'semantic-equivalence-unknown' | string;
13
- readonly evidenceRecords: number; readonly passedEvidenceRecords: number; readonly failedEvidenceRecords: number; readonly unknownEvidenceRecords: number; readonly confidenceScore: number; readonly confidenceLevel: string; readonly confidenceDimensions: Readonly<Record<string,string>>; readonly missingEvidenceMatrix: JsTsProjectSafeMergeMissingEvidenceTelemetry; readonly missingSignals: number;
17
+ readonly proofEvidenceRecords: number; readonly proofEvidencePassed: number; readonly proofEvidenceFailed: number; readonly proofEvidenceSkipped: number; readonly proofEvidenceUnknown: number; readonly proofEvidenceMissing: number; readonly proofEvidenceMissingLevels: readonly JsTsProjectMergeProofLevel[]; readonly proofEvidenceMissingSignals: readonly string[]; readonly proofEvidenceNextMissingCode?: string; readonly proofEvidenceNextMissingLevel?: JsTsProjectMergeProofLevel; readonly proofEvidenceNextMissingScope?: string; readonly proofEvidenceLevelStatuses: Readonly<Record<string,JsTsProjectMergeSummaryProofStatus>>; readonly proofSyntaxIdentityStatus: JsTsProjectMergeSummaryProofStatus; readonly proofSourceSpanRoundtripStatus: JsTsProjectMergeSummaryProofStatus; readonly proofSemanticEditReplayCleanStatus: JsTsProjectMergeSummaryProofStatus; readonly proofDiagnosticsStatus: JsTsProjectMergeSummaryProofStatus; readonly proofDeclarationOutputStatus: JsTsProjectMergeSummaryProofStatus; readonly proofFocusedTestStatus: JsTsProjectMergeSummaryProofStatus; readonly proofSemanticEquivalenceStatus: JsTsProjectMergeSummaryProofStatus; readonly semanticEquivalenceLevel: 'semantic-equivalence-unknown' | string; readonly semanticEquivalenceClaim: boolean;
18
+ readonly evidenceRecords: number; readonly passedEvidenceRecords: number; readonly failedEvidenceRecords: number; readonly unknownEvidenceRecords: number; readonly confidenceScore: number; readonly confidenceLevel: string; readonly confidenceDimensions: Readonly<Record<string,string>>; readonly missingEvidenceMatrix: JsTsProjectSafeMergeMissingEvidenceTelemetry; readonly routingCalibration?: Readonly<Record<string,unknown>>; readonly missingSignals: number; readonly admissionMatrixPartialRows: number;
14
19
  readonly nextMissingEvidenceCode?: string; readonly nextMissingEvidenceKind?: string; readonly nextMissingEvidenceScope?: string; readonly nextMissingProofLevel?: string; readonly nextMissingEvidenceAction?: string; readonly nextMissingEvidenceRouteId?: string; readonly nextMissingEvidenceRouteLane?: string; readonly nextMissingEvidenceRouteNext?: string;
15
20
  readonly projectMoveRenameClassifications: number; readonly projectFileMoveRenameClassifications: number; readonly projectSymbolMoveClassifications: number; readonly projectExportedSymbolMoveClassifications: number; readonly projectImportedSymbolMoveClassifications: number; readonly projectSymbolMoveAdmissions: number; readonly projectExportedSymbolMoveAdmissions: number; readonly projectImportedSymbolMoveAdmissions: number; readonly projectCrossFileSymbolRenameClassifications: number; readonly projectCrossFileSymbolRenameAdmissions: number;
16
21
  readonly projectSplitMergeClassifications: number; readonly projectModuleSplitClassifications: number; readonly projectModuleMergeClassifications: number; readonly projectClassSplitClassifications: number; readonly projectClassMergeClassifications: number; readonly projectSplitMergeAdmissions: number; readonly projectModuleSplitAdmissions: number; readonly projectModuleMergeAdmissions: number; readonly projectClassSplitAdmissions: number; readonly projectClassMergeAdmissions: number;
@@ -21,7 +21,7 @@ export type { JsTsProjectMergeQualityGate, JsTsProjectMergeQualityGateDecision,
21
21
  export type { JsTsProjectMergeProofEvidence, JsTsProjectMergeProofEvidenceRecord, JsTsProjectMergeProofEvidenceRecordStatus, JsTsProjectMergeProofEvidenceStatus, JsTsProjectMergeProofEvidenceSummary, JsTsProjectMergeProofLevel, JsTsProjectMergeProofMissingEvidence } from './js-ts-project-merge-proof-levels.js';
22
22
  export type { JsTsProjectSafeMergeAdmissionRoute, JsTsProjectSafeMergeAdmissionRouteSummary } from './js-ts-project-merge-admission-routes.js';
23
23
  export type { JsTsProjectSafeMergeConfidenceSummary, JsTsProjectSafeMergeMissingEvidence, JsTsProjectSafeMergeMissingEvidenceRoute, JsTsProjectSafeMergeMissingEvidenceTelemetry, JsTsProjectSafeMergeRecommendedAction } from './js-ts-project-merge-confidence.js';
24
- export type { JsTsProjectSafeMergeSummary } from './js-ts-project-merge-summary.js';
24
+ export type { JsTsProjectMergeSummaryProofStatus, JsTsProjectSafeMergeSummary, JsTsProjectSourceTextMergeCandidateStatus } from './js-ts-project-merge-summary.js';
25
25
  export type { JsTsProjectCommonJsRuntimeInteropProof } from './js-ts-project-merge-commonjs-interop.js';
26
26
  export type { JsTsProjectGlobalAugmentationCompatibilityProof } from './js-ts-project-merge-global-augmentation.js'; export type { JsTsProjectJsxRenderReturnBranchArmOrigin, JsTsProjectJsxRenderReturnBranchControlKind, JsTsProjectJsxRenderReturnBranchProof } from './js-ts-project-merge-jsx-render-branch.js';
27
27
 
@@ -106,6 +106,7 @@ function projectAdmissionRouteFromMissingEvidence(item) {
106
106
  const routeId = item?.routeId ?? route.id;
107
107
  if (!routeId) return undefined;
108
108
  const action = normalizedRouteAction(item?.action);
109
+ const missingEvidence = missingEvidenceCodes(item);
109
110
  return routeRecord({
110
111
  routeId,
111
112
  routeKind: action,
@@ -118,6 +119,14 @@ function projectAdmissionRouteFromMissingEvidence(item) {
118
119
  proofLevel: item?.proofLevel,
119
120
  evidenceId: item?.evidenceId,
120
121
  reasonCodes: uniqueStrings([item?.code, ...(item?.relatedSignals ?? [])]),
122
+ requiredEvidence: item?.requiredEvidence ?? inferredRequiredEvidence(item),
123
+ presentEvidence: item?.presentEvidence ?? inferredPresentEvidence(item),
124
+ missingEvidence,
125
+ recommendedAction: item?.recommendedAction ?? recommendedActionFromMissingEvidence(item),
126
+ confidenceDimension: item?.confidenceDimension ?? confidenceDimensionFromMissingEvidence(item),
127
+ blocksSemanticEquivalence: item?.blocksSemanticEquivalence ?? semanticEquivalenceEvidenceGap(item),
128
+ summary: item?.summary,
129
+ nextAction: item?.nextAction,
121
130
  details: item
122
131
  });
123
132
  }
@@ -175,6 +184,11 @@ function routeRecord(input) {
175
184
  requiredEvidence: input.requiredEvidence,
176
185
  presentEvidence: input.presentEvidence,
177
186
  missingEvidence: input.missingEvidence,
187
+ recommendedAction: input.recommendedAction,
188
+ confidenceDimension: input.confidenceDimension,
189
+ blocksSemanticEquivalence: input.blocksSemanticEquivalence,
190
+ summary: input.summary,
191
+ nextAction: input.nextAction,
178
192
  details: input.details,
179
193
  autoMergeClaim: false,
180
194
  semanticEquivalenceClaim: false
@@ -200,6 +214,45 @@ function normalizedRouteAction(action) {
200
214
  return 'review';
201
215
  }
202
216
 
217
+ function missingEvidenceCodes(item) {
218
+ return uniqueStrings([item?.code, ...(item?.missingEvidence ?? []), ...(item?.missingSignals ?? [])]);
219
+ }
220
+
221
+ function inferredRequiredEvidence(item) {
222
+ if (semanticEquivalenceEvidenceGap(item)) return ['semantic-equivalence-external'];
223
+ return item?.proofLevel ? [item.proofLevel] : undefined;
224
+ }
225
+
226
+ function inferredPresentEvidence(item) {
227
+ if (item?.proofLevel === 'semantic-equivalence-unknown') return ['semantic-equivalence-unknown'];
228
+ if (item?.proofLevel === 'semantic-equivalence-external' && item?.status === 'failed') return ['semantic-equivalence-external'];
229
+ return undefined;
230
+ }
231
+
232
+ function recommendedActionFromMissingEvidence(item) {
233
+ const action = normalizedRouteAction(item?.action);
234
+ if (action === 'reject' || action === 'block') return 'block';
235
+ if (action === 'rerun') return 'rerun';
236
+ return 'review';
237
+ }
238
+
239
+ function confidenceDimensionFromMissingEvidence(item) {
240
+ if (semanticEquivalenceEvidenceGap(item)) return 'semanticEquivalence';
241
+ if (item?.scope === 'project-output' && item?.kind === 'diagnostics') return 'diagnostics';
242
+ if (item?.scope === 'project-output' && item?.kind === 'declaration-output') return 'declarations';
243
+ if (item?.scope === 'quality-gates') return 'quality';
244
+ if (item?.scope === 'project-graph') return 'graph';
245
+ if (item?.scope === 'source-files') return 'proof';
246
+ return undefined;
247
+ }
248
+
249
+ function semanticEquivalenceEvidenceGap(item) {
250
+ return item?.code === 'semantic-equivalence-proof-not-available'
251
+ || item?.code === 'semantic-equivalence-proof-failed'
252
+ || item?.proofLevel === 'semantic-equivalence-unknown'
253
+ || item?.proofLevel === 'semantic-equivalence-external';
254
+ }
255
+
203
256
  function routeSpec(routeId, routeLane, routeNext) { return Object.freeze({ routeId, routeLane, routeNext }); }
204
257
  function countField(values, field) { const result = {}; for (const value of values) if (value?.[field]) result[value[field]] = (result[value[field]] ?? 0) + 1; return result; }
205
258
  function uniqueStrings(values) { return [...new Set((values ?? []).filter((value) => typeof value === 'string' && value.length > 0))]; }
@@ -15,7 +15,7 @@ function htmlCssProjectMergeMissingEvidenceRoutes(route, signals) {
15
15
  [signals.cssParserEvidence]: route('prove-css-parser-source-evidence', 'layout-style-parser', 'supply-postcss-source-span-and-trivia-evidence'),
16
16
  [signals.htmlIdentityEvidence]: route('prove-html-identity-evidence', 'layout-markup-identity', 'supply-stable-element-identity-and-structural-addressability-evidence'),
17
17
  [signals.cssSelectorTargetEvidence]: route('prove-css-selector-target-evidence', 'layout-style-targets', 'supply-selector-target-graph-and-rebase-evidence'),
18
- [signals.htmlStructuralMerge]: route('admit-html-structural-merge', 'layout-markup-graph', 'supply-html-parser-reference-and-boundary-evidence'),
18
+ [signals.htmlStructuralMerge]: route('admit-html-structural-merge', 'layout-markup-graph', 'attach-source-bound-html-runtime-proof-or-fix-duplicate-identity'),
19
19
  [signals.cssCascadeMerge]: route('admit-css-cascade-merge', 'layout-style-graph', 'supply-css-parser-cascade-and-scope-evidence'),
20
20
  [signals.cssDependencyGraphEvidence]: route('prove-css-dependency-graph', 'layout-style-graph', 'supply-css-custom-property-animation-font-and-asset-dependency-graph'),
21
21
  [signals.htmlCssBrowserRuntimeProof]: route('prove-html-css-browser-runtime', 'browser-proof', 'attach-browser-runtime-proof-bundle')
@@ -41,7 +41,7 @@ function htmlCssProjectMergeMissingEvidenceItems(summary, signals, missingEviden
41
41
  if (summary.cssFiles && summary.cssParserEvidenceFiles !== summary.cssFiles) items.push(missingEvidenceItem({ code: signals.cssParserEvidence, scope: 'layout-style-parser', kind: 'css-parser-source-evidence', proofLevel: 'css-parser-source-evidence', action: 'review', summary: `CSS project merge has parser/source evidence for ${summary.cssParserEvidenceFiles}/${summary.cssFiles} file(s); require PostCSS rule/declaration spans, raw trivia hashes, and zero parse errors before parser evidence admission.` }));
42
42
  if (summary.htmlFiles && summary.htmlIdentityEvidenceFiles !== summary.htmlFiles) items.push(missingEvidenceItem({ code: signals.htmlIdentityEvidence, scope: 'layout-markup-identity', kind: 'html-identity-evidence', proofLevel: 'html-identity-evidence', action: 'review', summary: `HTML project merge has structural identity evidence for ${summary.htmlIdentityEvidenceFiles}/${summary.htmlFiles} file(s) with ${summary.htmlDuplicateIdentityEvidenceFiles ?? 0} duplicate identity evidence file(s); require parser-backed structural spans, unique explicit identity keys, and stable explicit/path identity accounting before structural admission.` }));
43
43
  if (summary.cssFiles && (summary.cssSelectorTargetEvidenceFiles !== summary.cssFiles || summary.cssSelectorTargetConflictFiles)) items.push(missingEvidenceItem({ code: signals.cssSelectorTargetEvidence, scope: 'layout-style-targets', kind: 'css-selector-target-evidence', proofLevel: 'css-selector-target-evidence', action: 'review', summary: `CSS project merge has selector-target evidence for ${summary.cssSelectorTargetEvidenceFiles}/${summary.cssFiles} file(s) with ${summary.cssSelectorTargetConflictFiles} selector target conflict(s); require selector target graph and proven rebase before target-moving merges.` }));
44
- if (summary.htmlBlockedFiles) items.push(missingEvidenceItem({ code: signals.htmlStructuralMerge, scope: 'layout-markup-graph', kind: 'html-structural-merge-proof', proofLevel: 'html-structural-merge', action: 'review', summary: `HTML project merge has ${summary.htmlBlockedFiles} blocked file(s); supply parser/source-span evidence, stable element identity, and runtime-boundary proof before admission.` }));
44
+ if (summary.htmlBlockedFiles) items.push(missingEvidenceItem({ code: signals.htmlStructuralMerge, scope: 'layout-markup-graph', kind: 'html-structural-merge-proof', proofLevel: 'html-structural-merge', action: 'review', summary: `HTML project merge has ${summary.htmlBlockedFiles} blocked file(s); for runtime-boundary changes attach htmlRuntimeBoundaryProofsByPath[sourcePath] with exact base/worker/head/output binding, and for duplicate identity keys make explicit HTML identities unique before admission.`, suggestedInput: { htmlRuntimeBoundaryProofsByPath: true, htmlUniqueExplicitIdentityKeys: true } }));
45
45
  if (summary.cssBlockedFiles) items.push(missingEvidenceItem({ code: signals.cssCascadeMerge, scope: 'layout-style-graph', kind: 'css-cascade-merge-proof', proofLevel: 'css-cascade-merge', action: 'review', summary: `CSS project merge has ${summary.cssBlockedFiles} blocked file(s), including ${summary.cssScopedCascadeBlockedFiles} scoped cascade proof block(s); supply parser/cascade/scope evidence, require scopedCascadeGraphHash for changed declarations under @media/@supports/@container/@layer/@scope or nested scopes, and keep browser claims false until runtime proof passes.` }));
46
46
  if (summary.cssDependencySurfaceFiles && (summary.cssDependencyGraphEvidenceFiles !== summary.cssDependencySurfaceFiles || summary.cssDependencyGraphMissingProofFiles || summary.cssDependencyGraphBlockedFiles)) items.push(missingEvidenceItem({ code: signals.cssDependencyGraphEvidence, scope: 'layout-style-graph', kind: 'css-dependency-graph-evidence', proofLevel: 'css-dependency-graph', action: 'review', summary: `CSS project merge has dependency graph evidence for ${summary.cssDependencyGraphEvidenceFiles}/${summary.cssDependencySurfaceFiles} dependency-surface file(s), ${summary.cssDependencyGraphMissingProofFiles} missing dependency graph proof(s), and ${summary.cssDependencyGraphBlockedFiles} dependency blocker(s); require custom property, var() fallback, @keyframes/animation-name, @font-face, and url() asset graph evidence before cascade/browser equivalence claims.`, suggestedInput: { cssDependencyGraphEvidence: true } }));
47
47
  if (summary.htmlCssMergedFiles && !summary.htmlCssBrowserRuntimeProofs) items.push(missingEvidenceItem({ code: signals.htmlCssBrowserRuntimeProof, scope: 'browser-proof', kind: 'browser-runtime-proof', proofLevel: 'browser-runtime-proof', action: 'review', summary: 'HTML/CSS structural source merge was available, but browser DOM/cascade/layout/runtime proof was not attached; keep browser equivalence claims false.', suggestedInput: { browserRuntimeProof: true } }));
@@ -42,7 +42,7 @@ function hasHtmlExplicitIdentityEvidence(file) {
42
42
  }
43
43
  function hasHtmlPathOnlyIdentityResidual(file) { return (file?.result?.identityEvidence?.pathOnlyIdentityElements ?? 0) > 0; }
44
44
  function hasHtmlRuntimeBoundaryEvidence(file) {
45
- return (file?.result?.identityEvidence?.runtimeBoundaryElements ?? 0) > 0 || hasRuntimeBoundaryConflict(file);
45
+ return (file?.result?.identityEvidence?.runtimeBoundaryElements ?? 0) > 0 || hasRuntimeBoundaryConflict(file) || hasHtmlRuntimeBoundaryProof(file);
46
46
  }
47
47
  function hasHtmlFrameworkBoundaryEvidence(file) {
48
48
  return (file?.result?.identityEvidence?.frameworkBoundaryElements ?? 0) > 0 || hasFrameworkBoundaryConflict(file);
@@ -74,6 +74,9 @@ function hasHtmlProofGapBlockedConflict(file) {
74
74
  function hasRuntimeBoundaryConflict(file) {
75
75
  return (file?.result?.conflicts ?? file?.conflicts ?? []).some((conflict) => HtmlRuntimeBoundaryReasonCodes.has(conflict?.details?.reasonCode));
76
76
  }
77
+ function hasHtmlRuntimeBoundaryProof(file) {
78
+ return [...(file?.result?.runtimeBoundaryProofs ?? []), ...(file?.result?.admission?.htmlRuntimeBoundaryProofs ?? file?.admission?.htmlRuntimeBoundaryProofs ?? [])].some((proof) => proof?.status === 'passed' && HtmlRuntimeBoundaryReasonCodes.has(proof.reasonCode));
79
+ }
77
80
  function hasFrameworkBoundaryConflict(file) {
78
81
  return (file?.result?.conflicts ?? file?.conflicts ?? []).some((conflict) => HtmlFrameworkBoundaryReasonCodes.has(conflict?.details?.reasonCode));
79
82
  }
@@ -13,9 +13,10 @@ function maybeMergeHtmlCssProjectFile(options) {
13
13
  const merge = language === 'html' ? safeMergeHtmlSource : language === 'css' ? safeMergeCssSource : undefined;
14
14
  if (!merge) return undefined;
15
15
  const resultId = `${projectId}_${safeId(file.sourcePath)}`;
16
- const result = merge({ ...sourceInput, ...htmlCssMergeOptionsForProjectFile(input, file.sourcePath, language), ...context, id: resultId, baseSourceText: base, workerSourceText: worker, headSourceText: head });
16
+ const mergeOptions = htmlCssMergeOptionsForProjectFile(input, file.sourcePath, language);
17
+ const result = merge({ ...sourceInput, ...mergeOptions, ...context, id: resultId, baseSourceText: base, workerSourceText: worker, headSourceText: head });
17
18
  const admittedResult = language === 'html' && result.status === 'merged'
18
- ? blockHtmlProofGapChanges({ result, id: resultId, sourcePath: file.sourcePath, base, worker, head }) ?? result
19
+ ? blockHtmlProofGapChanges({ result, id: resultId, sourcePath: file.sourcePath, base, worker, head, runtimeBoundaryProofs: htmlRuntimeBoundaryProofCandidates(input, file.sourcePath, mergeOptions) }) ?? result
19
20
  : result;
20
21
  return admittedResult.status === 'merged' ? mergedHtmlCssFile(file, context, admittedResult, language) : blockedHtmlCssFile(file, context, admittedResult);
21
22
  }
@@ -36,12 +37,20 @@ function htmlCssMergeOptionsForProjectFile(input, sourcePath, language) {
36
37
  return compactRecord({ ...(language === 'css' ? input.cssMergeOptions ?? input.styleMergeOptions : input.htmlMergeOptions ?? input.markupMergeOptions), ...(byPath?.[sourcePath] ?? {}) });
37
38
  }
38
39
 
39
- function blockHtmlProofGapChanges({ result, id, sourcePath, base, worker, head }) {
40
+ function blockHtmlProofGapChanges({ result, id, sourcePath, base, worker, head, runtimeBoundaryProofs = [] }) {
41
+ const binding = { sourcePath, base, worker, head, output: result.mergedSourceText };
42
+ const runtimeBoundaryProofRecords = [];
43
+ const runtimeBoundaryConflicts = [];
44
+ for (const change of htmlRuntimeBoundaryChanges(base, worker, head)) {
45
+ const proof = htmlRuntimeBoundaryProofForChange(runtimeBoundaryProofs, change, binding);
46
+ if (proof) runtimeBoundaryProofRecords.push(htmlRuntimeBoundaryProofRecord(proof, change, binding));
47
+ else runtimeBoundaryConflicts.push(htmlProofGapConflict(id, sourcePath, change.reasonCode, change));
48
+ }
40
49
  const conflicts = [
41
- htmlDuplicateIdentityConflict(result),
42
- ...htmlRuntimeBoundaryChanges(base, worker, head).map((change) => htmlProofGapConflict(id, sourcePath, change.reasonCode, change))
50
+ htmlDuplicateIdentityConflict(result, sourcePath),
51
+ ...runtimeBoundaryConflicts
43
52
  ].filter(Boolean);
44
- if (!conflicts.length) return undefined;
53
+ if (!conflicts.length) return runtimeBoundaryProofRecords.length ? htmlRuntimeBoundaryProvenResult(result, runtimeBoundaryProofRecords) : undefined;
45
54
  const allConflicts = [...(result.conflicts ?? []), ...conflicts];
46
55
  const { mergedSourceText, mergedSourceHash, ...rest } = result;
47
56
  return compactRecord({
@@ -56,15 +65,32 @@ function blockHtmlProofGapChanges({ result, id, sourcePath, base, worker, head }
56
65
  });
57
66
  }
58
67
 
59
- function htmlDuplicateIdentityConflict(result) {
68
+ function htmlDuplicateIdentityConflict(result, sourcePath) {
60
69
  const duplicates = duplicateHtmlExplicitIdentityKeys(result?.identityEvidence);
61
70
  if (!duplicates.length) return undefined;
62
- return htmlProofGapConflict(result.id, result.sourcePath, 'html-duplicate-explicit-identity', {
71
+ return htmlProofGapConflict(result.id, result.sourcePath ?? sourcePath, 'html-duplicate-explicit-identity', {
63
72
  boundary: 'html-explicit-identity',
64
73
  duplicateIdentityKeys: duplicates
65
74
  }, 'html-duplicate-identity-blocked');
66
75
  }
67
76
 
77
+ function htmlRuntimeBoundaryProofCandidates(input, sourcePath, mergeOptions) {
78
+ return [
79
+ input.htmlRuntimeBoundaryProof,
80
+ input.htmlRuntimeBoundaryProofs,
81
+ input.htmlRuntimeBoundaryProofsByPath?.[sourcePath],
82
+ input.htmlSourceBoundRuntimeBoundaryProof,
83
+ input.htmlSourceBoundRuntimeBoundaryProofs,
84
+ input.htmlSourceBoundRuntimeBoundaryProofsByPath?.[sourcePath],
85
+ mergeOptions.htmlRuntimeBoundaryProof,
86
+ mergeOptions.htmlRuntimeBoundaryProofs,
87
+ mergeOptions.sourceBoundRuntimeBoundaryProof,
88
+ mergeOptions.sourceBoundRuntimeBoundaryProofs,
89
+ mergeOptions.runtimeBoundaryProof,
90
+ mergeOptions.runtimeBoundaryProofs
91
+ ].flatMap(asArray).filter(Boolean);
92
+ }
93
+
68
94
  function duplicateHtmlExplicitIdentityKeys(identityEvidence) {
69
95
  return Object.entries(identityEvidence?.sides ?? {}).flatMap(([side, evidence]) => {
70
96
  const counts = new Map();
@@ -95,6 +121,73 @@ function htmlRuntimeBoundaryChange(side, base, sourceText, baseEventHandlers) {
95
121
  };
96
122
  }
97
123
 
124
+ function htmlRuntimeBoundaryProofForChange(proofs, change, binding) {
125
+ return proofs.find((proof) => isHtmlRuntimeBoundaryProofForChange(proof, change, binding));
126
+ }
127
+
128
+ function isHtmlRuntimeBoundaryProofForChange(proof, change, binding) {
129
+ return Boolean(proof && typeof proof === 'object') &&
130
+ HtmlRuntimeBoundaryProofKinds.has(proof.kind) &&
131
+ proof.status === 'passed' &&
132
+ proof.sourcePath === binding.sourcePath &&
133
+ htmlProofCoversValue(proof.reasonCode, proof.reasonCodes, change.reasonCode) &&
134
+ htmlProofCoversValue(proof.side, proof.sides, change.side) &&
135
+ proof.boundary === change.boundary &&
136
+ sameStringSet(proof.boundaryAttributes ?? proof.changedBoundaryAttributes, change.boundaryAttributes) &&
137
+ htmlRuntimeBoundaryProofSourceBound(proof, binding);
138
+ }
139
+
140
+ function htmlRuntimeBoundaryProofSourceBound(proof, binding) {
141
+ return htmlRuntimeBoundaryProofSourceMatches(proof, 'base', binding.base) &&
142
+ htmlRuntimeBoundaryProofSourceMatches(proof, 'worker', binding.worker) &&
143
+ htmlRuntimeBoundaryProofSourceMatches(proof, 'head', binding.head) &&
144
+ htmlRuntimeBoundaryProofSourceMatches(proof, 'output', binding.output);
145
+ }
146
+
147
+ function htmlRuntimeBoundaryProofSourceMatches(proof, role, sourceText) {
148
+ if (typeof sourceText !== 'string') return false;
149
+ const hash = hashText(sourceText);
150
+ const textFields = role === 'output' ? ['outputSourceText', 'mergedSourceText'] : [`${role}SourceText`];
151
+ const hashFields = role === 'output' ? ['outputSourceHash', 'mergedSourceHash'] : [`${role}SourceHash`];
152
+ const aliases = role === 'output' ? ['output', 'merged'] : [role];
153
+ return textFields.some((field) => proof[field] === sourceText) ||
154
+ aliases.some((alias) => proof.sourceTexts?.[alias] === sourceText || proof.sources?.[alias] === sourceText) ||
155
+ hashFields.some((field) => proof[field] === hash) ||
156
+ aliases.some((alias) => proof.sourceHashes?.[alias] === hash || proof.hashes?.[alias] === hash);
157
+ }
158
+
159
+ function htmlRuntimeBoundaryProofRecord(proof, change, binding) {
160
+ return compactRecord({
161
+ id: proof.id,
162
+ kind: proof.kind,
163
+ status: 'passed',
164
+ proofLevel: proof.proofLevel ?? 'html-runtime-boundary-source-bound',
165
+ reasonCode: change.reasonCode,
166
+ side: change.side,
167
+ boundary: change.boundary,
168
+ boundaryAttributes: change.boundaryAttributes,
169
+ sourcePath: binding.sourcePath,
170
+ baseSourceHash: hashText(binding.base),
171
+ workerSourceHash: hashText(binding.worker),
172
+ headSourceHash: hashText(binding.head),
173
+ outputSourceHash: hashText(binding.output)
174
+ });
175
+ }
176
+
177
+ function htmlRuntimeBoundaryProvenResult(result, runtimeBoundaryProofs) {
178
+ return compactRecord({
179
+ ...result,
180
+ runtimeBoundaryProofs,
181
+ browserRuntimeEquivalenceClaim: true,
182
+ admission: compactRecord({
183
+ ...(result.admission ?? {}),
184
+ browserRuntimeEquivalenceClaim: true,
185
+ htmlRuntimeBoundaryProofs: runtimeBoundaryProofs,
186
+ reasonCodes: uniqueStrings([...(result.admission?.reasonCodes ?? []), 'html-runtime-boundary-source-bound'])
187
+ })
188
+ });
189
+ }
190
+
98
191
  function htmlEventHandlerBoundaryFingerprint(sourceText) {
99
192
  return htmlEventHandlerBoundaryAttributes(sourceText)
100
193
  .map((attribute) => `${attribute.tagName}:${attribute.name}=${String(attribute.value)}`)
@@ -126,6 +219,22 @@ function parseHtmlAttributes(text) {
126
219
  return attributes;
127
220
  }
128
221
 
222
+ function htmlProofCoversValue(value, values, expected) {
223
+ return value === expected || (Array.isArray(values) && values.includes(expected));
224
+ }
225
+
226
+ function sameStringSet(actual, expected) {
227
+ const actualSet = uniqueStrings(asArray(actual).map((value) => String(value)));
228
+ const expectedSet = uniqueStrings(asArray(expected).map((value) => String(value)));
229
+ return actualSet.length === expectedSet.length && expectedSet.every((value) => actualSet.includes(value));
230
+ }
231
+
232
+ function asArray(value) {
233
+ return Array.isArray(value) ? value : value === undefined ? [] : [value];
234
+ }
235
+
236
+ const HtmlRuntimeBoundaryProofKinds = new Set(['html-runtime-boundary-proof', 'html-source-bound-runtime-boundary-proof']);
237
+
129
238
  function htmlProofGapConflict(id, sourcePath, reasonCode, details = {}, code = 'html-proof-gap-blocked') {
130
239
  return {
131
240
  code,
@@ -138,6 +247,7 @@ function htmlProofGapConflict(id, sourcePath, reasonCode, details = {}, code = '
138
247
  code: reasonCode,
139
248
  status: 'not-claimed',
140
249
  summary: htmlProofGapSummary(reasonCode),
250
+ nextProof: htmlProofGapNextProof(reasonCode),
141
251
  failClosed: true,
142
252
  semanticEquivalenceClaim: false
143
253
  },
@@ -152,6 +262,12 @@ function htmlProofGapSummary(reasonCode) {
152
262
  return 'HTML proof gap requires source-bound evidence before structural merge admission.';
153
263
  }
154
264
 
265
+ function htmlProofGapNextProof(reasonCode) {
266
+ if (reasonCode === 'html-duplicate-explicit-identity') return 'Rename duplicate explicit HTML identity keys or supply parser-backed identity evidence with unique explicitIdentityKeys on every side.';
267
+ if (reasonCode === 'event-handler-runtime-boundary') return 'Attach htmlRuntimeBoundaryProofsByPath[sourcePath] with kind html-source-bound-runtime-boundary-proof, status passed, sourcePath, reasonCode, side, boundary, boundaryAttributes, and exact base/worker/head/output source text or hashes.';
268
+ return 'Attach source-bound HTML parser, identity, and runtime-boundary evidence for the changed file before structural admission.';
269
+ }
270
+
155
271
  function blockedHtmlProofGapAdmission(admission = {}, conflicts = []) {
156
272
  return {
157
273
  ...admission,
@@ -15,7 +15,8 @@ const ProjectMergeMissingSignals = Object.freeze({
15
15
  unsupportedJsTsSurface: 'unsupported-js-ts-surface-proof-not-available',
16
16
  ...HtmlCssProjectMergeMissingSignals,
17
17
  cssModuleUseSiteGraph: 'css-module-use-site-graph-proof-blocked',
18
- semanticEquivalenceProof: 'semantic-equivalence-proof-not-available'
18
+ semanticEquivalenceProof: 'semantic-equivalence-proof-not-available',
19
+ semanticEquivalenceProofFailed: 'semantic-equivalence-proof-failed'
19
20
  });
20
21
 
21
22
  const ProjectMergeMissingEvidenceRoutes = Object.freeze({
@@ -33,7 +34,8 @@ const ProjectMergeMissingEvidenceRoutes = Object.freeze({
33
34
  [ProjectMergeMissingSignals.unsupportedJsTsSurface]: route('prove-unsupported-js-ts-surface', 'semantic-proof', 'supply-unsupported-surface-evidence'),
34
35
  ...htmlCssProjectMergeMissingEvidenceRoutes(route, ProjectMergeMissingSignals),
35
36
  [ProjectMergeMissingSignals.cssModuleUseSiteGraph]: route('prove-css-module-use-site-graph', 'layout-style-graph', 'supply-css-module-transform-and-use-site-proof'),
36
- [ProjectMergeMissingSignals.semanticEquivalenceProof]: route('external-semantic-equivalence-proof', 'semantic-proof', 'attach-external-equivalence-proof')
37
+ [ProjectMergeMissingSignals.semanticEquivalenceProof]: route('external-semantic-equivalence-proof', 'semantic-proof', 'attach-external-equivalence-proof'),
38
+ [ProjectMergeMissingSignals.semanticEquivalenceProofFailed]: route('reject-semantic-equivalence-proof', 'semantic-proof', 'inspect-external-equivalence-proof-binding')
37
39
  });
38
40
 
39
41
  const ProjectMergeAdmissionMatrixRows = Object.freeze([
@@ -48,7 +50,7 @@ const ProjectMergeAdmissionMatrixRows = Object.freeze([
48
50
  matrixRow('unsupported-js-ts-surface-coverage', 'partial', ['unsupported-js-ts-surface-review'], [ProjectMergeMissingSignals.unsupportedJsTsSurface]),
49
51
  ...htmlCssProjectMergeAdmissionMatrixRows(matrixRow, ProjectMergeMissingSignals),
50
52
  matrixRow('css-modules-use-site-graph', 'partial', ['css-module-use-site-graph', 'css-module-transform-proof', 'project-graph-evidence'], [ProjectMergeMissingSignals.cssModuleUseSiteGraph]),
51
- matrixRow('semantic-equivalence-proof', 'bounded-evidence', ['semantic-equivalence-external', 'semantic-equivalence-unknown'], [ProjectMergeMissingSignals.semanticEquivalenceProof]),
53
+ matrixRow('semantic-equivalence-proof', 'bounded-evidence', ['semantic-equivalence-external', 'semantic-equivalence-unknown'], [ProjectMergeMissingSignals.semanticEquivalenceProof, ProjectMergeMissingSignals.semanticEquivalenceProofFailed]),
52
54
  matrixRow('cross-file-symbol-rename', 'partial', ['diagnostics-clean', 'declaration-output-stable', 'project-graph-delta'], [ProjectMergeMissingSignals.outputDiagnosticsGate, ProjectMergeMissingSignals.declarationGate, ProjectMergeMissingSignals.projectGraphEvidence, ProjectMergeMissingSignals.projectGraphDeltaEvidence]),
53
55
  matrixRow('symbol-move-between-files', 'partial', ['diagnostics-clean', 'declaration-output-stable', 'project-graph-delta'], [ProjectMergeMissingSignals.outputDiagnosticsGate, ProjectMergeMissingSignals.declarationGate, ProjectMergeMissingSignals.projectGraphEvidence, ProjectMergeMissingSignals.projectGraphDeltaEvidence]),
54
56
  matrixRow('split-merge-modules-classes', 'partial', ['diagnostics-clean', 'declaration-output-stable', 'project-graph-delta'], [ProjectMergeMissingSignals.outputDiagnosticsGate, ProjectMergeMissingSignals.declarationGate, ProjectMergeMissingSignals.projectGraphEvidence, ProjectMergeMissingSignals.projectGraphDeltaEvidence]),
@@ -133,12 +135,10 @@ function missingEvidenceItems(summary, context = {}) {
133
135
  summary: 'Semantic edit artifacts were produced, but clean replay proof was not available for every semantic edit candidate.'
134
136
  }));
135
137
  if (summary.semanticEquivalenceLevel === 'semantic-equivalence-unknown') items.push(missingEvidenceItem({
136
- code: ProjectMergeMissingSignals.semanticEquivalenceProof,
137
- scope: 'project',
138
- kind: 'semantic-equivalence',
139
- proofLevel: 'semantic-equivalence-unknown',
140
- action: 'review',
141
- summary: 'Executable semantic equivalence is still unknown; keep semanticEquivalenceClaim false and require human or external proof for equivalence claims.'
138
+ code: ProjectMergeMissingSignals.semanticEquivalenceProof, scope: 'project', kind: 'semantic-equivalence', proofLevel: 'semantic-equivalence-unknown', action: 'review',
139
+ requiredEvidence: ['semantic-equivalence-external'], presentEvidence: ['semantic-equivalence-unknown'], recommendedAction: 'review', confidenceDimension: 'semanticEquivalence', blocksSemanticEquivalence: true,
140
+ summary: 'Executable semantic equivalence is still unknown; keep semanticEquivalenceClaim false and require human or external proof for equivalence claims.',
141
+ nextAction: 'Attach a source/output/gate-bound external semantic equivalence proof or keep the route in human review.'
142
142
  }));
143
143
  if (summary.projectGraphCssModuleUseSiteConflicts) items.push(missingEvidenceItem({
144
144
  code: ProjectMergeMissingSignals.cssModuleUseSiteGraph, scope: 'layout-style-graph', kind: 'css-module-use-site-proof', proofLevel: 'css-module-use-site-graph', action: 'review',
@@ -220,8 +220,9 @@ function missingEvidenceItem(input) {
220
220
  routeLane: route?.lane,
221
221
  routeNext: route?.next,
222
222
  relatedSignals: input.relatedSignals,
223
- summary: input.summary,
224
- suggestedInput: input.suggestedInput,
223
+ requiredEvidence: input.requiredEvidence, presentEvidence: input.presentEvidence, recommendedAction: input.recommendedAction,
224
+ confidenceDimension: input.confidenceDimension, blocksSemanticEquivalence: input.blocksSemanticEquivalence,
225
+ summary: input.summary, nextAction: input.nextAction, suggestedInput: input.suggestedInput,
225
226
  autoMergeClaim: false,
226
227
  semanticEquivalenceClaim: false
227
228
  });
@@ -5,6 +5,12 @@ const ExternalSemanticEquivalenceLevel = 'semantic-equivalence-external';
5
5
  const ExternalSemanticEquivalenceSchema = 'frontier.lang.jsTsProjectSemanticEquivalenceProof.v1';
6
6
  const ExternalSemanticEquivalenceKind = 'frontier.lang.jsTsProjectSemanticEquivalenceProof';
7
7
  const ExternalSemanticEquivalenceClaimBoundary = 'exact-js-ts-project-source-output-and-gates';
8
+ const FailedSemanticEquivalenceProofSignal = 'semantic-equivalence-proof-failed';
9
+ const FailedSemanticEquivalenceProofRoute = Object.freeze({
10
+ id: 'reject-semantic-equivalence-proof',
11
+ lane: 'semantic-proof',
12
+ next: 'inspect-external-equivalence-proof-binding'
13
+ });
8
14
 
9
15
  function semanticEquivalenceExternalEvidence(id, input = {}) {
10
16
  const proof = input.externalSemanticEquivalenceProof ?? input.semanticEquivalenceProof;
@@ -34,6 +40,7 @@ function semanticEquivalenceExternalEvidence(id, input = {}) {
34
40
  artifactHash: proof?.artifactHash,
35
41
  expected,
36
42
  reasonCodes,
43
+ nextMissingEvidence: status === 'failed' ? failedSemanticEquivalenceProofMissingEvidence(reasonCodes) : undefined,
37
44
  proofHash: proof?.proofHash,
38
45
  expectedProofHash: proof && typeof proof === 'object' ? jsTsProjectSemanticEquivalenceProofHash(proof) : undefined,
39
46
  proofClaim: status === 'passed',
@@ -43,6 +50,31 @@ function semanticEquivalenceExternalEvidence(id, input = {}) {
43
50
  };
44
51
  }
45
52
 
53
+ function failedSemanticEquivalenceProofMissingEvidence(reasonCodes = []) {
54
+ return {
55
+ code: FailedSemanticEquivalenceProofSignal,
56
+ kind: 'semantic-equivalence',
57
+ scope: 'project',
58
+ status: 'failed',
59
+ action: 'reject-proof',
60
+ proofLevel: ExternalSemanticEquivalenceLevel,
61
+ route: FailedSemanticEquivalenceProofRoute,
62
+ routeId: FailedSemanticEquivalenceProofRoute.id,
63
+ routeLane: FailedSemanticEquivalenceProofRoute.lane,
64
+ routeNext: FailedSemanticEquivalenceProofRoute.next,
65
+ relatedSignals: reasonCodes,
66
+ requiredEvidence: [ExternalSemanticEquivalenceLevel],
67
+ presentEvidence: [ExternalSemanticEquivalenceLevel],
68
+ recommendedAction: 'block',
69
+ confidenceDimension: 'semanticEquivalence',
70
+ blocksSemanticEquivalence: true,
71
+ summary: 'External semantic equivalence proof failed validation; reject the proof and keep semanticEquivalenceClaim false.',
72
+ nextAction: 'Inspect the external proof binding, then attach a valid source/output/gate-bound proof before claiming semantic equivalence.',
73
+ autoMergeClaim: false,
74
+ semanticEquivalenceClaim: false
75
+ };
76
+ }
77
+
46
78
  function jsTsProjectSemanticEquivalenceExpectedBinding(id, input = {}) {
47
79
  const sourceFileBindings = normalizeSourceFileBindings(input.fileResults ?? []);
48
80
  const sourceSetHash = hashSemanticValue({ kind: 'frontier.lang.jsTsProjectSemanticEquivalenceSourceSet.v1', sourceFileBindings: sourceFileBindings.map(sourceBinding) });
@@ -2,6 +2,7 @@ function sourceTextMergeSummary(files = []) {
2
2
  const mergedFiles = files.filter((file) => file.status === 'merged');
3
3
  const blockedFiles = files.filter((file) => file.status === 'blocked');
4
4
  const outputFiles = files.filter((file) => typeof file.outputSourceText === 'string');
5
+ const sourceTextMergeDisposition = sourceTextMergeDispositionFor(files.length, mergedFiles.length, blockedFiles.length);
5
6
  return {
6
7
  mergedFiles: mergedFiles.length,
7
8
  blockedFiles: blockedFiles.length,
@@ -9,7 +10,10 @@ function sourceTextMergeSummary(files = []) {
9
10
  sourceTextMergeCandidateFiles: mergedFiles.length,
10
11
  sourceTextMergeBlockedFiles: blockedFiles.length,
11
12
  sourceTextMergeOutputFiles: outputFiles.length,
12
- sourceTextMergeCandidateStatus: files.length ? (blockedFiles.length ? 'failed' : 'passed') : 'absent'
13
+ sourceTextMergeCandidateStatus: files.length ? (blockedFiles.length ? 'failed' : 'passed') : 'absent',
14
+ sourceTextMergeDisposition,
15
+ sourceTextMergeAdmissionBoundary: sourceTextMergeAdmissionBoundary(sourceTextMergeDisposition),
16
+ sourceTextMergeFileStatusCounts: countFileStatuses(files)
13
17
  };
14
18
  }
15
19
 
@@ -28,6 +32,9 @@ function sourceTextMergeCandidateEvidenceRecord(id, summary) {
28
32
  sourceTextMergeCandidateFiles: summary.sourceTextMergeCandidateFiles,
29
33
  sourceTextMergeBlockedFiles: summary.sourceTextMergeBlockedFiles,
30
34
  sourceTextMergeOutputFiles: summary.sourceTextMergeOutputFiles,
35
+ sourceTextMergeDisposition: summary.sourceTextMergeDisposition,
36
+ sourceTextMergeAdmissionBoundary: summary.sourceTextMergeAdmissionBoundary,
37
+ sourceTextMergeFileStatusCounts: summary.sourceTextMergeFileStatusCounts,
31
38
  outputFiles: summary.outputFiles,
32
39
  autoMergeClaim: false,
33
40
  semanticEquivalenceClaim: false
@@ -56,9 +63,28 @@ function sourceTextMergeMatrixProofStatus(level, summary) {
56
63
  }
57
64
 
58
65
  function sourceTextMergeCandidateEvidenceSummary(summary, passed, failed) {
59
- if (passed) return `Produced concrete source merge candidates for ${summary.sourceTextMergeCandidateFiles} file(s).`;
60
- if (failed) return `Source merge candidate blocked for ${summary.sourceTextMergeBlockedFiles} file(s) before semantic admission.`;
61
- return 'No source files were available for source text merge candidate production.';
66
+ if (passed) return `Produced concrete mechanical source merge candidates for ${summary.sourceTextMergeCandidateFiles} file(s); semantic review remains required for equivalence claims.`;
67
+ if (failed) return `Source merge candidate blocked for ${summary.sourceTextMergeBlockedFiles} overlapping file(s) before semantic admission.`;
68
+ return 'No source files were available; no mechanical source merge candidate was produced.';
69
+ }
70
+
71
+ function sourceTextMergeDispositionFor(files, candidateFiles, blockedFiles) {
72
+ if (!files) return 'absent-source-files';
73
+ if (blockedFiles) return 'blocked-overlap';
74
+ return candidateFiles === files ? 'passed-candidate' : 'incomplete-candidate';
75
+ }
76
+
77
+ function sourceTextMergeAdmissionBoundary(disposition) {
78
+ if (disposition === 'passed-candidate') return 'mechanical-candidate-needs-semantic-review';
79
+ if (disposition === 'blocked-overlap') return 'blocked-overlap-before-semantic-review';
80
+ if (disposition === 'absent-source-files') return 'absent-source-files-no-candidate';
81
+ return 'mechanical-candidate-incomplete';
82
+ }
83
+
84
+ function countFileStatuses(files) {
85
+ const counts = {};
86
+ for (const file of files) if (file?.status) counts[file.status] = (counts[file.status] ?? 0) + 1;
87
+ return counts;
62
88
  }
63
89
 
64
90
  function compactRecord(record) {
@@ -301,11 +301,12 @@ function compactConfidenceDimensions(status, summary, context, routingCalibratio
301
301
  diagnostics: gateConfidenceDimension(context.outputDiagnosticsGate),
302
302
  declarations: gateConfidenceDimension(context.outputDeclarationGate),
303
303
  quality: gateConfidenceDimension(context.outputQualityGate),
304
- proof: summary.proofEvidenceFailed ? 'failed' : summary.proofEvidenceMissing ? 'partial' : 'complete', semanticEquivalence: summary.semanticEquivalenceLevel === 'semantic-equivalence-unknown' ? 'unknown' : 'claimed', routeLane: routingCalibration.nextRouteLane, routeId: routingCalibration.nextRouteId, focusedProofGapRoute: routingCalibration.nextFocusedProofGapRouteId
304
+ proof: summary.proofEvidenceFailed ? 'failed' : summary.proofEvidenceMissing ? 'partial' : 'complete', semanticEquivalence: summary.semanticEquivalenceLevel === 'semantic-equivalence-unknown' ? 'unknown' : 'claimed', semanticEquivalenceProof: semanticEquivalenceProofDimension(summary), routeLane: routingCalibration.nextRouteLane, routeId: routingCalibration.nextRouteId, focusedProofGapRoute: routingCalibration.nextFocusedProofGapRouteId
305
305
  });
306
306
  }
307
307
 
308
308
  function gateConfidenceDimension(gate) { return !gate ? 'missing' : gate.status === 'passed' ? 'passed' : gate.status === 'skipped' ? 'missing' : 'failed'; }
309
+ function semanticEquivalenceProofDimension(summary) { return summary.proofSemanticEquivalenceStatus === 'failed' ? 'failed' : summary.semanticEquivalenceLevel === 'semantic-equivalence-unknown' ? 'missing' : 'passed'; }
309
310
 
310
311
  function uniqueRecords(records) { const seen = new Set(); return records.filter((record) => !record?.id || seen.has(record.id) ? false : (seen.add(record.id), true)); }
311
312
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.164",
3
+ "version": "0.2.165",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",