@termwright/protocol 0.2.0 → 0.3.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.
- package/README.md +213 -605
- package/dist/action-model-BP9Znu6L.d.ts +219 -0
- package/dist/action-model.d.ts +3 -0
- package/dist/action-model.js +15 -0
- package/dist/action-model.js.map +1 -0
- package/dist/capability-graph.d.ts +90 -0
- package/dist/capability-graph.js +43 -0
- package/dist/capability-graph.js.map +1 -0
- package/dist/chunk-B4VUTTUE.js +59 -0
- package/dist/chunk-B4VUTTUE.js.map +1 -0
- package/dist/chunk-CZK6NNP3.js +389 -0
- package/dist/chunk-CZK6NNP3.js.map +1 -0
- package/dist/chunk-ODOJRXL6.js +84 -0
- package/dist/chunk-ODOJRXL6.js.map +1 -0
- package/dist/chunk-PUXRCPGY.js +112 -0
- package/dist/chunk-PUXRCPGY.js.map +1 -0
- package/dist/chunk-VBLS6E6U.js +1109 -0
- package/dist/chunk-VBLS6E6U.js.map +1 -0
- package/dist/chunk-ZZIYHDJ4.js +202 -0
- package/dist/chunk-ZZIYHDJ4.js.map +1 -0
- package/dist/contract-CH9gmj2Y.d.ts +746 -0
- package/dist/contract.d.ts +2 -0
- package/dist/contract.js +21 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.d.ts +82 -798
- package/dist/index.js +1087 -766
- package/dist/index.js.map +1 -1
- package/dist/run-events.d.ts +158 -0
- package/dist/run-events.js +27 -0
- package/dist/run-events.js.map +1 -0
- package/dist/run-journal.d.ts +55 -0
- package/dist/run-journal.js +10 -0
- package/dist/run-journal.js.map +1 -0
- package/dist/run-state.d.ts +38 -0
- package/dist/run-state.js +19 -0
- package/dist/run-state.js.map +1 -0
- package/dist/test-provider.d.ts +22 -0
- package/dist/test-provider.js +32 -0
- package/dist/test-provider.js.map +1 -0
- package/package.json +33 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/capability-graph.ts"],"sourcesContent":["/**\n * Executable capability graph shared by certification, negotiation tooling,\n * documentation and every public action surface.\n *\n * A producer declaration is not itself a public guarantee. Edges make the\n * complete path explicit: producer fact -> frozen session evidence -> runtime\n * prerequisite -> planning strategy/public consumer. Diagnostic facts never\n * unlock a public API.\n */\n\nexport const CAPABILITY_GRAPH_VERSION = 5 as const;\n\nexport const CAPABILITY_NODE_CATEGORIES = Object.freeze([\n 'evidence',\n 'input',\n 'planning',\n 'synchronization',\n 'diagnostic',\n] as const);\nexport type CapabilityNodeCategory = (typeof CAPABILITY_NODE_CATEGORIES)[number];\n\nexport const CAPABILITY_NODE_LAYERS = Object.freeze([\n 'producer',\n 'session',\n 'runtime',\n 'strategy',\n 'public',\n] as const);\nexport type CapabilityNodeLayer = (typeof CAPABILITY_NODE_LAYERS)[number];\n\nexport const CAPABILITY_EDGE_KINDS = Object.freeze([\n 'produces',\n 'requires',\n 'requires-any',\n 'runtime-requires',\n 'diagnoses',\n] as const);\nexport type CapabilityEdgeKind = (typeof CAPABILITY_EDGE_KINDS)[number];\n\nexport const ADAPTER_CAPABILITIES = Object.freeze([\n 'tree',\n 'intended-geometry',\n 'clipped-geometry',\n 'states',\n 'focus-state',\n 'actions',\n 'action-recipes',\n 'text-ranges',\n 'render-revisions',\n 'logs',\n 'pointer-hit-grid',\n] as const);\nexport type AdapterCapability = (typeof ADAPTER_CAPABILITIES)[number];\n\nexport const PROBE_CAPABILITIES = Object.freeze([\n 'stable-identity',\n 'intended-rect',\n 'visible-rect',\n 'operations',\n 'annotations',\n 'frame-begin',\n 'paint-order',\n] as const);\nexport type ProbeCapability = (typeof PROBE_CAPABILITIES)[number];\n\nexport const EVIDENCE_PROVIDER_CAPABILITIES = Object.freeze([\n 'pointer-regions',\n 'hit-test',\n 'focus-state',\n 'action-recipes',\n 'scroll-state',\n 'painted-regions',\n 'terminal-input-modes',\n] as const);\nexport type EvidenceProviderCapability = (typeof EVIDENCE_PROVIDER_CAPABILITIES)[number];\n\nexport const EVIDENCE_PROVIDER_TYPES = Object.freeze([\n 'pointer-evidence',\n 'focus-evidence',\n 'action-strategy',\n 'scroll-evidence',\n 'paint-evidence',\n 'input-mode-evidence',\n] as const);\nexport type EvidenceProviderType = (typeof EVIDENCE_PROVIDER_TYPES)[number];\n\nexport const SESSION_CAPABILITIES = Object.freeze([\n 'semantic-tree',\n 'stable-identity',\n 'intended-geometry',\n 'clipped-geometry',\n 'painted-region',\n 'pointer-geometry',\n 'pointer-hit-testing',\n 'focus',\n 'scroll',\n 'render-order',\n 'action-strategies',\n 'keyboard-input',\n 'pointer-input',\n 'focus-input',\n 'paired-revisions',\n] as const);\nexport type SessionCapabilityId = (typeof SESSION_CAPABILITIES)[number];\n\nexport const RUNTIME_PREREQUISITES = Object.freeze([\n 'writable-pty',\n 'terminal-input-modes-authoritative',\n 'mouse-reporting-enabled',\n 'mouse-motion-enabled',\n 'focus-reporting-enabled',\n 'committed-observation',\n] as const);\nexport type RuntimePrerequisiteId = (typeof RUNTIME_PREREQUISITES)[number];\n\nexport const PUBLIC_CAPABILITY_CONSUMERS = Object.freeze([\n 'locator.semantic-query',\n 'locator.semantic-scroll',\n 'locator.painted-region',\n 'condition.attached',\n 'condition.displayed',\n 'condition.visible',\n 'condition.in-viewport',\n 'condition.focused',\n 'condition.value',\n 'action.click',\n 'action.hover',\n 'action.drag',\n 'action.focus',\n 'action.activate',\n 'action.type',\n 'action.fill',\n 'action.check',\n 'action.uncheck',\n 'device.keyboard',\n 'device.mouse',\n 'device.window-focus',\n 'checkpoint',\n 'runner.inspector',\n 'trace.action',\n 'recorder.semantic-action',\n 'mcp.semantic-action',\n 'runner.diagnostics',\n 'trace.diagnostics',\n] as const);\nexport type PublicCapabilityConsumer = (typeof PUBLIC_CAPABILITY_CONSUMERS)[number];\n\nexport const CAPABILITY_CONFORMANCE_CLAIMS = Object.freeze([\n 'claim.semantic-tree-authoritative',\n 'claim.stable-identity-authoritative',\n 'claim.intended-geometry-authoritative',\n 'claim.clipped-geometry-authoritative',\n 'claim.painted-region-authoritative',\n 'claim.pointer-region-authoritative',\n 'claim.pointer-hit-test-authoritative',\n 'claim.focus-authoritative',\n 'claim.scroll-authoritative',\n 'claim.render-order-authoritative',\n 'claim.action-strategy-authoritative',\n 'claim.keyboard-real-pty',\n 'claim.pointer-real-pty',\n 'claim.focus-report-real-pty',\n 'claim.paired-revisions',\n 'claim.logs-diagnostic',\n] as const);\nexport type CapabilityConformanceClaimId = (typeof CAPABILITY_CONFORMANCE_CLAIMS)[number];\n\nexport const CONDITION_KINDS = Object.freeze([\n 'attached',\n 'detached',\n 'displayed',\n 'hidden',\n 'visible',\n 'in-viewport',\n 'offscreen',\n 'receives-pointer',\n 'pointer-region',\n 'pointer-input',\n 'mouse-input-enabled',\n 'enabled',\n 'disabled',\n 'focused',\n 'checked',\n 'selected',\n 'expanded',\n 'collapsed',\n 'value',\n 'not',\n 'all',\n 'any',\n] as const);\nexport type ConditionKind = (typeof CONDITION_KINDS)[number];\n\nexport type CapabilityNodeId =\n | `adapter.${AdapterCapability}`\n | `probe.${ProbeCapability}`\n | `provider.${EvidenceProviderCapability}`\n | `terminal.${'writable-pty' | 'input-modes-observable'}`\n | `session.${SessionCapabilityId}`\n | `runtime.${RuntimePrerequisiteId}`\n | `strategy.${'pointer-target' | 'keyboard-activate' | 'pointer-activate' | 'focus-by-pointer' | 'type-focused'}`\n | `public.${PublicCapabilityConsumer}`\n | `diagnostic.${'semantic-tree' | 'geometry' | 'render-order' | 'logs'}`;\n\nexport interface CapabilityRemediation {\n readonly code:\n | 'select-certified-adapter'\n | 'register-application-provider'\n | 'enable-terminal-runtime'\n | 'wait-for-committed-observation'\n | 'no-authoritative-producer';\n readonly message: string;\n readonly providerType?: EvidenceProviderType;\n readonly runtimePrerequisite?: RuntimePrerequisiteId;\n}\n\nexport interface CapabilityGraphNode {\n readonly id: CapabilityNodeId;\n readonly category: CapabilityNodeCategory;\n readonly layer: CapabilityNodeLayer;\n readonly description: string;\n readonly conformanceClaims?: readonly CapabilityConformanceClaimId[];\n readonly conditions?: readonly ConditionKind[];\n readonly publicConsumer?: PublicCapabilityConsumer;\n readonly remediation: CapabilityRemediation;\n}\n\nexport interface CapabilityGraphEdge {\n readonly from: CapabilityNodeId;\n readonly to: CapabilityNodeId;\n readonly kind: CapabilityEdgeKind;\n}\n\nconst certified = (message: string): CapabilityRemediation =>\n Object.freeze({\n code: 'select-certified-adapter' as const,\n message,\n });\nconst provider = (providerType: EvidenceProviderType, message: string): CapabilityRemediation =>\n Object.freeze({\n code: 'register-application-provider' as const,\n providerType,\n message,\n });\nconst runtime = (\n runtimePrerequisite: RuntimePrerequisiteId,\n message: string,\n): CapabilityRemediation =>\n Object.freeze({\n code: 'enable-terminal-runtime' as const,\n runtimePrerequisite,\n message,\n });\nconst settle = (): CapabilityRemediation =>\n Object.freeze({\n code: 'wait-for-committed-observation' as const,\n message: 'Wait for one paired committed observation before using this capability.',\n });\nconst producerNodes: readonly CapabilityGraphNode[] = [\n ...ADAPTER_CAPABILITIES.map((id) => ({\n id: `adapter.${id}` as CapabilityNodeId,\n category:\n id === 'render-revisions'\n ? ('synchronization' as const)\n : id === 'logs'\n ? ('diagnostic' as const)\n : ('evidence' as const),\n layer: 'producer' as const,\n description: `Certified adapter handshake fact: ${id}.`,\n remediation: certified(`Use an exact certified adapter which publishes ${id}.`),\n })),\n ...PROBE_CAPABILITIES.map((id) => ({\n id: `probe.${id}` as CapabilityNodeId,\n category:\n id === 'frame-begin'\n ? ('synchronization' as const)\n : id === 'operations' || id === 'annotations'\n ? ('diagnostic' as const)\n : ('evidence' as const),\n layer: 'producer' as const,\n description: `Framework probe fact: ${id}.`,\n remediation: certified(`Use exact certified instrumentation which publishes ${id}.`),\n })),\n ...EVIDENCE_PROVIDER_CAPABILITIES.map((id) => ({\n id: `provider.${id}` as CapabilityNodeId,\n category: 'evidence' as const,\n layer: 'producer' as const,\n description: `Authoritative application production-router fact: ${id}.`,\n remediation: provider(\n id === 'action-recipes'\n ? 'action-strategy'\n : id === 'focus-state'\n ? 'focus-evidence'\n : id === 'scroll-state'\n ? 'scroll-evidence'\n : id === 'painted-regions'\n ? 'paint-evidence'\n : id === 'terminal-input-modes'\n ? 'input-mode-evidence'\n : 'pointer-evidence',\n id === 'action-recipes'\n ? \"Register an action-strategy provider backed by the application's production keybindings.\"\n : id === 'focus-state'\n ? \"Register a focus-evidence provider backed by the application's production focus manager.\"\n : id === 'scroll-state'\n ? \"Register a scroll-evidence provider backed by the application's production viewport model.\"\n : id === 'painted-regions'\n ? \"Register a paint-evidence provider backed by the application's production painter.\"\n : id === 'terminal-input-modes'\n ? \"Register an input-mode-evidence provider backed by the application's production terminal parser configuration.\"\n : `Register a pointer-evidence provider backed by the application's production router (${id}).`,\n ),\n })),\n {\n id: 'terminal.writable-pty',\n category: 'input',\n layer: 'producer',\n description: 'The native session owns a writable PTY input channel.',\n remediation: runtime('writable-pty', 'Launch the application in a writable real PTY.'),\n },\n {\n id: 'terminal.input-modes-observable',\n category: 'input',\n layer: 'producer',\n description: 'The terminal backend authoritatively observes application mouse modes.',\n remediation: runtime(\n 'terminal-input-modes-authoritative',\n 'Use a terminal backend that authoritatively observes terminal input modes.',\n ),\n },\n];\n\nconst sessionNode = (\n id: SessionCapabilityId,\n category: CapabilityNodeCategory,\n claim: CapabilityConformanceClaimId,\n remediation: CapabilityRemediation,\n): CapabilityGraphNode => ({\n id: `session.${id}`,\n category,\n layer: 'session',\n description: `Frozen session capability: ${id}.`,\n conformanceClaims: [claim],\n remediation,\n});\n\nconst sessionNodes: readonly CapabilityGraphNode[] = [\n sessionNode(\n 'semantic-tree',\n 'evidence',\n 'claim.semantic-tree-authoritative',\n certified('Use a certified semantic adapter.'),\n ),\n sessionNode(\n 'stable-identity',\n 'evidence',\n 'claim.stable-identity-authoritative',\n certified('Use a certified retained-identity adapter or explicit SemanticKey contract.'),\n ),\n sessionNode(\n 'intended-geometry',\n 'evidence',\n 'claim.intended-geometry-authoritative',\n certified('Use an adapter instrumented at the authoritative layout/render boundary.'),\n ),\n sessionNode(\n 'clipped-geometry',\n 'evidence',\n 'claim.clipped-geometry-authoritative',\n certified('Use an adapter that publishes authoritative clipping.'),\n ),\n sessionNode(\n 'painted-region',\n 'evidence',\n 'claim.painted-region-authoritative',\n provider(\n 'paint-evidence',\n \"Register a paint-evidence provider backed by the application's production painter.\",\n ),\n ),\n sessionNode(\n 'pointer-geometry',\n 'evidence',\n 'claim.pointer-region-authoritative',\n provider(\n 'pointer-evidence',\n 'Register the application production pointer router as a pointer-evidence provider.',\n ),\n ),\n sessionNode(\n 'pointer-hit-testing',\n 'evidence',\n 'claim.pointer-hit-test-authoritative',\n provider(\n 'pointer-evidence',\n 'Register a pointer-evidence provider with authoritative hit testing.',\n ),\n ),\n sessionNode(\n 'focus',\n 'evidence',\n 'claim.focus-authoritative',\n provider(\n 'focus-evidence',\n \"Use a certified adapter with focus-state or register the application's production focus manager.\",\n ),\n ),\n sessionNode(\n 'scroll',\n 'evidence',\n 'claim.scroll-authoritative',\n provider(\n 'scroll-evidence',\n \"Use a certified adapter with explicit scroll evidence or register the application's production viewport model.\",\n ),\n ),\n sessionNode(\n 'render-order',\n 'evidence',\n 'claim.render-order-authoritative',\n certified(\n 'Use a certified adapter which guarantees render order for every applicable semantic node.',\n ),\n ),\n sessionNode(\n 'action-strategies',\n 'planning',\n 'claim.action-strategy-authoritative',\n provider(\n 'action-strategy',\n \"Register the application's production keybindings as authoritative physical input recipes.\",\n ),\n ),\n sessionNode(\n 'keyboard-input',\n 'input',\n 'claim.keyboard-real-pty',\n runtime('writable-pty', 'Launch in a writable real PTY.'),\n ),\n sessionNode(\n 'pointer-input',\n 'input',\n 'claim.pointer-real-pty',\n provider(\n 'input-mode-evidence',\n \"Use a backend that observes terminal modes or register the application's authoritative production parser configuration.\",\n ),\n ),\n sessionNode(\n 'focus-input',\n 'input',\n 'claim.focus-report-real-pty',\n provider(\n 'input-mode-evidence',\n \"Use a backend that observes terminal modes or register the application's authoritative production parser configuration.\",\n ),\n ),\n sessionNode(\n 'paired-revisions',\n 'synchronization',\n 'claim.paired-revisions',\n certified('Use an adapter with exact render revision markers.'),\n ),\n];\n\nconst runtimeNodes: readonly CapabilityGraphNode[] = [\n {\n id: 'runtime.writable-pty',\n category: 'input',\n layer: 'runtime',\n description: 'PTY input remains writable.',\n remediation: runtime('writable-pty', 'Launch or retain a writable PTY.'),\n },\n {\n id: 'runtime.terminal-input-modes-authoritative',\n category: 'input',\n layer: 'runtime',\n description:\n \"Terminal mouse mode state is authoritative, either observed from VT output or supplied by the application's production parser.\",\n remediation: runtime(\n 'terminal-input-modes-authoritative',\n 'Use a backend with authoritative terminal mouse mode tracking or register input-mode evidence.',\n ),\n },\n {\n id: 'runtime.mouse-reporting-enabled',\n category: 'input',\n layer: 'runtime',\n description: 'The application currently enables compatible mouse reporting.',\n remediation: runtime(\n 'mouse-reporting-enabled',\n 'Enable terminal mouse reporting in the application.',\n ),\n },\n {\n id: 'runtime.mouse-motion-enabled',\n category: 'input',\n layer: 'runtime',\n description: 'The application currently requests unpressed pointer motion.',\n remediation: runtime(\n 'mouse-motion-enabled',\n 'Enable terminal any-event mouse motion reporting for hover.',\n ),\n },\n {\n id: 'runtime.focus-reporting-enabled',\n category: 'input',\n layer: 'runtime',\n description: 'The application currently enables terminal focus reports.',\n remediation: runtime(\n 'focus-reporting-enabled',\n 'Enable terminal focus reporting in the application.',\n ),\n },\n {\n id: 'runtime.committed-observation',\n category: 'synchronization',\n layer: 'runtime',\n description: 'Semantic and VT evidence share one committed checkpoint.',\n remediation: settle(),\n },\n];\n\nconst publicNode = (\n consumer: PublicCapabilityConsumer,\n category: CapabilityNodeCategory,\n conditions: readonly ConditionKind[] = [],\n conformanceClaims: readonly CapabilityConformanceClaimId[],\n): CapabilityGraphNode => ({\n id: `public.${consumer}`,\n category,\n layer: 'public',\n publicConsumer: consumer,\n description: `Public consumer ${consumer}.`,\n conditions,\n conformanceClaims,\n remediation: settle(),\n});\n\nconst strategyNodes: readonly CapabilityGraphNode[] = [\n {\n id: 'strategy.pointer-target',\n category: 'planning',\n layer: 'strategy',\n description: 'Resolve an authoritative safe physical pointer target.',\n remediation: provider(\n 'pointer-evidence',\n 'Provide authoritative pointer regions, optionally with hit testing.',\n ),\n },\n {\n id: 'strategy.keyboard-activate',\n category: 'planning',\n layer: 'strategy',\n description: 'Activate through a framework-declared keyboard convention and real PTY input.',\n remediation: certified('Expose an authoritative semantic keyboard action convention.'),\n },\n {\n id: 'strategy.pointer-activate',\n category: 'planning',\n layer: 'strategy',\n description: 'Activate through a planned real pointer click.',\n remediation: provider('pointer-evidence', 'Provide authoritative pointer evidence.'),\n },\n {\n id: 'strategy.focus-by-pointer',\n category: 'planning',\n layer: 'strategy',\n description: 'Focus using a real planned pointer action.',\n remediation: provider(\n 'pointer-evidence',\n 'Provide authoritative pointer evidence for the focus target.',\n ),\n },\n {\n id: 'strategy.type-focused',\n category: 'planning',\n layer: 'strategy',\n description: 'Type only after authoritative element focus is known.',\n remediation: certified('Use an adapter that guarantees focus state.'),\n },\n];\n\nconst publicNodes: readonly CapabilityGraphNode[] = [\n publicNode('locator.semantic-query', 'evidence', [], ['claim.semantic-tree-authoritative']),\n publicNode(\n 'locator.semantic-scroll',\n 'evidence',\n [],\n ['claim.scroll-authoritative', 'claim.paired-revisions'],\n ),\n publicNode(\n 'locator.painted-region',\n 'evidence',\n [],\n ['claim.painted-region-authoritative', 'claim.paired-revisions'],\n ),\n publicNode(\n 'condition.attached',\n 'evidence',\n ['attached', 'detached'],\n ['claim.semantic-tree-authoritative'],\n ),\n publicNode(\n 'condition.displayed',\n 'evidence',\n ['displayed', 'hidden'],\n ['claim.semantic-tree-authoritative'],\n ),\n publicNode(\n 'condition.visible',\n 'evidence',\n ['visible'],\n ['claim.clipped-geometry-authoritative'],\n ),\n publicNode(\n 'condition.in-viewport',\n 'evidence',\n ['in-viewport', 'offscreen'],\n ['claim.clipped-geometry-authoritative'],\n ),\n publicNode('condition.focused', 'evidence', ['focused'], ['claim.focus-authoritative']),\n publicNode('condition.value', 'evidence', ['value'], ['claim.semantic-tree-authoritative']),\n publicNode(\n 'action.click',\n 'planning',\n ['attached', 'enabled', 'visible', 'pointer-region', 'receives-pointer', 'mouse-input-enabled'],\n ['claim.pointer-region-authoritative', 'claim.pointer-real-pty', 'claim.paired-revisions'],\n ),\n publicNode(\n 'action.hover',\n 'planning',\n ['attached', 'visible', 'pointer-region', 'receives-pointer', 'mouse-input-enabled'],\n ['claim.pointer-region-authoritative', 'claim.pointer-real-pty'],\n ),\n publicNode(\n 'action.drag',\n 'planning',\n ['attached', 'enabled', 'visible', 'pointer-region', 'receives-pointer', 'mouse-input-enabled'],\n ['claim.pointer-region-authoritative', 'claim.pointer-real-pty'],\n ),\n publicNode(\n 'action.focus',\n 'planning',\n ['attached', 'enabled', 'displayed'],\n ['claim.keyboard-real-pty', 'claim.pointer-real-pty'],\n ),\n publicNode(\n 'action.activate',\n 'planning',\n ['attached', 'enabled', 'displayed'],\n ['claim.keyboard-real-pty', 'claim.pointer-real-pty'],\n ),\n publicNode(\n 'action.type',\n 'planning',\n ['attached', 'enabled', 'displayed', 'focused'],\n ['claim.focus-authoritative', 'claim.keyboard-real-pty'],\n ),\n publicNode(\n 'action.fill',\n 'planning',\n ['attached', 'enabled', 'displayed'],\n ['claim.focus-authoritative', 'claim.keyboard-real-pty'],\n ),\n publicNode(\n 'action.check',\n 'planning',\n ['attached', 'enabled', 'displayed', 'checked'],\n ['claim.keyboard-real-pty', 'claim.pointer-real-pty'],\n ),\n publicNode(\n 'action.uncheck',\n 'planning',\n ['attached', 'enabled', 'displayed', 'checked'],\n ['claim.keyboard-real-pty', 'claim.pointer-real-pty'],\n ),\n publicNode('device.keyboard', 'input', [], ['claim.keyboard-real-pty']),\n publicNode('device.mouse', 'input', [], ['claim.pointer-real-pty']),\n publicNode('device.window-focus', 'input', [], ['claim.focus-report-real-pty']),\n publicNode('checkpoint', 'synchronization', [], ['claim.paired-revisions']),\n publicNode('runner.inspector', 'diagnostic', [], ['claim.semantic-tree-authoritative']),\n publicNode(\n 'trace.action',\n 'diagnostic',\n [],\n ['claim.pointer-real-pty', 'claim.keyboard-real-pty'],\n ),\n publicNode('recorder.semantic-action', 'planning', [], ['claim.pointer-hit-test-authoritative']),\n publicNode(\n 'mcp.semantic-action',\n 'planning',\n [],\n ['claim.pointer-real-pty', 'claim.keyboard-real-pty'],\n ),\n publicNode('runner.diagnostics', 'diagnostic', [], ['claim.semantic-tree-authoritative']),\n publicNode('trace.diagnostics', 'diagnostic', [], ['claim.logs-diagnostic']),\n];\n\nconst diagnosticNodes: readonly CapabilityGraphNode[] = [\n {\n id: 'diagnostic.semantic-tree',\n category: 'diagnostic',\n layer: 'session',\n description: 'Best-effort semantic tree for inspector diagnostics only.',\n conformanceClaims: ['claim.semantic-tree-authoritative'],\n remediation: certified('Use certified semantic evidence for public queries.'),\n },\n {\n id: 'diagnostic.geometry',\n category: 'diagnostic',\n layer: 'session',\n description: 'Best-effort geometry that cannot unlock actions.',\n conformanceClaims: ['claim.intended-geometry-authoritative'],\n remediation: certified('Use certified geometry evidence for action planning.'),\n },\n {\n id: 'diagnostic.render-order',\n category: 'diagnostic',\n layer: 'session',\n description: 'Best-effort paint order that cannot prove actionability.',\n conformanceClaims: ['claim.render-order-authoritative'],\n remediation: certified('Use a universally certified render-order producer.'),\n },\n {\n id: 'diagnostic.logs',\n category: 'diagnostic',\n layer: 'session',\n description: 'Structured application logs.',\n conformanceClaims: ['claim.logs-diagnostic'],\n remediation: certified('Use an adapter that negotiates structured logs.'),\n },\n];\n\nconst edges: readonly CapabilityGraphEdge[] = [\n { from: 'adapter.tree', to: 'session.semantic-tree', kind: 'produces' },\n {\n from: 'probe.stable-identity',\n to: 'session.stable-identity',\n kind: 'produces',\n },\n {\n from: 'adapter.intended-geometry',\n to: 'session.intended-geometry',\n kind: 'produces',\n },\n {\n from: 'adapter.clipped-geometry',\n to: 'session.clipped-geometry',\n kind: 'produces',\n },\n { from: 'adapter.focus-state', to: 'session.focus', kind: 'produces' },\n { from: 'provider.focus-state', to: 'session.focus', kind: 'produces' },\n { from: 'provider.scroll-state', to: 'session.scroll', kind: 'produces' },\n {\n from: 'provider.painted-regions',\n to: 'session.painted-region',\n kind: 'produces',\n },\n {\n from: 'adapter.action-recipes',\n to: 'session.action-strategies',\n kind: 'produces',\n },\n {\n from: 'adapter.pointer-hit-grid',\n to: 'session.pointer-geometry',\n kind: 'produces',\n },\n {\n from: 'adapter.pointer-hit-grid',\n to: 'session.pointer-hit-testing',\n kind: 'produces',\n },\n {\n from: 'provider.pointer-regions',\n to: 'session.pointer-geometry',\n kind: 'produces',\n },\n {\n from: 'provider.hit-test',\n to: 'session.pointer-hit-testing',\n kind: 'produces',\n },\n {\n from: 'provider.action-recipes',\n to: 'session.action-strategies',\n kind: 'produces',\n },\n { from: 'probe.paint-order', to: 'session.render-order', kind: 'produces' },\n {\n from: 'probe.paint-order',\n to: 'diagnostic.render-order',\n kind: 'diagnoses',\n },\n { from: 'adapter.logs', to: 'diagnostic.logs', kind: 'diagnoses' },\n {\n from: 'terminal.writable-pty',\n to: 'session.keyboard-input',\n kind: 'produces',\n },\n {\n from: 'terminal.input-modes-observable',\n to: 'session.pointer-input',\n kind: 'produces',\n },\n {\n from: 'provider.terminal-input-modes',\n to: 'session.pointer-input',\n kind: 'produces',\n },\n {\n from: 'terminal.input-modes-observable',\n to: 'session.focus-input',\n kind: 'produces',\n },\n {\n from: 'provider.terminal-input-modes',\n to: 'session.focus-input',\n kind: 'produces',\n },\n {\n from: 'adapter.render-revisions',\n to: 'session.paired-revisions',\n kind: 'produces',\n },\n {\n from: 'terminal.writable-pty',\n to: 'runtime.writable-pty',\n kind: 'produces',\n },\n {\n from: 'terminal.input-modes-observable',\n to: 'runtime.terminal-input-modes-authoritative',\n kind: 'produces',\n },\n {\n from: 'provider.terminal-input-modes',\n to: 'runtime.terminal-input-modes-authoritative',\n kind: 'produces',\n },\n {\n from: 'session.pointer-geometry',\n to: 'strategy.pointer-target',\n kind: 'requires',\n },\n {\n from: 'runtime.committed-observation',\n to: 'strategy.pointer-target',\n kind: 'runtime-requires',\n },\n {\n from: 'strategy.pointer-target',\n to: 'strategy.pointer-activate',\n kind: 'requires',\n },\n {\n from: 'session.pointer-input',\n to: 'strategy.pointer-activate',\n kind: 'requires',\n },\n {\n from: 'runtime.terminal-input-modes-authoritative',\n to: 'strategy.pointer-activate',\n kind: 'runtime-requires',\n },\n {\n from: 'runtime.mouse-reporting-enabled',\n to: 'strategy.pointer-activate',\n kind: 'runtime-requires',\n },\n {\n from: 'session.keyboard-input',\n to: 'strategy.keyboard-activate',\n kind: 'requires',\n },\n {\n from: 'runtime.writable-pty',\n to: 'strategy.keyboard-activate',\n kind: 'runtime-requires',\n },\n {\n from: 'strategy.pointer-activate',\n to: 'strategy.focus-by-pointer',\n kind: 'requires',\n },\n { from: 'session.focus', to: 'strategy.type-focused', kind: 'requires' },\n {\n from: 'session.keyboard-input',\n to: 'strategy.type-focused',\n kind: 'requires',\n },\n {\n from: 'session.semantic-tree',\n to: 'public.locator.semantic-query',\n kind: 'requires',\n },\n {\n from: 'session.scroll',\n to: 'public.locator.semantic-scroll',\n kind: 'requires',\n },\n {\n from: 'runtime.committed-observation',\n to: 'public.locator.semantic-scroll',\n kind: 'runtime-requires',\n },\n {\n from: 'session.painted-region',\n to: 'public.locator.painted-region',\n kind: 'requires',\n },\n {\n from: 'runtime.committed-observation',\n to: 'public.locator.painted-region',\n kind: 'runtime-requires',\n },\n {\n from: 'session.semantic-tree',\n to: 'public.condition.attached',\n kind: 'requires',\n },\n {\n from: 'session.semantic-tree',\n to: 'public.condition.displayed',\n kind: 'requires',\n },\n {\n from: 'session.clipped-geometry',\n to: 'public.condition.visible',\n kind: 'requires',\n },\n {\n from: 'session.clipped-geometry',\n to: 'public.condition.in-viewport',\n kind: 'requires',\n },\n { from: 'session.focus', to: 'public.condition.focused', kind: 'requires' },\n {\n from: 'session.semantic-tree',\n to: 'public.condition.value',\n kind: 'requires',\n },\n {\n from: 'strategy.pointer-activate',\n to: 'public.action.click',\n kind: 'requires',\n },\n {\n from: 'strategy.pointer-target',\n to: 'public.action.hover',\n kind: 'requires',\n },\n {\n from: 'session.pointer-input',\n to: 'public.action.hover',\n kind: 'requires',\n },\n {\n from: 'runtime.terminal-input-modes-authoritative',\n to: 'public.action.hover',\n kind: 'runtime-requires',\n },\n {\n from: 'runtime.mouse-motion-enabled',\n to: 'public.action.hover',\n kind: 'runtime-requires',\n },\n {\n from: 'strategy.pointer-activate',\n to: 'public.action.drag',\n kind: 'requires',\n },\n {\n from: 'strategy.focus-by-pointer',\n to: 'public.action.focus',\n kind: 'requires-any',\n },\n {\n from: 'strategy.keyboard-activate',\n to: 'public.action.focus',\n kind: 'requires-any',\n },\n {\n from: 'strategy.pointer-activate',\n to: 'public.action.activate',\n kind: 'requires-any',\n },\n {\n from: 'strategy.keyboard-activate',\n to: 'public.action.activate',\n kind: 'requires-any',\n },\n { from: 'strategy.type-focused', to: 'public.action.type', kind: 'requires' },\n { from: 'public.action.focus', to: 'public.action.fill', kind: 'requires' },\n {\n from: 'session.keyboard-input',\n to: 'public.action.fill',\n kind: 'requires',\n },\n {\n from: 'public.action.activate',\n to: 'public.action.check',\n kind: 'requires',\n },\n {\n from: 'public.action.activate',\n to: 'public.action.uncheck',\n kind: 'requires',\n },\n {\n from: 'session.keyboard-input',\n to: 'public.device.keyboard',\n kind: 'requires',\n },\n {\n from: 'session.pointer-input',\n to: 'public.device.mouse',\n kind: 'requires',\n },\n {\n from: 'runtime.terminal-input-modes-authoritative',\n to: 'public.device.mouse',\n kind: 'runtime-requires',\n },\n {\n from: 'runtime.mouse-reporting-enabled',\n to: 'public.device.mouse',\n kind: 'runtime-requires',\n },\n {\n from: 'session.focus-input',\n to: 'public.device.window-focus',\n kind: 'requires',\n },\n {\n from: 'runtime.focus-reporting-enabled',\n to: 'public.device.window-focus',\n kind: 'runtime-requires',\n },\n {\n from: 'runtime.terminal-input-modes-authoritative',\n to: 'public.device.window-focus',\n kind: 'runtime-requires',\n },\n {\n from: 'session.paired-revisions',\n to: 'public.checkpoint',\n kind: 'requires',\n },\n {\n from: 'public.action.click',\n to: 'public.recorder.semantic-action',\n kind: 'requires',\n },\n {\n from: 'public.action.click',\n to: 'public.mcp.semantic-action',\n kind: 'requires',\n },\n {\n from: 'diagnostic.semantic-tree',\n to: 'public.runner.diagnostics',\n kind: 'diagnoses',\n },\n {\n from: 'diagnostic.geometry',\n to: 'public.runner.diagnostics',\n kind: 'diagnoses',\n },\n {\n from: 'diagnostic.logs',\n to: 'public.trace.diagnostics',\n kind: 'diagnoses',\n },\n {\n from: 'public.action.click',\n to: 'public.runner.inspector',\n kind: 'diagnoses',\n },\n { from: 'public.action.click', to: 'public.trace.action', kind: 'diagnoses' },\n];\n\nexport const CAPABILITY_GRAPH = deepFreeze({\n version: CAPABILITY_GRAPH_VERSION,\n nodes: [\n ...producerNodes,\n ...sessionNodes,\n ...runtimeNodes,\n ...strategyNodes,\n ...publicNodes,\n ...diagnosticNodes,\n ],\n edges,\n});\n\nexport interface CapabilityGraphValidationResult {\n readonly ok: boolean;\n readonly errors: readonly string[];\n}\n\n/** Mechanical integrity gate used by protocol and registry tests. */\nexport function validateCapabilityGraph(): CapabilityGraphValidationResult {\n const errors: string[] = [];\n const nodes = new Map<CapabilityNodeId, CapabilityGraphNode>();\n for (const node of CAPABILITY_GRAPH.nodes) {\n if (nodes.has(node.id)) errors.push(`duplicate capability node ${node.id}`);\n nodes.set(node.id, node);\n if (!CAPABILITY_NODE_CATEGORIES.includes(node.category))\n errors.push(`invalid category on ${node.id}`);\n if (!CAPABILITY_NODE_LAYERS.includes(node.layer)) errors.push(`invalid layer on ${node.id}`);\n for (const claim of node.conformanceClaims ?? []) {\n if (!CAPABILITY_CONFORMANCE_CLAIMS.includes(claim))\n errors.push(`unknown claim ${claim} on ${node.id}`);\n }\n for (const condition of node.conditions ?? []) {\n if (!CONDITION_KINDS.includes(condition))\n errors.push(`unknown condition ${condition} on ${node.id}`);\n }\n }\n const edgeKeys = new Set<string>();\n for (const edge of CAPABILITY_GRAPH.edges) {\n if (!nodes.has(edge.from)) errors.push(`edge source ${edge.from} is orphaned`);\n if (!nodes.has(edge.to)) errors.push(`edge target ${edge.to} is orphaned`);\n const key = `${edge.kind}:${edge.from}->${edge.to}`;\n if (edgeKeys.has(key)) errors.push(`duplicate edge ${key}`);\n edgeKeys.add(key);\n }\n for (const node of CAPABILITY_GRAPH.nodes) {\n if (\n (node.layer === 'session' || node.layer === 'public') &&\n (node.conformanceClaims?.length ?? 0) === 0\n ) {\n errors.push(`contract/public node ${node.id} has no mandatory conformance claim`);\n }\n if (node.remediation.code === 'register-application-provider') {\n const reachable = CAPABILITY_GRAPH.edges.some(\n (edge) =>\n edge.to === node.id && edge.from.startsWith('provider.') && edge.kind === 'produces',\n );\n if (!reachable && node.layer === 'session')\n errors.push(`impossible provider remediation on ${node.id}`);\n }\n if (\n node.remediation.code === 'enable-terminal-runtime' &&\n node.remediation.runtimePrerequisite === undefined\n ) {\n errors.push(`runtime remediation on ${node.id} has no prerequisite id`);\n }\n }\n const usedClaims = new Set(\n CAPABILITY_GRAPH.nodes.flatMap((node) => node.conformanceClaims ?? []),\n );\n for (const claim of CAPABILITY_CONFORMANCE_CLAIMS) {\n if (!usedClaims.has(claim)) errors.push(`orphan conformance claim ${claim}`);\n }\n return Object.freeze({\n ok: errors.length === 0,\n errors: Object.freeze(errors),\n });\n}\n\nexport function capabilityNode(id: CapabilityNodeId): CapabilityGraphNode {\n const node = CAPABILITY_GRAPH.nodes.find((candidate) => candidate.id === id);\n if (node === undefined) throw new RangeError(`unknown capability graph node ${id}`);\n return node;\n}\n\n/** Generated, deterministic remediation for a missing graph node. */\nexport function capabilityRemediation(id: CapabilityNodeId): CapabilityRemediation {\n return capabilityNode(id).remediation;\n}\n\nexport interface CapabilityResolution {\n readonly available: boolean;\n readonly target: CapabilityNodeId;\n readonly missing: readonly CapabilityNodeId[];\n readonly remediation: readonly CapabilityRemediation[];\n}\n\n/**\n * Resolves the frozen session facts produced by an exact set of negotiated\n * producer nodes. Only explicit `produces` edges may create a session\n * capability; similarly named adapter facts never imply extra guarantees.\n */\nexport function sessionCapabilitiesFromProducers(\n producers: ReadonlySet<CapabilityNodeId>,\n): ReadonlyMap<SessionCapabilityId, readonly CapabilityNodeId[]> {\n const resolved = new Map<SessionCapabilityId, CapabilityNodeId[]>();\n for (const edge of CAPABILITY_GRAPH.edges) {\n if (edge.kind !== 'produces' || !edge.to.startsWith('session.') || !producers.has(edge.from))\n continue;\n const capability = edge.to.slice('session.'.length) as SessionCapabilityId;\n const current = resolved.get(capability) ?? [];\n current.push(edge.from);\n resolved.set(capability, current);\n }\n return new Map(\n [...resolved].map(([capability, sources]) => [\n capability,\n Object.freeze([...new Set(sources)].sort()),\n ]),\n );\n}\n\n/**\n * Resolve a strategy or public consumer against one already-negotiated\n * session/runtime node set. Session nodes are leaves: producer declarations do\n * not opportunistically unlock them after negotiation.\n */\nexport function resolveCapability(\n target: CapabilityNodeId,\n available: ReadonlySet<CapabilityNodeId>,\n): CapabilityResolution {\n const visiting = new Set<CapabilityNodeId>();\n const resolve = (id: CapabilityNodeId): readonly CapabilityNodeId[] => {\n if (available.has(id)) return [];\n const node = capabilityNode(id);\n if (node.layer === 'producer' || node.layer === 'session' || node.layer === 'runtime')\n return [id];\n if (visiting.has(id)) throw new Error(`capability graph dependency cycle at ${id}`);\n visiting.add(id);\n const incoming = CAPABILITY_GRAPH.edges.filter(\n (edge) =>\n edge.to === id &&\n (edge.kind === 'requires' ||\n edge.kind === 'requires-any' ||\n edge.kind === 'runtime-requires'),\n );\n const mandatory = incoming\n .filter(({ kind }) => kind !== 'requires-any')\n .flatMap(({ from }) => resolve(from));\n const alternatives = incoming\n .filter(({ kind }) => kind === 'requires-any')\n .map(({ from }) => resolve(from));\n const bestAlternative =\n alternatives.length === 0\n ? []\n : alternatives.reduce((best, candidate) =>\n candidate.length < best.length ? candidate : best,\n );\n visiting.delete(id);\n return unique([...mandatory, ...bestAlternative]);\n };\n const missing = resolve(target);\n const remediation = uniqueBy(\n missing.map((id) => capabilityRemediation(id)),\n (item) =>\n `${item.code}:${item.providerType ?? ''}:${item.runtimePrerequisite ?? ''}:${item.message}`,\n );\n return Object.freeze({\n available: missing.length === 0,\n target,\n missing: Object.freeze(missing),\n remediation: Object.freeze(remediation),\n });\n}\n\nfunction unique<T>(values: readonly T[]): T[] {\n return [...new Set(values)];\n}\n\nfunction uniqueBy<T>(values: readonly T[], key: (value: T) => string): T[] {\n const found = new Map<string, T>();\n for (const value of values) found.set(key(value), value);\n return [...found.values()];\n}\n\nfunction deepFreeze<T>(value: T): Readonly<T> {\n if (typeof value !== 'object' || value === null || Object.isFrozen(value)) return value;\n for (const child of Object.values(value)) deepFreeze(child);\n return Object.freeze(value);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RunEventStreamValidator,
|
|
3
|
+
validateRunEvent
|
|
4
|
+
} from "./chunk-CZK6NNP3.js";
|
|
5
|
+
|
|
6
|
+
// src/run-journal.ts
|
|
7
|
+
var DEFAULT_RUN_EVENT_JOURNAL_LIMITS = Object.freeze({
|
|
8
|
+
maxAuthoritativeEvents: 1e4,
|
|
9
|
+
maxStateKeys: 1e4,
|
|
10
|
+
maxDiagnosticEvents: 1e3
|
|
11
|
+
});
|
|
12
|
+
var RunEventJournal = class {
|
|
13
|
+
#invocationId;
|
|
14
|
+
#runId;
|
|
15
|
+
#limits;
|
|
16
|
+
#validator = new RunEventStreamValidator();
|
|
17
|
+
#gapProducer;
|
|
18
|
+
#gapIdentity;
|
|
19
|
+
#entries = [];
|
|
20
|
+
#currentState = /* @__PURE__ */ new Map();
|
|
21
|
+
#gaps = [];
|
|
22
|
+
#barriers = /* @__PURE__ */ new Map();
|
|
23
|
+
#openGap;
|
|
24
|
+
#nextOrdinal = 0;
|
|
25
|
+
#nextBarrierToken = 0;
|
|
26
|
+
#flushedThrough = -1;
|
|
27
|
+
#sealedThrough = -1;
|
|
28
|
+
#flushActive = false;
|
|
29
|
+
constructor(options) {
|
|
30
|
+
this.#invocationId = options.invocationId;
|
|
31
|
+
this.#runId = options.runId;
|
|
32
|
+
this.#gapProducer = options.gapProducer;
|
|
33
|
+
this.#gapIdentity = Object.freeze({ invocationId: options.invocationId, runId: options.runId });
|
|
34
|
+
this.#limits = options.limits ?? DEFAULT_RUN_EVENT_JOURNAL_LIMITS;
|
|
35
|
+
for (const [name, value] of Object.entries(this.#limits)) {
|
|
36
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
37
|
+
throw new TypeError(`${name} must be a positive safe integer`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
append(value, options = {}) {
|
|
41
|
+
const parsed = validateRunEvent(value);
|
|
42
|
+
if (!parsed.ok) return parsed;
|
|
43
|
+
const event = parsed.value;
|
|
44
|
+
if (event.identity.invocationId !== this.#invocationId || event.identity.runId !== this.#runId) {
|
|
45
|
+
return failure("stale-run", "event belongs to another invocation or run");
|
|
46
|
+
}
|
|
47
|
+
if (event.eventClass === "state" && !validStateKey(options.stateKey)) {
|
|
48
|
+
return failure(
|
|
49
|
+
"state-key-required",
|
|
50
|
+
"state events require a bounded explicit coalescing key"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (event.eventClass === "authoritative" && this.#count("authoritative") >= this.#limits.maxAuthoritativeEvents) {
|
|
54
|
+
return failure(
|
|
55
|
+
"journal-full",
|
|
56
|
+
"authoritative queue is full; flush before accepting more events"
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (event.eventClass === "state" && !this.#currentState.has(options.stateKey) && this.#currentState.size >= this.#limits.maxStateKeys) {
|
|
60
|
+
return failure(
|
|
61
|
+
"journal-full",
|
|
62
|
+
"state key queue is full; create a barrier and flush before accepting another key"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const ordered = this.#validator.accept(event);
|
|
66
|
+
if (!ordered.ok) return ordered;
|
|
67
|
+
const ordinal = this.#nextOrdinal;
|
|
68
|
+
this.#nextOrdinal += 1;
|
|
69
|
+
const entry = Object.freeze({
|
|
70
|
+
ordinal,
|
|
71
|
+
event,
|
|
72
|
+
...options.stateKey === void 0 ? {} : { stateKey: options.stateKey }
|
|
73
|
+
});
|
|
74
|
+
if (event.eventClass === "state") {
|
|
75
|
+
const previous = this.#currentState.get(options.stateKey);
|
|
76
|
+
if (previous !== void 0) this.#removeEntry(previous);
|
|
77
|
+
this.#currentState.set(options.stateKey, entry);
|
|
78
|
+
this.#entries.push(entry);
|
|
79
|
+
return Object.freeze({ ok: true, ordinal });
|
|
80
|
+
}
|
|
81
|
+
if (event.eventClass === "diagnostic") {
|
|
82
|
+
while (this.#count("diagnostic") >= this.#limits.maxDiagnosticEvents) {
|
|
83
|
+
const dropped = this.#entries.find(
|
|
84
|
+
(candidate) => candidate.event.eventClass === "diagnostic" && candidate.ordinal > this.#sealedThrough
|
|
85
|
+
);
|
|
86
|
+
if (dropped === void 0) {
|
|
87
|
+
this.#recordDiagnosticGap(entry);
|
|
88
|
+
return Object.freeze({ ok: true, ordinal });
|
|
89
|
+
}
|
|
90
|
+
this.#removeEntry(dropped);
|
|
91
|
+
this.#recordDiagnosticGap(dropped);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this.#entries.push(entry);
|
|
95
|
+
return Object.freeze({ ok: true, ordinal });
|
|
96
|
+
}
|
|
97
|
+
/** Seals current coalescing and diagnostic-gap groups. */
|
|
98
|
+
barrier() {
|
|
99
|
+
this.#currentState.clear();
|
|
100
|
+
this.#sealGap();
|
|
101
|
+
const token = this.#nextBarrierToken;
|
|
102
|
+
this.#nextBarrierToken += 1;
|
|
103
|
+
const highWaterMark = this.#nextOrdinal - 1;
|
|
104
|
+
this.#sealedThrough = Math.max(this.#sealedThrough, highWaterMark);
|
|
105
|
+
this.#barriers.set(token, highWaterMark);
|
|
106
|
+
return Object.freeze({ token, highWaterMark });
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Deliver everything through the barrier and remove it only after the sink
|
|
110
|
+
* succeeds. A rejected sink leaves the exact batch available for retry.
|
|
111
|
+
*/
|
|
112
|
+
async flushThrough(barrier, sink) {
|
|
113
|
+
if (this.#flushActive) {
|
|
114
|
+
throw new RangeError("another journal flush is already in progress");
|
|
115
|
+
}
|
|
116
|
+
if (!Number.isSafeInteger(barrier.token) || this.#barriers.get(barrier.token) !== barrier.highWaterMark || !Number.isSafeInteger(barrier.highWaterMark) || barrier.highWaterMark < this.#flushedThrough || barrier.highWaterMark >= this.#nextOrdinal) {
|
|
117
|
+
throw new RangeError("flush barrier is stale, forged or beyond the journal high-water mark");
|
|
118
|
+
}
|
|
119
|
+
const ordinary = this.#entries.filter((entry) => entry.ordinal <= barrier.highWaterMark);
|
|
120
|
+
const gaps = this.#gaps.filter((gap) => gap.ordinal <= barrier.highWaterMark);
|
|
121
|
+
const batch = Object.freeze(
|
|
122
|
+
[
|
|
123
|
+
...ordinary.map((entry) => ({ ordinal: entry.ordinal, event: entry.event })),
|
|
124
|
+
...gaps.map((gap) => ({ ordinal: gap.ordinal, event: gap.event }))
|
|
125
|
+
].sort((left, right) => left.ordinal - right.ordinal).map(({ event }) => event)
|
|
126
|
+
);
|
|
127
|
+
this.#flushActive = true;
|
|
128
|
+
try {
|
|
129
|
+
await sink(batch);
|
|
130
|
+
} finally {
|
|
131
|
+
this.#flushActive = false;
|
|
132
|
+
}
|
|
133
|
+
const flushed = new Set(ordinary);
|
|
134
|
+
for (let index = this.#entries.length - 1; index >= 0; index -= 1) {
|
|
135
|
+
if (flushed.has(this.#entries[index])) this.#entries.splice(index, 1);
|
|
136
|
+
}
|
|
137
|
+
const flushedGaps = new Set(gaps);
|
|
138
|
+
for (let index = this.#gaps.length - 1; index >= 0; index -= 1) {
|
|
139
|
+
if (flushedGaps.has(this.#gaps[index])) this.#gaps.splice(index, 1);
|
|
140
|
+
}
|
|
141
|
+
this.#flushedThrough = barrier.highWaterMark;
|
|
142
|
+
for (const [token, highWaterMark] of this.#barriers) {
|
|
143
|
+
if (highWaterMark <= barrier.highWaterMark) this.#barriers.delete(token);
|
|
144
|
+
}
|
|
145
|
+
return batch;
|
|
146
|
+
}
|
|
147
|
+
get pending() {
|
|
148
|
+
return this.#entries.length + this.#gaps.length + (this.#openGap === void 0 ? 0 : 1);
|
|
149
|
+
}
|
|
150
|
+
#count(eventClass) {
|
|
151
|
+
return this.#entries.reduce(
|
|
152
|
+
(count, entry) => count + (entry.event.eventClass === eventClass ? 1 : 0),
|
|
153
|
+
0
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
#removeEntry(entry) {
|
|
157
|
+
const index = this.#entries.indexOf(entry);
|
|
158
|
+
if (index >= 0) this.#entries.splice(index, 1);
|
|
159
|
+
}
|
|
160
|
+
#recordDiagnosticGap(dropped) {
|
|
161
|
+
if (this.#openGap === void 0) {
|
|
162
|
+
this.#openGap = {
|
|
163
|
+
ordinal: dropped.ordinal,
|
|
164
|
+
count: 1,
|
|
165
|
+
firstEventId: dropped.event.eventId,
|
|
166
|
+
lastEventId: dropped.event.eventId
|
|
167
|
+
};
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
this.#openGap.count += 1;
|
|
171
|
+
this.#openGap.lastEventId = dropped.event.eventId;
|
|
172
|
+
}
|
|
173
|
+
#sealGap() {
|
|
174
|
+
const gap = this.#openGap;
|
|
175
|
+
if (gap === void 0) return;
|
|
176
|
+
gap.event = this.#gapProducer.emit({
|
|
177
|
+
eventClass: "diagnostic",
|
|
178
|
+
type: "journal.diagnostic-gap",
|
|
179
|
+
identity: this.#gapIdentity,
|
|
180
|
+
causedBy: [gap.lastEventId],
|
|
181
|
+
payload: Object.freeze({
|
|
182
|
+
dropped: gap.count,
|
|
183
|
+
firstEventId: gap.firstEventId,
|
|
184
|
+
lastEventId: gap.lastEventId
|
|
185
|
+
})
|
|
186
|
+
});
|
|
187
|
+
this.#gaps.push(gap);
|
|
188
|
+
this.#openGap = void 0;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
function validStateKey(value) {
|
|
192
|
+
return value !== void 0 && /^[a-zA-Z0-9][a-zA-Z0-9./:_-]{0,255}$/u.test(value);
|
|
193
|
+
}
|
|
194
|
+
function failure(code, detail) {
|
|
195
|
+
return Object.freeze({ ok: false, code, detail });
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export {
|
|
199
|
+
DEFAULT_RUN_EVENT_JOURNAL_LIMITS,
|
|
200
|
+
RunEventJournal
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=chunk-ZZIYHDJ4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/run-journal.ts"],"sourcesContent":["import {\n RunEventProducer,\n RunEventStreamValidator,\n validateRunEvent,\n type InvocationId,\n type RunEvent,\n type RunEventId,\n type RunEventIdentity,\n type RunEventValidationResult,\n type RunId,\n} from './run-events.js';\n\nexport interface RunEventJournalLimits {\n /** Lossless events are rejected with backpressure at this pending count. */\n readonly maxAuthoritativeEvents: number;\n /** Distinct coalescing keys pending between flushes. */\n readonly maxStateKeys: number;\n /** Diagnostic events retained; evictions produce an explicit gap event. */\n readonly maxDiagnosticEvents: number;\n}\n\nexport const DEFAULT_RUN_EVENT_JOURNAL_LIMITS: RunEventJournalLimits = Object.freeze({\n maxAuthoritativeEvents: 10_000,\n maxStateKeys: 10_000,\n maxDiagnosticEvents: 1_000,\n});\n\nexport interface RunEventFlushBarrier {\n readonly token: number;\n readonly highWaterMark: number;\n}\n\nexport type RunEventJournalViolationCode =\n | Extract<RunEventValidationResult, { readonly ok: false }>['code']\n | 'stale-run'\n | 'journal-full'\n | 'state-key-required'\n | 'invalid-barrier';\n\nexport type RunEventJournalAppendResult =\n | { readonly ok: true; readonly ordinal: number }\n | { readonly ok: false; readonly code: RunEventJournalViolationCode; readonly detail: string };\n\ninterface JournalEntry {\n readonly ordinal: number;\n readonly event: RunEvent;\n readonly stateKey?: string;\n}\n\ninterface DiagnosticGap {\n readonly ordinal: number;\n count: number;\n readonly firstEventId: RunEventId;\n lastEventId: RunEventId;\n event?: RunEvent;\n}\n\n/**\n * In-memory ordering core used by the first-class Termwright test host.\n *\n * Authoritative events are never dropped. State coalescing is explicit and is\n * stopped by every barrier. Diagnostics are bounded, and every eviction is\n * represented by a lossless synthetic `journal.diagnostic-gap` event.\n */\nexport class RunEventJournal {\n readonly #invocationId: InvocationId;\n readonly #runId: RunId;\n readonly #limits: RunEventJournalLimits;\n readonly #validator = new RunEventStreamValidator();\n readonly #gapProducer: RunEventProducer;\n readonly #gapIdentity: RunEventIdentity;\n readonly #entries: JournalEntry[] = [];\n readonly #currentState = new Map<string, JournalEntry>();\n readonly #gaps: DiagnosticGap[] = [];\n readonly #barriers = new Map<number, number>();\n #openGap: DiagnosticGap | undefined;\n #nextOrdinal = 0;\n #nextBarrierToken = 0;\n #flushedThrough = -1;\n #sealedThrough = -1;\n #flushActive = false;\n\n constructor(options: {\n readonly invocationId: InvocationId;\n readonly runId: RunId;\n readonly gapProducer: RunEventProducer;\n readonly limits?: RunEventJournalLimits;\n }) {\n this.#invocationId = options.invocationId;\n this.#runId = options.runId;\n this.#gapProducer = options.gapProducer;\n this.#gapIdentity = Object.freeze({ invocationId: options.invocationId, runId: options.runId });\n this.#limits = options.limits ?? DEFAULT_RUN_EVENT_JOURNAL_LIMITS;\n for (const [name, value] of Object.entries(this.#limits)) {\n if (!Number.isSafeInteger(value) || value < 1)\n throw new TypeError(`${name} must be a positive safe integer`);\n }\n }\n\n append(\n value: unknown,\n options: { readonly stateKey?: string } = {},\n ): RunEventJournalAppendResult {\n const parsed = validateRunEvent(value);\n if (!parsed.ok) return parsed;\n const event = parsed.value;\n if (\n event.identity.invocationId !== this.#invocationId ||\n event.identity.runId !== this.#runId\n ) {\n return failure('stale-run', 'event belongs to another invocation or run');\n }\n if (event.eventClass === 'state' && !validStateKey(options.stateKey)) {\n return failure(\n 'state-key-required',\n 'state events require a bounded explicit coalescing key',\n );\n }\n if (\n event.eventClass === 'authoritative' &&\n this.#count('authoritative') >= this.#limits.maxAuthoritativeEvents\n ) {\n return failure(\n 'journal-full',\n 'authoritative queue is full; flush before accepting more events',\n );\n }\n if (\n event.eventClass === 'state' &&\n !this.#currentState.has(options.stateKey!) &&\n this.#currentState.size >= this.#limits.maxStateKeys\n ) {\n return failure(\n 'journal-full',\n 'state key queue is full; create a barrier and flush before accepting another key',\n );\n }\n const ordered = this.#validator.accept(event);\n if (!ordered.ok) return ordered;\n\n const ordinal = this.#nextOrdinal;\n this.#nextOrdinal += 1;\n const entry = Object.freeze({\n ordinal,\n event,\n ...(options.stateKey === undefined ? {} : { stateKey: options.stateKey }),\n });\n if (event.eventClass === 'state') {\n const previous = this.#currentState.get(options.stateKey!);\n if (previous !== undefined) this.#removeEntry(previous);\n this.#currentState.set(options.stateKey!, entry);\n this.#entries.push(entry);\n return Object.freeze({ ok: true, ordinal });\n }\n if (event.eventClass === 'diagnostic') {\n while (this.#count('diagnostic') >= this.#limits.maxDiagnosticEvents) {\n const dropped = this.#entries.find(\n (candidate) =>\n candidate.event.eventClass === 'diagnostic' && candidate.ordinal > this.#sealedThrough,\n );\n if (dropped === undefined) {\n // A barrier froze every retained diagnostic. Drop the new event and\n // describe that loss at the next barrier; never rewrite a sealed batch.\n this.#recordDiagnosticGap(entry);\n return Object.freeze({ ok: true, ordinal });\n }\n this.#removeEntry(dropped);\n this.#recordDiagnosticGap(dropped);\n }\n }\n this.#entries.push(entry);\n return Object.freeze({ ok: true, ordinal });\n }\n\n /** Seals current coalescing and diagnostic-gap groups. */\n barrier(): RunEventFlushBarrier {\n this.#currentState.clear();\n this.#sealGap();\n const token = this.#nextBarrierToken;\n this.#nextBarrierToken += 1;\n const highWaterMark = this.#nextOrdinal - 1;\n this.#sealedThrough = Math.max(this.#sealedThrough, highWaterMark);\n this.#barriers.set(token, highWaterMark);\n return Object.freeze({ token, highWaterMark });\n }\n\n /**\n * Deliver everything through the barrier and remove it only after the sink\n * succeeds. A rejected sink leaves the exact batch available for retry.\n */\n async flushThrough(\n barrier: RunEventFlushBarrier,\n sink: (events: readonly RunEvent[]) => void | Promise<void>,\n ): Promise<readonly RunEvent[]> {\n if (this.#flushActive) {\n throw new RangeError('another journal flush is already in progress');\n }\n if (\n !Number.isSafeInteger(barrier.token) ||\n this.#barriers.get(barrier.token) !== barrier.highWaterMark ||\n !Number.isSafeInteger(barrier.highWaterMark) ||\n barrier.highWaterMark < this.#flushedThrough ||\n barrier.highWaterMark >= this.#nextOrdinal\n ) {\n throw new RangeError('flush barrier is stale, forged or beyond the journal high-water mark');\n }\n const ordinary = this.#entries.filter((entry) => entry.ordinal <= barrier.highWaterMark);\n const gaps = this.#gaps.filter((gap) => gap.ordinal <= barrier.highWaterMark);\n const batch = Object.freeze(\n [\n ...ordinary.map((entry) => ({ ordinal: entry.ordinal, event: entry.event })),\n ...gaps.map((gap) => ({ ordinal: gap.ordinal, event: gap.event! })),\n ]\n .sort((left, right) => left.ordinal - right.ordinal)\n .map(({ event }) => event),\n );\n this.#flushActive = true;\n try {\n await sink(batch);\n } finally {\n this.#flushActive = false;\n }\n const flushed = new Set(ordinary);\n for (let index = this.#entries.length - 1; index >= 0; index -= 1) {\n if (flushed.has(this.#entries[index]!)) this.#entries.splice(index, 1);\n }\n const flushedGaps = new Set(gaps);\n for (let index = this.#gaps.length - 1; index >= 0; index -= 1) {\n if (flushedGaps.has(this.#gaps[index]!)) this.#gaps.splice(index, 1);\n }\n this.#flushedThrough = barrier.highWaterMark;\n for (const [token, highWaterMark] of this.#barriers) {\n if (highWaterMark <= barrier.highWaterMark) this.#barriers.delete(token);\n }\n return batch;\n }\n\n get pending(): number {\n // An open diagnostic gap is not flushable until a barrier seals it, but it\n // is still durable journal work and must be visible to backpressure/polling\n // consumers. Counting it prevents an apparently empty journal from hiding\n // a dropped diagnostic before the next flush barrier is created.\n return this.#entries.length + this.#gaps.length + (this.#openGap === undefined ? 0 : 1);\n }\n\n #count(eventClass: RunEvent['eventClass']): number {\n return this.#entries.reduce(\n (count, entry) => count + (entry.event.eventClass === eventClass ? 1 : 0),\n 0,\n );\n }\n\n #removeEntry(entry: JournalEntry): void {\n const index = this.#entries.indexOf(entry);\n if (index >= 0) this.#entries.splice(index, 1);\n }\n\n #recordDiagnosticGap(dropped: JournalEntry): void {\n if (this.#openGap === undefined) {\n this.#openGap = {\n ordinal: dropped.ordinal,\n count: 1,\n firstEventId: dropped.event.eventId,\n lastEventId: dropped.event.eventId,\n };\n return;\n }\n this.#openGap.count += 1;\n this.#openGap.lastEventId = dropped.event.eventId;\n }\n\n #sealGap(): void {\n const gap = this.#openGap;\n if (gap === undefined) return;\n gap.event = this.#gapProducer.emit({\n eventClass: 'diagnostic',\n type: 'journal.diagnostic-gap',\n identity: this.#gapIdentity,\n causedBy: [gap.lastEventId],\n payload: Object.freeze({\n dropped: gap.count,\n firstEventId: gap.firstEventId,\n lastEventId: gap.lastEventId,\n }),\n });\n this.#gaps.push(gap);\n this.#openGap = undefined;\n }\n}\n\nfunction validStateKey(value: string | undefined): value is string {\n return value !== undefined && /^[a-zA-Z0-9][a-zA-Z0-9./:_-]{0,255}$/u.test(value);\n}\n\nfunction failure(\n code: RunEventJournalViolationCode,\n detail: string,\n): Extract<RunEventJournalAppendResult, { readonly ok: false }> {\n return Object.freeze({ ok: false, code, detail });\n}\n"],"mappings":";;;;;;AAqBO,IAAM,mCAA0D,OAAO,OAAO;AAAA,EACnF,wBAAwB;AAAA,EACxB,cAAc;AAAA,EACd,qBAAqB;AACvB,CAAC;AAuCM,IAAM,kBAAN,MAAsB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa,IAAI,wBAAwB;AAAA,EACzC;AAAA,EACA;AAAA,EACA,WAA2B,CAAC;AAAA,EAC5B,gBAAgB,oBAAI,IAA0B;AAAA,EAC9C,QAAyB,CAAC;AAAA,EAC1B,YAAY,oBAAI,IAAoB;AAAA,EAC7C;AAAA,EACA,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EAEf,YAAY,SAKT;AACD,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,SAAS,QAAQ;AACtB,SAAK,eAAe,QAAQ;AAC5B,SAAK,eAAe,OAAO,OAAO,EAAE,cAAc,QAAQ,cAAc,OAAO,QAAQ,MAAM,CAAC;AAC9F,SAAK,UAAU,QAAQ,UAAU;AACjC,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACxD,UAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ;AAC1C,cAAM,IAAI,UAAU,GAAG,IAAI,kCAAkC;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,OACE,OACA,UAA0C,CAAC,GACd;AAC7B,UAAM,SAAS,iBAAiB,KAAK;AACrC,QAAI,CAAC,OAAO,GAAI,QAAO;AACvB,UAAM,QAAQ,OAAO;AACrB,QACE,MAAM,SAAS,iBAAiB,KAAK,iBACrC,MAAM,SAAS,UAAU,KAAK,QAC9B;AACA,aAAO,QAAQ,aAAa,4CAA4C;AAAA,IAC1E;AACA,QAAI,MAAM,eAAe,WAAW,CAAC,cAAc,QAAQ,QAAQ,GAAG;AACpE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QACE,MAAM,eAAe,mBACrB,KAAK,OAAO,eAAe,KAAK,KAAK,QAAQ,wBAC7C;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QACE,MAAM,eAAe,WACrB,CAAC,KAAK,cAAc,IAAI,QAAQ,QAAS,KACzC,KAAK,cAAc,QAAQ,KAAK,QAAQ,cACxC;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAAU,KAAK,WAAW,OAAO,KAAK;AAC5C,QAAI,CAAC,QAAQ,GAAI,QAAO;AAExB,UAAM,UAAU,KAAK;AACrB,SAAK,gBAAgB;AACrB,UAAM,QAAQ,OAAO,OAAO;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,GAAI,QAAQ,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,QAAQ,SAAS;AAAA,IACzE,CAAC;AACD,QAAI,MAAM,eAAe,SAAS;AAChC,YAAM,WAAW,KAAK,cAAc,IAAI,QAAQ,QAAS;AACzD,UAAI,aAAa,OAAW,MAAK,aAAa,QAAQ;AACtD,WAAK,cAAc,IAAI,QAAQ,UAAW,KAAK;AAC/C,WAAK,SAAS,KAAK,KAAK;AACxB,aAAO,OAAO,OAAO,EAAE,IAAI,MAAM,QAAQ,CAAC;AAAA,IAC5C;AACA,QAAI,MAAM,eAAe,cAAc;AACrC,aAAO,KAAK,OAAO,YAAY,KAAK,KAAK,QAAQ,qBAAqB;AACpE,cAAM,UAAU,KAAK,SAAS;AAAA,UAC5B,CAAC,cACC,UAAU,MAAM,eAAe,gBAAgB,UAAU,UAAU,KAAK;AAAA,QAC5E;AACA,YAAI,YAAY,QAAW;AAGzB,eAAK,qBAAqB,KAAK;AAC/B,iBAAO,OAAO,OAAO,EAAE,IAAI,MAAM,QAAQ,CAAC;AAAA,QAC5C;AACA,aAAK,aAAa,OAAO;AACzB,aAAK,qBAAqB,OAAO;AAAA,MACnC;AAAA,IACF;AACA,SAAK,SAAS,KAAK,KAAK;AACxB,WAAO,OAAO,OAAO,EAAE,IAAI,MAAM,QAAQ,CAAC;AAAA,EAC5C;AAAA;AAAA,EAGA,UAAgC;AAC9B,SAAK,cAAc,MAAM;AACzB,SAAK,SAAS;AACd,UAAM,QAAQ,KAAK;AACnB,SAAK,qBAAqB;AAC1B,UAAM,gBAAgB,KAAK,eAAe;AAC1C,SAAK,iBAAiB,KAAK,IAAI,KAAK,gBAAgB,aAAa;AACjE,SAAK,UAAU,IAAI,OAAO,aAAa;AACvC,WAAO,OAAO,OAAO,EAAE,OAAO,cAAc,CAAC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aACJ,SACA,MAC8B;AAC9B,QAAI,KAAK,cAAc;AACrB,YAAM,IAAI,WAAW,8CAA8C;AAAA,IACrE;AACA,QACE,CAAC,OAAO,cAAc,QAAQ,KAAK,KACnC,KAAK,UAAU,IAAI,QAAQ,KAAK,MAAM,QAAQ,iBAC9C,CAAC,OAAO,cAAc,QAAQ,aAAa,KAC3C,QAAQ,gBAAgB,KAAK,mBAC7B,QAAQ,iBAAiB,KAAK,cAC9B;AACA,YAAM,IAAI,WAAW,sEAAsE;AAAA,IAC7F;AACA,UAAM,WAAW,KAAK,SAAS,OAAO,CAAC,UAAU,MAAM,WAAW,QAAQ,aAAa;AACvF,UAAM,OAAO,KAAK,MAAM,OAAO,CAAC,QAAQ,IAAI,WAAW,QAAQ,aAAa;AAC5E,UAAM,QAAQ,OAAO;AAAA,MACnB;AAAA,QACE,GAAG,SAAS,IAAI,CAAC,WAAW,EAAE,SAAS,MAAM,SAAS,OAAO,MAAM,MAAM,EAAE;AAAA,QAC3E,GAAG,KAAK,IAAI,CAAC,SAAS,EAAE,SAAS,IAAI,SAAS,OAAO,IAAI,MAAO,EAAE;AAAA,MACpE,EACG,KAAK,CAAC,MAAM,UAAU,KAAK,UAAU,MAAM,OAAO,EAClD,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,IAC7B;AACA,SAAK,eAAe;AACpB,QAAI;AACF,YAAM,KAAK,KAAK;AAAA,IAClB,UAAE;AACA,WAAK,eAAe;AAAA,IACtB;AACA,UAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,aAAS,QAAQ,KAAK,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AACjE,UAAI,QAAQ,IAAI,KAAK,SAAS,KAAK,CAAE,EAAG,MAAK,SAAS,OAAO,OAAO,CAAC;AAAA,IACvE;AACA,UAAM,cAAc,IAAI,IAAI,IAAI;AAChC,aAAS,QAAQ,KAAK,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC9D,UAAI,YAAY,IAAI,KAAK,MAAM,KAAK,CAAE,EAAG,MAAK,MAAM,OAAO,OAAO,CAAC;AAAA,IACrE;AACA,SAAK,kBAAkB,QAAQ;AAC/B,eAAW,CAAC,OAAO,aAAa,KAAK,KAAK,WAAW;AACnD,UAAI,iBAAiB,QAAQ,cAAe,MAAK,UAAU,OAAO,KAAK;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,UAAkB;AAKpB,WAAO,KAAK,SAAS,SAAS,KAAK,MAAM,UAAU,KAAK,aAAa,SAAY,IAAI;AAAA,EACvF;AAAA,EAEA,OAAO,YAA4C;AACjD,WAAO,KAAK,SAAS;AAAA,MACnB,CAAC,OAAO,UAAU,SAAS,MAAM,MAAM,eAAe,aAAa,IAAI;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa,OAA2B;AACtC,UAAM,QAAQ,KAAK,SAAS,QAAQ,KAAK;AACzC,QAAI,SAAS,EAAG,MAAK,SAAS,OAAO,OAAO,CAAC;AAAA,EAC/C;AAAA,EAEA,qBAAqB,SAA6B;AAChD,QAAI,KAAK,aAAa,QAAW;AAC/B,WAAK,WAAW;AAAA,QACd,SAAS,QAAQ;AAAA,QACjB,OAAO;AAAA,QACP,cAAc,QAAQ,MAAM;AAAA,QAC5B,aAAa,QAAQ,MAAM;AAAA,MAC7B;AACA;AAAA,IACF;AACA,SAAK,SAAS,SAAS;AACvB,SAAK,SAAS,cAAc,QAAQ,MAAM;AAAA,EAC5C;AAAA,EAEA,WAAiB;AACf,UAAM,MAAM,KAAK;AACjB,QAAI,QAAQ,OAAW;AACvB,QAAI,QAAQ,KAAK,aAAa,KAAK;AAAA,MACjC,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,UAAU,KAAK;AAAA,MACf,UAAU,CAAC,IAAI,WAAW;AAAA,MAC1B,SAAS,OAAO,OAAO;AAAA,QACrB,SAAS,IAAI;AAAA,QACb,cAAc,IAAI;AAAA,QAClB,aAAa,IAAI;AAAA,MACnB,CAAC;AAAA,IACH,CAAC;AACD,SAAK,MAAM,KAAK,GAAG;AACnB,SAAK,WAAW;AAAA,EAClB;AACF;AAEA,SAAS,cAAc,OAA4C;AACjE,SAAO,UAAU,UAAa,wCAAwC,KAAK,KAAK;AAClF;AAEA,SAAS,QACP,MACA,QAC8D;AAC9D,SAAO,OAAO,OAAO,EAAE,IAAI,OAAO,MAAM,OAAO,CAAC;AAClD;","names":[]}
|