libpetri 5.1.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/verification/analysis/scc-analyzer.ts","../../src/verification/analysis/time-petri-net-analyzer.ts"],"sourcesContent":["/**\n * Strongly Connected Component analysis using Tarjan's algorithm.\n * Generic over node type T. Uses a key function for Map-based lookups.\n */\n\n/** Computes all SCCs in a graph. O(V + E) via Tarjan's algorithm. */\nexport function computeSCCs<T>(\n nodes: Iterable<T>,\n successors: (node: T) => Iterable<T>,\n): Set<T>[] {\n const nodeArray = [...nodes];\n const indexMap = new Map<T, number>();\n const lowlink = new Map<T, number>();\n const onStack = new Set<T>();\n const stack: T[] = [];\n const sccs: Set<T>[] = [];\n let index = 0;\n\n function strongConnect(v: T): void {\n indexMap.set(v, index);\n lowlink.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n for (const w of successors(v)) {\n if (!indexMap.has(w)) {\n strongConnect(w);\n lowlink.set(v, Math.min(lowlink.get(v)!, lowlink.get(w)!));\n } else if (onStack.has(w)) {\n lowlink.set(v, Math.min(lowlink.get(v)!, indexMap.get(w)!));\n }\n }\n\n if (lowlink.get(v) === indexMap.get(v)) {\n const scc = new Set<T>();\n let w: T;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.add(w);\n } while (w !== v);\n sccs.push(scc);\n }\n }\n\n for (const node of nodeArray) {\n if (!indexMap.has(node)) {\n strongConnect(node);\n }\n }\n\n return sccs;\n}\n\n/** Finds terminal (bottom) SCCs — SCCs with no outgoing edges to other SCCs. */\nexport function findTerminalSCCs<T>(\n nodes: Iterable<T>,\n successors: (node: T) => Iterable<T>,\n): Set<T>[] {\n const allSCCs = computeSCCs(nodes, successors);\n\n const terminal: Set<T>[] = [];\n for (const scc of allSCCs) {\n let isTerminal = true;\n for (const node of scc) {\n for (const succ of successors(node)) {\n if (!scc.has(succ)) {\n isTerminal = false;\n break;\n }\n }\n if (!isTerminal) break;\n }\n if (isTerminal) {\n terminal.push(scc);\n }\n }\n\n return terminal;\n}\n","import type { Place } from '../../core/place.js';\nimport type { EnvironmentPlace } from '../../core/place.js';\nimport type { Transition } from '../../core/transition.js';\nimport type { PetriNet } from '../../core/petri-net.js';\nimport { enumerateBranches } from '../../core/out.js';\nimport { MarkingState } from '../marking-state.js';\nimport { StateClassGraph } from './state-class-graph.js';\nimport type { StateClass } from './state-class.js';\nimport { computeSCCs, findTerminalSCCs } from './scc-analyzer.js';\nimport type { EnvironmentAnalysisMode } from './environment-analysis-mode.js';\nimport { ignore } from './environment-analysis-mode.js';\n\n/** Result of liveness analysis. */\nexport interface LivenessResult {\n readonly stateClassGraph: StateClassGraph;\n readonly allSCCs: Set<StateClass>[];\n readonly terminalSCCs: Set<StateClass>[];\n readonly goalClasses: Set<StateClass>;\n readonly canReachGoal: Set<StateClass>;\n readonly isGoalLive: boolean;\n readonly isL4Live: boolean;\n readonly isComplete: boolean;\n readonly report: string;\n}\n\n/** Information about XOR branch coverage for a single transition. */\nexport interface XorBranchInfo {\n readonly totalBranches: number;\n readonly takenBranches: Set<number>;\n readonly untakenBranches: Set<number>;\n readonly branchOutputs: ReadonlyArray<ReadonlySet<Place<any>>>;\n}\n\n/** Result of XOR branch analysis. */\nexport interface XorBranchAnalysis {\n readonly transitionBranches: Map<Transition, XorBranchInfo>;\n unreachableBranches(): Map<Transition, Set<number>>;\n isXorComplete(): boolean;\n report(): string;\n}\n\n/**\n * Formal analyzer for Time Petri Nets using the State Class Graph method.\n * Implements Berthomieu-Diaz (1991) analysis.\n */\nexport class TimePetriNetAnalyzer {\n private readonly net: PetriNet;\n private readonly initialMarking: MarkingState;\n private readonly goalPlaces: Set<Place<any>>;\n private readonly maxClasses: number;\n private readonly environmentPlaces: Set<EnvironmentPlace<any>>;\n private readonly environmentMode: EnvironmentAnalysisMode;\n\n /** @internal Called by builder — use `TimePetriNetAnalyzer.forNet()` instead. */\n static create(\n net: PetriNet,\n initialMarking: MarkingState,\n goalPlaces: Set<Place<any>>,\n maxClasses: number,\n environmentPlaces: Set<EnvironmentPlace<any>>,\n environmentMode: EnvironmentAnalysisMode,\n ): TimePetriNetAnalyzer {\n return new TimePetriNetAnalyzer(net, initialMarking, goalPlaces, maxClasses, environmentPlaces, environmentMode);\n }\n\n private constructor(\n net: PetriNet,\n initialMarking: MarkingState,\n goalPlaces: Set<Place<any>>,\n maxClasses: number,\n environmentPlaces: Set<EnvironmentPlace<any>>,\n environmentMode: EnvironmentAnalysisMode,\n ) {\n this.net = net;\n this.initialMarking = initialMarking;\n this.goalPlaces = goalPlaces;\n this.maxClasses = maxClasses;\n this.environmentPlaces = environmentPlaces;\n this.environmentMode = environmentMode;\n }\n\n static forNet(net: PetriNet): TimePetriNetAnalyzerBuilder {\n return new TimePetriNetAnalyzerBuilder(net);\n }\n\n /** Performs formal liveness analysis. */\n analyze(): LivenessResult {\n const report: string[] = [];\n report.push('=== TIME PETRI NET FORMAL ANALYSIS ===\\n');\n report.push(`Method: State Class Graph (Berthomieu-Diaz 1991)`);\n report.push(`Net: ${this.net.name}`);\n report.push(`Places: ${this.net.places.size}`);\n report.push(`Transitions: ${this.net.transitions.size}`);\n report.push(`Goal places: [${[...this.goalPlaces].map(p => p.name).join(', ')}]\\n`);\n\n // Phase 1: Build State Class Graph\n report.push('Phase 1: Building State Class Graph...');\n if (this.environmentPlaces.size > 0) {\n report.push(` Environment places: ${this.environmentPlaces.size}`);\n report.push(` Environment mode: ${this.environmentMode.type}`);\n }\n const scg = StateClassGraph.build(this.net, this.initialMarking, this.maxClasses, this.environmentPlaces, this.environmentMode);\n report.push(` State classes: ${scg.size()}`);\n report.push(` Edges: ${scg.edgeCount()}`);\n report.push(` Complete: ${scg.isComplete() ? 'YES' : 'NO (truncated)'}`);\n\n if (!scg.isComplete()) {\n report.push(` WARNING: State class graph truncated at ${this.maxClasses} classes. Analysis may be incomplete.`);\n }\n report.push('');\n\n // Phase 2: Identify goal state classes\n report.push('Phase 2: Identifying goal state classes...');\n const goalClasses = new Set<StateClass>();\n for (const sc of scg.stateClasses()) {\n if (sc.marking.hasTokensInAny(this.goalPlaces)) {\n goalClasses.add(sc);\n }\n }\n report.push(` Goal state classes: ${goalClasses.size}\\n`);\n\n // Phase 3: Compute SCCs\n report.push('Phase 3: Computing Strongly Connected Components...');\n const successorFn = (sc: StateClass) => scg.successors(sc);\n const allSCCs = computeSCCs(scg.stateClasses(), successorFn);\n const terminalSCCs = findTerminalSCCs(scg.stateClasses(), successorFn);\n\n report.push(` Total SCCs: ${allSCCs.length}`);\n report.push(` Terminal SCCs: ${terminalSCCs.length}\\n`);\n\n // Phase 4: Check goal liveness\n report.push('Phase 4: Verifying Goal Liveness...');\n report.push(' Property: From every reachable state, a goal state is reachable');\n\n const terminalSCCsWithGoal: Set<StateClass>[] = [];\n const terminalSCCsWithoutGoal: Set<StateClass>[] = [];\n\n for (const scc of terminalSCCs) {\n let hasGoal = false;\n for (const sc of scc) {\n if (goalClasses.has(sc)) { hasGoal = true; break; }\n }\n (hasGoal ? terminalSCCsWithGoal : terminalSCCsWithoutGoal).push(scc);\n }\n\n report.push(` Terminal SCCs with goal: ${terminalSCCsWithGoal.length}`);\n report.push(` Terminal SCCs without goal: ${terminalSCCsWithoutGoal.length}`);\n\n const canReachGoal = computeBackwardReachability(scg, goalClasses);\n const statesNotReachingGoal = scg.size() - canReachGoal.size;\n\n report.push(` States that can reach goal: ${canReachGoal.size}/${scg.size()}\\n`);\n\n const isGoalLive = terminalSCCsWithoutGoal.length === 0 && statesNotReachingGoal === 0;\n\n // Phase 5: Check classical liveness (L4)\n report.push('Phase 5: Verifying Classical Liveness (L4)...');\n report.push(' Property: Every transition can fire from every reachable marking');\n\n const allTransitions = new Set(this.net.transitions);\n const terminalSCCsMissingTransitions: Set<StateClass>[] = [];\n\n for (const scc of terminalSCCs) {\n const transitionsInSCC = new Set<Transition>();\n for (const sc of scc) {\n for (const t of scg.enabledTransitions(sc)) {\n const edges = scg.branchEdges(sc, t);\n for (const edge of edges) {\n if (scc.has(edge.target)) {\n transitionsInSCC.add(t);\n }\n }\n }\n }\n let missingAny = false;\n for (const t of allTransitions) {\n if (!transitionsInSCC.has(t)) { missingAny = true; break; }\n }\n if (missingAny) {\n terminalSCCsMissingTransitions.push(scc);\n const missing = [...allTransitions].filter(t => !transitionsInSCC.has(t));\n report.push(` Terminal SCC missing transitions: [${missing.map(t => t.name).join(', ')}]`);\n }\n }\n\n const isL4Live = terminalSCCsMissingTransitions.length === 0 && scg.isComplete();\n\n // Summary\n report.push('\\n=== ANALYSIS RESULT ===\\n');\n\n if (isGoalLive && scg.isComplete()) {\n report.push('GOAL LIVENESS VERIFIED');\n report.push(' From every reachable state class, a goal marking is reachable.');\n } else if (isGoalLive && !scg.isComplete()) {\n report.push('GOAL LIVENESS LIKELY (incomplete proof)');\n } else {\n report.push('GOAL LIVENESS VIOLATION');\n if (terminalSCCsWithoutGoal.length > 0) {\n report.push(` ${terminalSCCsWithoutGoal.length} terminal SCC(s) have no goal state.`);\n }\n if (statesNotReachingGoal > 0) {\n report.push(` ${statesNotReachingGoal} state class(es) cannot reach goal.`);\n }\n }\n\n report.push('');\n\n if (isL4Live) {\n report.push('CLASSICAL LIVENESS (L4) VERIFIED');\n } else {\n report.push('CLASSICAL LIVENESS (L4) NOT VERIFIED');\n if (terminalSCCsMissingTransitions.length > 0) {\n report.push(\" Some terminal SCCs don't contain all transitions.\");\n }\n if (!scg.isComplete()) {\n report.push(' (State class graph incomplete - cannot prove L4)');\n }\n }\n\n return {\n stateClassGraph: scg,\n allSCCs,\n terminalSCCs,\n goalClasses,\n canReachGoal,\n isGoalLive,\n isL4Live,\n isComplete: scg.isComplete(),\n report: report.join('\\n'),\n };\n }\n\n /** Analyzes XOR branch coverage for a built state class graph. */\n static analyzeXorBranches(scg: StateClassGraph): XorBranchAnalysis {\n const result = new Map<Transition, XorBranchInfo>();\n\n for (const transition of scg.net.transitions) {\n if (transition.outputSpec === null) continue;\n\n const allBranches = enumerateBranches(transition.outputSpec);\n if (allBranches.length <= 1) continue;\n\n const takenBranches = new Set<number>();\n for (const sc of scg.stateClasses()) {\n const edges = scg.branchEdges(sc, transition);\n for (const edge of edges) {\n takenBranches.add(edge.branchIndex);\n }\n }\n\n const untakenBranches = new Set<number>();\n for (let i = 0; i < allBranches.length; i++) {\n if (!takenBranches.has(i)) untakenBranches.add(i);\n }\n\n result.set(transition, {\n totalBranches: allBranches.length,\n takenBranches,\n untakenBranches,\n branchOutputs: allBranches,\n });\n }\n\n return createXorBranchAnalysis(result);\n }\n}\n\nfunction createXorBranchAnalysis(transitionBranches: Map<Transition, XorBranchInfo>): XorBranchAnalysis {\n return {\n transitionBranches,\n unreachableBranches(): Map<Transition, Set<number>> {\n const result = new Map<Transition, Set<number>>();\n for (const [t, info] of transitionBranches) {\n if (info.untakenBranches.size > 0) {\n result.set(t, info.untakenBranches);\n }\n }\n return result;\n },\n isXorComplete(): boolean {\n for (const info of transitionBranches.values()) {\n if (info.untakenBranches.size > 0) return false;\n }\n return true;\n },\n report(): string {\n if (transitionBranches.size === 0) return 'No XOR transitions in net.';\n\n const lines: string[] = [];\n lines.push('XOR Branch Coverage Analysis');\n lines.push('============================\\n');\n\n for (const [t, info] of transitionBranches) {\n lines.push(`Transition: ${t.name}`);\n lines.push(` Branches: ${info.totalBranches}`);\n lines.push(` Taken: [${[...info.takenBranches].join(', ')}]`);\n\n if (info.untakenBranches.size > 0) {\n lines.push(` UNREACHABLE: [${[...info.untakenBranches].join(', ')}]`);\n for (const idx of info.untakenBranches) {\n const places = [...info.branchOutputs[idx]!].map(p => p.name).join(', ');\n lines.push(` Branch ${idx} outputs: [${places}]`);\n }\n } else {\n lines.push(' All branches reachable');\n }\n lines.push('');\n }\n\n if (this.isXorComplete()) {\n lines.push('RESULT: All XOR branches are reachable.');\n } else {\n lines.push('RESULT: Some XOR branches are unreachable!');\n }\n\n return lines.join('\\n');\n },\n };\n}\n\nfunction computeBackwardReachability(scg: StateClassGraph, goals: Set<StateClass>): Set<StateClass> {\n const reachable = new Set(goals);\n const queue = [...goals];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const pred of scg.predecessors(current)) {\n if (!reachable.has(pred)) {\n reachable.add(pred);\n queue.push(pred);\n }\n }\n }\n\n return reachable;\n}\n\n/** Builder for TimePetriNetAnalyzer. */\nexport class TimePetriNetAnalyzerBuilder {\n private readonly net: PetriNet;\n private _initialMarking: MarkingState = MarkingState.empty();\n private readonly _goalPlaces = new Set<Place<any>>();\n private _maxClasses = 100_000;\n private readonly _environmentPlaces = new Set<EnvironmentPlace<any>>();\n private _environmentMode: EnvironmentAnalysisMode = ignore();\n\n constructor(net: PetriNet) {\n this.net = net;\n }\n\n initialMarking(marking: MarkingState): this {\n this._initialMarking = marking;\n return this;\n }\n\n goalPlaces(...places: Place<any>[]): this {\n for (const p of places) this._goalPlaces.add(p);\n return this;\n }\n\n maxClasses(max: number): this {\n this._maxClasses = max;\n return this;\n }\n\n environmentPlaces(...places: EnvironmentPlace<any>[]): this {\n for (const ep of places) this._environmentPlaces.add(ep);\n return this;\n }\n\n environmentMode(mode: EnvironmentAnalysisMode): this {\n this._environmentMode = mode;\n return this;\n }\n\n build(): TimePetriNetAnalyzer {\n if (this._goalPlaces.size === 0) {\n throw new Error('At least one goal place must be specified');\n }\n return TimePetriNetAnalyzer.create(\n this.net,\n this._initialMarking,\n this._goalPlaces,\n this._maxClasses,\n this._environmentPlaces,\n this._environmentMode,\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/verification/analysis/scc-analyzer.ts","../../src/verification/analysis/time-petri-net-analyzer.ts","../../src/verification/open-net/contract.ts","../../src/verification/open-net/closure.ts","../../src/verification/open-net/predicate.ts","../../src/verification/open-net/result.ts","../../src/verification/open-net/graph-route.ts","../../src/verification/open-net/report.ts","../../src/verification/open-net/smt-route.ts","../../src/verification/open-net/verify-open-net.ts"],"sourcesContent":["/**\n * Strongly Connected Component analysis using Tarjan's algorithm.\n * Generic over node type T. Uses a key function for Map-based lookups.\n */\n\n/** Computes all SCCs in a graph. O(V + E) via Tarjan's algorithm. */\nexport function computeSCCs<T>(\n nodes: Iterable<T>,\n successors: (node: T) => Iterable<T>,\n): Set<T>[] {\n const nodeArray = [...nodes];\n const indexMap = new Map<T, number>();\n const lowlink = new Map<T, number>();\n const onStack = new Set<T>();\n const stack: T[] = [];\n const sccs: Set<T>[] = [];\n let index = 0;\n\n function strongConnect(v: T): void {\n indexMap.set(v, index);\n lowlink.set(v, index);\n index++;\n stack.push(v);\n onStack.add(v);\n\n for (const w of successors(v)) {\n if (!indexMap.has(w)) {\n strongConnect(w);\n lowlink.set(v, Math.min(lowlink.get(v)!, lowlink.get(w)!));\n } else if (onStack.has(w)) {\n lowlink.set(v, Math.min(lowlink.get(v)!, indexMap.get(w)!));\n }\n }\n\n if (lowlink.get(v) === indexMap.get(v)) {\n const scc = new Set<T>();\n let w: T;\n do {\n w = stack.pop()!;\n onStack.delete(w);\n scc.add(w);\n } while (w !== v);\n sccs.push(scc);\n }\n }\n\n for (const node of nodeArray) {\n if (!indexMap.has(node)) {\n strongConnect(node);\n }\n }\n\n return sccs;\n}\n\n/** Finds terminal (bottom) SCCs — SCCs with no outgoing edges to other SCCs. */\nexport function findTerminalSCCs<T>(\n nodes: Iterable<T>,\n successors: (node: T) => Iterable<T>,\n): Set<T>[] {\n const allSCCs = computeSCCs(nodes, successors);\n\n const terminal: Set<T>[] = [];\n for (const scc of allSCCs) {\n let isTerminal = true;\n for (const node of scc) {\n for (const succ of successors(node)) {\n if (!scc.has(succ)) {\n isTerminal = false;\n break;\n }\n }\n if (!isTerminal) break;\n }\n if (isTerminal) {\n terminal.push(scc);\n }\n }\n\n return terminal;\n}\n","import type { Place } from '../../core/place.js';\nimport type { EnvironmentPlace } from '../../core/place.js';\nimport type { Transition } from '../../core/transition.js';\nimport type { PetriNet } from '../../core/petri-net.js';\nimport { enumerateBranches } from '../../core/out.js';\nimport { MarkingState } from '../marking-state.js';\nimport { StateClassGraph } from './state-class-graph.js';\nimport type { StateClass } from './state-class.js';\nimport { computeSCCs, findTerminalSCCs } from './scc-analyzer.js';\nimport type { EnvironmentAnalysisMode } from './environment-analysis-mode.js';\nimport { ignore } from './environment-analysis-mode.js';\n\n/** Result of liveness analysis. */\nexport interface LivenessResult {\n readonly stateClassGraph: StateClassGraph;\n readonly allSCCs: Set<StateClass>[];\n readonly terminalSCCs: Set<StateClass>[];\n readonly goalClasses: Set<StateClass>;\n readonly canReachGoal: Set<StateClass>;\n readonly isGoalLive: boolean;\n readonly isL4Live: boolean;\n readonly isComplete: boolean;\n readonly report: string;\n}\n\n/** Information about XOR branch coverage for a single transition. */\nexport interface XorBranchInfo {\n readonly totalBranches: number;\n readonly takenBranches: Set<number>;\n readonly untakenBranches: Set<number>;\n readonly branchOutputs: ReadonlyArray<ReadonlySet<Place<any>>>;\n}\n\n/** Result of XOR branch analysis. */\nexport interface XorBranchAnalysis {\n readonly transitionBranches: Map<Transition, XorBranchInfo>;\n unreachableBranches(): Map<Transition, Set<number>>;\n isXorComplete(): boolean;\n report(): string;\n}\n\n/**\n * Formal analyzer for Time Petri Nets using the State Class Graph method.\n * Implements Berthomieu-Diaz (1991) analysis.\n */\nexport class TimePetriNetAnalyzer {\n private readonly net: PetriNet;\n private readonly initialMarking: MarkingState;\n private readonly goalPlaces: Set<Place<any>>;\n private readonly maxClasses: number;\n private readonly environmentPlaces: Set<EnvironmentPlace<any>>;\n private readonly environmentMode: EnvironmentAnalysisMode;\n\n /** @internal Called by builder — use `TimePetriNetAnalyzer.forNet()` instead. */\n static create(\n net: PetriNet,\n initialMarking: MarkingState,\n goalPlaces: Set<Place<any>>,\n maxClasses: number,\n environmentPlaces: Set<EnvironmentPlace<any>>,\n environmentMode: EnvironmentAnalysisMode,\n ): TimePetriNetAnalyzer {\n return new TimePetriNetAnalyzer(net, initialMarking, goalPlaces, maxClasses, environmentPlaces, environmentMode);\n }\n\n private constructor(\n net: PetriNet,\n initialMarking: MarkingState,\n goalPlaces: Set<Place<any>>,\n maxClasses: number,\n environmentPlaces: Set<EnvironmentPlace<any>>,\n environmentMode: EnvironmentAnalysisMode,\n ) {\n this.net = net;\n this.initialMarking = initialMarking;\n this.goalPlaces = goalPlaces;\n this.maxClasses = maxClasses;\n this.environmentPlaces = environmentPlaces;\n this.environmentMode = environmentMode;\n }\n\n static forNet(net: PetriNet): TimePetriNetAnalyzerBuilder {\n return new TimePetriNetAnalyzerBuilder(net);\n }\n\n /** Performs formal liveness analysis. */\n analyze(): LivenessResult {\n const report: string[] = [];\n report.push('=== TIME PETRI NET FORMAL ANALYSIS ===\\n');\n report.push(`Method: State Class Graph (Berthomieu-Diaz 1991)`);\n report.push(`Net: ${this.net.name}`);\n report.push(`Places: ${this.net.places.size}`);\n report.push(`Transitions: ${this.net.transitions.size}`);\n report.push(`Goal places: [${[...this.goalPlaces].map(p => p.name).join(', ')}]\\n`);\n\n // Phase 1: Build State Class Graph\n report.push('Phase 1: Building State Class Graph...');\n if (this.environmentPlaces.size > 0) {\n report.push(` Environment places: ${this.environmentPlaces.size}`);\n report.push(` Environment mode: ${this.environmentMode.type}`);\n }\n const scg = StateClassGraph.build(this.net, this.initialMarking, this.maxClasses, this.environmentPlaces, this.environmentMode);\n report.push(` State classes: ${scg.size()}`);\n report.push(` Edges: ${scg.edgeCount()}`);\n report.push(` Complete: ${scg.isComplete() ? 'YES' : 'NO (truncated)'}`);\n\n if (!scg.isComplete()) {\n report.push(` WARNING: State class graph truncated at ${this.maxClasses} classes. Analysis may be incomplete.`);\n }\n report.push('');\n\n // Phase 2: Identify goal state classes\n report.push('Phase 2: Identifying goal state classes...');\n const goalClasses = new Set<StateClass>();\n for (const sc of scg.stateClasses()) {\n if (sc.marking.hasTokensInAny(this.goalPlaces)) {\n goalClasses.add(sc);\n }\n }\n report.push(` Goal state classes: ${goalClasses.size}\\n`);\n\n // Phase 3: Compute SCCs\n report.push('Phase 3: Computing Strongly Connected Components...');\n const successorFn = (sc: StateClass) => scg.successors(sc);\n const allSCCs = computeSCCs(scg.stateClasses(), successorFn);\n const terminalSCCs = findTerminalSCCs(scg.stateClasses(), successorFn);\n\n report.push(` Total SCCs: ${allSCCs.length}`);\n report.push(` Terminal SCCs: ${terminalSCCs.length}\\n`);\n\n // Phase 4: Check goal liveness\n report.push('Phase 4: Verifying Goal Liveness...');\n report.push(' Property: From every reachable state, a goal state is reachable');\n\n const terminalSCCsWithGoal: Set<StateClass>[] = [];\n const terminalSCCsWithoutGoal: Set<StateClass>[] = [];\n\n for (const scc of terminalSCCs) {\n let hasGoal = false;\n for (const sc of scc) {\n if (goalClasses.has(sc)) { hasGoal = true; break; }\n }\n (hasGoal ? terminalSCCsWithGoal : terminalSCCsWithoutGoal).push(scc);\n }\n\n report.push(` Terminal SCCs with goal: ${terminalSCCsWithGoal.length}`);\n report.push(` Terminal SCCs without goal: ${terminalSCCsWithoutGoal.length}`);\n\n const canReachGoal = computeBackwardReachability(scg, goalClasses);\n const statesNotReachingGoal = scg.size() - canReachGoal.size;\n\n report.push(` States that can reach goal: ${canReachGoal.size}/${scg.size()}\\n`);\n\n const isGoalLive = terminalSCCsWithoutGoal.length === 0 && statesNotReachingGoal === 0;\n\n // Phase 5: Check classical liveness (L4)\n report.push('Phase 5: Verifying Classical Liveness (L4)...');\n report.push(' Property: Every transition can fire from every reachable marking');\n\n const allTransitions = new Set(this.net.transitions);\n const terminalSCCsMissingTransitions: Set<StateClass>[] = [];\n\n for (const scc of terminalSCCs) {\n const transitionsInSCC = new Set<Transition>();\n for (const sc of scc) {\n for (const t of scg.enabledTransitions(sc)) {\n const edges = scg.branchEdges(sc, t);\n for (const edge of edges) {\n if (scc.has(edge.target)) {\n transitionsInSCC.add(t);\n }\n }\n }\n }\n let missingAny = false;\n for (const t of allTransitions) {\n if (!transitionsInSCC.has(t)) { missingAny = true; break; }\n }\n if (missingAny) {\n terminalSCCsMissingTransitions.push(scc);\n const missing = [...allTransitions].filter(t => !transitionsInSCC.has(t));\n report.push(` Terminal SCC missing transitions: [${missing.map(t => t.name).join(', ')}]`);\n }\n }\n\n const isL4Live = terminalSCCsMissingTransitions.length === 0 && scg.isComplete();\n\n // Summary\n report.push('\\n=== ANALYSIS RESULT ===\\n');\n\n if (isGoalLive && scg.isComplete()) {\n report.push('GOAL LIVENESS VERIFIED');\n report.push(' From every reachable state class, a goal marking is reachable.');\n } else if (isGoalLive && !scg.isComplete()) {\n report.push('GOAL LIVENESS LIKELY (incomplete proof)');\n } else {\n report.push('GOAL LIVENESS VIOLATION');\n if (terminalSCCsWithoutGoal.length > 0) {\n report.push(` ${terminalSCCsWithoutGoal.length} terminal SCC(s) have no goal state.`);\n }\n if (statesNotReachingGoal > 0) {\n report.push(` ${statesNotReachingGoal} state class(es) cannot reach goal.`);\n }\n }\n\n report.push('');\n\n if (isL4Live) {\n report.push('CLASSICAL LIVENESS (L4) VERIFIED');\n } else {\n report.push('CLASSICAL LIVENESS (L4) NOT VERIFIED');\n if (terminalSCCsMissingTransitions.length > 0) {\n report.push(\" Some terminal SCCs don't contain all transitions.\");\n }\n if (!scg.isComplete()) {\n report.push(' (State class graph incomplete - cannot prove L4)');\n }\n }\n\n return {\n stateClassGraph: scg,\n allSCCs,\n terminalSCCs,\n goalClasses,\n canReachGoal,\n isGoalLive,\n isL4Live,\n isComplete: scg.isComplete(),\n report: report.join('\\n'),\n };\n }\n\n /** Analyzes XOR branch coverage for a built state class graph. */\n static analyzeXorBranches(scg: StateClassGraph): XorBranchAnalysis {\n const result = new Map<Transition, XorBranchInfo>();\n\n for (const transition of scg.net.transitions) {\n if (transition.outputSpec === null) continue;\n\n const allBranches = enumerateBranches(transition.outputSpec);\n if (allBranches.length <= 1) continue;\n\n const takenBranches = new Set<number>();\n for (const sc of scg.stateClasses()) {\n const edges = scg.branchEdges(sc, transition);\n for (const edge of edges) {\n takenBranches.add(edge.branchIndex);\n }\n }\n\n const untakenBranches = new Set<number>();\n for (let i = 0; i < allBranches.length; i++) {\n if (!takenBranches.has(i)) untakenBranches.add(i);\n }\n\n result.set(transition, {\n totalBranches: allBranches.length,\n takenBranches,\n untakenBranches,\n branchOutputs: allBranches,\n });\n }\n\n return createXorBranchAnalysis(result);\n }\n}\n\nfunction createXorBranchAnalysis(transitionBranches: Map<Transition, XorBranchInfo>): XorBranchAnalysis {\n return {\n transitionBranches,\n unreachableBranches(): Map<Transition, Set<number>> {\n const result = new Map<Transition, Set<number>>();\n for (const [t, info] of transitionBranches) {\n if (info.untakenBranches.size > 0) {\n result.set(t, info.untakenBranches);\n }\n }\n return result;\n },\n isXorComplete(): boolean {\n for (const info of transitionBranches.values()) {\n if (info.untakenBranches.size > 0) return false;\n }\n return true;\n },\n report(): string {\n if (transitionBranches.size === 0) return 'No XOR transitions in net.';\n\n const lines: string[] = [];\n lines.push('XOR Branch Coverage Analysis');\n lines.push('============================\\n');\n\n for (const [t, info] of transitionBranches) {\n lines.push(`Transition: ${t.name}`);\n lines.push(` Branches: ${info.totalBranches}`);\n lines.push(` Taken: [${[...info.takenBranches].join(', ')}]`);\n\n if (info.untakenBranches.size > 0) {\n lines.push(` UNREACHABLE: [${[...info.untakenBranches].join(', ')}]`);\n for (const idx of info.untakenBranches) {\n const places = [...info.branchOutputs[idx]!].map(p => p.name).join(', ');\n lines.push(` Branch ${idx} outputs: [${places}]`);\n }\n } else {\n lines.push(' All branches reachable');\n }\n lines.push('');\n }\n\n if (this.isXorComplete()) {\n lines.push('RESULT: All XOR branches are reachable.');\n } else {\n lines.push('RESULT: Some XOR branches are unreachable!');\n }\n\n return lines.join('\\n');\n },\n };\n}\n\nfunction computeBackwardReachability(scg: StateClassGraph, goals: Set<StateClass>): Set<StateClass> {\n const reachable = new Set(goals);\n const queue = [...goals];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const pred of scg.predecessors(current)) {\n if (!reachable.has(pred)) {\n reachable.add(pred);\n queue.push(pred);\n }\n }\n }\n\n return reachable;\n}\n\n/** Builder for TimePetriNetAnalyzer. */\nexport class TimePetriNetAnalyzerBuilder {\n private readonly net: PetriNet;\n private _initialMarking: MarkingState = MarkingState.empty();\n private readonly _goalPlaces = new Set<Place<any>>();\n private _maxClasses = 100_000;\n private readonly _environmentPlaces = new Set<EnvironmentPlace<any>>();\n private _environmentMode: EnvironmentAnalysisMode = ignore();\n\n constructor(net: PetriNet) {\n this.net = net;\n }\n\n initialMarking(marking: MarkingState): this {\n this._initialMarking = marking;\n return this;\n }\n\n goalPlaces(...places: Place<any>[]): this {\n for (const p of places) this._goalPlaces.add(p);\n return this;\n }\n\n maxClasses(max: number): this {\n this._maxClasses = max;\n return this;\n }\n\n environmentPlaces(...places: EnvironmentPlace<any>[]): this {\n for (const ep of places) this._environmentPlaces.add(ep);\n return this;\n }\n\n environmentMode(mode: EnvironmentAnalysisMode): this {\n this._environmentMode = mode;\n return this;\n }\n\n build(): TimePetriNetAnalyzer {\n if (this._goalPlaces.size === 0) {\n throw new Error('At least one goal place must be specified');\n }\n return TimePetriNetAnalyzer.create(\n this.net,\n this._initialMarking,\n this._goalPlaces,\n this._maxClasses,\n this._environmentPlaces,\n this._environmentMode,\n );\n }\n}\n","/**\n * @module open-net/contract\n *\n * What a subnet promises when verified on its own, with its ports played by the environment\n * ([VER-022]).\n *\n * The **assumption**: the tokens the subnet holds before anything arrives, and arrival\n * groups, each delivering between `min` and `max` tokens onto its places at any point of the\n * run. Every bound is finite: a bound is both the runtime cap and the width of the claim.\n *\n * The **guarantee**: at every quiescent marking the count clauses hold, and tokens rest only\n * on clause, rest or environment places, or where a marked designed terminal excuses them;\n * every other place is internal and empty. Every run comes to rest unless\n * {@link OpenNetContractBuilder.requireTermination} is turned off.\n */\nimport type { Place } from '../../core/place.js';\nimport type { Transition } from '../../core/transition.js';\nimport { MarkingState, type MarkingStateBuilder } from '../marking-state.js';\nimport { countPhrase } from '../count-clause.js';\n\n/**\n * The environment delivers between `min` and `max` tokens in total, each onto one of\n * `places`, each at any point of the run.\n */\nexport interface ArrivalGroup {\n readonly places: readonly Place<any>[];\n readonly min: number;\n readonly max: number;\n}\n\n/**\n * At every quiescent marking the tokens across `places` number between `min` and `max`\n * (`max` may be `Infinity`). A marked designed terminal waives `min`, never `max`: a halt\n * stops progress, it does not license a token too many.\n */\nexport interface CountClause {\n readonly name: string;\n readonly places: readonly Place<any>[];\n readonly min: number;\n readonly max: number;\n}\n\n/**\n * While `marker` holds a token, the clauses' lower bounds are waived and tokens may rest on\n * `excused`: the places where the work the marker interrupted was delivered. The marker\n * itself may always rest, as a conditional-sink marker may ([VER-014]).\n */\nexport interface DesignedTerminal {\n readonly marker: Place<any>;\n readonly excused: readonly Place<any>[];\n}\n\nconst CONTRACT_KEY = Symbol('OpenNetContract.internal');\n\n/**\n * A subnet's contract: the environment it assumes and what it guarantees at quiescence\n * ([VER-022]). Build one with {@link OpenNetContract.builder}; check it with `verifyOpenNet`.\n *\n * ```ts\n * const contract = OpenNetContract.builder()\n * .initialMarking(m => m.tokens(idle, 1).tokens(budget, k))\n * .arrive(1, inData, inEmpty) // exactly one arrival on the input edge\n * .arriveAtMost(1, halt) // never or once\n * .expect('e3', 1, e3Data, e3Empty) // one of data / empty per outgoing edge, once it runs\n * .expect('idle', 1, idle)\n * .expect('budget', k, budget)\n * .expect('history', 1, done, skipped)\n * .terminal(halt, inData, inEmpty) // a halted run leaves the arrival where it was delivered\n * .terminal(skipped) // a skipped run writes no output edge at all\n * .build();\n * ```\n *\n * **A node that can skip needs its edge clauses conditional.** `expect('e3', 1, …)` alone\n * reports a node that rests having skipped the edge. Name the place that marks a skip as a\n * {@link OpenNetContractBuilder.terminal}: while it is marked the lower bounds are waived, and\n * the upper bounds still catch an edge written twice.\n *\n * **A subnet that asks something of its neighbours needs an environment.** Alone, a node that\n * sends a request and waits quiesces with the request outstanding. Give the contract the\n * transitions the neighbours fire; their own places are never counted as stranded.\n *\n * ```ts\n * // A node that runs again on every answer, against an environment that answers twice.\n * const again = Transition.builder('env/again').inputs(one(request), one(rounds))\n * .outputs(outPlace(reply)).build();\n * const end = Transition.builder('env/end').inputs(one(request)).outputs(outPlace(ended)).build();\n *\n * const agent = OpenNetContract.builder()\n * .initialMarking(m => m.tokens(rounds, 2)) // the environment's own budget\n * .arrive(1, inPlace)\n * .expectBetween('done', 0, 1, done) // it may end without finishing\n * .environment(again, end)\n * .build();\n * ```\n *\n * An environment transition is never executed, so it needs no action.\n */\nexport class OpenNetContract {\n /** Tokens the subnet holds before anything arrives: its own resources and any shared pool it borrows from. */\n readonly initialMarking: MarkingState;\n readonly arrivals: readonly ArrivalGroup[];\n readonly clauses: readonly CountClause[];\n /** Places that may hold any number of tokens at quiescence. */\n readonly rest: readonly Place<any>[];\n readonly terminals: readonly DesignedTerminal[];\n /** Transitions the environment fires: neighbours that react to what the subnet sends. */\n readonly environment: readonly Transition[];\n /** Whether every run must come to rest. */\n readonly requiresTermination: boolean;\n\n /** @internal Use {@link OpenNetContract.builder}. */\n constructor(\n key: symbol,\n initialMarking: MarkingState,\n arrivals: readonly ArrivalGroup[],\n clauses: readonly CountClause[],\n rest: readonly Place<any>[],\n terminals: readonly DesignedTerminal[],\n environment: readonly Transition[],\n requiresTermination: boolean,\n ) {\n if (key !== CONTRACT_KEY) throw new Error('Use OpenNetContract.builder() to create instances');\n this.initialMarking = initialMarking;\n this.arrivals = arrivals;\n this.clauses = clauses;\n this.rest = rest;\n this.terminals = terminals;\n this.environment = environment;\n this.requiresTermination = requiresTermination;\n }\n\n static builder(): OpenNetContractBuilder {\n return new OpenNetContractBuilder();\n }\n\n /**\n * Every place the initial marking, an arrival group, a clause, the rest set or a terminal\n * marker names, then every place an environment transition touches, in first-mention\n * order: the places a port trace reports. A terminal's excused places are not included;\n * `closeOpenNet` adds them to the closed net itself.\n */\n places(): Place<any>[] {\n const seen = new Map<string, Place<any>>();\n const add = (p: Place<any>): void => {\n if (!seen.has(p.name)) seen.set(p.name, p);\n };\n for (const p of this.initialMarking.placesWithTokens()) add(p);\n for (const g of this.arrivals) g.places.forEach(add);\n for (const c of this.clauses) c.places.forEach(add);\n this.rest.forEach(add);\n for (const t of this.terminals) add(t.marker);\n for (const t of this.environment) transitionPlaces(t).forEach(add);\n return [...seen.values()];\n }\n\n /** The contract as the report prints it, one line per part. */\n describe(): string[] {\n const names = (ps: readonly Place<any>[]): string => ps.map(p => p.name).join(', ');\n const lines = [` Initial marking: ${this.initialMarking.toString()}`];\n lines.push(this.arrivals.length === 0\n ? ' Arrivals: none'\n : ` Arrivals: ${this.arrivals.map(g => `${countPhrase(g.min, g.max)} onto {${names(g.places)}}`).join('; ')}`);\n lines.push(this.clauses.length === 0\n ? ' At quiescence: no count clauses'\n : ` At quiescence: ${this.clauses.map(c => `${c.name} = ${countPhrase(c.min, c.max)} across {${names(c.places)}}`).join('; ')}`);\n if (this.rest.length > 0) lines.push(` Rest: ${names(this.rest)}`);\n for (const t of this.terminals) {\n lines.push(t.excused.length === 0\n ? ` Terminal: when ${t.marker.name}`\n : ` Terminal: when ${t.marker.name}: ${names(t.excused)}`);\n }\n if (this.environment.length > 0) {\n lines.push(` Environment transitions: ${this.environment.map(t => t.name).join(', ')}`);\n }\n lines.push(` Termination: ${this.requiresTermination ? 'every run comes to rest' : 'not required'}`);\n return lines;\n }\n}\n\n/** Every place an arc of `t` touches: inputs, reads, inhibitors, resets, then outputs. */\nexport function transitionPlaces(t: Transition): Place<any>[] {\n return [\n ...t.inputSpecs.map(s => s.place),\n ...t.reads.map(a => a.place),\n ...t.inhibitors.map(a => a.place),\n ...t.resets.map(a => a.place),\n ...t.outputPlaces(),\n ];\n}\n\nexport class OpenNetContractBuilder {\n private _initialMarking: MarkingState = MarkingState.empty();\n private readonly _arrivals: ArrivalGroup[] = [];\n private readonly _clauses: CountClause[] = [];\n private readonly _rest = new Map<string, Place<any>>();\n private readonly _terminals: { marker: Place<any>; excused: Map<string, Place<any>> }[] = [];\n private readonly _environment: Transition[] = [];\n private _requiresTermination = true;\n\n /** Tokens the subnet holds before anything arrives. */\n initialMarking(marking: MarkingState): this;\n initialMarking(configurator: (builder: MarkingStateBuilder) => void): this;\n initialMarking(arg: MarkingState | ((builder: MarkingStateBuilder) => void)): this {\n if (arg instanceof MarkingState) {\n this._initialMarking = arg;\n } else {\n const builder = MarkingState.builder();\n arg(builder);\n this._initialMarking = builder.build();\n }\n return this;\n }\n\n /** The environment delivers exactly `count` tokens, each onto one of `places`, at any point of the run. */\n arrive(count: number, ...places: Place<any>[]): this {\n return this.arriveBetween(count, count, ...places);\n }\n\n /** The environment delivers at most `max` tokens, possibly none. `arriveAtMost(1, halt)` is \"never or once\". */\n arriveAtMost(max: number, ...places: Place<any>[]): this {\n return this.arriveBetween(0, max, ...places);\n }\n\n /** The environment delivers between `min` and `max` tokens in total, each onto one of `places`, at any point of the run. */\n arriveBetween(min: number, max: number, ...places: Place<any>[]): this {\n if (!Number.isInteger(min) || !Number.isInteger(max) || min < 0 || max < min || max < 1) {\n throw new Error(\n `OpenNetContract: an arrival group needs whole bounds with 0 <= min <= max and max >= 1, ` +\n `got ${min}..${max}. A bound is both the runtime cap and the width of the claim, so it is finite.`,\n );\n }\n this._arrivals.push({ places: distinct(places, 'an arrival group'), min, max });\n return this;\n }\n\n /** At every quiescent marking, exactly `count` tokens across `places`. */\n expect(name: string, count: number, ...places: Place<any>[]): this {\n return this.expectBetween(name, count, count, ...places);\n }\n\n /** At every quiescent marking, between `min` and `max` tokens across `places`; `max` may be `Infinity`. */\n expectBetween(name: string, min: number, max: number, ...places: Place<any>[]): this {\n if (name.length === 0) throw new Error('OpenNetContract: a clause needs a name');\n if (this._clauses.some(c => c.name === name)) {\n throw new Error(`OpenNetContract: duplicate clause name '${name}'`);\n }\n if (!Number.isInteger(min) || min < 0 || !(max === Infinity || Number.isInteger(max)) || max < min) {\n throw new Error(`OpenNetContract: clause '${name}' needs whole bounds with 0 <= min <= max, got ${min}..${max}`);\n }\n this._clauses.push({ name, places: distinct(places, `clause '${name}'`), min, max });\n return this;\n }\n\n /** Places that may hold any number of tokens at quiescence. */\n rest(...places: Place<any>[]): this {\n for (const p of places) if (!this._rest.has(p.name)) this._rest.set(p.name, p);\n return this;\n }\n\n /**\n * A designed terminal: while `marker` holds a token, lower bounds are waived and tokens may\n * rest on `excused`. Repeated calls for one marker accumulate.\n */\n terminal(marker: Place<any>, ...excused: Place<any>[]): this {\n let entry = this._terminals.find(t => t.marker.name === marker.name);\n if (entry == null) {\n entry = { marker, excused: new Map() };\n this._terminals.push(entry);\n }\n for (const p of excused) if (!entry.excused.has(p.name)) entry.excused.set(p.name, p);\n return this;\n }\n\n /**\n * Transitions the environment fires: a neighbour that reacts to what the subnet sends, such\n * as a tool answering a request. An arrival group cannot say that: its tokens do not wait\n * for a request.\n *\n * They join the closed net unchanged and are marked as environment steps in the port trace.\n * A place only they touch belongs to the environment and may hold tokens at quiescence; a\n * place they share with the subnet is a port, judged like any other. Their actions never\n * run, so one that declares outputs may keep `passthrough()`.\n */\n environment(...transitions: Transition[]): this {\n for (const t of transitions) {\n if (this._environment.some(e => e.name === t.name)) {\n throw new Error(`OpenNetContract: duplicate environment transition '${t.name}'`);\n }\n this._environment.push(t);\n }\n return this;\n }\n\n /** Whether every run must come to rest (default `true`). */\n requireTermination(required: boolean): this {\n this._requiresTermination = required;\n return this;\n }\n\n build(): OpenNetContract {\n return new OpenNetContract(\n CONTRACT_KEY,\n this._initialMarking,\n [...this._arrivals],\n [...this._clauses],\n [...this._rest.values()],\n this._terminals.map(t => ({ marker: t.marker, excused: [...t.excused.values()] })),\n [...this._environment],\n this._requiresTermination,\n );\n }\n}\n\nfunction distinct(places: readonly Place<any>[], what: string): Place<any>[] {\n if (places.length === 0) throw new Error(`OpenNetContract: ${what} names no place`);\n const byName = new Map<string, Place<any>>();\n for (const p of places) if (!byName.has(p.name)) byName.set(p.name, p);\n return [...byName.values()];\n}\n","/**\n * @module open-net/closure\n *\n * An open net closed by the environment its contract describes ([VER-022]).\n *\n * Each arrival group becomes a source place holding the tokens it must deliver, one\n * transition per target place moving a token across, and a second source for the optional\n * part whose tokens may also be declined. The contract's environment transitions join\n * unchanged. Every interleaving of environment steps with the subnet's firings is a run of\n * the closed net, which is quiescent only once the environment has delivered what it must\n * and decided about the rest. Every route then verifies a plain net.\n *\n * Ordinary places, not the environment places of [VER-006]: those never run dry, so a net\n * with one is never quiescent and every quiescence property would hold vacuously.\n */\nimport { PetriNet } from '../../core/petri-net.js';\nimport { place, type Place } from '../../core/place.js';\nimport { Transition } from '../../core/transition.js';\nimport { one } from '../../core/in.js';\nimport { outPlace } from '../../core/out.js';\nimport { fork, isPassthrough, transform } from '../../core/transition-action.js';\nimport { MarkingState } from '../marking-state.js';\nimport { transitionPlaces, type OpenNetContract } from './contract.js';\n\n/** What an environment transition of the closure does, for the port trace. */\nexport type EnvironmentStep =\n | { readonly kind: 'arrival'; readonly group: number; readonly place: string }\n | { readonly kind: 'decline'; readonly group: number }\n /** One of the contract's own environment transitions. */\n | { readonly kind: 'transition' };\n\n/** An open net and its environment, as one closed net. */\nexport interface ClosedNet {\n readonly net: PetriNet;\n readonly initialMarking: MarkingState;\n /** Each environment transition by name, with what it does. */\n readonly environment: ReadonlyMap<string, EnvironmentStep>;\n /**\n * Places only the contract's environment transitions touch: the environment's own state.\n * A token left on one at quiescence is never stranded.\n */\n readonly environmentPlaces: readonly Place<any>[];\n /**\n * Places the contract names that no arc touches, in contract order. They join the closed\n * net as places of their own, so every route resolves them. A clause over a place nothing\n * writes then counts zero there, which is the finding, not an error.\n */\n readonly undeclared: readonly string[];\n}\n\n/** The action an environment transition that declares outputs gets when it has none: it never runs. */\nconst ENVIRONMENT_ACTION = transform(() => null);\n\n/**\n * Closes `net` with the environment of `contract`: its environment transitions, and for\n * arrival group `i` a source `env:arrivals[i]` holding `min` tokens and a source\n * `env:optional[i]` holding `max − min`, with transitions `env:arrive[i]:<place>` /\n * `env:arrive?[i]:<place>` moving a token onto each of the group's places, and\n * `env:decline[i]` discarding an optional one.\n *\n * @throws when a name the closure would add is already taken in `net`\n */\nexport function closeOpenNet(net: PetriNet, contract: OpenNetContract): ClosedNet {\n const byName = new Map<string, Place<any>>();\n for (const p of net.places) if (!byName.has(p.name)) byName.set(p.name, p);\n const taken = new Set<string>(byName.keys());\n for (const t of net.transitions) taken.add(t.name);\n const fresh = (name: string): string => {\n if (taken.has(name)) {\n throw new Error(`VER-022: closing the net would add '${name}', which the net already declares`);\n }\n taken.add(name);\n return name;\n };\n\n const environment = new Map<string, EnvironmentStep>();\n const environmentPlaces = new Map<string, Place<any>>();\n for (const t of contract.environment) {\n environment.set(fresh(t.name), { kind: 'transition' });\n for (const p of transitionPlaces(t)) {\n if (!byName.has(p.name) && !environmentPlaces.has(p.name)) environmentPlaces.set(p.name, p);\n }\n }\n // Before the undeclared sweep, so an environment place is never reported as undeclared.\n for (const [name, p] of environmentPlaces) {\n taken.add(name);\n byName.set(name, p);\n }\n\n // Every place the contract names joins the closed net, excused places included. The SMT\n // encoder drops a sink or excuse that does not resolve and the graph route does not, so an\n // unregistered excused place would make the routes disagree on the rest set.\n const undeclared: string[] = [];\n const extra: Place<any>[] = [];\n const named = [...contract.places(), ...contract.terminals.flatMap(t => t.excused)];\n for (const p of named) {\n if (byName.has(p.name)) continue;\n undeclared.push(p.name);\n byName.set(p.name, p);\n extra.push(p);\n }\n // The net's own place objects, so an arc and a contract place with one name stay one place.\n const canonical = (p: Place<any>): Place<any> => byName.get(p.name) ?? p;\n\n const envTransitions: Transition[] = [];\n const marking = MarkingState.builder().copyFrom(contract.initialMarking);\n const inject = (group: number, source: Place<any>, target: Place<any>, optional: boolean): void => {\n const name = fresh(`env:arrive${optional ? '?' : ''}[${group}]:${target.name}`);\n envTransitions.push(\n Transition.builder(name).inputs(one(source)).outputs(outPlace(target)).action(fork()).build(),\n );\n environment.set(name, { kind: 'arrival', group, place: target.name });\n };\n\n contract.arrivals.forEach((group, i) => {\n if (group.min > 0) {\n const source = place<unknown>(fresh(`env:arrivals[${i}]`));\n marking.tokens(source, group.min);\n for (const p of group.places) inject(i, source, canonical(p), false);\n }\n if (group.max > group.min) {\n const source = place<unknown>(fresh(`env:optional[${i}]`));\n marking.tokens(source, group.max - group.min);\n for (const p of group.places) inject(i, source, canonical(p), true);\n const name = fresh(`env:decline[${i}]`);\n envTransitions.push(Transition.builder(name).inputs(one(source)).build());\n environment.set(name, { kind: 'decline', group: i });\n }\n });\n\n // An environment transition's action never runs, so it need not produce: give one that\n // declares outputs a placeholder rather than refuse it under CORE-043.\n const placeholder = new Set(contract.environment\n .filter(t => t.outputSpec !== null && isPassthrough(t.action))\n .map(t => t.name));\n const closed = PetriNet.builder(`${net.name}+environment`)\n .places(...net.places, ...extra)\n .transitions(...net.transitions, ...contract.environment, ...envTransitions)\n .build()\n .bindActionsWithResolver(name => (placeholder.has(name) ? ENVIRONMENT_ACTION : null));\n return {\n net: closed,\n initialMarking: marking.build(),\n environment,\n environmentPlaces: [...environmentPlaces.values()],\n undeclared,\n };\n}\n","/**\n * @module open-net/predicate\n *\n * The contract's guarantee at one quiescent marking ([VER-022]): which clauses it breaks and\n * which places it strands. Stranding is the [VER-014] rest set every `DeadlockFree` route\n * reads, so the SMT route can ask for it with `deadlockFree()`.\n */\nimport type { Place } from '../../core/place.js';\nimport { compareCodePoints } from '../../core/internal/code-point-order.js';\nimport { countAcross, countViolation, tokensAcross } from '../count-clause.js';\nimport type { MarkingState } from '../marking-state.js';\nimport { strandedPlaces, type ConditionalSinks } from '../rest-set.js';\nimport type { ClosedNet } from './closure.js';\nimport type { CountClause, OpenNetContract } from './contract.js';\n\n/** One thing a quiescent marking breaks. */\nexport type Finding =\n | { readonly kind: 'clause'; readonly clause: CountClause; readonly count: number; readonly bound: 'lower' | 'upper' }\n | { readonly kind: 'stranded'; readonly place: string; readonly count: number };\n\n/** The contract's rest set in [VER-014] form. */\nexport interface RestDeclaration {\n readonly sinks: ReadonlySet<Place<any>>;\n readonly conditional: readonly ConditionalSinks[];\n}\n\n/**\n * Clause places, rest places and the environment's own places as sinks; each designed\n * terminal as a conditional sink.\n */\nexport function restDeclarationOf(contract: OpenNetContract, closed: ClosedNet): RestDeclaration {\n const sinks = new Map<string, Place<any>>();\n for (const c of contract.clauses) for (const p of c.places) if (!sinks.has(p.name)) sinks.set(p.name, p);\n for (const p of contract.rest) if (!sinks.has(p.name)) sinks.set(p.name, p);\n for (const p of closed.environmentPlaces) if (!sinks.has(p.name)) sinks.set(p.name, p);\n return {\n sinks: new Set(sinks.values()),\n conditional: contract.terminals.map(t => ({ marker: t.marker, places: new Set(t.excused) })),\n };\n}\n\n/** The clause lower bounds' waivers, for both routes: every designed terminal's marker ([VER-002]). */\nexport function waiverMarkers(contract: OpenNetContract): Place<any>[] {\n return contract.terminals.map(t => t.marker);\n}\n\n/**\n * The places `m` strands, in code-point order of their names ([VER-013]). Both routes\n * attribute a stranding through this: marked **and** unexcused, with the [VER-014]\n * widening, so neither reports a stranding the other proves impossible.\n */\nexport function strandedNames(m: MarkingState, rest: RestDeclaration): Place<any>[] {\n return strandedPlaces(m, rest.sinks, rest.conditional).sort((a, b) => compareCodePoints(a.name, b.name));\n}\n\n/**\n * What the quiescent marking `m` breaks: clauses in contract order, then stranded places by\n * name. Empty when `m` meets the contract.\n */\nexport function quiescenceFindings(m: MarkingState, contract: OpenNetContract, rest: RestDeclaration): Finding[] {\n const findings: Finding[] = [];\n // Each clause is a QuiescentCount waived by every terminal marker ([VER-002]).\n const markers = waiverMarkers(contract);\n for (const clause of contract.clauses) {\n const bound = countViolation(m, clause.places, clause.min, clause.max, markers);\n if (bound !== null) findings.push({ kind: 'clause', clause, count: tokensAcross(m, clause.places), bound });\n }\n for (const place of strandedNames(m, rest)) {\n findings.push({ kind: 'stranded', place: place.name, count: m.tokens(place) });\n }\n return findings;\n}\n\n/** The finding's subject: its clause's name or its place's name. */\nexport function subjectOf(f: Finding): string {\n return f.kind === 'clause' ? f.clause.name : f.place;\n}\n\n/** The finding in words. */\nexport function describeFinding(f: Finding): string {\n if (f.kind === 'stranded') {\n return `${f.place} holds ${f.count} at quiescence, and nothing in the contract lets a token rest there`;\n }\n const { clause } = f;\n const expected = countAcross(clause.min, clause.max, clause.places);\n return f.bound === 'upper'\n ? `${expected} at quiescence, found ${f.count} (an upper bound holds under a terminal too)`\n : `${expected} at quiescence, found ${f.count}`;\n}\n","/**\n * @module open-net/result\n *\n * What `verifyOpenNet` returns ([VER-022]), and how a witness becomes a port trace.\n */\nimport type { PetriNet } from '../../core/petri-net.js';\nimport type { Place } from '../../core/place.js';\nimport type { MarkingState } from '../marking-state.js';\nimport type { Verdict } from '../smt-verification-result.js';\nimport type { ClosedNet, EnvironmentStep } from './closure.js';\n\n/** Which part of the contract a violation breaks. */\nexport type ContractViolationKind =\n /** A count clause: too few tokens across its places at quiescence with no terminal marked, or too many. */\n | 'clause'\n /** A token rests where the contract lets none rest: on an internal place, or on one only an unmarked terminal excuses. */\n | 'stranded'\n /** A run that never comes to rest: a reachable cycle. */\n | 'termination';\n\n/** A token-count change on one contract place. */\nexport interface PortChange {\n readonly place: string;\n readonly delta: number;\n}\n\n/** A firing that touches the subnet's boundary: an environment step, or a change on a contract place. */\nexport interface PortStep {\n /** The firing's position in {@link ContractViolation.transitions}, counting from 1. */\n readonly step: number;\n readonly transition: string;\n /**\n * Set when the environment fired it: `arrival` or `decline` for an arrival group,\n * `transition` for one of the contract's environment transitions. `null` for the subnet.\n */\n readonly environment: EnvironmentStep['kind'] | null;\n /** Token changes on the contract's places, in the contract's order. */\n readonly changes: readonly PortChange[];\n}\n\n/** One broken part of the contract, with a firing sequence that breaks it. */\nexport interface ContractViolation {\n readonly kind: ContractViolationKind;\n /**\n * The clause's name, a stranded place's name, or `termination`. The SMT route reports one\n * stranding for the whole query, naming every stranded place comma-separated.\n */\n readonly subject: string;\n /** What was found, in words. */\n readonly detail: string;\n /** The firing sequence from the initial marking, environment transitions included. */\n readonly transitions: readonly string[];\n /** The marking before the first firing and after each one, when the route has them in order. */\n readonly markings: readonly MarkingState[];\n /** For `termination`, the index into {@link transitions} where the repeating cycle starts. */\n readonly cycleStart: number | null;\n /** The firings of {@link transitions} that touch the boundary. */\n readonly portTrace: readonly PortStep[];\n /**\n * Whether {@link transitions} is a real firing sequence in order. Always on the graph\n * route; on the SMT route it is the counterexample replay's outcome ([VER-003]).\n */\n readonly confirmed: boolean;\n}\n\n/** Which route decided the verdict. */\nexport type OpenNetRoute = 'enumeration' | 'smt';\n\n/** The outcome of `verifyOpenNet`. */\nexport interface OpenNetResult {\n /** `proven`, `violated` (see {@link violations}), or `unknown` with the reason. */\n readonly verdict: Verdict;\n /**\n * Every broken part found. The graph route lists clauses in contract order, then stranded\n * places by name, then termination; the SMT route asks for stranding first, so it lists\n * that, then clauses in contract order, then termination.\n */\n readonly violations: readonly ContractViolation[];\n readonly route: OpenNetRoute;\n /** Classes the state-class graph explored; `0` when it was skipped. */\n readonly classCount: number;\n /** Whether the state-class graph closed within its budget. */\n readonly graphComplete: boolean;\n readonly report: string;\n /** The subnet closed by its environment: what every route verified. */\n readonly closedNet: PetriNet;\n readonly closedMarking: MarkingState;\n readonly elapsedMs: number;\n}\n\n/** A violation with its port trace, read off consecutive markings of the witness. */\nexport function contractViolation(\n closed: ClosedNet,\n tracedPlaces: readonly Place<any>[],\n violation: Omit<ContractViolation, 'portTrace'>,\n): ContractViolation {\n const { transitions, markings } = violation;\n const portTrace: PortStep[] = [];\n if (markings.length === transitions.length + 1) {\n for (let i = 0; i < transitions.length; i++) {\n const before = markings[i]!;\n const after = markings[i + 1]!;\n const changes: PortChange[] = [];\n for (const p of tracedPlaces) {\n const delta = after.tokens(p) - before.tokens(p);\n if (delta !== 0) changes.push({ place: p.name, delta });\n }\n const env = closed.environment.get(transitions[i]!);\n if (changes.length > 0 || env !== undefined) {\n portTrace.push({ step: i + 1, transition: transitions[i]!, environment: env?.kind ?? null, changes });\n }\n }\n }\n return { ...violation, portTrace };\n}\n","/**\n * @module open-net/graph-route\n *\n * The contract decided on the closed net's state-class graph ([VER-022]), built **untimed**\n * ([VER-004]): every clock gets `immediate()`, so the graph holds the markings the untimed\n * encoders reason about. Priority- and value-blind, like every graph route.\n *\n * A closed graph decides exactly: every quiescent class is judged, and any cycle is a run\n * that never rests. A truncated graph's findings are still real, since a class with nothing\n * enabled is quiescent whether or not it was expanded and an explored cycle is a real cycle;\n * only the absence of findings needs the graph to close.\n */\nimport type { Place } from '../../core/place.js';\nimport { compareCodePoints } from '../../core/internal/code-point-order.js';\nimport { StateClassGraph } from '../analysis/state-class-graph.js';\nimport type { StateClass } from '../analysis/state-class.js';\nimport type { ClosedNet } from './closure.js';\nimport type { OpenNetContract } from './contract.js';\nimport { describeFinding, quiescenceFindings, restDeclarationOf, subjectOf, type Finding } from './predicate.js';\nimport { contractViolation, type ContractViolation } from './result.js';\n\n/** What the graph route found. */\nexport interface GraphRouteOutcome {\n readonly complete: boolean;\n readonly classCount: number;\n /** Real violations: the shallowest witness per subject, then termination. */\n readonly violations: readonly ContractViolation[];\n}\n\n/** Builds the closed net's untimed graph and judges it against `contract`. */\nexport function decideOnGraph(\n closed: ClosedNet,\n contract: OpenNetContract,\n maxClasses: number,\n tracedPlaces: readonly Place<any>[],\n): GraphRouteOutcome {\n const graph = StateClassGraph.build(\n closed.net, closed.initialMarking, maxClasses, undefined, undefined, { untimed: true },\n );\n const classes = graph.stateClasses();\n const rest = restDeclarationOf(contract, closed);\n const tree = bfsTree(graph);\n\n // Classes come in BFS order, so the first class showing a subject is a shallowest one.\n const first = new Map<string, { finding: Finding; target: StateClass }>();\n for (const sc of classes) {\n // Untimed, every enabled transition can fire: nothing enabled is quiescence, expanded or not.\n if (sc.enabledTransitions.length > 0) continue;\n for (const finding of quiescenceFindings(sc.marking, contract, rest)) {\n const key = `${finding.kind}:${subjectOf(finding)}`;\n if (!first.has(key)) first.set(key, { finding, target: sc });\n }\n }\n\n // Clauses in contract order, then stranded places in code-point order ([VER-013]).\n const clauseOrder = new Map(contract.clauses.map((c, i) => [c.name, i]));\n const rank = (f: Finding): number =>\n f.kind === 'clause' ? clauseOrder.get(f.clause.name)! : contract.clauses.length;\n const ordered = [...first.values()].sort((a, b) => rank(a.finding) - rank(b.finding)\n || compareCodePoints(subjectOf(a.finding), subjectOf(b.finding)));\n\n const violations: ContractViolation[] = ordered.map(({ finding, target }) => {\n const path = pathTo(tree, target);\n return contractViolation(closed, tracedPlaces, {\n kind: finding.kind,\n subject: subjectOf(finding),\n detail: describeFinding(finding),\n transitions: path.transitions,\n markings: path.classes.map(c => c.marking),\n cycleStart: null,\n confirmed: true,\n });\n });\n\n if (contract.requiresTermination) {\n const cycle = findCycle(graph, tree);\n if (cycle !== null) violations.push(contractViolation(closed, tracedPlaces, cycle));\n }\n return { complete: graph.isComplete(), classCount: classes.length, violations };\n}\n\ninterface TreeEdge {\n readonly parent: StateClass;\n readonly via: string;\n}\n\n/** Each explored class's BFS parent and the transition that first reached it. */\nfunction bfsTree(graph: StateClassGraph): Map<StateClass, TreeEdge> {\n const tree = new Map<StateClass, TreeEdge>();\n const seen = new Set<StateClass>([graph.initialClass]);\n const queue: StateClass[] = [graph.initialClass];\n for (let head = 0; head < queue.length; head++) {\n const current = queue[head]!;\n for (const [transition, edges] of graph.outgoingBranchEdges(current)) {\n for (const edge of edges) {\n if (seen.has(edge.target)) continue;\n seen.add(edge.target);\n tree.set(edge.target, { parent: current, via: transition.name });\n queue.push(edge.target);\n }\n }\n }\n return tree;\n}\n\n/** The shortest firing sequence from the initial class to `target`. */\nfunction pathTo(tree: Map<StateClass, TreeEdge>, target: StateClass): { classes: StateClass[]; transitions: string[] } {\n const classes: StateClass[] = [];\n const transitions: string[] = [];\n for (let cur: StateClass | undefined = target; cur !== undefined;) {\n classes.push(cur);\n const edge = tree.get(cur);\n if (edge === undefined) break;\n transitions.push(edge.via);\n cur = edge.parent;\n }\n return { classes: classes.reverse(), transitions: transitions.reverse() };\n}\n\ninterface Frame {\n readonly node: StateClass;\n readonly edges: readonly (readonly [string, StateClass])[];\n next: number;\n /** The transition that entered this frame's class from the one below it. */\n readonly via: string | null;\n}\n\n/**\n * A reachable cycle as a lasso (the shortest stem to its entry class, then the loop), or\n * `null`. Iterative depth-first search, so a deep graph cannot overflow the stack.\n */\nfunction findCycle(\n graph: StateClassGraph,\n tree: Map<StateClass, TreeEdge>,\n): Omit<ContractViolation, 'portTrace'> | null {\n const edgesOf = (sc: StateClass): (readonly [string, StateClass])[] => {\n const out: (readonly [string, StateClass])[] = [];\n for (const [t, edges] of graph.outgoingBranchEdges(sc)) for (const e of edges) out.push([t.name, e.target]);\n return out;\n };\n // A class's position on the stack while it is open, -1 once it is finished.\n const position = new Map<StateClass, number>([[graph.initialClass, 0]]);\n const stack: Frame[] = [{ node: graph.initialClass, edges: edgesOf(graph.initialClass), next: 0, via: null }];\n while (stack.length > 0) {\n const top = stack[stack.length - 1]!;\n if (top.next >= top.edges.length) {\n position.set(top.node, -1);\n stack.pop();\n continue;\n }\n const [via, target] = top.edges[top.next++]!;\n const at = position.get(target);\n if (at === undefined) {\n position.set(target, stack.length);\n stack.push({ node: target, edges: edgesOf(target), next: 0, via });\n } else if (at >= 0) {\n // A back edge: the stack from `target` up to `top`, closed by `via`, is a cycle.\n const loop = stack.slice(at);\n const stem = pathTo(tree, target);\n const cycle = [...loop.slice(1).map(f => f.via!), via];\n return {\n kind: 'termination',\n subject: 'termination',\n detail: `a run can repeat ${cycle.join(' → ')} forever without coming to rest`,\n transitions: [...stem.transitions, ...cycle],\n markings: [...stem.classes.map(c => c.marking), ...loop.slice(1).map(f => f.node.marking), target.marking],\n cycleStart: stem.transitions.length,\n confirmed: true,\n };\n }\n }\n return null;\n}\n","/**\n * @module open-net/report\n *\n * The human-readable report of an open-net verification ([VER-022]).\n */\nimport type { PetriNet } from '../../core/petri-net.js';\nimport type { Verdict } from '../smt-verification-result.js';\nimport type { ClosedNet } from './closure.js';\nimport type { OpenNetContract } from './contract.js';\nimport type { GraphRouteOutcome } from './graph-route.js';\nimport type { ContractViolation } from './result.js';\n\nexport interface ReportInput {\n readonly net: PetriNet;\n readonly closed: ClosedNet;\n readonly contract: OpenNetContract;\n readonly maxClasses: number;\n readonly graph: GraphRouteOutcome | null;\n /** Why the graph was not built, when {@link graph} is `null`. */\n readonly graphSkipped: string | null;\n readonly smtLines: readonly string[] | null;\n readonly verdict: Verdict;\n readonly violations: readonly ContractViolation[];\n}\n\nexport function renderReport(input: ReportInput): string {\n const { net, closed, contract, graph, smtLines, verdict, violations } = input;\n const lines: string[] = ['=== OPEN-NET CONTRACT VERIFICATION (VER-022) ===', ''];\n lines.push(`Net: ${net.name}, closed by ${closed.environment.size} environment transitions ` +\n `over ${contract.arrivals.length} arrival groups`);\n lines.push('Contract:', ...contract.describe());\n if (closed.undeclared.length > 0) {\n lines.push(`Not declared by the net: ${closed.undeclared.join(', ')} (no arc touches them; a clause there counts zero)`);\n }\n lines.push('');\n\n if (graph === null) {\n lines.push(`State-class graph: skipped (${input.graphSkipped ?? 'class budget 0'})`);\n } else {\n lines.push('=== State-class graph (untimed, priority-blind) ===');\n lines.push(graph.complete\n ? ` Classes: ${graph.classCount}, closed`\n : ` Classes: ${graph.classCount}, truncated at the class budget of ${input.maxClasses}`);\n }\n if (smtLines !== null) {\n lines.push('', '=== SMT route ===', ...smtLines);\n }\n\n lines.push('', '=== RESULT ===');\n switch (verdict.type) {\n case 'proven':\n lines.push(`PROVEN: every quiescent marking meets the contract${contract.requiresTermination ? ' and every run comes to rest' : ''} (${verdict.method})`);\n break;\n case 'unknown':\n lines.push(`UNKNOWN: ${verdict.reason}`);\n break;\n case 'violated':\n lines.push(`VIOLATED: ${violations.length} ${violations.length === 1 ? 'part' : 'parts'} of the contract broken`);\n for (const v of violations) lines.push(...renderViolation(v));\n break;\n }\n return lines.join('\\n');\n}\n\nfunction renderViolation(v: ContractViolation): string[] {\n const lines = [` [${v.subject}] ${v.kind}: ${v.detail}`];\n if (!v.confirmed) lines.push(' (the solver\\'s counterexample did not replay as an ordered firing sequence)');\n if (v.portTrace.length > 0) {\n lines.push(' Port trace:');\n for (const s of v.portTrace) {\n if (v.cycleStart !== null && s.step === v.cycleStart + 1) lines.push(' -- the cycle starts here --');\n const env = s.environment === null ? ''\n : s.environment === 'transition' ? ' [environment]' : ` [environment ${s.environment}]`;\n const changes = s.changes.map(c => `${c.place} ${c.delta > 0 ? '+' : ''}${c.delta}`).join(', ');\n lines.push(` ${s.step}. ${s.transition}${env}${changes.length > 0 ? ` ${changes}` : ''}`);\n }\n }\n if (v.cycleStart !== null) {\n const stem = v.transitions.slice(0, v.cycleStart);\n const cycle = `then repeating ${v.transitions.slice(v.cycleStart).join(', ')}`;\n lines.push(` Firing sequence: ${stem.length === 0 ? cycle : `${stem.join(', ')}, ${cycle}`}`);\n } else if (v.transitions.length > 0) {\n lines.push(` Firing sequence: ${v.transitions.join(', ')}`);\n }\n const last = v.markings.at(-1);\n if (last !== undefined) lines.push(` ${v.kind === 'termination' ? 'Marking on the cycle' : 'Quiescent marking'}: ${last.toString()}`);\n return lines;\n}\n","/**\n * @module open-net/smt-route\n *\n * The contract asked of the SMT pipeline when the graph does not close ([VER-022]). Each part\n * is one query on the closed net, deciding exactly the predicate the graph route reads:\n *\n * - **stranding**: `deadlockFree()` with clause, rest and environment places as sinks and each\n * terminal as a conditional sink ([VER-014]);\n * - **a count clause**: `quiescentCount(places, min, max, markers)` ([VER-002]), every\n * terminal marker a waiver;\n * - **termination**: the firing-bound ranking of [VER-019]; without one the part is undecided,\n * naming the firings the marking equation lets repeat.\n */\nimport { PetriNet } from '../../core/petri-net.js';\nimport type { Place } from '../../core/place.js';\nimport { Transition } from '../../core/transition.js';\nimport { flatten } from '../encoding/net-flattener.js';\nimport { countAcross, tokensAcross } from '../count-clause.js';\nimport { rethrowIfProgrammingError } from '../programming-error.js';\nimport type { ConditionalSinks } from '../rest-set.js';\nimport { isUntimed } from '../scg-verifier.js';\nimport {\n deadlockFree, propertyDescription, quiescentCount, type SmtProperty,\n} from '../smt-property.js';\nimport type { SmtVerificationResult } from '../smt-verification-result.js';\nimport { SmtVerifier } from '../smt-verifier.js';\nimport { findFiringBound, formatRanking } from '../z3/bounded-run.js';\nimport { failureReason, resolveZ3, runZ3Text, timeoutBudget, Z3Unavailable, type Z3Solver } from '../z3/z3-process.js';\nimport type { ClosedNet } from './closure.js';\nimport type { OpenNetContract } from './contract.js';\nimport { restDeclarationOf, strandedNames, waiverMarkers } from './predicate.js';\nimport { contractViolation, type ContractViolation } from './result.js';\n\n/** What the SMT route found. */\nexport interface SmtRouteOutcome {\n readonly violations: readonly ContractViolation[];\n /** The parts of the contract no query decided, each with its reason. */\n readonly undecided: readonly string[];\n /** One report line per query. */\n readonly lines: readonly string[];\n /** The inductive invariant each proven query returned, in query order; a `proven` verdict is their conjunction. */\n readonly certificates: readonly SubjectCertificate[];\n}\n\n/** One part of the contract and the invariant that proved it. */\nexport interface SubjectCertificate {\n readonly subject: string;\n readonly invariant: string;\n}\n\ninterface Query {\n readonly subject: string;\n readonly property: SmtProperty;\n readonly sinks: readonly Place<any>[];\n readonly conditional: readonly ConditionalSinks[];\n /** The violation a `violated` verdict means. */\n readonly onViolated: (result: SmtVerificationResult) => Omit<ContractViolation, 'portTrace'>;\n}\n\n/**\n * A part of the contract: a query to run, or a clause no marking can fail.\n *\n * A `[0, ∞]` clause is the second kind: the graph route finds nothing for it either, and its\n * places still count as sinks of the stranding query. Asking would only risk `unknown`, so it\n * is skipped with a report line.\n */\ntype Part =\n | { readonly kind: 'query'; readonly query: Query }\n | { readonly kind: 'vacuous'; readonly subject: string; readonly detail: string };\n\n/** Runs one query per part of the contract, in contract order, then the firing bound. */\nexport async function decideViaSmt(\n closed: ClosedNet,\n contract: OpenNetContract,\n tracedPlaces: readonly Place<any>[],\n configure: (verifier: SmtVerifier) => SmtVerifier,\n terminationTimeoutMs: number,\n): Promise<SmtRouteOutcome> {\n const violations: ContractViolation[] = [];\n const undecided: string[] = [];\n const lines: string[] = [];\n const certificates: SubjectCertificate[] = [];\n const net = untimed(closed.net);\n for (const part of partsFor(closed, contract)) {\n if (part.kind === 'vacuous') {\n lines.push(` [${part.subject}] ${part.detail}: proven (no query needed)`);\n continue;\n }\n const q = part.query;\n let verifier = SmtVerifier.forNet(net)\n .initialMarking(closed.initialMarking)\n .property(q.property)\n .sinkPlaces(...q.sinks)\n // The graph route already enumerated as far as its budget allows.\n .enumerationMaxClasses(0);\n for (const c of q.conditional) verifier = verifier.sinkPlacesWhen(c.marker, ...c.places);\n const result = await configure(verifier).verify();\n const verdict = result.verdict;\n lines.push(` [${q.subject}] ${propertyDescription(q.property)}: ${verdict.type}`\n + (verdict.type === 'unknown' ? ` (${verdict.reason})` : ''));\n if (verdict.type === 'unknown') undecided.push(`${q.subject}: ${verdict.reason}`);\n else if (verdict.type === 'violated') violations.push(contractViolation(closed, tracedPlaces, q.onViolated(result)));\n // Some routes prove without a certificate; keep the ones that come with one.\n else if (verdict.inductiveInvariant !== null) {\n certificates.push({ subject: q.subject, invariant: verdict.inductiveInvariant });\n }\n }\n if (contract.requiresTermination) {\n const termination = await terminationByRanking(closed, terminationTimeoutMs);\n if (termination.proven) {\n lines.push(` [termination] Firing bound (VER-019): ${termination.detail}`);\n } else {\n lines.push(` [termination] Firing bound (VER-019): undecided (${termination.reason})`);\n undecided.push(`termination: ${termination.reason}`);\n }\n }\n return { violations, undecided, lines, certificates };\n}\n\n/**\n * `net` with every transition `immediate`, so each query decides the untimed claim ([VER-004]).\n * The flat encoders ignore timing, but a ν-net's quiescence query goes to the name-aware graph\n * (NU-050), which keeps it and would prove the weaker timed claim.\n */\nfunction untimed(net: PetriNet): PetriNet {\n if (isUntimed(net)) return net;\n const transitions = [...net.transitions].map(t => {\n if (t.timing.type === 'immediate') return t;\n const b = Transition.builder(t.name).inputs(...t.inputSpecs).priority(t.priority).action(t.action);\n if (t.outputSpec !== null) b.outputs(t.outputSpec);\n for (const arc of t.inhibitors) b.inhibitor(arc.place);\n for (const arc of t.reads) b.read(arc.place);\n for (const arc of t.resets) b.reset(arc.place);\n if (t.matchSpec !== null) b.match(t.matchSpec);\n return b.build();\n });\n return PetriNet.builder(net.name).places(...net.places).transitions(...transitions).build();\n}\n\nfunction partsFor(closed: ClosedNet, contract: OpenNetContract): Part[] {\n const rest = restDeclarationOf(contract, closed);\n const markers = waiverMarkers(contract);\n // A replay-confirmed counterexample ends in the quiescent marking it reached.\n const quiescentMarking = (result: SmtVerificationResult) =>\n result.counterexampleConfirmed === true ? result.counterexampleTrace.at(-1) : undefined;\n const witness = (result: SmtVerificationResult) => ({\n transitions: [...result.counterexampleTransitions],\n markings: [...result.counterexampleTrace],\n cycleStart: null,\n confirmed: result.counterexampleConfirmed === true,\n });\n\n const stranding: Query = {\n subject: 'stranding',\n property: deadlockFree(),\n sinks: [...rest.sinks],\n conditional: rest.conditional,\n onViolated: result => {\n // The verdict stands without the replay; naming the stranded places needs its marking.\n const last = quiescentMarking(result);\n const stranded = last === undefined ? [] : strandedNames(last, rest).map(p => p.name);\n return {\n kind: 'stranded',\n subject: stranded.length === 0 ? 'stranding' : stranded.join(', '),\n detail: stranded.length === 0\n ? 'the solver found a reachable quiescent marking that leaves a token where the contract lets none rest'\n : `${stranded.join(', ')} ${stranded.length === 1 ? 'holds' : 'hold'} a token at quiescence, and nothing in the contract lets one rest there`,\n ...witness(result),\n };\n },\n };\n\n const parts: Part[] = [{ kind: 'query', query: stranding }];\n\n for (const clause of contract.clauses) {\n const across = countAcross(clause.min, clause.max, clause.places);\n if (clause.min === 0 && clause.max === Infinity) {\n parts.push({ kind: 'vacuous', subject: clause.name, detail: `${across} at quiescence` });\n continue;\n }\n const query: Query = {\n subject: clause.name,\n property: quiescentCount(clause.places, clause.min, clause.max, markers),\n sinks: [],\n conditional: [],\n onViolated: result => {\n const last = quiescentMarking(result);\n return {\n kind: 'clause',\n subject: clause.name,\n detail: last === undefined\n ? `${across} at quiescence: the solver found a quiescent marking outside it`\n : `${across} at quiescence, found ${tokensAcross(last, clause.places)}`,\n ...witness(result),\n };\n },\n };\n parts.push({ kind: 'query', query });\n }\n return parts;\n}\n\n/** Termination by the firing-bound ranking of [VER-019] on the closed net: no run has more than `r·M0` firings. */\nasync function terminationByRanking(\n closed: ClosedNet,\n timeoutMs: number,\n): Promise<{ readonly proven: true; readonly detail: string } | { readonly proven: false; readonly reason: string }> {\n const flat = flatten(closed.net);\n const initial = flat.places.map(p => closed.initialMarking.tokens(p));\n let solver: Z3Solver;\n try {\n solver = resolveZ3();\n } catch (e) {\n if (e instanceof Z3Unavailable) return { proven: false, reason: e.message };\n throw e;\n }\n // A reply is read only when its first non-blank line is the verdict.\n const ask = async (script: string): Promise<string | Error> => {\n try {\n const reply = await runZ3Text(solver, script, 'ranking', timeoutMs, []);\n const answer = firstLine(reply.stdout);\n if (answer === 'sat' || answer === 'unsat' || answer === 'unknown') return reply.stdout;\n return new Error(failureReason(reply, timeoutBudget(timeoutMs)));\n } catch (e) {\n rethrowIfProgrammingError(e);\n return new Error(String((e as Error)?.message ?? e));\n }\n };\n\n const ranking = await findFiringBound(flat, initial, ask);\n switch (ranking.kind) {\n case 'bound':\n return {\n proven: true,\n detail: `every run has at most ${ranking.bound.bound} firings (${formatRanking(flat, ranking.bound)} drops on every firing)`,\n };\n case 'unbounded':\n return {\n proven: false,\n reason: ranking.repeatable === null\n ? 'no firing bound: no weights drop on every firing'\n : `no firing bound: the marking equation lets ${ranking.repeatable.map(t => flat.transitions[t]!.name).join(', ')} repeat`,\n };\n case 'rejected':\n return { proven: false, reason: 'the firing-bound ranking failed the exact re-check' };\n case 'unknown':\n return { proven: false, reason: 'the firing-bound query answered unknown' };\n case 'failed':\n return { proven: false, reason: ranking.reason };\n }\n}\n\nfunction firstLine(stdout: string): string {\n return stdout.split('\\n').find(line => line.trim() !== '')?.trim() ?? '';\n}\n","/**\n * @module open-net/verify-open-net\n *\n * A subnet verified on its own against a contract, with its ports played by the environment\n * ([VER-022]). The closed net's untimed state-class graph decides exactly when it closes; a\n * violation it finds stands either way, and otherwise the SMT pipeline gets the contract.\n * Composing the per-subnet proofs into a claim about a whole net is the caller's theorem.\n */\nimport type { PetriNet } from '../../core/petri-net.js';\nimport type { SmtVerifier } from '../smt-verifier.js';\nimport type { Verdict } from '../smt-verification-result.js';\nimport { closeOpenNet } from './closure.js';\nimport type { OpenNetContract } from './contract.js';\nimport { decideOnGraph } from './graph-route.js';\nimport { renderReport } from './report.js';\nimport type { ContractViolation, OpenNetResult, OpenNetRoute } from './result.js';\nimport { decideViaSmt, type SubjectCertificate } from './smt-route.js';\n\n/** Options for {@link verifyOpenNet}. */\nexport interface OpenNetOptions {\n /** Class budget for the state-class graph (default 50 000, as for [VER-017]). `0` skips the graph. */\n readonly maxClasses?: number;\n /** Whether to ask the SMT pipeline when the graph does not close (default `true`). */\n readonly smt?: boolean;\n /** Configures each `SmtVerifier` the SMT route builds, e.g. `v => v.timeout(120_000).stateEquation(true)`. */\n readonly configureSmt?: (verifier: SmtVerifier) => SmtVerifier;\n /** Time for the firing-bound query that decides termination on the SMT route (default 60 s). */\n readonly terminationTimeoutMs?: number;\n}\n\nconst DEFAULT_MAX_CLASSES = 50_000;\nconst METHOD_ENUMERATION = 'open-net contract by state-space enumeration (VER-022)';\nconst METHOD_SMT = 'open-net contract by the SMT pipeline (VER-022)';\nconst SKIPPED_BY_BUDGET = 'class budget 0';\nconst SKIPPED_BY_MATCH = 'the closed net declares match (ν-join) transitions, which the graph does not model';\n\n/**\n * Verifies `net` in isolation against `contract` ([VER-022]).\n *\n * `proven` means that, in every run of the environment the contract assumes, every\n * quiescent marking meets the contract, and (unless termination is waived) every run comes\n * to rest. The claim is untimed, priority-blind and value-blind, like every route's\n * ([VER-004]). `violated` lists every broken part with a shortest witness, and\n * `unknown` says why neither route decided.\n *\n * @throws when the net violates CORE-043, as every verifier does, or when the closure's\n * names collide with the net's\n */\nexport async function verifyOpenNet(\n net: PetriNet,\n contract: OpenNetContract,\n options: OpenNetOptions = {},\n): Promise<OpenNetResult> {\n const start = performance.now();\n const closed = closeOpenNet(net, contract);\n const maxClasses = options.maxClasses ?? DEFAULT_MAX_CLASSES;\n const useSmt = options.smt ?? true;\n // The places a port trace reports changes on.\n const tracedPlaces = contract.places();\n // The graph is name-blind: it fires a ν-join on tokens whose names differ and never strands\n // the inputs of a join that cannot match, so for a quiescence contract neither its `proven`\n // nor its `violated` stands ([VER-017] condition 1). The SMT pipeline has exact ν routes.\n const graphSkipped = [...closed.net.transitions].some(t => t.matchSpec !== null)\n ? SKIPPED_BY_MATCH\n : maxClasses > 0 ? null : SKIPPED_BY_BUDGET;\n const graph = graphSkipped === null ? decideOnGraph(closed, contract, maxClasses, tracedPlaces) : null;\n\n const result = (\n verdict: Verdict,\n route: OpenNetRoute,\n violations: readonly ContractViolation[],\n smtLines: readonly string[] | null,\n ): OpenNetResult => ({\n verdict,\n violations,\n route,\n classCount: graph?.classCount ?? 0,\n graphComplete: graph?.complete ?? false,\n report: renderReport({ net, closed, contract, maxClasses, graph, graphSkipped, smtLines, verdict, violations }),\n closedNet: closed.net,\n closedMarking: closed.initialMarking,\n elapsedMs: performance.now() - start,\n });\n\n if (graph !== null) {\n if (graph.violations.length > 0) {\n return result({ type: 'violated' }, 'enumeration', graph.violations, null);\n }\n if (graph.complete) {\n // No invariant: the exhausted graph is the evidence.\n return result({ type: 'proven', method: METHOD_ENUMERATION, inductiveInvariant: null }, 'enumeration', [], null);\n }\n }\n const why = graph !== null\n ? `the state-class graph did not close within ${maxClasses} classes`\n : graphSkipped === SKIPPED_BY_BUDGET\n ? 'the state-class graph was skipped'\n : `the state-class graph was skipped: ${graphSkipped}`;\n if (!useSmt) {\n return result({ type: 'unknown', reason: `${why}, and the SMT route is disabled` }, 'enumeration', [], null);\n }\n\n const smt = await decideViaSmt(\n closed, contract, tracedPlaces, options.configureSmt ?? (v => v), options.terminationTimeoutMs ?? 60_000,\n );\n if (smt.violations.length > 0) return result({ type: 'violated' }, 'smt', smt.violations, smt.lines);\n if (smt.undecided.length === 0) {\n return result(\n { type: 'proven', method: METHOD_SMT, inductiveInvariant: combineCertificates(smt.certificates) },\n 'smt', [], smt.lines,\n );\n }\n return result(\n { type: 'unknown', reason: `${why}; left undecided by the SMT route: ${smt.undecided.join('; ')}` },\n 'smt', [], smt.lines,\n );\n}\n\n/**\n * The route's certificates, each labelled with the contract part it proves, or `null` when no\n * query returned one (a part proven by a bound or by enumeration has none).\n */\nfunction combineCertificates(certificates: readonly SubjectCertificate[]): string | null {\n if (certificates.length === 0) return null;\n return certificates.map(c => `[${c.subject}] ${c.invariant}`).join('\\n');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMO,SAAS,YACd,OACA,YACU;AACV,QAAM,YAAY,CAAC,GAAG,KAAK;AAC3B,QAAM,WAAW,oBAAI,IAAe;AACpC,QAAM,UAAU,oBAAI,IAAe;AACnC,QAAM,UAAU,oBAAI,IAAO;AAC3B,QAAM,QAAa,CAAC;AACpB,QAAM,OAAiB,CAAC;AACxB,MAAI,QAAQ;AAEZ,WAAS,cAAc,GAAY;AACjC,aAAS,IAAI,GAAG,KAAK;AACrB,YAAQ,IAAI,GAAG,KAAK;AACpB;AACA,UAAM,KAAK,CAAC;AACZ,YAAQ,IAAI,CAAC;AAEb,eAAW,KAAK,WAAW,CAAC,GAAG;AAC7B,UAAI,CAAC,SAAS,IAAI,CAAC,GAAG;AACpB,sBAAc,CAAC;AACf,gBAAQ,IAAI,GAAG,KAAK,IAAI,QAAQ,IAAI,CAAC,GAAI,QAAQ,IAAI,CAAC,CAAE,CAAC;AAAA,MAC3D,WAAW,QAAQ,IAAI,CAAC,GAAG;AACzB,gBAAQ,IAAI,GAAG,KAAK,IAAI,QAAQ,IAAI,CAAC,GAAI,SAAS,IAAI,CAAC,CAAE,CAAC;AAAA,MAC5D;AAAA,IACF;AAEA,QAAI,QAAQ,IAAI,CAAC,MAAM,SAAS,IAAI,CAAC,GAAG;AACtC,YAAM,MAAM,oBAAI,IAAO;AACvB,UAAI;AACJ,SAAG;AACD,YAAI,MAAM,IAAI;AACd,gBAAQ,OAAO,CAAC;AAChB,YAAI,IAAI,CAAC;AAAA,MACX,SAAS,MAAM;AACf,WAAK,KAAK,GAAG;AAAA,IACf;AAAA,EACF;AAEA,aAAW,QAAQ,WAAW;AAC5B,QAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,oBAAc,IAAI;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,iBACd,OACA,YACU;AACV,QAAM,UAAU,YAAY,OAAO,UAAU;AAE7C,QAAM,WAAqB,CAAC;AAC5B,aAAW,OAAO,SAAS;AACzB,QAAI,aAAa;AACjB,eAAW,QAAQ,KAAK;AACtB,iBAAW,QAAQ,WAAW,IAAI,GAAG;AACnC,YAAI,CAAC,IAAI,IAAI,IAAI,GAAG;AAClB,uBAAa;AACb;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,WAAY;AAAA,IACnB;AACA,QAAI,YAAY;AACd,eAAS,KAAK,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;;;ACnCO,IAAM,uBAAN,MAAM,sBAAqB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGjB,OAAO,OACL,KACA,gBACA,YACA,YACA,mBACA,iBACsB;AACtB,WAAO,IAAI,sBAAqB,KAAK,gBAAgB,YAAY,YAAY,mBAAmB,eAAe;AAAA,EACjH;AAAA,EAEQ,YACN,KACA,gBACA,YACA,YACA,mBACA,iBACA;AACA,SAAK,MAAM;AACX,SAAK,iBAAiB;AACtB,SAAK,aAAa;AAClB,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,OAAO,OAAO,KAA4C;AACxD,WAAO,IAAI,4BAA4B,GAAG;AAAA,EAC5C;AAAA;AAAA,EAGA,UAA0B;AACxB,UAAM,SAAmB,CAAC;AAC1B,WAAO,KAAK,0CAA0C;AACtD,WAAO,KAAK,kDAAkD;AAC9D,WAAO,KAAK,QAAQ,KAAK,IAAI,IAAI,EAAE;AACnC,WAAO,KAAK,WAAW,KAAK,IAAI,OAAO,IAAI,EAAE;AAC7C,WAAO,KAAK,gBAAgB,KAAK,IAAI,YAAY,IAAI,EAAE;AACvD,WAAO,KAAK,iBAAiB,CAAC,GAAG,KAAK,UAAU,EAAE,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,CAAK;AAGlF,WAAO,KAAK,wCAAwC;AACpD,QAAI,KAAK,kBAAkB,OAAO,GAAG;AACnC,aAAO,KAAK,yBAAyB,KAAK,kBAAkB,IAAI,EAAE;AAClE,aAAO,KAAK,uBAAuB,KAAK,gBAAgB,IAAI,EAAE;AAAA,IAChE;AACA,UAAM,MAAM,gBAAgB,MAAM,KAAK,KAAK,KAAK,gBAAgB,KAAK,YAAY,KAAK,mBAAmB,KAAK,eAAe;AAC9H,WAAO,KAAK,oBAAoB,IAAI,KAAK,CAAC,EAAE;AAC5C,WAAO,KAAK,YAAY,IAAI,UAAU,CAAC,EAAE;AACzC,WAAO,KAAK,eAAe,IAAI,WAAW,IAAI,QAAQ,gBAAgB,EAAE;AAExE,QAAI,CAAC,IAAI,WAAW,GAAG;AACrB,aAAO,KAAK,6CAA6C,KAAK,UAAU,uCAAuC;AAAA,IACjH;AACA,WAAO,KAAK,EAAE;AAGd,WAAO,KAAK,4CAA4C;AACxD,UAAM,cAAc,oBAAI,IAAgB;AACxC,eAAW,MAAM,IAAI,aAAa,GAAG;AACnC,UAAI,GAAG,QAAQ,eAAe,KAAK,UAAU,GAAG;AAC9C,oBAAY,IAAI,EAAE;AAAA,MACpB;AAAA,IACF;AACA,WAAO,KAAK,yBAAyB,YAAY,IAAI;AAAA,CAAI;AAGzD,WAAO,KAAK,qDAAqD;AACjE,UAAM,cAAc,CAAC,OAAmB,IAAI,WAAW,EAAE;AACzD,UAAM,UAAU,YAAY,IAAI,aAAa,GAAG,WAAW;AAC3D,UAAM,eAAe,iBAAiB,IAAI,aAAa,GAAG,WAAW;AAErE,WAAO,KAAK,iBAAiB,QAAQ,MAAM,EAAE;AAC7C,WAAO,KAAK,oBAAoB,aAAa,MAAM;AAAA,CAAI;AAGvD,WAAO,KAAK,qCAAqC;AACjD,WAAO,KAAK,mEAAmE;AAE/E,UAAM,uBAA0C,CAAC;AACjD,UAAM,0BAA6C,CAAC;AAEpD,eAAW,OAAO,cAAc;AAC9B,UAAI,UAAU;AACd,iBAAW,MAAM,KAAK;AACpB,YAAI,YAAY,IAAI,EAAE,GAAG;AAAE,oBAAU;AAAM;AAAA,QAAO;AAAA,MACpD;AACA,OAAC,UAAU,uBAAuB,yBAAyB,KAAK,GAAG;AAAA,IACrE;AAEA,WAAO,KAAK,8BAA8B,qBAAqB,MAAM,EAAE;AACvE,WAAO,KAAK,iCAAiC,wBAAwB,MAAM,EAAE;AAE7E,UAAM,eAAe,4BAA4B,KAAK,WAAW;AACjE,UAAM,wBAAwB,IAAI,KAAK,IAAI,aAAa;AAExD,WAAO,KAAK,iCAAiC,aAAa,IAAI,IAAI,IAAI,KAAK,CAAC;AAAA,CAAI;AAEhF,UAAM,aAAa,wBAAwB,WAAW,KAAK,0BAA0B;AAGrF,WAAO,KAAK,+CAA+C;AAC3D,WAAO,KAAK,oEAAoE;AAEhF,UAAM,iBAAiB,IAAI,IAAI,KAAK,IAAI,WAAW;AACnD,UAAM,iCAAoD,CAAC;AAE3D,eAAW,OAAO,cAAc;AAC9B,YAAM,mBAAmB,oBAAI,IAAgB;AAC7C,iBAAW,MAAM,KAAK;AACpB,mBAAW,KAAK,IAAI,mBAAmB,EAAE,GAAG;AAC1C,gBAAM,QAAQ,IAAI,YAAY,IAAI,CAAC;AACnC,qBAAW,QAAQ,OAAO;AACxB,gBAAI,IAAI,IAAI,KAAK,MAAM,GAAG;AACxB,+BAAiB,IAAI,CAAC;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,aAAa;AACjB,iBAAW,KAAK,gBAAgB;AAC9B,YAAI,CAAC,iBAAiB,IAAI,CAAC,GAAG;AAAE,uBAAa;AAAM;AAAA,QAAO;AAAA,MAC5D;AACA,UAAI,YAAY;AACd,uCAA+B,KAAK,GAAG;AACvC,cAAM,UAAU,CAAC,GAAG,cAAc,EAAE,OAAO,OAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC;AACxE,eAAO,KAAK,wCAAwC,QAAQ,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,GAAG;AAAA,MAC5F;AAAA,IACF;AAEA,UAAM,WAAW,+BAA+B,WAAW,KAAK,IAAI,WAAW;AAG/E,WAAO,KAAK,6BAA6B;AAEzC,QAAI,cAAc,IAAI,WAAW,GAAG;AAClC,aAAO,KAAK,wBAAwB;AACpC,aAAO,KAAK,kEAAkE;AAAA,IAChF,WAAW,cAAc,CAAC,IAAI,WAAW,GAAG;AAC1C,aAAO,KAAK,yCAAyC;AAAA,IACvD,OAAO;AACL,aAAO,KAAK,yBAAyB;AACrC,UAAI,wBAAwB,SAAS,GAAG;AACtC,eAAO,KAAK,KAAK,wBAAwB,MAAM,sCAAsC;AAAA,MACvF;AACA,UAAI,wBAAwB,GAAG;AAC7B,eAAO,KAAK,KAAK,qBAAqB,qCAAqC;AAAA,MAC7E;AAAA,IACF;AAEA,WAAO,KAAK,EAAE;AAEd,QAAI,UAAU;AACZ,aAAO,KAAK,kCAAkC;AAAA,IAChD,OAAO;AACL,aAAO,KAAK,sCAAsC;AAClD,UAAI,+BAA+B,SAAS,GAAG;AAC7C,eAAO,KAAK,qDAAqD;AAAA,MACnE;AACA,UAAI,CAAC,IAAI,WAAW,GAAG;AACrB,eAAO,KAAK,oDAAoD;AAAA,MAClE;AAAA,IACF;AAEA,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,IAAI,WAAW;AAAA,MAC3B,QAAQ,OAAO,KAAK,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,mBAAmB,KAAyC;AACjE,UAAM,SAAS,oBAAI,IAA+B;AAElD,eAAW,cAAc,IAAI,IAAI,aAAa;AAC5C,UAAI,WAAW,eAAe,KAAM;AAEpC,YAAM,cAAc,kBAAkB,WAAW,UAAU;AAC3D,UAAI,YAAY,UAAU,EAAG;AAE7B,YAAM,gBAAgB,oBAAI,IAAY;AACtC,iBAAW,MAAM,IAAI,aAAa,GAAG;AACnC,cAAM,QAAQ,IAAI,YAAY,IAAI,UAAU;AAC5C,mBAAW,QAAQ,OAAO;AACxB,wBAAc,IAAI,KAAK,WAAW;AAAA,QACpC;AAAA,MACF;AAEA,YAAM,kBAAkB,oBAAI,IAAY;AACxC,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,YAAI,CAAC,cAAc,IAAI,CAAC,EAAG,iBAAgB,IAAI,CAAC;AAAA,MAClD;AAEA,aAAO,IAAI,YAAY;AAAA,QACrB,eAAe,YAAY;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AAEA,WAAO,wBAAwB,MAAM;AAAA,EACvC;AACF;AAEA,SAAS,wBAAwB,oBAAuE;AACtG,SAAO;AAAA,IACL;AAAA,IACA,sBAAoD;AAClD,YAAM,SAAS,oBAAI,IAA6B;AAChD,iBAAW,CAAC,GAAG,IAAI,KAAK,oBAAoB;AAC1C,YAAI,KAAK,gBAAgB,OAAO,GAAG;AACjC,iBAAO,IAAI,GAAG,KAAK,eAAe;AAAA,QACpC;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,gBAAyB;AACvB,iBAAW,QAAQ,mBAAmB,OAAO,GAAG;AAC9C,YAAI,KAAK,gBAAgB,OAAO,EAAG,QAAO;AAAA,MAC5C;AACA,aAAO;AAAA,IACT;AAAA,IACA,SAAiB;AACf,UAAI,mBAAmB,SAAS,EAAG,QAAO;AAE1C,YAAM,QAAkB,CAAC;AACzB,YAAM,KAAK,8BAA8B;AACzC,YAAM,KAAK,gCAAgC;AAE3C,iBAAW,CAAC,GAAG,IAAI,KAAK,oBAAoB;AAC1C,cAAM,KAAK,eAAe,EAAE,IAAI,EAAE;AAClC,cAAM,KAAK,eAAe,KAAK,aAAa,EAAE;AAC9C,cAAM,KAAK,aAAa,CAAC,GAAG,KAAK,aAAa,EAAE,KAAK,IAAI,CAAC,GAAG;AAE7D,YAAI,KAAK,gBAAgB,OAAO,GAAG;AACjC,gBAAM,KAAK,mBAAmB,CAAC,GAAG,KAAK,eAAe,EAAE,KAAK,IAAI,CAAC,GAAG;AACrE,qBAAW,OAAO,KAAK,iBAAiB;AACtC,kBAAM,SAAS,CAAC,GAAG,KAAK,cAAc,GAAG,CAAE,EAAE,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI;AACvE,kBAAM,KAAK,cAAc,GAAG,cAAc,MAAM,GAAG;AAAA,UACrD;AAAA,QACF,OAAO;AACL,gBAAM,KAAK,0BAA0B;AAAA,QACvC;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,UAAI,KAAK,cAAc,GAAG;AACxB,cAAM,KAAK,yCAAyC;AAAA,MACtD,OAAO;AACL,cAAM,KAAK,4CAA4C;AAAA,MACzD;AAEA,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AACF;AAEA,SAAS,4BAA4B,KAAsB,OAAyC;AAClG,QAAM,YAAY,IAAI,IAAI,KAAK;AAC/B,QAAM,QAAQ,CAAC,GAAG,KAAK;AAEvB,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,UAAU,MAAM,MAAM;AAC5B,eAAW,QAAQ,IAAI,aAAa,OAAO,GAAG;AAC5C,UAAI,CAAC,UAAU,IAAI,IAAI,GAAG;AACxB,kBAAU,IAAI,IAAI;AAClB,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGO,IAAM,8BAAN,MAAkC;AAAA,EACtB;AAAA,EACT,kBAAgC,aAAa,MAAM;AAAA,EAC1C,cAAc,oBAAI,IAAgB;AAAA,EAC3C,cAAc;AAAA,EACL,qBAAqB,oBAAI,IAA2B;AAAA,EAC7D,mBAA4C,OAAO;AAAA,EAE3D,YAAY,KAAe;AACzB,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,eAAe,SAA6B;AAC1C,SAAK,kBAAkB;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,QAA4B;AACxC,eAAW,KAAK,OAAQ,MAAK,YAAY,IAAI,CAAC;AAC9C,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,KAAmB;AAC5B,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,qBAAqB,QAAuC;AAC1D,eAAW,MAAM,OAAQ,MAAK,mBAAmB,IAAI,EAAE;AACvD,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB,MAAqC;AACnD,SAAK,mBAAmB;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,QAA8B;AAC5B,QAAI,KAAK,YAAY,SAAS,GAAG;AAC/B,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,WAAO,qBAAqB;AAAA,MAC1B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;;;AChVA,IAAM,eAAe,uBAAO,0BAA0B;AA6C/C,IAAM,kBAAN,MAAsB;AAAA;AAAA,EAElB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAGT,YACE,KACA,gBACA,UACA,SACA,MACA,WACA,aACA,qBACA;AACA,QAAI,QAAQ,aAAc,OAAM,IAAI,MAAM,mDAAmD;AAC7F,SAAK,iBAAiB;AACtB,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,OAAO,UAAkC;AACvC,WAAO,IAAI,uBAAuB;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAuB;AACrB,UAAM,OAAO,oBAAI,IAAwB;AACzC,UAAM,MAAM,CAAC,MAAwB;AACnC,UAAI,CAAC,KAAK,IAAI,EAAE,IAAI,EAAG,MAAK,IAAI,EAAE,MAAM,CAAC;AAAA,IAC3C;AACA,eAAW,KAAK,KAAK,eAAe,iBAAiB,EAAG,KAAI,CAAC;AAC7D,eAAW,KAAK,KAAK,SAAU,GAAE,OAAO,QAAQ,GAAG;AACnD,eAAW,KAAK,KAAK,QAAS,GAAE,OAAO,QAAQ,GAAG;AAClD,SAAK,KAAK,QAAQ,GAAG;AACrB,eAAW,KAAK,KAAK,UAAW,KAAI,EAAE,MAAM;AAC5C,eAAW,KAAK,KAAK,YAAa,kBAAiB,CAAC,EAAE,QAAQ,GAAG;AACjE,WAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAAA,EAC1B;AAAA;AAAA,EAGA,WAAqB;AACnB,UAAM,QAAQ,CAAC,OAAsC,GAAG,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI;AAClF,UAAM,QAAQ,CAAC,sBAAsB,KAAK,eAAe,SAAS,CAAC,EAAE;AACrE,UAAM,KAAK,KAAK,SAAS,WAAW,IAChC,qBACA,eAAe,KAAK,SAAS,IAAI,OAAK,GAAG,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,UAAU,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AAChH,UAAM,KAAK,KAAK,QAAQ,WAAW,IAC/B,sCACA,oBAAoB,KAAK,QAAQ,IAAI,OAAK,GAAG,EAAE,IAAI,MAAM,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,YAAY,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AAClI,QAAI,KAAK,KAAK,SAAS,EAAG,OAAM,KAAK,WAAW,MAAM,KAAK,IAAI,CAAC,EAAE;AAClE,eAAW,KAAK,KAAK,WAAW;AAC9B,YAAM,KAAK,EAAE,QAAQ,WAAW,IAC5B,oBAAoB,EAAE,OAAO,IAAI,KACjC,oBAAoB,EAAE,OAAO,IAAI,KAAK,MAAM,EAAE,OAAO,CAAC,EAAE;AAAA,IAC9D;AACA,QAAI,KAAK,YAAY,SAAS,GAAG;AAC/B,YAAM,KAAK,8BAA8B,KAAK,YAAY,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IACzF;AACA,UAAM,KAAK,kBAAkB,KAAK,sBAAsB,4BAA4B,cAAc,EAAE;AACpG,WAAO;AAAA,EACT;AACF;AAGO,SAAS,iBAAiB,GAA6B;AAC5D,SAAO;AAAA,IACL,GAAG,EAAE,WAAW,IAAI,OAAK,EAAE,KAAK;AAAA,IAChC,GAAG,EAAE,MAAM,IAAI,OAAK,EAAE,KAAK;AAAA,IAC3B,GAAG,EAAE,WAAW,IAAI,OAAK,EAAE,KAAK;AAAA,IAChC,GAAG,EAAE,OAAO,IAAI,OAAK,EAAE,KAAK;AAAA,IAC5B,GAAG,EAAE,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,yBAAN,MAA6B;AAAA,EAC1B,kBAAgC,aAAa,MAAM;AAAA,EAC1C,YAA4B,CAAC;AAAA,EAC7B,WAA0B,CAAC;AAAA,EAC3B,QAAQ,oBAAI,IAAwB;AAAA,EACpC,aAAyE,CAAC;AAAA,EAC1E,eAA6B,CAAC;AAAA,EACvC,uBAAuB;AAAA,EAK/B,eAAe,KAAoE;AACjF,QAAI,eAAe,cAAc;AAC/B,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,OAAO;AACX,WAAK,kBAAkB,QAAQ,MAAM;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,UAAkB,QAA4B;AACnD,WAAO,KAAK,cAAc,OAAO,OAAO,GAAG,MAAM;AAAA,EACnD;AAAA;AAAA,EAGA,aAAa,QAAgB,QAA4B;AACvD,WAAO,KAAK,cAAc,GAAG,KAAK,GAAG,MAAM;AAAA,EAC7C;AAAA;AAAA,EAGA,cAAc,KAAa,QAAgB,QAA4B;AACrE,QAAI,CAAC,OAAO,UAAU,GAAG,KAAK,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,GAAG;AACvF,YAAM,IAAI;AAAA,QACR,+FACO,GAAG,KAAK,GAAG;AAAA,MACpB;AAAA,IACF;AACA,SAAK,UAAU,KAAK,EAAE,QAAQ,SAAS,QAAQ,kBAAkB,GAAG,KAAK,IAAI,CAAC;AAC9E,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,MAAc,UAAkB,QAA4B;AACjE,WAAO,KAAK,cAAc,MAAM,OAAO,OAAO,GAAG,MAAM;AAAA,EACzD;AAAA;AAAA,EAGA,cAAc,MAAc,KAAa,QAAgB,QAA4B;AACnF,QAAI,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM,wCAAwC;AAC/E,QAAI,KAAK,SAAS,KAAK,OAAK,EAAE,SAAS,IAAI,GAAG;AAC5C,YAAM,IAAI,MAAM,2CAA2C,IAAI,GAAG;AAAA,IACpE;AACA,QAAI,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,KAAK,EAAE,QAAQ,YAAY,OAAO,UAAU,GAAG,MAAM,MAAM,KAAK;AAClG,YAAM,IAAI,MAAM,4BAA4B,IAAI,kDAAkD,GAAG,KAAK,GAAG,EAAE;AAAA,IACjH;AACA,SAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,QAAQ,WAAW,IAAI,GAAG,GAAG,KAAK,IAAI,CAAC;AACnF,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,QAAQ,QAA4B;AAClC,eAAW,KAAK,OAAQ,KAAI,CAAC,KAAK,MAAM,IAAI,EAAE,IAAI,EAAG,MAAK,MAAM,IAAI,EAAE,MAAM,CAAC;AAC7E,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,WAAuB,SAA6B;AAC3D,QAAI,QAAQ,KAAK,WAAW,KAAK,OAAK,EAAE,OAAO,SAAS,OAAO,IAAI;AACnE,QAAI,SAAS,MAAM;AACjB,cAAQ,EAAE,QAAQ,SAAS,oBAAI,IAAI,EAAE;AACrC,WAAK,WAAW,KAAK,KAAK;AAAA,IAC5B;AACA,eAAW,KAAK,QAAS,KAAI,CAAC,MAAM,QAAQ,IAAI,EAAE,IAAI,EAAG,OAAM,QAAQ,IAAI,EAAE,MAAM,CAAC;AACpF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,eAAe,aAAiC;AAC9C,eAAW,KAAK,aAAa;AAC3B,UAAI,KAAK,aAAa,KAAK,OAAK,EAAE,SAAS,EAAE,IAAI,GAAG;AAClD,cAAM,IAAI,MAAM,sDAAsD,EAAE,IAAI,GAAG;AAAA,MACjF;AACA,WAAK,aAAa,KAAK,CAAC;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,mBAAmB,UAAyB;AAC1C,SAAK,uBAAuB;AAC5B,WAAO;AAAA,EACT;AAAA,EAEA,QAAyB;AACvB,WAAO,IAAI;AAAA,MACT;AAAA,MACA,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,SAAS;AAAA,MAClB,CAAC,GAAG,KAAK,QAAQ;AAAA,MACjB,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC;AAAA,MACvB,KAAK,WAAW,IAAI,QAAM,EAAE,QAAQ,EAAE,QAAQ,SAAS,CAAC,GAAG,EAAE,QAAQ,OAAO,CAAC,EAAE,EAAE;AAAA,MACjF,CAAC,GAAG,KAAK,YAAY;AAAA,MACrB,KAAK;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,SAAS,QAA+B,MAA4B;AAC3E,MAAI,OAAO,WAAW,EAAG,OAAM,IAAI,MAAM,oBAAoB,IAAI,iBAAiB;AAClF,QAAM,SAAS,oBAAI,IAAwB;AAC3C,aAAW,KAAK,OAAQ,KAAI,CAAC,OAAO,IAAI,EAAE,IAAI,EAAG,QAAO,IAAI,EAAE,MAAM,CAAC;AACrE,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;;;AC3QA,IAAM,qBAAqB,UAAU,MAAM,IAAI;AAWxC,SAAS,aAAa,KAAe,UAAsC;AAChF,QAAM,SAAS,oBAAI,IAAwB;AAC3C,aAAW,KAAK,IAAI,OAAQ,KAAI,CAAC,OAAO,IAAI,EAAE,IAAI,EAAG,QAAO,IAAI,EAAE,MAAM,CAAC;AACzE,QAAM,QAAQ,IAAI,IAAY,OAAO,KAAK,CAAC;AAC3C,aAAW,KAAK,IAAI,YAAa,OAAM,IAAI,EAAE,IAAI;AACjD,QAAM,QAAQ,CAAC,SAAyB;AACtC,QAAI,MAAM,IAAI,IAAI,GAAG;AACnB,YAAM,IAAI,MAAM,uCAAuC,IAAI,mCAAmC;AAAA,IAChG;AACA,UAAM,IAAI,IAAI;AACd,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,oBAAI,IAA6B;AACrD,QAAM,oBAAoB,oBAAI,IAAwB;AACtD,aAAW,KAAK,SAAS,aAAa;AACpC,gBAAY,IAAI,MAAM,EAAE,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AACrD,eAAW,KAAK,iBAAiB,CAAC,GAAG;AACnC,UAAI,CAAC,OAAO,IAAI,EAAE,IAAI,KAAK,CAAC,kBAAkB,IAAI,EAAE,IAAI,EAAG,mBAAkB,IAAI,EAAE,MAAM,CAAC;AAAA,IAC5F;AAAA,EACF;AAEA,aAAW,CAAC,MAAM,CAAC,KAAK,mBAAmB;AACzC,UAAM,IAAI,IAAI;AACd,WAAO,IAAI,MAAM,CAAC;AAAA,EACpB;AAKA,QAAM,aAAuB,CAAC;AAC9B,QAAM,QAAsB,CAAC;AAC7B,QAAM,QAAQ,CAAC,GAAG,SAAS,OAAO,GAAG,GAAG,SAAS,UAAU,QAAQ,OAAK,EAAE,OAAO,CAAC;AAClF,aAAW,KAAK,OAAO;AACrB,QAAI,OAAO,IAAI,EAAE,IAAI,EAAG;AACxB,eAAW,KAAK,EAAE,IAAI;AACtB,WAAO,IAAI,EAAE,MAAM,CAAC;AACpB,UAAM,KAAK,CAAC;AAAA,EACd;AAEA,QAAM,YAAY,CAAC,MAA8B,OAAO,IAAI,EAAE,IAAI,KAAK;AAEvE,QAAM,iBAA+B,CAAC;AACtC,QAAM,UAAU,aAAa,QAAQ,EAAE,SAAS,SAAS,cAAc;AACvE,QAAM,SAAS,CAAC,OAAe,QAAoB,QAAoB,aAA4B;AACjG,UAAM,OAAO,MAAM,aAAa,WAAW,MAAM,EAAE,IAAI,KAAK,KAAK,OAAO,IAAI,EAAE;AAC9E,mBAAe;AAAA,MACb,WAAW,QAAQ,IAAI,EAAE,OAAO,IAAI,MAAM,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM;AAAA,IAC9F;AACA,gBAAY,IAAI,MAAM,EAAE,MAAM,WAAW,OAAO,OAAO,OAAO,KAAK,CAAC;AAAA,EACtE;AAEA,WAAS,SAAS,QAAQ,CAAC,OAAO,MAAM;AACtC,QAAI,MAAM,MAAM,GAAG;AACjB,YAAM,SAAS,MAAe,MAAM,gBAAgB,CAAC,GAAG,CAAC;AACzD,cAAQ,OAAO,QAAQ,MAAM,GAAG;AAChC,iBAAW,KAAK,MAAM,OAAQ,QAAO,GAAG,QAAQ,UAAU,CAAC,GAAG,KAAK;AAAA,IACrE;AACA,QAAI,MAAM,MAAM,MAAM,KAAK;AACzB,YAAM,SAAS,MAAe,MAAM,gBAAgB,CAAC,GAAG,CAAC;AACzD,cAAQ,OAAO,QAAQ,MAAM,MAAM,MAAM,GAAG;AAC5C,iBAAW,KAAK,MAAM,OAAQ,QAAO,GAAG,QAAQ,UAAU,CAAC,GAAG,IAAI;AAClE,YAAM,OAAO,MAAM,eAAe,CAAC,GAAG;AACtC,qBAAe,KAAK,WAAW,QAAQ,IAAI,EAAE,OAAO,IAAI,MAAM,CAAC,EAAE,MAAM,CAAC;AACxE,kBAAY,IAAI,MAAM,EAAE,MAAM,WAAW,OAAO,EAAE,CAAC;AAAA,IACrD;AAAA,EACF,CAAC;AAID,QAAM,cAAc,IAAI,IAAI,SAAS,YAClC,OAAO,OAAK,EAAE,eAAe,QAAQ,cAAc,EAAE,MAAM,CAAC,EAC5D,IAAI,OAAK,EAAE,IAAI,CAAC;AACnB,QAAM,SAAS,SAAS,QAAQ,GAAG,IAAI,IAAI,cAAc,EACtD,OAAO,GAAG,IAAI,QAAQ,GAAG,KAAK,EAC9B,YAAY,GAAG,IAAI,aAAa,GAAG,SAAS,aAAa,GAAG,cAAc,EAC1E,MAAM,EACN,wBAAwB,UAAS,YAAY,IAAI,IAAI,IAAI,qBAAqB,IAAK;AACtF,SAAO;AAAA,IACL,KAAK;AAAA,IACL,gBAAgB,QAAQ,MAAM;AAAA,IAC9B;AAAA,IACA,mBAAmB,CAAC,GAAG,kBAAkB,OAAO,CAAC;AAAA,IACjD;AAAA,EACF;AACF;;;ACrHO,SAAS,kBAAkB,UAA2B,QAAoC;AAC/F,QAAM,QAAQ,oBAAI,IAAwB;AAC1C,aAAW,KAAK,SAAS,QAAS,YAAW,KAAK,EAAE,OAAQ,KAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAG,OAAM,IAAI,EAAE,MAAM,CAAC;AACvG,aAAW,KAAK,SAAS,KAAM,KAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAG,OAAM,IAAI,EAAE,MAAM,CAAC;AAC1E,aAAW,KAAK,OAAO,kBAAmB,KAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAG,OAAM,IAAI,EAAE,MAAM,CAAC;AACrF,SAAO;AAAA,IACL,OAAO,IAAI,IAAI,MAAM,OAAO,CAAC;AAAA,IAC7B,aAAa,SAAS,UAAU,IAAI,QAAM,EAAE,QAAQ,EAAE,QAAQ,QAAQ,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE;AAAA,EAC7F;AACF;AAGO,SAAS,cAAc,UAAyC;AACrE,SAAO,SAAS,UAAU,IAAI,OAAK,EAAE,MAAM;AAC7C;AAOO,SAAS,cAAc,GAAiB,MAAqC;AAClF,SAAO,eAAe,GAAG,KAAK,OAAO,KAAK,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,kBAAkB,EAAE,MAAM,EAAE,IAAI,CAAC;AACzG;AAMO,SAAS,mBAAmB,GAAiB,UAA2B,MAAkC;AAC/G,QAAM,WAAsB,CAAC;AAE7B,QAAM,UAAU,cAAc,QAAQ;AACtC,aAAW,UAAU,SAAS,SAAS;AACrC,UAAM,QAAQ,eAAe,GAAG,OAAO,QAAQ,OAAO,KAAK,OAAO,KAAK,OAAO;AAC9E,QAAI,UAAU,KAAM,UAAS,KAAK,EAAE,MAAM,UAAU,QAAQ,OAAO,aAAa,GAAG,OAAO,MAAM,GAAG,MAAM,CAAC;AAAA,EAC5G;AACA,aAAWA,UAAS,cAAc,GAAG,IAAI,GAAG;AAC1C,aAAS,KAAK,EAAE,MAAM,YAAY,OAAOA,OAAM,MAAM,OAAO,EAAE,OAAOA,MAAK,EAAE,CAAC;AAAA,EAC/E;AACA,SAAO;AACT;AAGO,SAAS,UAAU,GAAoB;AAC5C,SAAO,EAAE,SAAS,WAAW,EAAE,OAAO,OAAO,EAAE;AACjD;AAGO,SAAS,gBAAgB,GAAoB;AAClD,MAAI,EAAE,SAAS,YAAY;AACzB,WAAO,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK;AAAA,EACpC;AACA,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,WAAW,YAAY,OAAO,KAAK,OAAO,KAAK,OAAO,MAAM;AAClE,SAAO,EAAE,UAAU,UACf,GAAG,QAAQ,yBAAyB,EAAE,KAAK,iDAC3C,GAAG,QAAQ,yBAAyB,EAAE,KAAK;AACjD;;;ACGO,SAAS,kBACd,QACA,cACA,WACmB;AACnB,QAAM,EAAE,aAAa,SAAS,IAAI;AAClC,QAAM,YAAwB,CAAC;AAC/B,MAAI,SAAS,WAAW,YAAY,SAAS,GAAG;AAC9C,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,YAAM,SAAS,SAAS,CAAC;AACzB,YAAM,QAAQ,SAAS,IAAI,CAAC;AAC5B,YAAM,UAAwB,CAAC;AAC/B,iBAAW,KAAK,cAAc;AAC5B,cAAM,QAAQ,MAAM,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC;AAC/C,YAAI,UAAU,EAAG,SAAQ,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAAA,MACxD;AACA,YAAM,MAAM,OAAO,YAAY,IAAI,YAAY,CAAC,CAAE;AAClD,UAAI,QAAQ,SAAS,KAAK,QAAQ,QAAW;AAC3C,kBAAU,KAAK,EAAE,MAAM,IAAI,GAAG,YAAY,YAAY,CAAC,GAAI,aAAa,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAAA,MACtG;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,GAAG,WAAW,UAAU;AACnC;;;ACpFO,SAAS,cACd,QACA,UACA,YACA,cACmB;AACnB,QAAM,QAAQ,gBAAgB;AAAA,IAC5B,OAAO;AAAA,IAAK,OAAO;AAAA,IAAgB;AAAA,IAAY;AAAA,IAAW;AAAA,IAAW,EAAE,SAAS,KAAK;AAAA,EACvF;AACA,QAAM,UAAU,MAAM,aAAa;AACnC,QAAM,OAAO,kBAAkB,UAAU,MAAM;AAC/C,QAAM,OAAO,QAAQ,KAAK;AAG1B,QAAM,QAAQ,oBAAI,IAAsD;AACxE,aAAW,MAAM,SAAS;AAExB,QAAI,GAAG,mBAAmB,SAAS,EAAG;AACtC,eAAW,WAAW,mBAAmB,GAAG,SAAS,UAAU,IAAI,GAAG;AACpE,YAAM,MAAM,GAAG,QAAQ,IAAI,IAAI,UAAU,OAAO,CAAC;AACjD,UAAI,CAAC,MAAM,IAAI,GAAG,EAAG,OAAM,IAAI,KAAK,EAAE,SAAS,QAAQ,GAAG,CAAC;AAAA,IAC7D;AAAA,EACF;AAGA,QAAM,cAAc,IAAI,IAAI,SAAS,QAAQ,IAAI,CAAC,GAAG,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACvE,QAAM,OAAO,CAAC,MACZ,EAAE,SAAS,WAAW,YAAY,IAAI,EAAE,OAAO,IAAI,IAAK,SAAS,QAAQ;AAC3E,QAAM,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAC9E,kBAAkB,UAAU,EAAE,OAAO,GAAG,UAAU,EAAE,OAAO,CAAC,CAAC;AAElE,QAAM,aAAkC,QAAQ,IAAI,CAAC,EAAE,SAAS,OAAO,MAAM;AAC3E,UAAM,OAAO,OAAO,MAAM,MAAM;AAChC,WAAO,kBAAkB,QAAQ,cAAc;AAAA,MAC7C,MAAM,QAAQ;AAAA,MACd,SAAS,UAAU,OAAO;AAAA,MAC1B,QAAQ,gBAAgB,OAAO;AAAA,MAC/B,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK,QAAQ,IAAI,OAAK,EAAE,OAAO;AAAA,MACzC,YAAY;AAAA,MACZ,WAAW;AAAA,IACb,CAAC;AAAA,EACH,CAAC;AAED,MAAI,SAAS,qBAAqB;AAChC,UAAM,QAAQ,UAAU,OAAO,IAAI;AACnC,QAAI,UAAU,KAAM,YAAW,KAAK,kBAAkB,QAAQ,cAAc,KAAK,CAAC;AAAA,EACpF;AACA,SAAO,EAAE,UAAU,MAAM,WAAW,GAAG,YAAY,QAAQ,QAAQ,WAAW;AAChF;AAQA,SAAS,QAAQ,OAAmD;AAClE,QAAM,OAAO,oBAAI,IAA0B;AAC3C,QAAM,OAAO,oBAAI,IAAgB,CAAC,MAAM,YAAY,CAAC;AACrD,QAAM,QAAsB,CAAC,MAAM,YAAY;AAC/C,WAAS,OAAO,GAAG,OAAO,MAAM,QAAQ,QAAQ;AAC9C,UAAM,UAAU,MAAM,IAAI;AAC1B,eAAW,CAAC,YAAY,KAAK,KAAK,MAAM,oBAAoB,OAAO,GAAG;AACpE,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,IAAI,KAAK,MAAM,EAAG;AAC3B,aAAK,IAAI,KAAK,MAAM;AACpB,aAAK,IAAI,KAAK,QAAQ,EAAE,QAAQ,SAAS,KAAK,WAAW,KAAK,CAAC;AAC/D,cAAM,KAAK,KAAK,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,OAAO,MAAiC,QAAsE;AACrH,QAAM,UAAwB,CAAC;AAC/B,QAAM,cAAwB,CAAC;AAC/B,WAAS,MAA8B,QAAQ,QAAQ,UAAY;AACjE,YAAQ,KAAK,GAAG;AAChB,UAAM,OAAO,KAAK,IAAI,GAAG;AACzB,QAAI,SAAS,OAAW;AACxB,gBAAY,KAAK,KAAK,GAAG;AACzB,UAAM,KAAK;AAAA,EACb;AACA,SAAO,EAAE,SAAS,QAAQ,QAAQ,GAAG,aAAa,YAAY,QAAQ,EAAE;AAC1E;AAcA,SAAS,UACP,OACA,MAC6C;AAC7C,QAAM,UAAU,CAAC,OAAsD;AACrE,UAAM,MAAyC,CAAC;AAChD,eAAW,CAAC,GAAG,KAAK,KAAK,MAAM,oBAAoB,EAAE,EAAG,YAAW,KAAK,MAAO,KAAI,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC;AAC1G,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,oBAAI,IAAwB,CAAC,CAAC,MAAM,cAAc,CAAC,CAAC,CAAC;AACtE,QAAM,QAAiB,CAAC,EAAE,MAAM,MAAM,cAAc,OAAO,QAAQ,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,KAAK,CAAC;AAC5G,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,MAAM,MAAM,MAAM,SAAS,CAAC;AAClC,QAAI,IAAI,QAAQ,IAAI,MAAM,QAAQ;AAChC,eAAS,IAAI,IAAI,MAAM,EAAE;AACzB,YAAM,IAAI;AACV;AAAA,IACF;AACA,UAAM,CAAC,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,MAAM;AAC1C,UAAM,KAAK,SAAS,IAAI,MAAM;AAC9B,QAAI,OAAO,QAAW;AACpB,eAAS,IAAI,QAAQ,MAAM,MAAM;AACjC,YAAM,KAAK,EAAE,MAAM,QAAQ,OAAO,QAAQ,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAAA,IACnE,WAAW,MAAM,GAAG;AAElB,YAAM,OAAO,MAAM,MAAM,EAAE;AAC3B,YAAM,OAAO,OAAO,MAAM,MAAM;AAChC,YAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,CAAC,EAAE,IAAI,OAAK,EAAE,GAAI,GAAG,GAAG;AACrD,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ,oBAAoB,MAAM,KAAK,UAAK,CAAC;AAAA,QAC7C,aAAa,CAAC,GAAG,KAAK,aAAa,GAAG,KAAK;AAAA,QAC3C,UAAU,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAK,EAAE,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC,EAAE,IAAI,OAAK,EAAE,KAAK,OAAO,GAAG,OAAO,OAAO;AAAA,QACzG,YAAY,KAAK,YAAY;AAAA,QAC7B,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACnJO,SAAS,aAAa,OAA4B;AACvD,QAAM,EAAE,KAAK,QAAQ,UAAU,OAAO,UAAU,SAAS,WAAW,IAAI;AACxE,QAAM,QAAkB,CAAC,oDAAoD,EAAE;AAC/E,QAAM,KAAK,QAAQ,IAAI,IAAI,eAAe,OAAO,YAAY,IAAI,iCACvD,SAAS,SAAS,MAAM,iBAAiB;AACnD,QAAM,KAAK,aAAa,GAAG,SAAS,SAAS,CAAC;AAC9C,MAAI,OAAO,WAAW,SAAS,GAAG;AAChC,UAAM,KAAK,4BAA4B,OAAO,WAAW,KAAK,IAAI,CAAC,oDAAoD;AAAA,EACzH;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,UAAU,MAAM;AAClB,UAAM,KAAK,+BAA+B,MAAM,gBAAgB,gBAAgB,GAAG;AAAA,EACrF,OAAO;AACL,UAAM,KAAK,qDAAqD;AAChE,UAAM,KAAK,MAAM,WACb,cAAc,MAAM,UAAU,aAC9B,cAAc,MAAM,UAAU,sCAAsC,MAAM,UAAU,EAAE;AAAA,EAC5F;AACA,MAAI,aAAa,MAAM;AACrB,UAAM,KAAK,IAAI,qBAAqB,GAAG,QAAQ;AAAA,EACjD;AAEA,QAAM,KAAK,IAAI,gBAAgB;AAC/B,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,YAAM,KAAK,qDAAqD,SAAS,sBAAsB,iCAAiC,EAAE,KAAK,QAAQ,MAAM,GAAG;AACxJ;AAAA,IACF,KAAK;AACH,YAAM,KAAK,YAAY,QAAQ,MAAM,EAAE;AACvC;AAAA,IACF,KAAK;AACH,YAAM,KAAK,aAAa,WAAW,MAAM,IAAI,WAAW,WAAW,IAAI,SAAS,OAAO,yBAAyB;AAChH,iBAAW,KAAK,WAAY,OAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC;AAC5D;AAAA,EACJ;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,gBAAgB,GAAgC;AACvD,QAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,IAAI,KAAK,EAAE,MAAM,EAAE;AACxD,MAAI,CAAC,EAAE,UAAW,OAAM,KAAK,gFAAiF;AAC9G,MAAI,EAAE,UAAU,SAAS,GAAG;AAC1B,UAAM,KAAK,iBAAiB;AAC5B,eAAW,KAAK,EAAE,WAAW;AAC3B,UAAI,EAAE,eAAe,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAG,OAAM,KAAK,mCAAmC;AACxG,YAAM,MAAM,EAAE,gBAAgB,OAAO,KACjC,EAAE,gBAAgB,eAAe,mBAAmB,iBAAiB,EAAE,WAAW;AACtF,YAAM,UAAU,EAAE,QAAQ,IAAI,OAAK,GAAG,EAAE,KAAK,IAAI,EAAE,QAAQ,IAAI,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI;AAC9F,YAAM,KAAK,SAAS,EAAE,IAAI,KAAK,EAAE,UAAU,GAAG,GAAG,GAAG,QAAQ,SAAS,IAAI,KAAK,OAAO,KAAK,EAAE,EAAE;AAAA,IAChG;AAAA,EACF;AACA,MAAI,EAAE,eAAe,MAAM;AACzB,UAAM,OAAO,EAAE,YAAY,MAAM,GAAG,EAAE,UAAU;AAChD,UAAM,QAAQ,kBAAkB,EAAE,YAAY,MAAM,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;AAC5E,UAAM,KAAK,wBAAwB,KAAK,WAAW,IAAI,QAAQ,GAAG,KAAK,KAAK,IAAI,CAAC,KAAK,KAAK,EAAE,EAAE;AAAA,EACjG,WAAW,EAAE,YAAY,SAAS,GAAG;AACnC,UAAM,KAAK,wBAAwB,EAAE,YAAY,KAAK,IAAI,CAAC,EAAE;AAAA,EAC/D;AACA,QAAM,OAAO,EAAE,SAAS,GAAG,EAAE;AAC7B,MAAI,SAAS,OAAW,OAAM,KAAK,OAAO,EAAE,SAAS,gBAAgB,yBAAyB,mBAAmB,KAAK,KAAK,SAAS,CAAC,EAAE;AACvI,SAAO;AACT;;;AChBA,eAAsB,aACpB,QACA,UACA,cACA,WACA,sBAC0B;AAC1B,QAAM,aAAkC,CAAC;AACzC,QAAM,YAAsB,CAAC;AAC7B,QAAM,QAAkB,CAAC;AACzB,QAAM,eAAqC,CAAC;AAC5C,QAAM,MAAM,QAAQ,OAAO,GAAG;AAC9B,aAAW,QAAQ,SAAS,QAAQ,QAAQ,GAAG;AAC7C,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,MAAM,4BAA4B;AACzE;AAAA,IACF;AACA,UAAM,IAAI,KAAK;AACf,QAAI,WAAW,YAAY,OAAO,GAAG,EAClC,eAAe,OAAO,cAAc,EACpC,SAAS,EAAE,QAAQ,EACnB,WAAW,GAAG,EAAE,KAAK,EAErB,sBAAsB,CAAC;AAC1B,eAAW,KAAK,EAAE,YAAa,YAAW,SAAS,eAAe,EAAE,QAAQ,GAAG,EAAE,MAAM;AACvF,UAAM,SAAS,MAAM,UAAU,QAAQ,EAAE,OAAO;AAChD,UAAM,UAAU,OAAO;AACvB,UAAM,KAAK,MAAM,EAAE,OAAO,KAAK,oBAAoB,EAAE,QAAQ,CAAC,KAAK,QAAQ,IAAI,MAC1E,QAAQ,SAAS,YAAY,KAAK,QAAQ,MAAM,MAAM,GAAG;AAC9D,QAAI,QAAQ,SAAS,UAAW,WAAU,KAAK,GAAG,EAAE,OAAO,KAAK,QAAQ,MAAM,EAAE;AAAA,aACvE,QAAQ,SAAS,WAAY,YAAW,KAAK,kBAAkB,QAAQ,cAAc,EAAE,WAAW,MAAM,CAAC,CAAC;AAAA,aAE1G,QAAQ,uBAAuB,MAAM;AAC5C,mBAAa,KAAK,EAAE,SAAS,EAAE,SAAS,WAAW,QAAQ,mBAAmB,CAAC;AAAA,IACjF;AAAA,EACF;AACA,MAAI,SAAS,qBAAqB;AAChC,UAAM,cAAc,MAAM,qBAAqB,QAAQ,oBAAoB;AAC3E,QAAI,YAAY,QAAQ;AACtB,YAAM,KAAK,2CAA2C,YAAY,MAAM,EAAE;AAAA,IAC5E,OAAO;AACL,YAAM,KAAK,sDAAsD,YAAY,MAAM,GAAG;AACtF,gBAAU,KAAK,gBAAgB,YAAY,MAAM,EAAE;AAAA,IACrD;AAAA,EACF;AACA,SAAO,EAAE,YAAY,WAAW,OAAO,aAAa;AACtD;AAOA,SAAS,QAAQ,KAAyB;AACxC,MAAI,UAAU,GAAG,EAAG,QAAO;AAC3B,QAAM,cAAc,CAAC,GAAG,IAAI,WAAW,EAAE,IAAI,OAAK;AAChD,QAAI,EAAE,OAAO,SAAS,YAAa,QAAO;AAC1C,UAAM,IAAI,WAAW,QAAQ,EAAE,IAAI,EAAE,OAAO,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM;AACjG,QAAI,EAAE,eAAe,KAAM,GAAE,QAAQ,EAAE,UAAU;AACjD,eAAW,OAAO,EAAE,WAAY,GAAE,UAAU,IAAI,KAAK;AACrD,eAAW,OAAO,EAAE,MAAO,GAAE,KAAK,IAAI,KAAK;AAC3C,eAAW,OAAO,EAAE,OAAQ,GAAE,MAAM,IAAI,KAAK;AAC7C,QAAI,EAAE,cAAc,KAAM,GAAE,MAAM,EAAE,SAAS;AAC7C,WAAO,EAAE,MAAM;AAAA,EACjB,CAAC;AACD,SAAO,SAAS,QAAQ,IAAI,IAAI,EAAE,OAAO,GAAG,IAAI,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,MAAM;AAC5F;AAEA,SAAS,SAAS,QAAmB,UAAmC;AACtE,QAAM,OAAO,kBAAkB,UAAU,MAAM;AAC/C,QAAM,UAAU,cAAc,QAAQ;AAEtC,QAAM,mBAAmB,CAAC,WACxB,OAAO,4BAA4B,OAAO,OAAO,oBAAoB,GAAG,EAAE,IAAI;AAChF,QAAM,UAAU,CAAC,YAAmC;AAAA,IAClD,aAAa,CAAC,GAAG,OAAO,yBAAyB;AAAA,IACjD,UAAU,CAAC,GAAG,OAAO,mBAAmB;AAAA,IACxC,YAAY;AAAA,IACZ,WAAW,OAAO,4BAA4B;AAAA,EAChD;AAEA,QAAM,YAAmB;AAAA,IACvB,SAAS;AAAA,IACT,UAAU,aAAa;AAAA,IACvB,OAAO,CAAC,GAAG,KAAK,KAAK;AAAA,IACrB,aAAa,KAAK;AAAA,IAClB,YAAY,YAAU;AAEpB,YAAM,OAAO,iBAAiB,MAAM;AACpC,YAAM,WAAW,SAAS,SAAY,CAAC,IAAI,cAAc,MAAM,IAAI,EAAE,IAAI,OAAK,EAAE,IAAI;AACpF,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,SAAS,WAAW,IAAI,cAAc,SAAS,KAAK,IAAI;AAAA,QACjE,QAAQ,SAAS,WAAW,IACxB,yGACA,GAAG,SAAS,KAAK,IAAI,CAAC,IAAI,SAAS,WAAW,IAAI,UAAU,MAAM;AAAA,QACtE,GAAG,QAAQ,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAgB,CAAC,EAAE,MAAM,SAAS,OAAO,UAAU,CAAC;AAE1D,aAAW,UAAU,SAAS,SAAS;AACrC,UAAM,SAAS,YAAY,OAAO,KAAK,OAAO,KAAK,OAAO,MAAM;AAChE,QAAI,OAAO,QAAQ,KAAK,OAAO,QAAQ,UAAU;AAC/C,YAAM,KAAK,EAAE,MAAM,WAAW,SAAS,OAAO,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC;AACvF;AAAA,IACF;AACA,UAAM,QAAe;AAAA,MACnB,SAAS,OAAO;AAAA,MAChB,UAAU,eAAe,OAAO,QAAQ,OAAO,KAAK,OAAO,KAAK,OAAO;AAAA,MACvE,OAAO,CAAC;AAAA,MACR,aAAa,CAAC;AAAA,MACd,YAAY,YAAU;AACpB,cAAM,OAAO,iBAAiB,MAAM;AACpC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,OAAO;AAAA,UAChB,QAAQ,SAAS,SACb,GAAG,MAAM,oEACT,GAAG,MAAM,yBAAyB,aAAa,MAAM,OAAO,MAAM,CAAC;AAAA,UACvE,GAAG,QAAQ,MAAM;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,EAAE,MAAM,SAAS,MAAM,CAAC;AAAA,EACrC;AACA,SAAO;AACT;AAGA,eAAe,qBACb,QACA,WACmH;AACnH,QAAM,OAAO,QAAQ,OAAO,GAAG;AAC/B,QAAM,UAAU,KAAK,OAAO,IAAI,OAAK,OAAO,eAAe,OAAO,CAAC,CAAC;AACpE,MAAI;AACJ,MAAI;AACF,aAAS,UAAU;AAAA,EACrB,SAAS,GAAG;AACV,QAAI,aAAa,cAAe,QAAO,EAAE,QAAQ,OAAO,QAAQ,EAAE,QAAQ;AAC1E,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,OAAO,WAA4C;AAC7D,QAAI;AACF,YAAM,QAAQ,MAAM,UAAU,QAAQ,QAAQ,WAAW,WAAW,CAAC,CAAC;AACtE,YAAM,SAAS,UAAU,MAAM,MAAM;AACrC,UAAI,WAAW,SAAS,WAAW,WAAW,WAAW,UAAW,QAAO,MAAM;AACjF,aAAO,IAAI,MAAM,cAAc,OAAO,cAAc,SAAS,CAAC,CAAC;AAAA,IACjE,SAAS,GAAG;AACV,gCAA0B,CAAC;AAC3B,aAAO,IAAI,MAAM,OAAQ,GAAa,WAAW,CAAC,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,gBAAgB,MAAM,SAAS,GAAG;AACxD,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ,yBAAyB,QAAQ,MAAM,KAAK,aAAa,cAAc,MAAM,QAAQ,KAAK,CAAC;AAAA,MACrG;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ,QAAQ,eAAe,OAC3B,qDACA,8CAA8C,QAAQ,WAAW,IAAI,OAAK,KAAK,YAAY,CAAC,EAAG,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,MACrH;AAAA,IACF,KAAK;AACH,aAAO,EAAE,QAAQ,OAAO,QAAQ,qDAAqD;AAAA,IACvF,KAAK;AACH,aAAO,EAAE,QAAQ,OAAO,QAAQ,0CAA0C;AAAA,IAC5E,KAAK;AACH,aAAO,EAAE,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,EACnD;AACF;AAEA,SAAS,UAAU,QAAwB;AACzC,SAAO,OAAO,MAAM,IAAI,EAAE,KAAK,UAAQ,KAAK,KAAK,MAAM,EAAE,GAAG,KAAK,KAAK;AACxE;;;AChOA,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAC3B,IAAM,aAAa;AACnB,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AAczB,eAAsB,cACpB,KACA,UACA,UAA0B,CAAC,GACH;AACxB,QAAM,QAAQ,YAAY,IAAI;AAC9B,QAAM,SAAS,aAAa,KAAK,QAAQ;AACzC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,SAAS,QAAQ,OAAO;AAE9B,QAAM,eAAe,SAAS,OAAO;AAIrC,QAAM,eAAe,CAAC,GAAG,OAAO,IAAI,WAAW,EAAE,KAAK,OAAK,EAAE,cAAc,IAAI,IAC3E,mBACA,aAAa,IAAI,OAAO;AAC5B,QAAM,QAAQ,iBAAiB,OAAO,cAAc,QAAQ,UAAU,YAAY,YAAY,IAAI;AAElG,QAAM,SAAS,CACb,SACA,OACA,YACA,cACmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,OAAO,cAAc;AAAA,IACjC,eAAe,OAAO,YAAY;AAAA,IAClC,QAAQ,aAAa,EAAE,KAAK,QAAQ,UAAU,YAAY,OAAO,cAAc,UAAU,SAAS,WAAW,CAAC;AAAA,IAC9G,WAAW,OAAO;AAAA,IAClB,eAAe,OAAO;AAAA,IACtB,WAAW,YAAY,IAAI,IAAI;AAAA,EACjC;AAEA,MAAI,UAAU,MAAM;AAClB,QAAI,MAAM,WAAW,SAAS,GAAG;AAC/B,aAAO,OAAO,EAAE,MAAM,WAAW,GAAG,eAAe,MAAM,YAAY,IAAI;AAAA,IAC3E;AACA,QAAI,MAAM,UAAU;AAElB,aAAO,OAAO,EAAE,MAAM,UAAU,QAAQ,oBAAoB,oBAAoB,KAAK,GAAG,eAAe,CAAC,GAAG,IAAI;AAAA,IACjH;AAAA,EACF;AACA,QAAM,MAAM,UAAU,OAClB,8CAA8C,UAAU,aACxD,iBAAiB,oBACf,sCACA,sCAAsC,YAAY;AACxD,MAAI,CAAC,QAAQ;AACX,WAAO,OAAO,EAAE,MAAM,WAAW,QAAQ,GAAG,GAAG,kCAAkC,GAAG,eAAe,CAAC,GAAG,IAAI;AAAA,EAC7G;AAEA,QAAM,MAAM,MAAM;AAAA,IAChB;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAc,QAAQ,iBAAiB,OAAK;AAAA,IAAI,QAAQ,wBAAwB;AAAA,EACpG;AACA,MAAI,IAAI,WAAW,SAAS,EAAG,QAAO,OAAO,EAAE,MAAM,WAAW,GAAG,OAAO,IAAI,YAAY,IAAI,KAAK;AACnG,MAAI,IAAI,UAAU,WAAW,GAAG;AAC9B,WAAO;AAAA,MACL,EAAE,MAAM,UAAU,QAAQ,YAAY,oBAAoB,oBAAoB,IAAI,YAAY,EAAE;AAAA,MAChG;AAAA,MAAO,CAAC;AAAA,MAAG,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AAAA,IACL,EAAE,MAAM,WAAW,QAAQ,GAAG,GAAG,sCAAsC,IAAI,UAAU,KAAK,IAAI,CAAC,GAAG;AAAA,IAClG;AAAA,IAAO,CAAC;AAAA,IAAG,IAAI;AAAA,EACjB;AACF;AAMA,SAAS,oBAAoB,cAA4D;AACvF,MAAI,aAAa,WAAW,EAAG,QAAO;AACtC,SAAO,aAAa,IAAI,OAAK,IAAI,EAAE,OAAO,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,IAAI;AACzE;","names":["place"]}
@@ -5,7 +5,7 @@ import {
5
5
  colorForPrefix,
6
6
  discoverClusters,
7
7
  mount
8
- } from "../chunk-BPGE7GZR.js";
8
+ } from "../chunk-5LE2M5PW.js";
9
9
  export {
10
10
  DEFAULT_PANZOOM_OPTS,
11
11
  VERSION,
@@ -6354,7 +6354,7 @@ textContent??"").replace(/^cluster_/,"");Mn.classList.toggle("is-hidden",!N.has(
6354
6354
  en",!bn.has(v))}if(!Q)for(let Mn of Array.from(P.querySelectorAll("g.node.petri-replica")))Mn.classList.add("is-hidden");let Sn=new Map;for(let Mn of Array.from(P.querySelectorAll("g.node"))){let v=Mn.getAttribute("data-id");v&&Sn.set(v,Mn)}for(let Mn of Array.from(P.querySelectorAll("g.edge"))){let v=Mn.getAttribute("data-src")??"",Vn=Mn.getAttribute("data-dst")??"",te=Sn.get(v)?.classList.contains(
6355
6355
  "is-hidden")??!1,pe=Sn.get(Vn)?.classList.contains("is-hidden")??!1;Mn.classList.toggle("is-hidden",te||pe)}}var Pfe=["--lpv-bg","--lpv-header-bg","--lpv-border","--lpv-text","--lpv-muted","--lpv-cluster-bg","--lpv-cluster-bg-collapsed","--lpv-cluster-stroke-width","--lpv-cluster-stroke-dash","--lpv-cluster-fill-tint","--lpv-dim-opacity","--lpv-active-filter-outline","--lpv-legend-bg","--lpv-chip-bg","--lpv-chip-active-bg","--lpv-sidebar-bg","--lpv-sidebar-border","--lpv-sidebar-text","--lpv-sidebar-mute\
6356
6356
  d","--lpv-sidebar-chip-bg","--lpv-sidebar-chip-hover-bg","--lpv-sidebar-chip-off-opacity","--lpv-shared-glyph-color","--lpv-replica-fill","--lpv-replica-stroke","--lpv-highlight-stroke","--lpv-highlight-glow","--lpv-neighbor-stroke","--lpv-faded-node-opacity","--lpv-faded-edge-opacity","--lpv-faded-cluster-opacity"];var XPe=/^\s*subgraph\s+cluster_[A-Za-z0-9_]+\s*\{\s*$/,KPe=/^\s*\}\s*$/;function Cfe(P){let O=P.split("\n"),N=[],Q=0;for(let bn of O){if(XPe.test(bn)){Q++;continue}if(Q>0){if(KPe.test(bn)){Q--;continue}(bn.includes("[")||bn.includes("->"))&&N.push(_fe(bn));continue}if(bn.includes("->")&&(bn.includes("ltail=")||bn.includes("lhead="))){N.push(_fe(bn));continue}N.push(bn)}return N.join("\n")}function _fe(P){
6357
- return P.replace(/,\s*ltail="cluster_[^"]*"/g,"").replace(/,\s*lhead="cluster_[^"]*"/g,"").replace(/\[\s*ltail="cluster_[^"]*"\s*,\s*/g,"[").replace(/\[\s*lhead="cluster_[^"]*"\s*,\s*/g,"[").replace(/\[\s*ltail="cluster_[^"]*"\s*\]/g,"[]").replace(/\[\s*lhead="cluster_[^"]*"\s*\]/g,"[]")}var Ofe="5.1.0";async function ale(P,O,N={}){let Q=N.previousHandle??null,bn=Q?new Set(Q.collapsedPrefixes):new Set,Sn=Q?.activeFilter??null,Mn=N.subnets??Q?.subnets??"show";Q&&Q.dispose();let v=await Promise.resolve().then(()=>(lle(),fle)),Vn=(N.layout??"elk")==="elk",te=Mn==="hide"?Cfe(P):P,pe={clusterLayout:N.clusterLayout,leafPacking:N.leafPacking},Fe=Vn?await v.renderDotToSvgWithElkLayout(te,pe):await v.renderDotToSvg(
6357
+ return P.replace(/,\s*ltail="cluster_[^"]*"/g,"").replace(/,\s*lhead="cluster_[^"]*"/g,"").replace(/\[\s*ltail="cluster_[^"]*"\s*,\s*/g,"[").replace(/\[\s*lhead="cluster_[^"]*"\s*,\s*/g,"[").replace(/\[\s*ltail="cluster_[^"]*"\s*\]/g,"[]").replace(/\[\s*lhead="cluster_[^"]*"\s*\]/g,"[]")}var Ofe="6.0.0";async function ale(P,O,N={}){let Q=N.previousHandle??null,bn=Q?new Set(Q.collapsedPrefixes):new Set,Sn=Q?.activeFilter??null,Mn=N.subnets??Q?.subnets??"show";Q&&Q.dispose();let v=await Promise.resolve().then(()=>(lle(),fle)),Vn=(N.layout??"elk")==="elk",te=Mn==="hide"?Cfe(P):P,pe={clusterLayout:N.clusterLayout,leafPacking:N.leafPacking},Fe=Vn?await v.renderDotToSvgWithElkLayout(te,pe):await v.renderDotToSvg(
6358
6358
  te);O.innerHTML="",O.appendChild(Fe),O.classList.add("libpetri-viewer");let ft=mfe(Fe,N.panzoom),gt=X0n(Fe);Ffe(gt);let $t=N.layout??"elk";$t==="elk"&&(xfe(Fe),vX(Fe));let $e=new Set,dt=null,Ie=null,Ct=!1,We=null,Pn=null,Bt=!0;function It(){if(!N.chrome||We&&We.parentNode===O)return;We=document.createElement("div"),We.className="libpetri-viewer-chrome",We.style.position="absolute",We.style.inset="\
6359
6359
  0",We.style.pointerEvents="none";let Rt=document.createElement("div");Rt.className="diagram-controls",Rt.style.pointerEvents="auto";let or=document.createElement("button");or.type="button",or.className="diagram-btn btn-reset",or.title="Reset view",or.textContent="Reset",or.addEventListener("click",()=>Ir.fit());let ui=document.createElement("button");ui.type="button",ui.className="diagram-btn btn-\
6360
6360
  fullscreen",ui.title="Toggle fullscreen",ui.textContent="Fullscreen",ui.addEventListener("click",()=>Yr(O,ui));let wr=document.createElement("button");wr.type="button",wr.className="diagram-btn btn-subnets",wr.title=Mn==="show"?"Hide subnet groupings":"Show subnet groupings",wr.textContent=Mn==="show"?"Flat view":"Subnets view",wr.addEventListener("click",()=>{Ir.toggleSubnets()}),Rt.appendChild(wr),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libpetri",
3
- "version": "5.1.0",
3
+ "version": "6.0.0",
4
4
  "description": "Coloured Time Petri Net engine — TypeScript port",
5
5
  "homepage": "https://libpetri.org",
6
6
  "repository": {