v1.1.0: pooled runtime, 959 tests, production hardening (0 squash)

This commit is contained in:
John Dvorak
2025-08-15 10:00:00 -07:00
commit 92deb689cd
321 changed files with 79170 additions and 0 deletions
@@ -0,0 +1,357 @@
/**
* Mock helpers for cross-package integration tests.
*
* Provides dependency-injected builders for geometry worlds,
* extraction results, solver results, and complete mock scenes.
*/
import type {
GeometryWorld,
ClauseDescriptor,
ClauseResult,
} from 'imhotep-solver'
import type { EvaluationOutput } from 'imhotep-solver'
import type { GeometrySnapshot, SnapshotMetadata } from 'imhotep-state'
import type { Diagnostic as CoreDiagnostic } from './diagnostics.js'
import type { ImhotepId } from './types.js'
import type { SemanticIr } from './ir.js'
// ---------------------------------------------------------------------------
// Geometry World Builder
// ---------------------------------------------------------------------------
export interface MockSubject {
id: number
selector: string
box: {
top: number
bottom: number
left: number
right: number
}
}
export interface MockFrame {
id: number
kind: string
subjectId: number
}
export interface MockWorldOptions {
sceneId?: string
snapshotId?: string
subjects: MockSubject[]
frames?: MockFrame[]
topology?: {
nearestPositionedAncestorOf?: number[]
scrollContainerOf?: number[]
stackingContextOf?: number[]
containingBlockOf?: number[]
}
}
/**
* Build a solver-compatible geometry world from a declarative description.
*/
export function buildMockGeometryWorld(opts: MockWorldOptions): GeometryWorld {
const subjectCount = opts.subjects.length
const world: GeometryWorld = {
sceneId: opts.sceneId ?? 'scene_test',
snapshotId: opts.snapshotId ?? 'snap_test',
env: {
viewportWidth: 1280,
viewportHeight: 720,
deviceScaleFactor: 1,
colorScheme: 'light',
pointer: 'fine',
hover: false,
reducedMotion: false,
locale: 'en',
writingMode: 'horizontal-tb',
},
strings: { values: [] },
subjects: {
ids: opts.subjects.map((s) => s.id),
domNodeId: new Array(subjectCount).fill(0),
subjectKind: new Array(subjectCount).fill(0),
primaryBoxId: opts.subjects.map((_, i) => i),
firstFragmentId: new Array(subjectCount).fill(0),
fragmentCount: new Array(subjectCount).fill(0),
},
dom: {
nodeId: opts.subjects.map((s) => s.id),
parentNodeId: new Array(subjectCount).fill(0),
childCount: new Array(subjectCount).fill(0),
tagNameStringId: new Array(subjectCount).fill(0),
},
boxes: {
boxId: opts.subjects.map((_, i) => i),
subjectId: opts.subjects.map((s) => s.id),
frameId: new Array(subjectCount).fill(0),
borderLeft: opts.subjects.map((s) => s.box.left),
borderTop: opts.subjects.map((s) => s.box.top),
borderRight: opts.subjects.map((s) => s.box.right),
borderBottom: opts.subjects.map((s) => s.box.bottom),
paddingLeft: opts.subjects.map((s) => s.box.left),
paddingTop: opts.subjects.map((s) => s.box.top),
paddingRight: opts.subjects.map((s) => s.box.right),
paddingBottom: opts.subjects.map((s) => s.box.bottom),
contentLeft: opts.subjects.map((s) => s.box.left),
contentTop: opts.subjects.map((s) => s.box.top),
contentRight: opts.subjects.map((s) => s.box.right),
contentBottom: opts.subjects.map((s) => s.box.bottom),
},
rects: {
rectId: opts.subjects.map((_, i) => i),
left: opts.subjects.map((s) => s.box.left),
top: opts.subjects.map((s) => s.box.top),
right: opts.subjects.map((s) => s.box.right),
bottom: opts.subjects.map((s) => s.box.bottom),
},
topology: {
containingBlockOf: opts.topology?.containingBlockOf ?? [],
nearestPositionedAncestorOf:
opts.topology?.nearestPositionedAncestorOf ?? [],
scrollContainerOf: opts.topology?.scrollContainerOf ?? [],
stackingContextOf: opts.topology?.stackingContextOf ?? [],
formattingContextOf: [],
clippingRootOf: [],
paintOrderBucket: [],
paintOrderIndex: [],
},
scroll: {
containerId: [],
scrollLeft: [],
scrollTop: [],
scrollWidth: [],
scrollHeight: [],
clientWidth: [],
clientHeight: [],
},
visualBoxes: {
boxId: opts.subjects.map((_, i) => i),
subjectId: opts.subjects.map((s) => s.id),
frameId: new Array(subjectCount).fill(0),
borderLeft: opts.subjects.map((s) => s.box.left),
borderTop: opts.subjects.map((s) => s.box.top),
borderRight: opts.subjects.map((s) => s.box.right),
borderBottom: opts.subjects.map((s) => s.box.bottom),
paddingLeft: opts.subjects.map((s) => s.box.left),
paddingTop: opts.subjects.map((s) => s.box.top),
paddingRight: opts.subjects.map((s) => s.box.right),
paddingBottom: opts.subjects.map((s) => s.box.bottom),
contentLeft: opts.subjects.map((s) => s.box.left),
contentTop: opts.subjects.map((s) => s.box.top),
contentRight: opts.subjects.map((s) => s.box.right),
contentBottom: opts.subjects.map((s) => s.box.bottom),
},
transforms: {
transformId: [],
subjectId: [],
matrixStart: [],
matrixLength: [],
originX: [],
originY: [],
},
matrices: {
values: [],
},
clipping: {
clipNodeId: [],
subjectId: [],
clipKind: [],
clipLeft: [],
clipTop: [],
clipRight: [],
clipBottom: [],
parentClipNodeId: [],
},
visibility: {
subjectId: [],
isRendered: [],
isVisible: [],
visibleArea: [],
clippedArea: [],
},
}
return world
}
// ---------------------------------------------------------------------------
// Clause Descriptor Builder
// ---------------------------------------------------------------------------
export function buildClauseDescriptor(opts: {
clauseId: string
clauseKind: string
subjectRef: number
referenceRef?: number
frameRef?: number
bounds?: { minGap?: number; maxGap?: number; tolerance?: number; min?: number; max?: number }
options?: Record<string, unknown>
}): ClauseDescriptor {
return {
clauseId: opts.clauseId,
clauseKind: opts.clauseKind,
version: 1,
subjectRef: opts.subjectRef,
referenceRef: opts.referenceRef,
frameRef: opts.frameRef,
bounds: opts.bounds ?? {},
options: opts.options ?? {},
}
}
// ---------------------------------------------------------------------------
// Solver Result Builder
// ---------------------------------------------------------------------------
export function buildMockSolverResult(opts: {
clauseResults?: ClauseResult[]
diagnostics?: Array<{
code: string
severity: 'error' | 'warning' | 'info'
category: string
message: string
clauseId?: string
}>
}): EvaluationOutput {
return {
clauseResults: opts.clauseResults ?? [],
groupResults: [],
proofs: [],
diagnostics: opts.diagnostics ?? [],
trace: [],
}
}
// ---------------------------------------------------------------------------
// Extraction Result Builder
// ---------------------------------------------------------------------------
export function buildMockExtractionResult(opts: {
requestId?: string
worlds: GeometryWorld[]
diagnostics?: CoreDiagnostic[]
}): {
requestId: string
status: 'ok' | 'partial' | 'error'
worlds: GeometryWorld[]
diagnostics: CoreDiagnostic[]
} {
return {
requestId: opts.requestId ?? 'req_1',
status: 'ok',
worlds: opts.worlds,
diagnostics: opts.diagnostics ?? [],
}
}
// ---------------------------------------------------------------------------
// Scene Builder
// ---------------------------------------------------------------------------
export interface MockScene {
world: GeometryWorld
clauses: ClauseDescriptor[]
}
export function createMockScene(opts: {
subjects: MockSubject[]
relations: Array<{
kind: string
subjectId: number
referenceId: number
bounds?: { minGap?: number; maxGap?: number }
}>
}): MockScene {
const world = buildMockGeometryWorld({ subjects: opts.subjects })
const clauses = opts.relations.map((r, i) =>
buildClauseDescriptor({
clauseId: `clause_${i + 1}`,
clauseKind: r.kind,
subjectRef: r.subjectId,
referenceRef: r.referenceId,
bounds: r.bounds,
}),
)
return { world, clauses }
}
// ---------------------------------------------------------------------------
// Semantic IR to Solver Clause Mapping
// ---------------------------------------------------------------------------
/**
* Map a compiled Semantic IR to solver ClauseDescriptors.
*
* This bridges the DSL compiler output to the solver evaluation input.
* The `subjectIdMap` translates semantic IR subject ids to world subject ids.
*/
export function mapSemanticIrToClauses(
semanticIr: SemanticIr,
subjectIdMap: Map<ImhotepId, number>,
): ClauseDescriptor[] {
const clauses: ClauseDescriptor[] = []
for (const [, clause] of semanticIr.clauses) {
const subjectRef = subjectIdMap.get(clause.subjectRef)
const referenceRef = clause.referenceRef
? subjectIdMap.get(clause.referenceRef)
: undefined
if (subjectRef === undefined) continue
const tolerance = semanticIr.tolerances.get(clause.toleranceRef)
const bounds: Record<string, number> = {}
if (clause.bounds.minGap) {
bounds.minGap = clause.bounds.minGap.value
}
if (clause.bounds.maxGap) {
bounds.maxGap = clause.bounds.maxGap.value
}
if (tolerance) {
bounds.tolerance = tolerance.value
}
clauses.push({
clauseId: clause.id,
clauseKind: `relation.${clause.relation}`,
version: 1,
subjectRef,
referenceRef,
bounds,
})
}
return clauses
}
// ---------------------------------------------------------------------------
// Snapshot Builder
// ---------------------------------------------------------------------------
export function buildMockSnapshot(opts: {
id?: string
stateKind?: string
stateSource?: string
selector?: string
world: GeometryWorld
}): GeometrySnapshot {
const metadata: SnapshotMetadata = {
snapshotId: opts.id ?? 'snap_1',
stateKind: (opts.stateKind as any) ?? 'default',
stateSource: (opts.stateSource as any) ?? 'synthetic',
selector: opts.selector,
timestamp: Date.now(),
}
return {
id: opts.id ?? 'snap_1',
metadata,
world: opts.world,
}
}