@opetope/devtools 0.1.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/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/README.ru.md +105 -0
- package/dist/activity-export.d.ts +4 -0
- package/dist/activity.d.ts +63 -0
- package/dist/conformance-activity.d.ts +8 -0
- package/dist/conformance.d.ts +37 -0
- package/dist/control-subject.d.ts +15 -0
- package/dist/control-ui-DMmVy9Ob.js +16 -0
- package/dist/control-ui-DMmVy9Ob.js.map +1 -0
- package/dist/control.d.ts +45 -0
- package/dist/corpus.d.ts +33 -0
- package/dist/decode-activity.d.ts +4 -0
- package/dist/decode-shapes.d.ts +32 -0
- package/dist/decode-values.d.ts +36 -0
- package/dist/decode.d.ts +41 -0
- package/dist/digest.d.ts +17 -0
- package/dist/export-run-DIQZax_d.js +2 -0
- package/dist/export-run-DIQZax_d.js.map +1 -0
- package/dist/export-snapshot-Buw-c6ZG.js +2 -0
- package/dist/export-snapshot-Buw-c6ZG.js.map +1 -0
- package/dist/export-snapshot.d.ts +34 -0
- package/dist/extension-points.d.ts +45 -0
- package/dist/fixture-plan.d.ts +62 -0
- package/dist/fixture-runtime.d.ts +37 -0
- package/dist/fixture.d.ts +23 -0
- package/dist/fold-snapshot-DjiURn8v.js +2 -0
- package/dist/fold-snapshot-DjiURn8v.js.map +1 -0
- package/dist/fold-snapshot.d.ts +15 -0
- package/dist/graph-index.d.ts +104 -0
- package/dist/graph-store.d.ts +77 -0
- package/dist/graph.d.ts +211 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector.d.ts +70 -0
- package/dist/install.d.ts +44 -0
- package/dist/install.js +2 -0
- package/dist/install.js.map +1 -0
- package/dist/integration.d.ts +42 -0
- package/dist/integration.js +2 -0
- package/dist/integration.js.map +1 -0
- package/dist/legend-DT7j0_pD.js +2 -0
- package/dist/legend-DT7j0_pD.js.map +1 -0
- package/dist/node-facts.d.ts +20 -0
- package/dist/node-state.d.ts +152 -0
- package/dist/optional.d.ts +9 -0
- package/dist/panel-5jvisQBr.js +367 -0
- package/dist/panel-5jvisQBr.js.map +1 -0
- package/dist/producer-ids.d.ts +15 -0
- package/dist/protocol-joKTjlMj.js +2 -0
- package/dist/protocol-joKTjlMj.js.map +1 -0
- package/dist/protocol.d.ts +238 -0
- package/dist/react/activity-rows.d.ts +12 -0
- package/dist/react/activity-view.d.ts +9 -0
- package/dist/react/control-locale.d.ts +25 -0
- package/dist/react/control-styles.d.ts +7 -0
- package/dist/react/control-ui.d.ts +37 -0
- package/dist/react/edge-filter.d.ts +36 -0
- package/dist/react/edge-filters.d.ts +17 -0
- package/dist/react/export-delivery.d.ts +33 -0
- package/dist/react/export-run.d.ts +20 -0
- package/dist/react/format.d.ts +17 -0
- package/dist/react/glyph.d.ts +20 -0
- package/dist/react/graph-layout.d.ts +67 -0
- package/dist/react/graph-view.d.ts +30 -0
- package/dist/react/graph-viewport.d.ts +48 -0
- package/dist/react/icons.d.ts +12 -0
- package/dist/react/inspector-view.d.ts +29 -0
- package/dist/react/label.d.ts +28 -0
- package/dist/react/lazy-module.d.ts +38 -0
- package/dist/react/legend-locale.d.ts +23 -0
- package/dist/react/legend.d.ts +10 -0
- package/dist/react/locale-context.d.ts +17 -0
- package/dist/react/locale.d.ts +115 -0
- package/dist/react/main-column.d.ts +22 -0
- package/dist/react/panel-header.d.ts +20 -0
- package/dist/react/panel-mode.d.ts +3 -0
- package/dist/react/panel-status.d.ts +19 -0
- package/dist/react/panel.d.ts +41 -0
- package/dist/react/search-results.d.ts +18 -0
- package/dist/react/selection.d.ts +15 -0
- package/dist/react/styles.d.ts +13 -0
- package/dist/react/theme.d.ts +39 -0
- package/dist/react/timeline-locale.d.ts +20 -0
- package/dist/react/timeline-view.d.ts +14 -0
- package/dist/react/tree.d.ts +26 -0
- package/dist/react/use-store.d.ts +11 -0
- package/dist/react.d.ts +16 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +1 -0
- package/dist/search-CC7avy6I.js +2 -0
- package/dist/search-CC7avy6I.js.map +1 -0
- package/dist/search.d.ts +20 -0
- package/dist/session-qjKT0E69.js +2 -0
- package/dist/session-qjKT0E69.js.map +1 -0
- package/dist/session.d.ts +59 -0
- package/dist/testing.d.ts +10 -0
- package/dist/testing.js +4 -0
- package/dist/testing.js.map +1 -0
- package/dist/timeline-view-ByPB1a7-.js +2 -0
- package/dist/timeline-view-ByPB1a7-.js.map +1 -0
- package/dist/timeline.d.ts +57 -0
- package/dist/visual-axes.d.ts +35 -0
- package/package.json +107 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sources":["../src/conformance-activity.ts","../src/conformance.ts","../src/producer-ids.ts","../src/fixture-plan.ts","../src/fixture-runtime.ts","../src/fixture.ts"],"sourcesContent":["import type { CallActivity, RuntimeActivitySnapshot } from './activity';\n\n/** Only the acceptance kit renames opaque identities across independent runs. Repeated identities stay repeated. */\nclass IdentityNames {\n private readonly names = new Map<string, string>();\n\n name(id: string): string {\n let name = this.names.get(id);\n\n if (name === undefined) {\n name = `known:${this.names.size}`;\n this.names.set(id, name);\n }\n\n return name;\n }\n}\n\nfunction comparableLane(\n lane: CallActivity['lane'],\n calls: ReadonlyMap<string, string>,\n lanes: IdentityNames,\n): CallActivity['lane'] {\n if (lane === null) return null;\n\n return {\n ...lane,\n blockedBy: lane.blockedBy === 'unknown' ? 'unknown' : lane.blockedBy.map(id => calls.get(id) ?? `unresolved:${id}`),\n id: lanes.name(lane.id),\n };\n}\n\n/**\n * D216: compare the same work in different applications without mistaking execution-local names for behavior.\n * Keep declarations, owner feature/instance/generation, load attempt/generation, order, counts and all states.\n * Call references are remapped through the same table as their subjects; unresolved references stay observable.\n */\nfunction comparableActivity(activity: RuntimeActivitySnapshot | undefined): RuntimeActivitySnapshot | undefined {\n if (activity === undefined) return undefined;\n\n const features = new IdentityNames();\n const calls = new IdentityNames();\n const lanes = new IdentityNames();\n const resources = new IdentityNames();\n const loads = new IdentityNames();\n const callIds = new Map(activity.calls.map(call => [call.id, calls.name(call.id)]));\n\n return {\n ...activity,\n calls: activity.calls.map(call => ({\n ...call,\n id: calls.name(call.id),\n lane: comparableLane(call.lane, callIds, lanes),\n })),\n executionId: 'execution',\n features: activity.features.map(feature => ({ ...feature, id: features.name(feature.id) })),\n resources: activity.resources.map(resource => ({\n ...resource,\n id: resources.name(resource.id),\n loads:\n resource.loads === 'unknown' ? 'unknown' : resource.loads.map(load => ({ ...load, id: loads.name(load.id) })),\n })),\n };\n}\n\nexport { comparableActivity };\n","/**\n * The acceptance list of `docs/devtools.md` §8, made executable.\n *\n * A runtime that implements `RuntimeInspectionSession` runs this kit against its own port and learns whether it holds\n * the contract, without reading a line of devtools. The kit deliberately does not depend on a test framework: it\n * throws one error listing every failed check, so it works from jest, from `node --test` and from a script.\n *\n * What it cannot check from outside is stated here rather than pretended: it observes demand neutrality only through\n * the snapshots the producer publishes, and it observes atomicity only as \"no partial frame was ever readable\".\n * Proving that no record is allocated without an observer belongs to the runtime's own gates (§6).\n */\n\nimport { comparableActivity } from './conformance-activity';\nimport { sameProtocolValue } from './digest';\nimport { foldFrames } from './fold-snapshot';\nimport type { RuntimeGraphFrame, RuntimeGraphSnapshot } from './graph';\nimport { frameSchemaRevision } from './graph';\nimport { DevtoolsGraphStore } from './graph-store';\nimport type { DiagnosticSequence } from './protocol';\nimport { diagnosticSequence, diagnosticSessionId, diagnosticStateRevision } from './protocol';\nimport type { ReadLimits, RuntimeInspectionSession } from './session';\nimport { connectDevtoolsSession } from './session';\n\n/**\n * What the kit needs beyond the session itself: a way to make the producer commit. A real port is driven by the\n * application, so the harness is whatever the caller uses to provoke one transaction.\n */\ntype InspectionSessionHarness = Readonly<{\n /** Commits one transaction. Returns `false` when the corpus is exhausted. */\n commit: () => boolean;\n /** Commits one transaction and drops it from the servable ring, provoking the `gap → resync` path of §7. */\n dropCommit?: () => boolean;\n session: RuntimeInspectionSession;\n}>;\n\ntype InspectionSessionFactory = () => InspectionSessionHarness;\n\ntype ContractCheckStatus = 'failed' | 'passed' | 'skipped';\n\ntype ContractCheck = Readonly<{\n detail?: string;\n name: string;\n status: ContractCheckStatus;\n}>;\n\nclass InspectionContractError extends Error {\n public constructor(public readonly checks: readonly ContractCheck[]) {\n const failed = checks.filter(check => check.status === 'failed');\n\n super(\n `RuntimeInspectionSession failed ${failed.length} of ${checks.length} contract checks:\\n${failed\n .map(check => ` - ${check.name}: ${check.detail ?? 'no detail'}`)\n .join('\\n')}`,\n );\n this.name = 'InspectionContractError';\n }\n}\n\nconst wideLimits: ReadLimits = { maxBytes: 8 * 1024 * 1024, maxFrames: 1024 };\nconst immediate = (task: () => void): (() => void) => {\n task();\n\n return () => undefined;\n};\n\ntype Recorder = {\n check: (name: string, ok: boolean, detail?: string) => void;\n readonly checks: ContractCheck[];\n skip: (name: string, detail: string) => void;\n};\n\nfunction createRecorder(): Recorder {\n const checks: ContractCheck[] = [];\n\n return {\n check: (name, ok, detail) => {\n checks.push({ ...(ok || detail === undefined ? {} : { detail }), name, status: ok ? 'passed' : 'failed' });\n },\n checks,\n skip: (name, detail) => void checks.push({ detail, name, status: 'skipped' }),\n };\n}\n\n/** Reads everything the producer will serve from this cursor, in bounded batches. */\nfunction drain(session: RuntimeInspectionSession, cursor: DiagnosticSequence): readonly RuntimeGraphFrame[] {\n const frames: RuntimeGraphFrame[] = [];\n let at = cursor;\n\n for (let pulls = 0; pulls < 64; pulls += 1) {\n const result = session.readSince(at, wideLimits);\n\n if (result.kind === 'resync-required' || result.frames.length === 0) return frames;\n\n frames.push(...result.frames);\n at = result.frames[result.frames.length - 1]?.lastSequence ?? at;\n }\n\n return frames;\n}\n\nfunction frameFault(frame: RuntimeGraphFrame, revision: number, sequence: number): string | undefined {\n if (frame.schemaRevision !== frameSchemaRevision) return 'has a foreign schema';\n\n if (frame.baseRevision !== revision) return 'does not continue the revision';\n\n if (frame.firstSequence !== sequence + 1) return 'leaves a sequence hole';\n\n return frame.operations.length === 0 && frame.activity === undefined ? 'commits nothing' : undefined;\n}\n\n/** The first place the feed stops being a contiguous log of whole transactions, or `undefined` when it never does. */\nfunction firstDiscontinuity(frames: readonly RuntimeGraphFrame[], base: RuntimeGraphSnapshot): string | undefined {\n let revision: number = base.stateRevision;\n let sequence: number = base.lastSequence;\n\n for (const frame of frames) {\n const fault = frameFault(frame, revision, sequence);\n\n if (fault !== undefined) return `frame ${frame.lastSequence} ${fault}`;\n\n revision = frame.nextRevision;\n sequence = frame.lastSequence;\n }\n\n return undefined;\n}\n\n/** D216: names are local to a run; activity states, generations and identity relationships remain comparable. */\nfunction withoutSession(snapshot: RuntimeGraphSnapshot): unknown {\n const { sessionId: _sessionId, ...rest } = snapshot;\n\n return { ...rest, activity: comparableActivity(snapshot.activity) };\n}\n\n/**\n * The core acceptance: at every commit boundary the state reached by folding the frames onto the first\n * snapshot must equal a snapshot taken fresh from the producer. A producer that drifts here is a debugger that will\n * eventually show a graph the application never had.\n */\nfunction checkSnapshotFolding(harness: InspectionSessionHarness, recorder: Recorder): void {\n const { session } = harness;\n const base = session.getSnapshot();\n const applied: RuntimeGraphFrame[] = [];\n let boundaries = 0;\n let mismatch: string | undefined;\n let cursor = base.lastSequence;\n\n while (harness.commit()) {\n const frames = drain(session, cursor);\n\n applied.push(...frames);\n cursor = applied[applied.length - 1]?.lastSequence ?? cursor;\n boundaries += 1;\n\n if (mismatch === undefined && !sameProtocolValue(foldFrames(base, applied), session.getSnapshot())) {\n mismatch = `snapshot and fold disagree after commit ${boundaries}`;\n }\n }\n\n recorder.check('snapshot equals snapshot plus frames at every commit boundary', mismatch === undefined, mismatch);\n recorder.check('the corpus commits at least one transaction', boundaries > 0, 'the harness never committed');\n}\n\n/**\n * §8: a frame is visible only after an atomic commit. From outside, that is exactly \"the producer never serves a\n * frame before the transaction that produced it\", and \"frames arrive contiguous in both revision and sequence\", so\n * no consumer can ever observe half of one.\n */\nfunction checkAtomicDelivery(harness: InspectionSessionHarness, recorder: Recorder): void {\n const { session } = harness;\n const base = session.getSnapshot();\n const idle = session.readSince(base.lastSequence, wideLimits);\n\n recorder.check(\n 'nothing is readable before the first commit',\n idle.kind === 'changes' && idle.frames.length === 0,\n 'the producer served a frame the application had not committed',\n );\n\n while (harness.commit());\n\n const broken = firstDiscontinuity(drain(session, base.lastSequence), base);\n\n recorder.check('frames arrive contiguous and whole', broken === undefined, broken);\n}\n\n/** §3.4: zero, one and several attached inspectors must leave the producer with the same story to tell. */\nfunction checkDemandNeutrality(factory: InspectionSessionFactory, recorder: Recorder): void {\n const unobserved = factory();\n\n while (unobserved.commit());\n\n const alone = unobserved.session.getSnapshot();\n unobserved.session.close();\n\n const shared = factory();\n const first = connectDevtoolsSession(shared.session, { schedule: immediate });\n const second = connectDevtoolsSession(shared.session, { schedule: immediate });\n\n while (shared.commit());\n\n const observed = shared.session.getSnapshot();\n const sameTerminalState = sameProtocolValue(withoutSession(alone), withoutSession(observed));\n\n recorder.check(\n 'the number of inspectors does not change what the producer reports',\n sameTerminalState,\n 'an observed run reached a different workspace snapshot than an unobserved one',\n );\n recorder.check(\n 'every attached inspector reduces the same state',\n first.store.status.stateRevision === second.store.status.stateRevision,\n 'two clients of one producer disagreed on the state revision',\n );\n\n first.close();\n second.close();\n}\n\n/** §7: a duplicate, a hole and a foreign session must never be applied to a live graph. */\nfunction checkFrameRejection(harness: InspectionSessionHarness, recorder: Recorder): void {\n const { session } = harness;\n const base = session.getSnapshot();\n\n if (!harness.commit()) {\n recorder.skip('rejects duplicate, gapped and stale frames', 'the harness committed nothing to replay');\n\n return;\n }\n\n const [frame] = drain(session, base.lastSequence);\n\n if (frame === undefined) {\n recorder.skip('rejects duplicate, gapped and stale frames', 'the producer served no frame to replay');\n\n return;\n }\n\n const store = new DevtoolsGraphStore(base);\n\n recorder.check('accepts the first contiguous frame', store.applyFrame(frame).kind === 'applied');\n recorder.check(\n 'rejects a duplicate frame',\n store.applyFrame(frame).kind === 'resync-required',\n 'a replayed frame advanced the graph twice',\n );\n\n const gapped = new DevtoolsGraphStore(base);\n const holed: RuntimeGraphFrame = {\n ...frame,\n firstSequence: diagnosticSequence(frame.firstSequence + 5),\n lastSequence: diagnosticSequence(frame.lastSequence + 5),\n nextRevision: diagnosticStateRevision(frame.nextRevision + 5),\n };\n\n recorder.check(\n 'rejects a frame that leaves a hole',\n gapped.applyFrame(holed).kind === 'resync-required',\n 'a gapped frame was applied instead of forcing a resync',\n );\n\n const stale = new DevtoolsGraphStore(base);\n const foreign: RuntimeGraphFrame = { ...frame, sessionId: diagnosticSessionId('conformance-foreign-session') };\n const outcome = stale.applyFrame(foreign);\n\n recorder.check(\n 'ignores a frame from another session',\n outcome.kind === 'ignored',\n 'a frame from a replaced plan reached the graph',\n );\n recorder.check(\n 'a rejected frame leaves the graph untouched',\n stale.status.stateRevision === base.stateRevision,\n 'a rejected frame still moved the state revision',\n );\n}\n\n/**\n * §3.3: the listener is called outside the scheduler callback, so reading from inside it must be safe and must not\n * be able to reenter a transition. From outside that is checkable as \"reading inside the listener sees a settled,\n * self-consistent snapshot\", and as \"doing so does not change what the next read returns\".\n */\nfunction checkListenerIsolation(harness: InspectionSessionHarness, recorder: Recorder): void {\n const { session } = harness;\n let reentrant: RuntimeGraphSnapshot | undefined;\n let threw: unknown;\n\n const release = session.subscribe(() => {\n try {\n reentrant ??= session.getSnapshot();\n } catch (error) {\n threw ??= error;\n }\n });\n\n harness.commit();\n release();\n\n recorder.check('reading from inside a listener does not throw', threw === undefined, String(threw));\n\n /**\n * §3.3 lets a producer notify out of band, and a real application commits on its own schedule rather than inside\n * the call that provoked it. When nothing arrived while `commit()` ran there is no notification to judge, so the\n * two checks below are skipped rather than failed: a kit that reported a defect here would be reporting its own\n * inability to drive the producer synchronously.\n */\n if (reentrant === undefined) {\n const reason = 'the producer did not notify while commit() ran, which §3.3 allows';\n\n recorder.skip('a listener observes a settled snapshot', reason);\n recorder.skip('the listener did not consume the frame it was notified about', reason);\n\n return;\n }\n\n recorder.check(\n 'a listener observes a settled snapshot',\n reentrant.stateRevision >= 0,\n 'the listener could not read the graph it was notified about',\n );\n recorder.check(\n 'the listener did not consume the frame it was notified about',\n sameProtocolValue(session.getSnapshot(), reentrant),\n 'reading inside the listener changed what a later read returns',\n );\n}\n\n/** §7: a throwing consumer is detached and reported out of band; the application keeps running. */\nfunction checkThrowingConsumer(harness: InspectionSessionHarness, recorder: Recorder): void {\n const failures: unknown[] = [];\n let reads = 0;\n const hostile: RuntimeInspectionSession = {\n close: () => undefined,\n getSnapshot: () => harness.session.getSnapshot(),\n readSince: () => {\n reads += 1;\n\n throw new Error('conformance: the producer refused to serve');\n },\n subscribe: listener => harness.session.subscribe(listener),\n };\n\n const connection = connectDevtoolsSession(hostile, {\n onFailure: failure => void failures.push(failure),\n schedule: immediate,\n });\n\n harness.commit();\n harness.commit();\n\n recorder.check('a throwing producer is reported out of band', failures.length === 1, `${failures.length} reports`);\n recorder.check('a throwing producer is read once and then detached', reads === 1, `${reads} reads`);\n\n connection.close();\n}\n\n/** §5.4 and §7: `close()` releases the subscription and stops the client, without stopping the application. */\nfunction checkCloseRevokes(factory: InspectionSessionFactory, recorder: Recorder): void {\n const harness = factory();\n let listeners = 0;\n const counted: RuntimeInspectionSession = {\n close: () => harness.session.close(),\n getSnapshot: () => harness.session.getSnapshot(),\n readSince: (cursor, limits) => harness.session.readSince(cursor, limits),\n subscribe: listener => {\n listeners += 1;\n\n const release = harness.session.subscribe(listener);\n\n return () => {\n listeners -= 1;\n release();\n };\n },\n };\n\n const connection = connectDevtoolsSession(counted, { schedule: immediate });\n\n recorder.check('connecting subscribes exactly once', listeners === 1, `${listeners} listeners`);\n harness.commit();\n\n const revisionAtClose = connection.store.status.stateRevision;\n connection.close();\n\n while (harness.commit());\n\n recorder.check('close releases the subscription', listeners === 0, `${listeners} listeners survived close`);\n recorder.check(\n 'a closed client stops reducing',\n connection.store.status.stateRevision === revisionAtClose,\n 'the store advanced after close',\n );\n}\n\n/**\n * Runs the whole acceptance list against a producer and throws one error naming every check that failed. Returns the\n * full list — including skipped checks — so a caller can assert coverage rather than assume it.\n */\nfunction runInspectionSessionContract(factory: InspectionSessionFactory): readonly ContractCheck[] {\n const recorder = createRecorder();\n\n checkSnapshotFolding(factory(), recorder);\n checkAtomicDelivery(factory(), recorder);\n checkDemandNeutrality(factory, recorder);\n checkFrameRejection(factory(), recorder);\n checkListenerIsolation(factory(), recorder);\n checkThrowingConsumer(factory(), recorder);\n checkCloseRevokes(factory, recorder);\n\n const resync = factory();\n\n if (resync.dropCommit === undefined) {\n recorder.skip('a dropped frame forces a snapshot resync', 'the harness cannot drop a committed frame');\n } else {\n const connection = connectDevtoolsSession(resync.session, { schedule: immediate });\n\n resync.dropCommit();\n\n while (resync.commit());\n\n recorder.check(\n 'a dropped frame forces a snapshot resync',\n resync.session.getSnapshot().stateRevision === connection.store.status.stateRevision,\n 'the client did not recover the state it missed',\n );\n recorder.check(\n 'a resync leaves a gap marker in the history',\n connection.store.timeline.list().some(entry => entry.kind === 'gap'),\n 'history closed over a hole without marking it',\n );\n connection.close();\n }\n\n if (recorder.checks.some(check => check.status === 'failed')) throw new InspectionContractError(recorder.checks);\n\n return recorder.checks;\n}\n\n/** Each harness owns one session, including checks that finish before they ever attach a client. */\nfunction ownHarness(harness: InspectionSessionHarness, releases: Set<() => void>): InspectionSessionHarness {\n const producer = harness.session;\n let closed = false;\n const close = (): void => {\n if (closed) return;\n\n closed = true;\n releases.delete(close);\n producer.close();\n };\n\n releases.add(close);\n\n return {\n commit: () => harness.commit(),\n ...(harness.dropCommit === undefined ? {} : { dropCommit: () => harness.dropCommit?.() ?? false }),\n session: {\n close,\n getSnapshot: () => producer.getSnapshot(),\n readSince: (cursor, limits) => producer.readSince(cursor, limits),\n subscribe: listener => producer.subscribe(listener),\n },\n };\n}\n\nfunction closeSessions(releases: Set<() => void>): { readonly failed: boolean; readonly failure: unknown } {\n let failed = false;\n let failure: unknown;\n\n for (const release of releases) {\n try {\n release();\n } catch (error) {\n if (!failed) {\n failed = true;\n failure = error;\n }\n }\n }\n\n return { failed, failure };\n}\n\nfunction assertInspectionSessionContract(factory: InspectionSessionFactory): readonly ContractCheck[] {\n const releases = new Set<() => void>();\n let outcome:\n | { readonly checks: readonly ContractCheck[]; readonly failed: false }\n | { readonly failed: true; readonly failure: unknown };\n\n try {\n outcome = { checks: runInspectionSessionContract(() => ownHarness(factory(), releases)), failed: false };\n } catch (failure) {\n outcome = { failed: true, failure };\n }\n\n const cleanup = closeSessions(releases);\n\n // A cleanup failure must not replace the producer or acceptance failure that brought us here.\n if (outcome.failed) throw outcome.failure;\n\n if (cleanup.failed) throw cleanup.failure;\n\n return outcome.checks;\n}\n\nexport { assertInspectionSessionContract, InspectionContractError };\nexport type { ContractCheck, ContractCheckStatus, InspectionSessionFactory, InspectionSessionHarness };\n","/**\n * The producer's own id composition, modelled once so the fixture composes ids the way a real application does\n * (D200, `docs/devtools.md` §2.6).\n *\n * The runtime escapes every part of an id before it joins the parts, because a declaration id may hold `/` and `:`\n * and a condition group key joins its conditions with `|` — none of which the consumer's grammar admits, and the\n * last of which it would read as a separator. The escape is reversible, so `probe.inspect/a` and `probe.inspect-a`\n * stay two nodes rather than folding into one.\n *\n * This package cannot import the runtime, so these are the same rules written out again. That is a copy with a\n * purpose: `__tests__/producer-ids.spec.ts` states the producer's output for every rule as a literal, so a change on\n * either side breaks a test here rather than quietly giving the fixture a composition of its own.\n */\n\nconst idEscapes = new Map<string, string>([\n ['/', '_s'],\n [':', '_c'],\n ['_', '__'],\n ['|', '_p'],\n]);\n\nfunction encodeIdPart(value: string): string {\n let encoded = '';\n\n for (const character of value) {\n const escape = idEscapes.get(character);\n\n if (escape !== undefined) {\n encoded += escape;\n continue;\n }\n\n // Anything else the grammar rejects keeps its code point, so an unexpected id stays readable and still unique.\n encoded += /[A-Za-z0-9.-]/u.test(character) ? character : `_u${(character.codePointAt(0) ?? 0).toString(16)}_`;\n }\n\n return encoded;\n}\n\nexport { encodeIdPart };\n","/**\n * A synthetic workspace application's compiled topology. It exercises the same kinds of nodes and relationships\n * that the runtime compiler emits, including hard/optional providers, on-demand hosts and a lazy feature body.\n *\n * Two features declare `when: [authorizedCondition]` and therefore form one condition group, the inferred owner of\n * activation (D93). The other nine have an empty `when` and are owned by the application itself; one of those nine\n * is a header whose `body` is still on the way, which the plan compiles like any other feature (D186).\n *\n * The story it encodes: the session ends, the group retires, `tasks.resource` fails its cleanup and is quarantined,\n * so the group never finishes closing — and the feature that weakly imports it keeps running on a `missing` lookup\n * instead of failing with it (D105). That is the case this tool exists for.\n */\n\nimport type {\n AbsentProviderPlanNode,\n ApplicationPlanSnapshot,\n ConditionGroupPlanNode,\n ConditionPlanNode,\n ContributionPlanNode,\n ContributionTargetPlanNode,\n FeaturePlanNode,\n HostContractPlanNode,\n PortPlanNode,\n} from './graph';\nimport { encodeIdPart } from './producer-ids';\nimport type {\n DiagnosticEdge,\n DiagnosticEdgeKind,\n DiagnosticNodeId,\n HostContractDemand,\n StructuralEdgeKind,\n WeakEdgeState,\n} from './protocol';\nimport { diagnosticConditionId, diagnosticEdgeId, diagnosticNodeId } from './protocol';\n\nconst id = diagnosticNodeId;\n\nconst fixtureIds = {\n absentExperiments: id('absent:experiments.exports'),\n accountReminder: id('accountReminder.autoOpen'),\n application: id('sampleApp'),\n appInfo: id('appInfo.polling'),\n catalogResolve: id('catalog.resolve'),\n authorizedGroup: id('group:sampleApp.authorized'),\n condition: id('sampleApp.authorized'),\n checkoutItemLookup: id('checkout.itemLookup'),\n checkoutCreateForm: id('checkout.createForm'),\n inventoryFeed: id('inventoryFeed'),\n hostCatalogPlatform: id('host:catalog.resolve.platform'),\n hostQuoteTelemetry: id('host:inventoryFeed.telemetry'),\n hostConfirmActionCommands: id('host:sessions.confirmAction.commands'),\n hostConfirmActionView: id('host:sessions.confirmAction.view'),\n hostHelpPlatform: id('host:utility.contributions.platform'),\n hostTasksPlatform: id('host:tasks.resource.platform'),\n dashboardPage: id('dashboard.page'),\n portQuote: id('port:inventoryFeed.quote'),\n portReceiptSink: id('port:checkout.receiptSink'),\n portResolveItem: id('port:catalog.resolveItem'),\n reportsPage: id('reports.page'),\n confirmAction: id('sessions.confirmAction'),\n helpContributions: id('utility.contributions'),\n targetHomeHeader: id('target:utility.homeHeader'),\n targetDashboardPage: id('target:dashboard.page'),\n targetOrderToolbar: id('target:checkout.orderHeaderToolbar'),\n targetConfirmActionContent: id('target:confirmAction.content'),\n tasksResource: id('tasks.resource'),\n} as const;\n\nconst fixtureContributionIds = {\n dashboardPage: id('contribution:dashboard.page.page'),\n orderToolbar: id('contribution:checkout.createForm.toolbar'),\n confirmActionContent: id('contribution:sessions.confirmAction.content'),\n supportHomeHeader: id('contribution:utility.contributions.homeHeader'),\n} as const;\n\nconst authorizedConditionId = diagnosticConditionId('sampleApp.authorized');\n\n/** The ends are themselves composed ids, so they are escaped again before `:` joins the three parts, as D200 does. */\nfunction edgeId(kind: DiagnosticEdgeKind, from: DiagnosticNodeId, to: DiagnosticNodeId) {\n return diagnosticEdgeId(`${kind}:${encodeIdPart(from)}:${encodeIdPart(to)}`);\n}\n\n/** A structural edge names a relation the compiler decided and nothing reports on later. */\nfunction structuralEdge(kind: StructuralEdgeKind, from: DiagnosticNodeId, to: DiagnosticNodeId): DiagnosticEdge {\n return { from, id: edgeId(kind, from, to), kind, to };\n}\n\n/** A hard edge is the only kind an activation waits on, so it is the only kind that can be pending. */\nfunction hardEdge(\n kind: 'hard-import' | 'requires-port',\n from: DiagnosticNodeId,\n to: DiagnosticNodeId,\n pending = false,\n): DiagnosticEdge {\n return { from, id: edgeId(kind, from, to), kind, pending, to };\n}\n\n/** A weak edge reports the `Lookup` its consumer reads and never waits (D105). */\nfunction weakEdge(\n kind: 'absent-import' | 'absent-port' | 'optional-import' | 'optional-port',\n from: DiagnosticNodeId,\n to: DiagnosticNodeId,\n lookup: WeakEdgeState,\n): DiagnosticEdge {\n return { from, id: edgeId(kind, from, to), kind, lookup, to };\n}\n\nconst applicationFeatures: readonly DiagnosticNodeId[] = [\n fixtureIds.accountReminder,\n fixtureIds.appInfo,\n fixtureIds.catalogResolve,\n fixtureIds.checkoutItemLookup,\n fixtureIds.checkoutCreateForm,\n fixtureIds.inventoryFeed,\n fixtureIds.dashboardPage,\n /** A header whose `body` is a dynamic import: the plan compiles without it, and the instance waits (D186). */\n fixtureIds.reportsPage,\n fixtureIds.helpContributions,\n];\n\n/** Members of the group open in this order and close in reverse; the compiler derived it from the hard edges. */\nconst groupFeatures: readonly DiagnosticNodeId[] = [fixtureIds.confirmAction, fixtureIds.tasksResource];\n\nfunction feature(nodeId: DiagnosticNodeId, owner: DiagnosticNodeId, provenance?: string): FeaturePlanNode {\n return {\n id: nodeId,\n kind: 'feature',\n label: nodeId,\n owner,\n ...(provenance === undefined ? {} : { provenance }),\n };\n}\n\nconst features: readonly FeaturePlanNode[] = [\n ...applicationFeatures.map(nodeId => feature(nodeId, fixtureIds.application)),\n feature(fixtureIds.confirmAction, fixtureIds.authorizedGroup, 'examples/workspace/sessions/confirm-action'),\n feature(fixtureIds.tasksResource, fixtureIds.authorizedGroup, 'examples/workspace/tasks'),\n];\n\nconst conditions: readonly ConditionPlanNode[] = [\n {\n conditionId: authorizedConditionId,\n id: fixtureIds.condition,\n kind: 'condition',\n label: 'sampleApp.authorized',\n provenance: 'examples/workspace/auth/conditions.contract.ts',\n source: 'host',\n },\n];\n\nconst groups: readonly ConditionGroupPlanNode[] = [\n {\n conditions: [authorizedConditionId],\n id: fixtureIds.authorizedGroup,\n kind: 'condition-group',\n label: 'when sampleApp.authorized',\n order: groupFeatures,\n },\n];\n\nconst ports: readonly PortPlanNode[] = [\n {\n id: fixtureIds.portResolveItem,\n kind: 'port',\n label: 'catalog.resolveItem',\n provider: fixtureIds.catalogResolve,\n },\n { id: fixtureIds.portQuote, kind: 'port', label: 'inventoryFeed.quote', provider: fixtureIds.inventoryFeed },\n { id: fixtureIds.portReceiptSink, kind: 'port', label: 'checkout.receiptSink' },\n];\n\nfunction hostContract(\n nodeId: DiagnosticNodeId,\n label: string,\n demand: HostContractDemand = 'instance',\n optional = false,\n): HostContractPlanNode {\n return { demand, id: nodeId, kind: 'host-contract', label, optional };\n}\n\nconst hostContracts: readonly HostContractPlanNode[] = [\n hostContract(fixtureIds.hostCatalogPlatform, 'catalog.resolve.platform'),\n hostContract(fixtureIds.hostQuoteTelemetry, 'inventoryFeed.telemetry', 'instance', true),\n hostContract(fixtureIds.hostConfirmActionCommands, 'sessions.confirmAction.commands', 'onDemand'),\n hostContract(fixtureIds.hostConfirmActionView, 'sessions.confirmAction.view'),\n hostContract(fixtureIds.hostHelpPlatform, 'utility.contributions.platform'),\n hostContract(fixtureIds.hostTasksPlatform, 'tasks.resource.platform'),\n];\n\n/** `optional(experimentsFeature)` where the application never enabled it: the `absent` provider of the IR (D105). */\nconst absentProviders: readonly AbsentProviderPlanNode[] = [\n { id: fixtureIds.absentExperiments, kind: 'absent-provider', label: 'experiments.exports' },\n];\n\nconst targets: readonly ContributionTargetPlanNode[] = [\n { id: fixtureIds.targetHomeHeader, kind: 'contribution-target', label: 'utility.homeHeader' },\n { id: fixtureIds.targetDashboardPage, kind: 'contribution-target', label: 'dashboard.page' },\n { id: fixtureIds.targetOrderToolbar, kind: 'contribution-target', label: 'checkout.orderHeaderToolbar' },\n { id: fixtureIds.targetConfirmActionContent, kind: 'contribution-target', label: 'confirmAction.content' },\n];\n\nfunction contribution(\n nodeId: DiagnosticNodeId,\n label: string,\n contributor: DiagnosticNodeId,\n target: DiagnosticNodeId,\n priority: number,\n): ContributionPlanNode {\n return { contributor, id: nodeId, kind: 'contribution', label, priority, target };\n}\n\nconst contributions: readonly ContributionPlanNode[] = [\n contribution(\n fixtureContributionIds.dashboardPage,\n 'dashboard.page',\n fixtureIds.dashboardPage,\n fixtureIds.targetDashboardPage,\n 0,\n ),\n contribution(\n fixtureContributionIds.orderToolbar,\n 'checkout.createForm.toolbar',\n fixtureIds.checkoutCreateForm,\n fixtureIds.targetOrderToolbar,\n 10,\n ),\n contribution(\n fixtureContributionIds.confirmActionContent,\n 'sessions.confirmAction.content',\n fixtureIds.confirmAction,\n fixtureIds.targetConfirmActionContent,\n 0,\n ),\n contribution(\n fixtureContributionIds.supportHomeHeader,\n 'utility.contributions.homeHeader',\n fixtureIds.helpContributions,\n fixtureIds.targetHomeHeader,\n 0,\n ),\n];\n\nconst planEdges: readonly DiagnosticEdge[] = [\n ...applicationFeatures.map(nodeId => structuralEdge('owns', fixtureIds.application, nodeId)),\n ...groupFeatures.map(nodeId => structuralEdge('owns', fixtureIds.authorizedGroup, nodeId)),\n structuralEdge('condition-control', fixtureIds.condition, fixtureIds.authorizedGroup),\n structuralEdge('provides-port', fixtureIds.catalogResolve, fixtureIds.portResolveItem),\n structuralEdge('provides-port', fixtureIds.inventoryFeed, fixtureIds.portQuote),\n structuralEdge('on-demand-import', fixtureIds.hostConfirmActionCommands, fixtureIds.confirmAction),\n ...contributions.flatMap(entry => [\n structuralEdge('owns', entry.contributor, entry.id),\n structuralEdge('contributes-to', entry.id, entry.target),\n ]),\n];\n\nconst fixturePlan: ApplicationPlanSnapshot = {\n absentProviders,\n application: {\n features: features.length,\n groups: groups.length,\n id: fixtureIds.application,\n kind: 'application',\n label: 'sampleApp',\n },\n conditions,\n contributions,\n edges: planEdges,\n features,\n groups,\n hostContracts,\n ports,\n targets,\n};\n\n/** Exported so a test can assert the fixture really covers every edge semantic the protocol distinguishes. */\nconst fixtureEdgeKinds: readonly DiagnosticEdgeKind[] = [\n 'absent-import',\n 'absent-port',\n 'condition-control',\n 'contributes-to',\n 'hard-import',\n 'on-demand-import',\n 'optional-import',\n 'optional-port',\n 'owns',\n 'provides-port',\n 'requires-port',\n];\n\nexport { hardEdge as fixtureHardEdge, structuralEdge as fixtureStructuralEdge, weakEdge as fixtureWeakEdge };\nexport { authorizedConditionId, fixtureContributionIds, fixtureEdgeKinds, fixtureIds, fixturePlan };\n","/**\n * The live world of the fixture plan and the commits that take it apart.\n *\n * The initial snapshot is a healthy authorized session. The six frames are one logout: the condition flips, the\n * group retires its members in reverse canonical order, `sessions.confirmAction` closes cleanly, and\n * `tasks.resource` fails the cleanup of its resource attachment and is quarantined — so the group never reaches\n * `closed`, and the feature that weakly imports tasks flips from `found` to `missing` and keeps running (D105).\n *\n * The snapshot is deliberately taken *before* the cascade, so connecting to the fixture exercises the reducer and\n * populates the causal chain instead of handing the panel a finished picture it never had to reduce.\n */\n\nimport {\n authorizedConditionId,\n fixtureContributionIds,\n fixtureHardEdge,\n fixtureIds,\n fixturePlan,\n fixtureStructuralEdge,\n fixtureWeakEdge,\n} from './fixture-plan';\nimport type {\n AttachmentNode,\n ConditionGroupRuntimeNode,\n ConditionRuntimeNode,\n ContributionRuntimeNode,\n FeatureInstanceNode,\n HostContractRuntimeNode,\n PortRuntimeNode,\n RuntimeGraphFrame,\n RuntimeGraphSnapshot,\n RuntimeStateSnapshot,\n} from './graph';\nimport { frameSchemaRevision, graphSchemaRevision } from './graph';\nimport type { AttachmentState, ConditionGroupState, ContributionState, FeatureInstanceState } from './node-state';\nimport type { DiagnosticCauseRef, DiagnosticEdge, DiagnosticNodeId, DiagnosticTimestamp } from './protocol';\nimport {\n diagnosticNodeId,\n diagnosticPlanFingerprint,\n diagnosticSequence,\n diagnosticSessionId,\n diagnosticStateRevision,\n diagnosticTopologyRevision,\n} from './protocol';\n\nconst fixtureSessionId = diagnosticSessionId('session-7');\nconst planFingerprint = diagnosticPlanFingerprint('a3f9c2');\nconst topologyRevision = diagnosticTopologyRevision(1);\n\nconst baseSequence = 1280;\nconst baseRevision = 508;\n\nconst t0: DiagnosticTimestamp = Date.UTC(2026, 8, 3, 14, 2, 31, 72);\n\nfunction instanceId(feature: DiagnosticNodeId): DiagnosticNodeId {\n return diagnosticNodeId(`instance:${feature}`);\n}\n\nconst fixtureInstanceIds = {\n accountReminder: instanceId(fixtureIds.accountReminder),\n appInfo: instanceId(fixtureIds.appInfo),\n catalogResolve: instanceId(fixtureIds.catalogResolve),\n checkoutItemLookup: instanceId(fixtureIds.checkoutItemLookup),\n checkoutCreateForm: instanceId(fixtureIds.checkoutCreateForm),\n inventoryFeed: instanceId(fixtureIds.inventoryFeed),\n dashboardPage: instanceId(fixtureIds.dashboardPage),\n confirmAction: instanceId(fixtureIds.confirmAction),\n helpContributions: instanceId(fixtureIds.helpContributions),\n tasksResource: instanceId(fixtureIds.tasksResource),\n} as const;\n\nconst fixtureAttachmentIds = {\n confirmActionCommands: diagnosticNodeId('attachment:sessions.confirmAction.commands'),\n tasksResource: diagnosticNodeId('attachment:tasks.resource.tasks'),\n} as const;\n\nconst conditionChange = (at: DiagnosticTimestamp): DiagnosticCauseRef => ({\n at,\n condition: authorizedConditionId,\n kind: 'condition-change',\n});\n\nfunction condition(active: boolean, cause?: DiagnosticCauseRef): ConditionRuntimeNode {\n return {\n ...(cause === undefined ? {} : { cause }),\n id: fixtureIds.condition,\n kind: 'condition',\n label: 'sampleApp.authorized',\n state: active ? { kind: 'true' } : { kind: 'false' },\n };\n}\n\nfunction group(state: ConditionGroupState, active: boolean, cause?: DiagnosticCauseRef): ConditionGroupRuntimeNode {\n const desired = active ? 'active' : 'inactive';\n\n return {\n ...(cause === undefined ? {} : { cause }),\n desired: { effective: desired, override: 'none', source: desired },\n id: fixtureIds.authorizedGroup,\n kind: 'condition-group',\n label: 'when sampleApp.authorized',\n state,\n };\n}\n\nfunction instance(\n feature: DiagnosticNodeId,\n generation: number,\n state: FeatureInstanceState,\n owner?: DiagnosticNodeId,\n cause?: DiagnosticCauseRef,\n): FeatureInstanceNode {\n return {\n ...(cause === undefined ? {} : { cause }),\n declaration: feature,\n generation,\n ...(owner === undefined ? {} : { group: owner }),\n id: instanceId(feature),\n kind: 'feature-instance',\n label: feature,\n state,\n };\n}\n\nconst ready: FeatureInstanceState = { kind: 'ready' };\n\nfunction attachment(nodeId: DiagnosticNodeId, label: string, owner: DiagnosticNodeId, state: AttachmentState) {\n return { id: nodeId, kind: 'attachment' as const, label, owner, state } satisfies AttachmentNode;\n}\n\nfunction contribution(nodeId: DiagnosticNodeId, state: ContributionState): ContributionRuntimeNode {\n const declaration = fixturePlan.contributions.find(entry => entry.id === nodeId);\n\n return {\n contributor: instanceId(declaration?.contributor ?? nodeId),\n declaration: nodeId,\n id: nodeId,\n kind: 'contribution',\n label: declaration?.label ?? nodeId,\n state,\n target: declaration?.target ?? nodeId,\n };\n}\n\n/**\n * The header of D186: the instance exists and is `opening` while its `body` is still being fetched. Loading is a\n * phase of opening, not a state of its own, so the panel reads the path it already knows and the schema is untouched.\n */\nconst loadingHeader = instance(fixtureIds.reportsPage, 1, { kind: 'opening' }, undefined, {\n at: t0,\n kind: 'instance-transition',\n node: instanceId(fixtureIds.reportsPage),\n});\n\nconst applicationInstances: readonly FeatureInstanceNode[] = [\n instance(fixtureIds.accountReminder, 1, ready),\n instance(fixtureIds.appInfo, 1, ready),\n instance(fixtureIds.catalogResolve, 1, ready),\n instance(fixtureIds.checkoutItemLookup, 1, ready),\n instance(fixtureIds.checkoutCreateForm, 1, ready),\n instance(fixtureIds.inventoryFeed, 1, ready),\n instance(fixtureIds.dashboardPage, 1, ready),\n loadingHeader,\n instance(fixtureIds.helpContributions, 1, ready),\n];\n\nconst openConfirmAction = instance(fixtureIds.confirmAction, 3, ready, fixtureIds.authorizedGroup, conditionChange(t0));\nconst openTasks = instance(fixtureIds.tasksResource, 3, ready, fixtureIds.authorizedGroup, conditionChange(t0));\n\nconst initialPorts: readonly PortRuntimeNode[] = [\n {\n declaration: fixtureIds.portResolveItem,\n id: fixtureIds.portResolveItem,\n kind: 'port',\n label: 'catalog.resolveItem',\n state: { instance: fixtureInstanceIds.catalogResolve, kind: 'available' },\n },\n {\n declaration: fixtureIds.portQuote,\n id: fixtureIds.portQuote,\n kind: 'port',\n label: 'inventoryFeed.quote',\n state: { instance: fixtureInstanceIds.inventoryFeed, kind: 'available' },\n },\n {\n declaration: fixtureIds.portReceiptSink,\n id: fixtureIds.portReceiptSink,\n kind: 'port',\n label: 'checkout.receiptSink',\n state: { kind: 'absent' },\n },\n];\n\nfunction hostContractNode(nodeId: DiagnosticNodeId, label: string, state: HostContractRuntimeNode['state']) {\n return { declaration: nodeId, id: nodeId, kind: 'host-contract' as const, label, state } as HostContractRuntimeNode;\n}\n\nconst initialHostContracts: readonly HostContractRuntimeNode[] = [\n hostContractNode(fixtureIds.hostCatalogPlatform, 'catalog.resolve.platform', { kind: 'bound' }),\n hostContractNode(fixtureIds.hostQuoteTelemetry, 'inventoryFeed.telemetry', { kind: 'unbound' }),\n hostContractNode(fixtureIds.hostConfirmActionCommands, 'sessions.confirmAction.commands', { kind: 'deferred' }),\n hostContractNode(fixtureIds.hostConfirmActionView, 'sessions.confirmAction.view', { kind: 'bound' }),\n hostContractNode(fixtureIds.hostHelpPlatform, 'utility.contributions.platform', { kind: 'bound' }),\n hostContractNode(fixtureIds.hostTasksPlatform, 'tasks.resource.platform', { kind: 'bound' }),\n];\n\nconst initialContributions: readonly ContributionRuntimeNode[] = [\n contribution(fixtureContributionIds.dashboardPage, { kind: 'published' }),\n /** Published and valid, but `when: imports.platform.submitAllowed` reads false, so the target omits it (D79). */\n contribution(fixtureContributionIds.orderToolbar, { kind: 'withheld' }),\n contribution(fixtureContributionIds.confirmActionContent, { kind: 'published' }),\n contribution(fixtureContributionIds.supportHomeHeader, { kind: 'published' }),\n];\n\nconst initialAttachments: readonly AttachmentNode[] = [\n attachment(fixtureAttachmentIds.confirmActionCommands, 'commands', fixtureInstanceIds.confirmAction, {\n kind: 'ready',\n }),\n attachment(fixtureAttachmentIds.tasksResource, 'tasks', fixtureInstanceIds.tasksResource, { kind: 'ready' }),\n];\n\nconst ownershipEdges: readonly DiagnosticEdge[] = [\n ...applicationInstances.map(node => fixtureStructuralEdge('owns', fixtureIds.application, node.id)),\n fixtureStructuralEdge('owns', fixtureIds.authorizedGroup, fixtureInstanceIds.confirmAction),\n fixtureStructuralEdge('owns', fixtureIds.authorizedGroup, fixtureInstanceIds.tasksResource),\n fixtureStructuralEdge('owns', fixtureInstanceIds.confirmAction, fixtureAttachmentIds.confirmActionCommands),\n fixtureStructuralEdge('owns', fixtureInstanceIds.tasksResource, fixtureAttachmentIds.tasksResource),\n ...fixturePlan.contributions.map(entry => fixtureStructuralEdge('owns', instanceId(entry.contributor), entry.id)),\n];\n\nconst dependencyEdges: readonly DiagnosticEdge[] = [\n fixtureHardEdge('hard-import', fixtureIds.hostCatalogPlatform, fixtureInstanceIds.catalogResolve),\n fixtureHardEdge('hard-import', fixtureIds.hostConfirmActionView, fixtureInstanceIds.confirmAction),\n fixtureHardEdge('hard-import', fixtureIds.hostHelpPlatform, fixtureInstanceIds.helpContributions),\n fixtureHardEdge('hard-import', fixtureIds.hostTasksPlatform, fixtureInstanceIds.tasksResource),\n fixtureHardEdge('requires-port', fixtureIds.portResolveItem, fixtureInstanceIds.checkoutItemLookup),\n fixtureWeakEdge('absent-port', fixtureIds.portReceiptSink, fixtureInstanceIds.checkoutCreateForm, 'missing'),\n fixtureWeakEdge('optional-port', fixtureIds.portQuote, fixtureInstanceIds.checkoutCreateForm, 'found'),\n fixtureWeakEdge('absent-import', fixtureIds.absentExperiments, fixtureInstanceIds.inventoryFeed, 'missing'),\n fixtureWeakEdge('optional-import', fixtureIds.hostQuoteTelemetry, fixtureInstanceIds.inventoryFeed, 'missing'),\n];\n\n/** The weak edge the cascade flips: help keeps running while tasks goes away (D105). */\nconst supportReadsTasks = (lookup: 'found' | 'missing'): DiagnosticEdge =>\n fixtureWeakEdge('optional-import', fixtureInstanceIds.tasksResource, fixtureInstanceIds.helpContributions, lookup);\n\nconst initialRuntime: RuntimeStateSnapshot = {\n attachments: initialAttachments,\n conditions: [condition(true)],\n contributions: initialContributions,\n edges: [...ownershipEdges, ...dependencyEdges, supportReadsTasks('found')],\n groups: [group({ kind: 'active' }, true)],\n hostContracts: initialHostContracts,\n instances: [...applicationInstances, openConfirmAction, openTasks],\n ports: initialPorts,\n};\n\nconst fixtureSnapshot: RuntimeGraphSnapshot = {\n lastSequence: diagnosticSequence(baseSequence),\n plan: fixturePlan,\n planFingerprint,\n runtime: initialRuntime,\n schemaRevision: graphSchemaRevision,\n sessionId: fixtureSessionId,\n stateRevision: diagnosticStateRevision(baseRevision),\n topologyRevision,\n};\n\nfunction frame(\n offset: number,\n cause: DiagnosticCauseRef,\n operations: RuntimeGraphFrame['operations'],\n): RuntimeGraphFrame {\n return {\n baseRevision: diagnosticStateRevision(baseRevision + offset - 1),\n cause,\n firstSequence: diagnosticSequence(baseSequence + offset),\n lastSequence: diagnosticSequence(baseSequence + offset),\n nextRevision: diagnosticStateRevision(baseRevision + offset),\n operations,\n schemaRevision: frameSchemaRevision,\n sessionId: fixtureSessionId,\n };\n}\n\nconst retiredByCondition: FeatureInstanceState = { kind: 'retired', reason: 'condition-inactive' };\n\nconst cleanupFailure = {\n cause: { kind: 'failure' as const, node: fixtureAttachmentIds.tasksResource },\n code: 'cleanup-failed' as const,\n phase: 'drain' as const,\n subject: 'feature' as const,\n};\n\nconst quarantineFailure = {\n cause: { kind: 'failure' as const, node: fixtureAttachmentIds.tasksResource },\n code: 'quarantined' as const,\n phase: 'drain' as const,\n subject: 'feature' as const,\n};\n\n/**\n * Seven commits, one visible scheduler transaction each: the session ends, one cleanup refuses to settle, and the\n * header whose body was still loading finishes opening — an ordinary `opening` → `ready` transition (D186).\n */\nconst fixtureFrames: readonly RuntimeGraphFrame[] = [\n frame(1, { ...conditionChange(t0), node: fixtureIds.condition }, [\n { node: condition(false, conditionChange(t0)), op: 'upsert-node' },\n { node: group({ kind: 'retiring', remaining: 2 }, false, conditionChange(t0)), op: 'upsert-node' },\n ]),\n frame(2, { at: t0 + 3, kind: 'instance-transition', node: fixtureInstanceIds.confirmAction }, [\n {\n node: instance(fixtureIds.confirmAction, 3, { kind: 'fencing' }, fixtureIds.authorizedGroup, conditionChange(t0)),\n op: 'upsert-node',\n },\n { node: contribution(fixtureContributionIds.confirmActionContent, { kind: 'withdrawn' }), op: 'upsert-node' },\n ]),\n frame(3, { at: t0 + 9, kind: 'instance-transition', node: fixtureInstanceIds.confirmAction }, [\n {\n node: instance(\n fixtureIds.confirmAction,\n 3,\n { kind: 'draining' },\n fixtureIds.authorizedGroup,\n conditionChange(t0),\n ),\n op: 'upsert-node',\n },\n {\n node: attachment(fixtureAttachmentIds.confirmActionCommands, 'commands', fixtureInstanceIds.confirmAction, {\n kind: 'closing',\n phase: 'close',\n }),\n op: 'upsert-node',\n },\n ]),\n frame(4, { at: t0 + 21, kind: 'group-transition', node: fixtureIds.authorizedGroup }, [\n {\n node: instance(fixtureIds.confirmAction, 3, retiredByCondition, fixtureIds.authorizedGroup, conditionChange(t0)),\n op: 'upsert-node',\n },\n { id: fixtureAttachmentIds.confirmActionCommands, op: 'remove-node' },\n { node: group({ kind: 'retiring', remaining: 1 }, false, conditionChange(t0)), op: 'upsert-node' },\n ]),\n frame(5, { at: t0 + 24, kind: 'instance-transition', node: fixtureInstanceIds.tasksResource }, [\n {\n node: instance(\n fixtureIds.tasksResource,\n 3,\n { kind: 'draining' },\n fixtureIds.authorizedGroup,\n conditionChange(t0),\n ),\n op: 'upsert-node',\n },\n {\n node: attachment(fixtureAttachmentIds.tasksResource, 'tasks', fixtureInstanceIds.tasksResource, {\n kind: 'closing',\n phase: 'close',\n }),\n op: 'upsert-node',\n },\n { edge: supportReadsTasks('missing'), op: 'upsert-edge' },\n ]),\n frame(6, { at: t0 + 102, kind: 'failure', node: fixtureAttachmentIds.tasksResource }, [\n {\n node: attachment(fixtureAttachmentIds.tasksResource, 'tasks', fixtureInstanceIds.tasksResource, {\n failure: cleanupFailure,\n kind: 'failed-close',\n }),\n op: 'upsert-node',\n },\n {\n node: instance(\n fixtureIds.tasksResource,\n 3,\n { failure: quarantineFailure, kind: 'quarantined' },\n fixtureIds.authorizedGroup,\n { at: t0 + 102, kind: 'failure', node: fixtureAttachmentIds.tasksResource },\n ),\n op: 'upsert-node',\n },\n ]),\n frame(7, { at: t0 + 140, kind: 'instance-transition', node: instanceId(fixtureIds.reportsPage) }, [\n {\n node: instance(fixtureIds.reportsPage, 1, ready, undefined, {\n at: t0 + 140,\n kind: 'instance-transition',\n node: instanceId(fixtureIds.reportsPage),\n }),\n op: 'upsert-node',\n },\n ]),\n];\n\nexport { fixtureAttachmentIds, fixtureFrames, fixtureInstanceIds, fixtureSessionId, fixtureSnapshot };\n","/**\n * A `RuntimeInspectionSession` backed by the sample state, so the panel and its tests run against the real pull /\n * cursor / resync path rather than a hand-placed store.\n *\n * It can also misbehave on purpose: `dropNext` commits a frame and drops it from the servable ring, which is exactly\n * the `queue overflow → bounded gap marker → snapshot resync` case of §7.\n */\n\nimport { fixtureFrames, fixtureSnapshot } from './fixture-runtime';\nimport { foldFrames } from './fold-snapshot';\nimport type { RuntimeGraphFrame, RuntimeGraphSnapshot } from './graph';\nimport type { DiagnosticSequence } from './protocol';\nimport type { ReadLimits, ReadResult, RuntimeInspectionSession } from './session';\n\ntype FixtureSession = Readonly<{\n /** Commits the next frame but drops it from the servable ring: the client must resync from a snapshot. */\n dropNext: () => boolean;\n emitAll: () => void;\n emitNext: () => boolean;\n pendingCount: () => number;\n}> &\n RuntimeInspectionSession;\n\ntype FixtureSessionOptions = Readonly<{\n frames?: readonly RuntimeGraphFrame[];\n snapshot?: RuntimeGraphSnapshot;\n}>;\n\nfunction createFixtureSession(options: FixtureSessionOptions = {}): FixtureSession {\n const base = options.snapshot ?? fixtureSnapshot;\n const pending = [...(options.frames ?? fixtureFrames)];\n const committed: RuntimeGraphFrame[] = [];\n const listeners = new Set<() => void>();\n\n let oldestServable = base.lastSequence + 1;\n let closed = false;\n\n const notify = (): void => {\n for (const listener of listeners) listener();\n };\n\n const commit = (servable: boolean): boolean => {\n const next = pending.shift();\n\n if (next === undefined) return false;\n\n committed.push(next);\n\n if (!servable) oldestServable = next.lastSequence + 1;\n\n notify();\n\n return true;\n };\n\n const current = (): RuntimeGraphSnapshot => foldFrames(base, committed);\n\n return {\n close: () => {\n closed = true;\n listeners.clear();\n pending.length = 0;\n },\n dropNext: () => commit(false),\n emitAll: () => {\n while (commit(true));\n },\n emitNext: () => commit(true),\n getSnapshot: current,\n pendingCount: () => pending.length,\n readSince: (cursor: DiagnosticSequence, limits: ReadLimits): ReadResult => {\n if (closed) return { frames: [], kind: 'changes' };\n\n if (cursor + 1 < oldestServable) return { kind: 'resync-required', snapshot: current() };\n\n const frames = committed.filter(frame => frame.firstSequence > cursor).slice(0, limits.maxFrames);\n\n return { frames, kind: 'changes' };\n },\n subscribe: (listener: () => void) => {\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\nexport { createFixtureSession };\nexport type { FixtureSession, FixtureSessionOptions };\n"],"names":["IdentityNames","id","name","comparableLane","lane","calls","lanes","comparableActivity","activity","features","resources","loads","callIds","call","feature","resource","load","InspectionContractError","checks","failed","check","wideLimits","immediate","task","createRecorder","ok","detail","drain","session","cursor","frames","at","pulls","result","_a","frameFault","frame","revision","sequence","frameSchemaRevision","firstDiscontinuity","base","fault","withoutSession","snapshot","_sessionId","rest","checkSnapshotFolding","harness","recorder","applied","boundaries","mismatch","sameProtocolValue","foldFrames","checkAtomicDelivery","idle","broken","checkDemandNeutrality","factory","unobserved","alone","shared","first","connectDevtoolsSession","second","observed","sameTerminalState","checkFrameRejection","store","DevtoolsGraphStore","gapped","holed","diagnosticSequence","diagnosticStateRevision","stale","foreign","diagnosticSessionId","outcome","checkListenerIsolation","reentrant","threw","release","error","reason","checkThrowingConsumer","failures","reads","connection","listener","failure","checkCloseRevokes","listeners","limits","revisionAtClose","runInspectionSessionContract","resync","entry","ownHarness","releases","producer","closed","close","closeSessions","assertInspectionSessionContract","cleanup","idEscapes","encodeIdPart","value","encoded","character","escape","diagnosticNodeId","fixtureIds","fixtureContributionIds","authorizedConditionId","diagnosticConditionId","edgeId","kind","from","to","diagnosticEdgeId","structuralEdge","hardEdge","pending","weakEdge","lookup","applicationFeatures","groupFeatures","nodeId","owner","provenance","conditions","groups","ports","hostContract","label","demand","optional","hostContracts","absentProviders","targets","contribution","contributor","target","priority","contributions","planEdges","fixturePlan","fixtureEdgeKinds","fixtureSessionId","planFingerprint","diagnosticPlanFingerprint","topologyRevision","diagnosticTopologyRevision","baseSequence","baseRevision","t0","instanceId","fixtureInstanceIds","fixtureAttachmentIds","conditionChange","condition","active","cause","group","state","desired","instance","generation","ready","attachment","declaration","loadingHeader","applicationInstances","openConfirmAction","openTasks","initialPorts","hostContractNode","initialHostContracts","initialContributions","initialAttachments","ownershipEdges","node","fixtureStructuralEdge","dependencyEdges","fixtureHardEdge","fixtureWeakEdge","supportReadsTasks","initialRuntime","fixtureSnapshot","graphSchemaRevision","offset","operations","retiredByCondition","cleanupFailure","quarantineFailure","fixtureFrames","createFixtureSession","options","committed","oldestServable","notify","commit","servable","next","current"],"mappings":"uNAGA,MAAMA,CAAa,CACA,MAAQ,IAAI,IAE7B,KAAKC,EAAU,CACb,IAAIC,EAAO,KAAK,MAAM,IAAID,CAAE,EAE5B,OAAIC,IAAS,SACXA,EAAO,SAAS,KAAK,MAAM,IAAI,GAC/B,KAAK,MAAM,IAAID,EAAIC,CAAI,GAGlBA,CACT,CACD,CAED,SAASC,GACPC,EACAC,EACAC,EAAoB,CAEpB,OAAIF,IAAS,KAAa,KAEnB,CACL,GAAGA,EACH,UAAWA,EAAK,YAAc,UAAY,UAAYA,EAAK,UAAU,IAAIH,GAAMI,EAAM,IAAIJ,CAAE,GAAK,cAAcA,CAAE,EAAE,EAClH,GAAIK,EAAM,KAAKF,EAAK,EAAE,EAE1B,CAOA,SAASG,GAAmBC,EAA6C,CACvE,GAAIA,IAAa,OAAW,OAE5B,MAAMC,EAAW,IAAIT,EACfK,EAAQ,IAAIL,EACZM,EAAQ,IAAIN,EACZU,EAAY,IAAIV,EAChBW,EAAQ,IAAIX,EACZY,EAAU,IAAI,IAAIJ,EAAS,MAAM,IAAIK,GAAQ,CAACA,EAAK,GAAIR,EAAM,KAAKQ,EAAK,EAAE,CAAC,CAAC,CAAC,EAElF,MAAO,CACL,GAAGL,EACH,MAAOA,EAAS,MAAM,IAAIK,IAAS,CACjC,GAAGA,EACH,GAAIR,EAAM,KAAKQ,EAAK,EAAE,EACtB,KAAMV,GAAeU,EAAK,KAAMD,EAASN,CAAK,CAC/C,EAAC,EACF,YAAa,YACb,SAAUE,EAAS,SAAS,IAAIM,IAAY,CAAE,GAAGA,EAAS,GAAIL,EAAS,KAAKK,EAAQ,EAAE,CAAC,EAAG,EAC1F,UAAWN,EAAS,UAAU,IAAIO,IAAa,CAC7C,GAAGA,EACH,GAAIL,EAAU,KAAKK,EAAS,EAAE,EAC9B,MACEA,EAAS,QAAU,UAAY,UAAYA,EAAS,MAAM,IAAIC,IAAS,CAAE,GAAGA,EAAM,GAAIL,EAAM,KAAKK,EAAK,EAAE,CAAC,EAAG,CAC/G,EAAC,EAEN,CClBA,MAAMC,UAAgC,KAAK,CACN,OAAnC,YAAmCC,EAAgC,CACjE,MAAMC,EAASD,EAAO,OAAOE,GAASA,EAAM,SAAW,QAAQ,EAE/D,MACE,mCAAmCD,EAAO,MAAM,OAAOD,EAAO,MAAM;AAAA,EAAsBC,EACvF,IAAIC,GAAS,OAAOA,EAAM,IAAI,KAAKA,EAAM,QAAU,WAAW,EAAE,EAChE,KAAK;AAAA,CAAI,CAAC,EAAE,EANgB,KAAA,OAAAF,EAQjC,KAAK,KAAO,yBACd,CACD,CAED,MAAMG,EAAyB,CAAE,SAAU,EAAI,KAAO,KAAM,UAAW,IAAI,EACrEC,EAAaC,IACjBA,EAAI,EAEG,QAST,SAASC,IAAc,CACrB,MAAMN,EAA0B,CAAA,EAEhC,MAAO,CACL,MAAO,CAAChB,EAAMuB,EAAIC,IAAU,CAC1BR,EAAO,KAAK,CAAE,GAAIO,GAAMC,IAAW,OAAY,CAAA,EAAK,CAAE,OAAAA,CAAM,EAAK,KAAAxB,EAAM,OAAQuB,EAAK,SAAW,SAAU,CAC3G,EACA,OAAAP,EACA,KAAM,CAAChB,EAAMwB,IAAM,CAAUR,EAAO,KAAK,CAAE,OAAAQ,EAAQ,KAAAxB,EAAM,OAAQ,SAAS,CAAE,GAEhF,CAGA,SAASyB,EAAMC,EAAmCC,EAA0B,OAC1E,MAAMC,EAA8B,CAAA,EACpC,IAAIC,EAAKF,EAET,QAASG,EAAQ,EAAGA,EAAQ,GAAIA,GAAS,EAAG,CAC1C,MAAMC,EAASL,EAAQ,UAAUG,EAAIV,CAAU,EAE/C,GAAIY,EAAO,OAAS,mBAAqBA,EAAO,OAAO,SAAW,EAAG,OAAOH,EAE5EA,EAAO,KAAK,GAAGG,EAAO,MAAM,EAC5BF,IAAKG,EAAAD,EAAO,OAAOA,EAAO,OAAO,OAAS,CAAC,IAAtC,YAAAC,EAAyC,eAAgBH,CAChE,CAEA,OAAOD,CACT,CAEA,SAASK,GAAWC,EAA0BC,EAAkBC,EAAgB,CAC9E,OAAIF,EAAM,iBAAmBG,EAA4B,uBAErDH,EAAM,eAAiBC,EAAiB,iCAExCD,EAAM,gBAAkBE,EAAW,EAAU,yBAE1CF,EAAM,WAAW,SAAW,GAAKA,EAAM,WAAa,OAAY,kBAAoB,MAC7F,CAGA,SAASI,GAAmBV,EAAsCW,EAA0B,CAC1F,IAAIJ,EAAmBI,EAAK,cACxBH,EAAmBG,EAAK,aAE5B,UAAWL,KAASN,EAAQ,CAC1B,MAAMY,EAAQP,GAAWC,EAAOC,EAAUC,CAAQ,EAElD,GAAII,IAAU,OAAW,MAAO,SAASN,EAAM,YAAY,IAAIM,CAAK,GAEpEL,EAAWD,EAAM,aACjBE,EAAWF,EAAM,YACnB,CAGF,CAGA,SAASO,EAAeC,EAA8B,CACpD,KAAM,CAAE,UAAWC,EAAY,GAAGC,CAAI,EAAKF,EAE3C,MAAO,CAAE,GAAGE,EAAM,SAAUvC,GAAmBqC,EAAS,QAAQ,CAAC,CACnE,CAOA,SAASG,GAAqBC,EAAmCC,EAAkB,OACjF,KAAM,CAAE,QAAArB,CAAO,EAAKoB,EACdP,EAAOb,EAAQ,YAAW,EAC1BsB,EAA+B,CAAA,EACrC,IAAIC,EAAa,EACbC,EACAvB,EAASY,EAAK,aAElB,KAAOO,EAAQ,UAAU,CACvB,MAAMlB,EAASH,EAAMC,EAASC,CAAM,EAEpCqB,EAAQ,KAAK,GAAGpB,CAAM,EACtBD,IAASK,EAAAgB,EAAQA,EAAQ,OAAS,CAAC,IAA1B,YAAAhB,EAA6B,eAAgBL,EACtDsB,GAAc,EAEVC,IAAa,QAAa,CAACC,EAAkBC,EAAWb,EAAMS,CAAO,EAAGtB,EAAQ,YAAW,CAAE,IAC/FwB,EAAW,2CAA2CD,CAAU,GAEpE,CAEAF,EAAS,MAAM,gEAAiEG,IAAa,OAAWA,CAAQ,EAChHH,EAAS,MAAM,8CAA+CE,EAAa,EAAG,6BAA6B,CAC7G,CAOA,SAASI,GAAoBP,EAAmCC,EAAkB,CAChF,KAAM,CAAE,QAAArB,CAAO,EAAKoB,EACdP,EAAOb,EAAQ,YAAW,EAC1B4B,EAAO5B,EAAQ,UAAUa,EAAK,aAAcpB,CAAU,EAQ5D,IANA4B,EAAS,MACP,8CACAO,EAAK,OAAS,WAAaA,EAAK,OAAO,SAAW,EAClD,+DAA+D,EAG1DR,EAAQ,OAAM,GAAG,CAExB,MAAMS,EAASjB,GAAmBb,EAAMC,EAASa,EAAK,YAAY,EAAGA,CAAI,EAEzEQ,EAAS,MAAM,qCAAsCQ,IAAW,OAAWA,CAAM,CACnF,CAGA,SAASC,GAAsBC,EAAmCV,EAAkB,CAClF,MAAMW,EAAaD,EAAO,EAE1B,KAAOC,EAAW,OAAM,GAAG,CAE3B,MAAMC,EAAQD,EAAW,QAAQ,YAAW,EAC5CA,EAAW,QAAQ,MAAK,EAExB,MAAME,EAASH,EAAO,EAChBI,EAAQC,EAAuBF,EAAO,QAAS,CAAE,SAAUxC,EAAW,EACtE2C,EAASD,EAAuBF,EAAO,QAAS,CAAE,SAAUxC,EAAW,EAE7E,KAAOwC,EAAO,OAAM,GAAG,CAEvB,MAAMI,EAAWJ,EAAO,QAAQ,YAAW,EACrCK,EAAoBd,EAAkBV,EAAekB,CAAK,EAAGlB,EAAeuB,CAAQ,CAAC,EAE3FjB,EAAS,MACP,qEACAkB,EACA,+EAA+E,EAEjFlB,EAAS,MACP,kDACAc,EAAM,MAAM,OAAO,gBAAkBE,EAAO,MAAM,OAAO,cACzD,6DAA6D,EAG/DF,EAAM,MAAK,EACXE,EAAO,MAAK,CACd,CAGA,SAASG,GAAoBpB,EAAmCC,EAAkB,CAChF,KAAM,CAAE,QAAArB,CAAO,EAAKoB,EACdP,EAAOb,EAAQ,YAAW,EAEhC,GAAI,CAACoB,EAAQ,SAAU,CACrBC,EAAS,KAAK,6CAA8C,yCAAyC,EAErG,MACF,CAEA,KAAM,CAACb,CAAK,EAAIT,EAAMC,EAASa,EAAK,YAAY,EAEhD,GAAIL,IAAU,OAAW,CACvBa,EAAS,KAAK,6CAA8C,wCAAwC,EAEpG,MACF,CAEA,MAAMoB,EAAQ,IAAIC,EAAmB7B,CAAI,EAEzCQ,EAAS,MAAM,qCAAsCoB,EAAM,WAAWjC,CAAK,EAAE,OAAS,SAAS,EAC/Fa,EAAS,MACP,4BACAoB,EAAM,WAAWjC,CAAK,EAAE,OAAS,kBACjC,2CAA2C,EAG7C,MAAMmC,EAAS,IAAID,EAAmB7B,CAAI,EACpC+B,EAA2B,CAC/B,GAAGpC,EACH,cAAeqC,EAAmBrC,EAAM,cAAgB,CAAC,EACzD,aAAcqC,EAAmBrC,EAAM,aAAe,CAAC,EACvD,aAAcsC,EAAwBtC,EAAM,aAAe,CAAC,GAG9Da,EAAS,MACP,qCACAsB,EAAO,WAAWC,CAAK,EAAE,OAAS,kBAClC,wDAAwD,EAG1D,MAAMG,EAAQ,IAAIL,EAAmB7B,CAAI,EACnCmC,EAA6B,CAAE,GAAGxC,EAAO,UAAWyC,EAAoB,6BAA6B,CAAC,EACtGC,EAAUH,EAAM,WAAWC,CAAO,EAExC3B,EAAS,MACP,uCACA6B,EAAQ,OAAS,UACjB,gDAAgD,EAElD7B,EAAS,MACP,8CACA0B,EAAM,OAAO,gBAAkBlC,EAAK,cACpC,iDAAiD,CAErD,CAOA,SAASsC,GAAuB/B,EAAmCC,EAAkB,CACnF,KAAM,CAAE,QAAArB,CAAO,EAAKoB,EACpB,IAAIgC,EACAC,EAEJ,MAAMC,EAAUtD,EAAQ,UAAU,IAAK,CACrC,GAAI,CACFoD,MAAcpD,EAAQ,YAAW,EACnC,OAASuD,EAAO,CACdF,MAAUE,EACZ,CACF,CAAC,EAaD,GAXAnC,EAAQ,OAAM,EACdkC,EAAO,EAEPjC,EAAS,MAAM,gDAAiDgC,IAAU,OAAW,OAAOA,CAAK,CAAC,EAQ9FD,IAAc,OAAW,CAC3B,MAAMI,EAAS,uEAEfnC,EAAS,KAAK,yCAA0CmC,CAAM,EAC9DnC,EAAS,KAAK,+DAAgEmC,CAAM,EAEpF,MACF,CAEAnC,EAAS,MACP,yCACA+B,EAAU,eAAiB,EAC3B,6DAA6D,EAE/D/B,EAAS,MACP,+DACAI,EAAkBzB,EAAQ,YAAW,EAAIoD,CAAS,EAClD,+DAA+D,CAEnE,CAGA,SAASK,GAAsBrC,EAAmCC,EAAkB,CAClF,MAAMqC,EAAsB,CAAA,EAC5B,IAAIC,EAAQ,EAYZ,MAAMC,EAAaxB,EAXuB,CACxC,MAAO,IAAA,GACP,YAAa,IAAMhB,EAAQ,QAAQ,YAAW,EAC9C,UAAW,IAAK,CACd,MAAAuC,GAAS,EAEH,IAAI,MAAM,4CAA4C,CAC9D,EACA,UAAWE,GAAYzC,EAAQ,QAAQ,UAAUyC,CAAQ,GAGR,CACjD,UAAWC,GAAO,CAASJ,EAAS,KAAKI,CAAO,GAChD,SAAUpE,CACX,CAAA,EAED0B,EAAQ,OAAM,EACdA,EAAQ,OAAM,EAEdC,EAAS,MAAM,8CAA+CqC,EAAS,SAAW,EAAG,GAAGA,EAAS,MAAM,UAAU,EACjHrC,EAAS,MAAM,qDAAsDsC,IAAU,EAAG,GAAGA,CAAK,QAAQ,EAElGC,EAAW,MAAK,CAClB,CAGA,SAASG,GAAkBhC,EAAmCV,EAAkB,CAC9E,MAAMD,EAAUW,EAAO,EACvB,IAAIiC,EAAY,EAiBhB,MAAMJ,EAAaxB,EAhBuB,CACxC,MAAO,IAAMhB,EAAQ,QAAQ,MAAK,EAClC,YAAa,IAAMA,EAAQ,QAAQ,YAAW,EAC9C,UAAW,CAACnB,EAAQgE,IAAW7C,EAAQ,QAAQ,UAAUnB,EAAQgE,CAAM,EACvE,UAAWJ,GAAW,CACpBG,GAAa,EAEb,MAAMV,EAAUlC,EAAQ,QAAQ,UAAUyC,CAAQ,EAElD,MAAO,IAAK,CACVG,GAAa,EACbV,EAAO,CACT,CACF,GAGiD,CAAE,SAAU5D,CAAS,CAAE,EAE1E2B,EAAS,MAAM,qCAAsC2C,IAAc,EAAG,GAAGA,CAAS,YAAY,EAC9F5C,EAAQ,OAAM,EAEd,MAAM8C,EAAkBN,EAAW,MAAM,OAAO,cAGhD,IAFAA,EAAW,MAAK,EAETxC,EAAQ,OAAM,GAAG,CAExBC,EAAS,MAAM,kCAAmC2C,IAAc,EAAG,GAAGA,CAAS,2BAA2B,EAC1G3C,EAAS,MACP,iCACAuC,EAAW,MAAM,OAAO,gBAAkBM,EAC1C,gCAAgC,CAEpC,CAMA,SAASC,GAA6BpC,EAAiC,CACrE,MAAMV,EAAWzB,GAAc,EAE/BuB,GAAqBY,EAAO,EAAIV,CAAQ,EACxCM,GAAoBI,EAAO,EAAIV,CAAQ,EACvCS,GAAsBC,EAASV,CAAQ,EACvCmB,GAAoBT,EAAO,EAAIV,CAAQ,EACvC8B,GAAuBpB,EAAO,EAAIV,CAAQ,EAC1CoC,GAAsB1B,EAAO,EAAIV,CAAQ,EACzC0C,GAAkBhC,EAASV,CAAQ,EAEnC,MAAM+C,EAASrC,EAAO,EAEtB,GAAIqC,EAAO,aAAe,OACxB/C,EAAS,KAAK,2CAA4C,2CAA2C,MAChG,CACL,MAAMuC,EAAaxB,EAAuBgC,EAAO,QAAS,CAAE,SAAU1E,EAAW,EAIjF,IAFA0E,EAAO,WAAU,EAEVA,EAAO,OAAM,GAAG,CAEvB/C,EAAS,MACP,2CACA+C,EAAO,QAAQ,YAAW,EAAG,gBAAkBR,EAAW,MAAM,OAAO,cACvE,gDAAgD,EAElDvC,EAAS,MACP,8CACAuC,EAAW,MAAM,SAAS,KAAI,EAAG,KAAKS,GAASA,EAAM,OAAS,KAAK,EACnE,+CAA+C,EAEjDT,EAAW,MAAK,CAClB,CAEA,GAAIvC,EAAS,OAAO,KAAK7B,GAASA,EAAM,SAAW,QAAQ,EAAG,MAAM,IAAIH,EAAwBgC,EAAS,MAAM,EAE/G,OAAOA,EAAS,MAClB,CAGA,SAASiD,GAAWlD,EAAmCmD,EAAyB,CAC9E,MAAMC,EAAWpD,EAAQ,QACzB,IAAIqD,EAAS,GACb,MAAMC,EAAQ,IAAW,CACnBD,IAEJA,EAAS,GACTF,EAAS,OAAOG,CAAK,EACrBF,EAAS,MAAK,EAChB,EAEA,OAAAD,EAAS,IAAIG,CAAK,EAEX,CACL,OAAQ,IAAMtD,EAAQ,OAAM,EAC5B,GAAIA,EAAQ,aAAe,OAAY,GAAK,CAAE,WAAY,IAAA,OAAM,QAAAd,EAAAc,EAAQ,aAAR,YAAAd,EAAA,KAAAc,KAA0B,KAC1F,QAAS,CACP,MAAAsD,EACA,YAAa,IAAMF,EAAS,YAAW,EACvC,UAAW,CAACvE,EAAQgE,IAAWO,EAAS,UAAUvE,EAAQgE,CAAM,EAChE,UAAWJ,GAAYW,EAAS,UAAUX,CAAQ,CACnD,EAEL,CAEA,SAASc,GAAcJ,EAAyB,CAC9C,IAAIhF,EAAS,GACTuE,EAEJ,UAAWR,KAAWiB,EACpB,GAAI,CACFjB,EAAO,CACT,OAASC,EAAO,CACThE,IACHA,EAAS,GACTuE,EAAUP,EAEd,CAGF,MAAO,CAAE,OAAAhE,EAAQ,QAAAuE,CAAO,CAC1B,CAEA,SAASc,GAAgC7C,EAAiC,CACxE,MAAMwC,EAAW,IAAI,IACrB,IAAIrB,EAIJ,GAAI,CACFA,EAAU,CAAE,OAAQiB,GAA6B,IAAMG,GAAWvC,EAAO,EAAIwC,CAAQ,CAAC,EAAG,OAAQ,EAAK,CACxG,OAAST,EAAS,CAChBZ,EAAU,CAAE,OAAQ,GAAM,QAAAY,CAAO,CACnC,CAEA,MAAMe,EAAUF,GAAcJ,CAAQ,EAGtC,GAAIrB,EAAQ,OAAQ,MAAMA,EAAQ,QAElC,GAAI2B,EAAQ,OAAQ,MAAMA,EAAQ,QAElC,OAAO3B,EAAQ,MACjB,CCxeA,MAAM4B,GAAY,IAAI,IAAoB,CACxC,CAAC,IAAK,IAAI,EACV,CAAC,IAAK,IAAI,EACV,CAAC,IAAK,IAAI,EACV,CAAC,IAAK,IAAI,CACX,CAAA,EAED,SAASC,GAAaC,EAAa,CACjC,IAAIC,EAAU,GAEd,UAAWC,KAAaF,EAAO,CAC7B,MAAMG,EAASL,GAAU,IAAII,CAAS,EAEtC,GAAIC,IAAW,OAAW,CACxBF,GAAWE,EACX,QACF,CAGAF,GAAW,iBAAiB,KAAKC,CAAS,EAAIA,EAAY,MAAMA,EAAU,YAAY,CAAC,GAAK,GAAG,SAAS,EAAE,CAAC,GAC7G,CAEA,OAAOD,CACT,CCFA,MAAM5G,EAAK+G,EAELC,EAAa,CACjB,kBAAmBhH,EAAG,4BAA4B,EAClD,gBAAiBA,EAAG,0BAA0B,EAC9C,YAAaA,EAAG,WAAW,EAC3B,QAASA,EAAG,iBAAiB,EAC7B,eAAgBA,EAAG,iBAAiB,EACpC,gBAAiBA,EAAG,4BAA4B,EAChD,UAAWA,EAAG,sBAAsB,EACpC,mBAAoBA,EAAG,qBAAqB,EAC5C,mBAAoBA,EAAG,qBAAqB,EAC5C,cAAeA,EAAG,eAAe,EACjC,oBAAqBA,EAAG,+BAA+B,EACvD,mBAAoBA,EAAG,8BAA8B,EACrD,0BAA2BA,EAAG,sCAAsC,EACpE,sBAAuBA,EAAG,kCAAkC,EAC5D,iBAAkBA,EAAG,qCAAqC,EAC1D,kBAAmBA,EAAG,8BAA8B,EACpD,cAAeA,EAAG,gBAAgB,EAClC,UAAWA,EAAG,0BAA0B,EACxC,gBAAiBA,EAAG,2BAA2B,EAC/C,gBAAiBA,EAAG,0BAA0B,EAC9C,YAAaA,EAAG,cAAc,EAC9B,cAAeA,EAAG,wBAAwB,EAC1C,kBAAmBA,EAAG,uBAAuB,EAC7C,iBAAkBA,EAAG,2BAA2B,EAChD,oBAAqBA,EAAG,uBAAuB,EAC/C,mBAAoBA,EAAG,oCAAoC,EAC3D,2BAA4BA,EAAG,8BAA8B,EAC7D,cAAeA,EAAG,gBAAgB,GAG9BiH,EAAyB,CAC7B,cAAejH,EAAG,kCAAkC,EACpD,aAAcA,EAAG,0CAA0C,EAC3D,qBAAsBA,EAAG,6CAA6C,EACtE,kBAAmBA,EAAG,+CAA+C,GAGjEkH,EAAwBC,GAAsB,sBAAsB,EAG1E,SAASC,EAAOC,EAA0BC,EAAwBC,EAAoB,CACpF,OAAOC,GAAiB,GAAGH,CAAI,IAAIX,GAAaY,CAAI,CAAC,IAAIZ,GAAaa,CAAE,CAAC,EAAE,CAC7E,CAGA,SAASE,EAAeJ,EAA0BC,EAAwBC,EAAoB,CAC5F,MAAO,CAAE,KAAAD,EAAM,GAAIF,EAAOC,EAAMC,EAAMC,CAAE,EAAG,KAAAF,EAAM,GAAAE,CAAE,CACrD,CAGA,SAASG,EACPL,EACAC,EACAC,EACAI,EAAU,GAAK,CAEf,MAAO,CAAE,KAAAL,EAAM,GAAIF,EAAOC,EAAMC,EAAMC,CAAE,EAAG,KAAAF,EAAM,QAAAM,EAAS,GAAAJ,CAAE,CAC9D,CAGA,SAASK,EACPP,EACAC,EACAC,EACAM,EAAqB,CAErB,MAAO,CAAE,KAAAP,EAAM,GAAIF,EAAOC,EAAMC,EAAMC,CAAE,EAAG,KAAAF,EAAM,OAAAQ,EAAQ,GAAAN,CAAE,CAC7D,CAEA,MAAMO,GAAmD,CACvDd,EAAW,gBACXA,EAAW,QACXA,EAAW,eACXA,EAAW,mBACXA,EAAW,mBACXA,EAAW,cACXA,EAAW,cAEXA,EAAW,YACXA,EAAW,mBAIPe,GAA6C,CAACf,EAAW,cAAeA,EAAW,aAAa,EAEtG,SAASnG,EAAQmH,EAA0BC,EAAyBC,EAAmB,CACrF,MAAO,CACL,GAAIF,EACJ,KAAM,UACN,MAAOA,EACP,MAAAC,EACA,GAAIC,IAAe,OAAY,GAAK,CAAE,WAAAA,CAAU,EAEpD,CAEA,MAAM1H,GAAuC,CAC3C,GAAGsH,GAAoB,IAAIE,GAAUnH,EAAQmH,EAAQhB,EAAW,WAAW,CAAC,EAC5EnG,EAAQmG,EAAW,cAAeA,EAAW,gBAAiB,4CAA4C,EAC1GnG,EAAQmG,EAAW,cAAeA,EAAW,gBAAiB,0BAA0B,GAGpFmB,GAA2C,CAC/C,CACE,YAAajB,EACb,GAAIF,EAAW,UACf,KAAM,YACN,MAAO,uBACP,WAAY,iDACZ,OAAQ,MACT,GAGGoB,GAA4C,CAChD,CACE,WAAY,CAAClB,CAAqB,EAClC,GAAIF,EAAW,gBACf,KAAM,kBACN,MAAO,4BACP,MAAOe,EACR,GAGGM,GAAiC,CACrC,CACE,GAAIrB,EAAW,gBACf,KAAM,OACN,MAAO,sBACP,SAAUA,EAAW,cACtB,EACD,CAAE,GAAIA,EAAW,UAAW,KAAM,OAAQ,MAAO,sBAAuB,SAAUA,EAAW,aAAa,EAC1G,CAAE,GAAIA,EAAW,gBAAiB,KAAM,OAAQ,MAAO,sBAAsB,GAG/E,SAASsB,EACPN,EACAO,EACAC,EAA6B,WAC7BC,EAAW,GAAK,CAEhB,MAAO,CAAE,OAAAD,EAAQ,GAAIR,EAAQ,KAAM,gBAAiB,MAAAO,EAAO,SAAAE,CAAQ,CACrE,CAEA,MAAMC,GAAiD,CACrDJ,EAAatB,EAAW,oBAAqB,0BAA0B,EACvEsB,EAAatB,EAAW,mBAAoB,0BAA2B,WAAY,EAAI,EACvFsB,EAAatB,EAAW,0BAA2B,kCAAmC,UAAU,EAChGsB,EAAatB,EAAW,sBAAuB,6BAA6B,EAC5EsB,EAAatB,EAAW,iBAAkB,gCAAgC,EAC1EsB,EAAatB,EAAW,kBAAmB,yBAAyB,GAIhE2B,GAAqD,CACzD,CAAE,GAAI3B,EAAW,kBAAmB,KAAM,kBAAmB,MAAO,qBAAqB,GAGrF4B,GAAiD,CACrD,CAAE,GAAI5B,EAAW,iBAAkB,KAAM,sBAAuB,MAAO,oBAAoB,EAC3F,CAAE,GAAIA,EAAW,oBAAqB,KAAM,sBAAuB,MAAO,gBAAgB,EAC1F,CAAE,GAAIA,EAAW,mBAAoB,KAAM,sBAAuB,MAAO,6BAA6B,EACtG,CAAE,GAAIA,EAAW,2BAA4B,KAAM,sBAAuB,MAAO,uBAAuB,GAG1G,SAAS6B,EACPb,EACAO,EACAO,EACAC,EACAC,EAAgB,CAEhB,MAAO,CAAE,YAAAF,EAAa,GAAId,EAAQ,KAAM,eAAgB,MAAAO,EAAO,SAAAS,EAAU,OAAAD,CAAM,CACjF,CAEA,MAAME,GAAiD,CACrDJ,EACE5B,EAAuB,cACvB,iBACAD,EAAW,cACXA,EAAW,oBACX,CAAC,EAEH6B,EACE5B,EAAuB,aACvB,8BACAD,EAAW,mBACXA,EAAW,mBACX,EAAE,EAEJ6B,EACE5B,EAAuB,qBACvB,iCACAD,EAAW,cACXA,EAAW,2BACX,CAAC,EAEH6B,EACE5B,EAAuB,kBACvB,mCACAD,EAAW,kBACXA,EAAW,iBACX,CAAC,GAICkC,GAAuC,CAC3C,GAAGpB,GAAoB,IAAIE,GAAUP,EAAe,OAAQT,EAAW,YAAagB,CAAM,CAAC,EAC3F,GAAGD,GAAc,IAAIC,GAAUP,EAAe,OAAQT,EAAW,gBAAiBgB,CAAM,CAAC,EACzFP,EAAe,oBAAqBT,EAAW,UAAWA,EAAW,eAAe,EACpFS,EAAe,gBAAiBT,EAAW,eAAgBA,EAAW,eAAe,EACrFS,EAAe,gBAAiBT,EAAW,cAAeA,EAAW,SAAS,EAC9ES,EAAe,mBAAoBT,EAAW,0BAA2BA,EAAW,aAAa,EACjG,GAAGiC,GAAc,QAAQjD,GAAS,CAChCyB,EAAe,OAAQzB,EAAM,YAAaA,EAAM,EAAE,EAClDyB,EAAe,iBAAkBzB,EAAM,GAAIA,EAAM,MAAM,EACxD,GAGGmD,EAAuC,CAC3C,gBAAAR,GACA,YAAa,CACX,SAAUnI,GAAS,OACnB,OAAQ4H,GAAO,OACf,GAAIpB,EAAW,YACf,KAAM,cACN,MAAO,WACR,EACD,WAAAmB,GACA,cAAAc,GACA,MAAOC,GACP,SAAA1I,GACA,OAAA4H,GACA,cAAAM,GACA,MAAAL,GACA,QAAAO,IAIIQ,GAAkD,CACtD,gBACA,cACA,oBACA,iBACA,cACA,mBACA,kBACA,gBACA,OACA,gBACA,iBCjPIC,EAAmBzE,EAAoB,WAAW,EAClD0E,GAAkBC,GAA0B,QAAQ,EACpDC,GAAmBC,GAA2B,CAAC,EAE/CC,EAAe,KACfC,EAAe,IAEfC,EAA0B,KAAK,IAAI,KAAM,EAAG,EAAG,GAAI,EAAG,GAAI,EAAE,EAElE,SAASC,EAAWhJ,EAAyB,CAC3C,OAAOkG,EAAiB,YAAYlG,CAAO,EAAE,CAC/C,CAEA,MAAMiJ,EAAqB,CACzB,gBAAiBD,EAAW7C,EAAW,eAAe,EACtD,QAAS6C,EAAW7C,EAAW,OAAO,EACtC,eAAgB6C,EAAW7C,EAAW,cAAc,EACpD,mBAAoB6C,EAAW7C,EAAW,kBAAkB,EAC5D,mBAAoB6C,EAAW7C,EAAW,kBAAkB,EAC5D,cAAe6C,EAAW7C,EAAW,aAAa,EAClD,cAAe6C,EAAW7C,EAAW,aAAa,EAClD,cAAe6C,EAAW7C,EAAW,aAAa,EAClD,kBAAmB6C,EAAW7C,EAAW,iBAAiB,EAC1D,cAAe6C,EAAW7C,EAAW,aAAa,GAG9C+C,EAAuB,CAC3B,sBAAuBhD,EAAiB,4CAA4C,EACpF,cAAeA,EAAiB,iCAAiC,GAG7DiD,EAAmBlI,IAAiD,CACxE,GAAAA,EACA,UAAWoF,EACX,KAAM,kBACP,GAED,SAAS+C,GAAUC,EAAiBC,EAA0B,CAC5D,MAAO,CACL,GAAIA,IAAU,OAAY,GAAK,CAAE,MAAAA,CAAK,EACtC,GAAInD,EAAW,UACf,KAAM,YACN,MAAO,uBACP,MAAOkD,EAAS,CAAE,KAAM,MAAM,EAAK,CAAE,KAAM,OAAO,EAEtD,CAEA,SAASE,EAAMC,EAA4BH,EAAiBC,EAA0B,CACpF,MAAMG,EAAUJ,EAAS,SAAW,WAEpC,MAAO,CACL,GAAIC,IAAU,OAAY,GAAK,CAAE,MAAAA,CAAK,EACtC,QAAS,CAAE,UAAWG,EAAS,SAAU,OAAQ,OAAQA,CAAO,EAChE,GAAItD,EAAW,gBACf,KAAM,kBACN,MAAO,4BACP,MAAAqD,EAEJ,CAEA,SAASE,EACP1J,EACA2J,EACAH,EACApC,EACAkC,EAA0B,CAE1B,MAAO,CACL,GAAIA,IAAU,OAAY,GAAK,CAAE,MAAAA,CAAK,EACtC,YAAatJ,EACb,WAAA2J,EACA,GAAIvC,IAAU,OAAY,CAAA,EAAK,CAAE,MAAOA,CAAK,EAC7C,GAAI4B,EAAWhJ,CAAO,EACtB,KAAM,mBACN,MAAOA,EACP,MAAAwJ,EAEJ,CAEA,MAAMI,EAA8B,CAAE,KAAM,OAAO,EAEnD,SAASC,EAAW1C,EAA0BO,EAAeN,EAAyBoC,EAAsB,CAC1G,MAAO,CAAE,GAAIrC,EAAQ,KAAM,aAAuB,MAAAO,EAAO,MAAAN,EAAO,MAAAoC,CAAK,CACvE,CAEA,SAASxB,EAAab,EAA0BqC,EAAwB,CACtE,MAAMM,EAAcxB,EAAY,cAAc,KAAKnD,GAASA,EAAM,KAAOgC,CAAM,EAE/E,MAAO,CACL,YAAa6B,GAAWc,GAAA,YAAAA,EAAa,cAAe3C,CAAM,EAC1D,YAAaA,EACb,GAAIA,EACJ,KAAM,eACN,OAAO2C,GAAA,YAAAA,EAAa,QAAS3C,EAC7B,MAAAqC,EACA,QAAQM,GAAA,YAAAA,EAAa,SAAU3C,EAEnC,CAMA,MAAM4C,GAAgBL,EAASvD,EAAW,YAAa,EAAG,CAAE,KAAM,SAAS,EAAI,OAAW,CACxF,GAAI4C,EACJ,KAAM,sBACN,KAAMC,EAAW7C,EAAW,WAAW,CACxC,CAAA,EAEK6D,GAAuD,CAC3DN,EAASvD,EAAW,gBAAiB,EAAGyD,CAAK,EAC7CF,EAASvD,EAAW,QAAS,EAAGyD,CAAK,EACrCF,EAASvD,EAAW,eAAgB,EAAGyD,CAAK,EAC5CF,EAASvD,EAAW,mBAAoB,EAAGyD,CAAK,EAChDF,EAASvD,EAAW,mBAAoB,EAAGyD,CAAK,EAChDF,EAASvD,EAAW,cAAe,EAAGyD,CAAK,EAC3CF,EAASvD,EAAW,cAAe,EAAGyD,CAAK,EAC3CG,GACAL,EAASvD,EAAW,kBAAmB,EAAGyD,CAAK,GAG3CK,GAAoBP,EAASvD,EAAW,cAAe,EAAGyD,EAAOzD,EAAW,gBAAiBgD,EAAgBJ,CAAE,CAAC,EAChHmB,GAAYR,EAASvD,EAAW,cAAe,EAAGyD,EAAOzD,EAAW,gBAAiBgD,EAAgBJ,CAAE,CAAC,EAExGoB,GAA2C,CAC/C,CACE,YAAahE,EAAW,gBACxB,GAAIA,EAAW,gBACf,KAAM,OACN,MAAO,sBACP,MAAO,CAAE,SAAU8C,EAAmB,eAAgB,KAAM,WAAW,CACxE,EACD,CACE,YAAa9C,EAAW,UACxB,GAAIA,EAAW,UACf,KAAM,OACN,MAAO,sBACP,MAAO,CAAE,SAAU8C,EAAmB,cAAe,KAAM,WAAW,CACvE,EACD,CACE,YAAa9C,EAAW,gBACxB,GAAIA,EAAW,gBACf,KAAM,OACN,MAAO,uBACP,MAAO,CAAE,KAAM,QAAQ,CACxB,GAGH,SAASiE,EAAiBjD,EAA0BO,EAAe8B,EAAuC,CACxG,MAAO,CAAE,YAAarC,EAAQ,GAAIA,EAAQ,KAAM,gBAA0B,MAAAO,EAAO,MAAA8B,CAAK,CACxF,CAEA,MAAMa,GAA2D,CAC/DD,EAAiBjE,EAAW,oBAAqB,2BAA4B,CAAE,KAAM,QAAS,EAC9FiE,EAAiBjE,EAAW,mBAAoB,0BAA2B,CAAE,KAAM,UAAW,EAC9FiE,EAAiBjE,EAAW,0BAA2B,kCAAmC,CAAE,KAAM,WAAY,EAC9GiE,EAAiBjE,EAAW,sBAAuB,8BAA+B,CAAE,KAAM,QAAS,EACnGiE,EAAiBjE,EAAW,iBAAkB,iCAAkC,CAAE,KAAM,QAAS,EACjGiE,EAAiBjE,EAAW,kBAAmB,0BAA2B,CAAE,KAAM,QAAS,GAGvFmE,GAA2D,CAC/DtC,EAAa5B,EAAuB,cAAe,CAAE,KAAM,WAAW,CAAE,EAExE4B,EAAa5B,EAAuB,aAAc,CAAE,KAAM,UAAU,CAAE,EACtE4B,EAAa5B,EAAuB,qBAAsB,CAAE,KAAM,WAAW,CAAE,EAC/E4B,EAAa5B,EAAuB,kBAAmB,CAAE,KAAM,WAAW,CAAE,GAGxEmE,GAAgD,CACpDV,EAAWX,EAAqB,sBAAuB,WAAYD,EAAmB,cAAe,CACnG,KAAM,QACP,EACDY,EAAWX,EAAqB,cAAe,QAASD,EAAmB,cAAe,CAAE,KAAM,QAAS,GAGvGuB,GAA4C,CAChD,GAAGR,GAAqB,IAAIS,GAAQC,EAAsB,OAAQvE,EAAW,YAAasE,EAAK,EAAE,CAAC,EAClGC,EAAsB,OAAQvE,EAAW,gBAAiB8C,EAAmB,aAAa,EAC1FyB,EAAsB,OAAQvE,EAAW,gBAAiB8C,EAAmB,aAAa,EAC1FyB,EAAsB,OAAQzB,EAAmB,cAAeC,EAAqB,qBAAqB,EAC1GwB,EAAsB,OAAQzB,EAAmB,cAAeC,EAAqB,aAAa,EAClG,GAAGZ,EAAY,cAAc,IAAInD,GAASuF,EAAsB,OAAQ1B,EAAW7D,EAAM,WAAW,EAAGA,EAAM,EAAE,CAAC,GAG5GwF,GAA6C,CACjDC,EAAgB,cAAezE,EAAW,oBAAqB8C,EAAmB,cAAc,EAChG2B,EAAgB,cAAezE,EAAW,sBAAuB8C,EAAmB,aAAa,EACjG2B,EAAgB,cAAezE,EAAW,iBAAkB8C,EAAmB,iBAAiB,EAChG2B,EAAgB,cAAezE,EAAW,kBAAmB8C,EAAmB,aAAa,EAC7F2B,EAAgB,gBAAiBzE,EAAW,gBAAiB8C,EAAmB,kBAAkB,EAClG4B,EAAgB,cAAe1E,EAAW,gBAAiB8C,EAAmB,mBAAoB,SAAS,EAC3G4B,EAAgB,gBAAiB1E,EAAW,UAAW8C,EAAmB,mBAAoB,OAAO,EACrG4B,EAAgB,gBAAiB1E,EAAW,kBAAmB8C,EAAmB,cAAe,SAAS,EAC1G4B,EAAgB,kBAAmB1E,EAAW,mBAAoB8C,EAAmB,cAAe,SAAS,GAIzG6B,GAAqB9D,GACzB6D,EAAgB,kBAAmB5B,EAAmB,cAAeA,EAAmB,kBAAmBjC,CAAM,EAE7G+D,GAAuC,CAC3C,YAAaR,GACb,WAAY,CAACnB,GAAU,EAAI,CAAC,EAC5B,cAAekB,GACf,MAAO,CAAC,GAAGE,GAAgB,GAAGG,GAAiBG,GAAkB,OAAO,CAAC,EACzE,OAAQ,CAACvB,EAAM,CAAE,KAAM,QAAQ,EAAI,EAAI,CAAC,EACxC,cAAec,GACf,UAAW,CAAC,GAAGL,GAAsBC,GAAmBC,EAAS,EACjE,MAAOC,IAGHa,GAAwC,CAC5C,aAAcrH,EAAmBkF,CAAY,EAC7C,KAAMP,EACN,gBAAAG,GACA,QAASsC,GACT,eAAgBE,GAChB,UAAWzC,EACX,cAAe5E,EAAwBkF,CAAY,EACnD,iBAAAH,IAGF,SAASrH,EACP4J,EACA5B,EACA6B,EAA2C,CAE3C,MAAO,CACL,aAAcvH,EAAwBkF,EAAeoC,EAAS,CAAC,EAC/D,MAAA5B,EACA,cAAe3F,EAAmBkF,EAAeqC,CAAM,EACvD,aAAcvH,EAAmBkF,EAAeqC,CAAM,EACtD,aAActH,EAAwBkF,EAAeoC,CAAM,EAC3D,WAAAC,EACA,eAAgB1J,EAChB,UAAW+G,EAEf,CAEA,MAAM4C,GAA2C,CAAE,KAAM,UAAW,OAAQ,oBAAoB,EAE1FC,GAAiB,CACrB,MAAO,CAAE,KAAM,UAAoB,KAAMnC,EAAqB,aAAa,EAC3E,KAAM,iBACN,MAAO,QACP,QAAS,WAGLoC,GAAoB,CACxB,MAAO,CAAE,KAAM,UAAoB,KAAMpC,EAAqB,aAAa,EAC3E,KAAM,cACN,MAAO,QACP,QAAS,WAOLqC,GAA8C,CAClDjK,EAAM,EAAG,CAAE,GAAG6H,EAAgBJ,CAAE,EAAG,KAAM5C,EAAW,WAAa,CAC/D,CAAE,KAAMiD,GAAU,GAAOD,EAAgBJ,CAAE,CAAC,EAAG,GAAI,aAAa,EAChE,CAAE,KAAMQ,EAAM,CAAE,KAAM,WAAY,UAAW,GAAK,GAAOJ,EAAgBJ,CAAE,CAAC,EAAG,GAAI,aAAa,EACjG,EACDzH,EAAM,EAAG,CAAE,GAAIyH,EAAK,EAAG,KAAM,sBAAuB,KAAME,EAAmB,aAAa,EAAI,CAC5F,CACE,KAAMS,EAASvD,EAAW,cAAe,EAAG,CAAE,KAAM,SAAS,EAAIA,EAAW,gBAAiBgD,EAAgBJ,CAAE,CAAC,EAChH,GAAI,aACL,EACD,CAAE,KAAMf,EAAa5B,EAAuB,qBAAsB,CAAE,KAAM,WAAW,CAAE,EAAG,GAAI,aAAa,EAC5G,EACD9E,EAAM,EAAG,CAAE,GAAIyH,EAAK,EAAG,KAAM,sBAAuB,KAAME,EAAmB,aAAa,EAAI,CAC5F,CACE,KAAMS,EACJvD,EAAW,cACX,EACA,CAAE,KAAM,UAAU,EAClBA,EAAW,gBACXgD,EAAgBJ,CAAE,CAAC,EAErB,GAAI,aACL,EACD,CACE,KAAMc,EAAWX,EAAqB,sBAAuB,WAAYD,EAAmB,cAAe,CACzG,KAAM,UACN,MAAO,QACR,EACD,GAAI,aACL,EACF,EACD3H,EAAM,EAAG,CAAE,GAAIyH,EAAK,GAAI,KAAM,mBAAoB,KAAM5C,EAAW,eAAe,EAAI,CACpF,CACE,KAAMuD,EAASvD,EAAW,cAAe,EAAGiF,GAAoBjF,EAAW,gBAAiBgD,EAAgBJ,CAAE,CAAC,EAC/G,GAAI,aACL,EACD,CAAE,GAAIG,EAAqB,sBAAuB,GAAI,aAAa,EACnE,CAAE,KAAMK,EAAM,CAAE,KAAM,WAAY,UAAW,GAAK,GAAOJ,EAAgBJ,CAAE,CAAC,EAAG,GAAI,aAAa,EACjG,EACDzH,EAAM,EAAG,CAAE,GAAIyH,EAAK,GAAI,KAAM,sBAAuB,KAAME,EAAmB,aAAa,EAAI,CAC7F,CACE,KAAMS,EACJvD,EAAW,cACX,EACA,CAAE,KAAM,UAAU,EAClBA,EAAW,gBACXgD,EAAgBJ,CAAE,CAAC,EAErB,GAAI,aACL,EACD,CACE,KAAMc,EAAWX,EAAqB,cAAe,QAASD,EAAmB,cAAe,CAC9F,KAAM,UACN,MAAO,QACR,EACD,GAAI,aACL,EACD,CAAE,KAAM6B,GAAkB,SAAS,EAAG,GAAI,aAAa,EACxD,EACDxJ,EAAM,EAAG,CAAE,GAAIyH,EAAK,IAAK,KAAM,UAAW,KAAMG,EAAqB,aAAa,EAAI,CACpF,CACE,KAAMW,EAAWX,EAAqB,cAAe,QAASD,EAAmB,cAAe,CAC9F,QAASoC,GACT,KAAM,eACP,EACD,GAAI,aACL,EACD,CACE,KAAM3B,EACJvD,EAAW,cACX,EACA,CAAE,QAASmF,GAAmB,KAAM,aAAa,EACjDnF,EAAW,gBACX,CAAE,GAAI4C,EAAK,IAAK,KAAM,UAAW,KAAMG,EAAqB,cAAe,EAE7E,GAAI,aACL,EACF,EACD5H,EAAM,EAAG,CAAE,GAAIyH,EAAK,IAAK,KAAM,sBAAuB,KAAMC,EAAW7C,EAAW,WAAW,CAAC,EAAI,CAChG,CACE,KAAMuD,EAASvD,EAAW,YAAa,EAAGyD,EAAO,OAAW,CAC1D,GAAIb,EAAK,IACT,KAAM,sBACN,KAAMC,EAAW7C,EAAW,WAAW,EACxC,EACD,GAAI,aACL,EACF,GC5WH,SAASqF,GAAqBC,EAAiC,GAAE,CAC/D,MAAM9J,EAAO8J,EAAQ,UAAYT,GAC3BlE,EAAU,CAAC,GAAI2E,EAAQ,QAAUF,EAAc,EAC/CG,EAAiC,CAAA,EACjC5G,EAAY,IAAI,IAEtB,IAAI6G,EAAiBhK,EAAK,aAAe,EACrC4D,EAAS,GAEb,MAAMqG,EAAS,IAAW,CACxB,UAAWjH,KAAYG,EAAWH,EAAQ,CAC5C,EAEMkH,EAAUC,GAA8B,CAC5C,MAAMC,EAAOjF,EAAQ,MAAK,EAE1B,OAAIiF,IAAS,OAAkB,IAE/BL,EAAU,KAAKK,CAAI,EAEdD,IAAUH,EAAiBI,EAAK,aAAe,GAEpDH,EAAM,EAEC,GACT,EAEMI,EAAU,IAA4BxJ,EAAWb,EAAM+J,CAAS,EAEtE,MAAO,CACL,MAAO,IAAK,CACVnG,EAAS,GACTT,EAAU,MAAK,EACfgC,EAAQ,OAAS,CACnB,EACA,SAAU,IAAM+E,EAAO,EAAK,EAC5B,QAAS,IAAK,CACZ,KAAOA,EAAO,EAAI,GAAE,CACtB,EACA,SAAU,IAAMA,EAAO,EAAI,EAC3B,YAAaG,EACb,aAAc,IAAMlF,EAAQ,OAC5B,UAAW,CAAC/F,EAA4BgE,IAClCQ,EAAe,CAAE,OAAQ,GAAI,KAAM,SAAS,EAE5CxE,EAAS,EAAI4K,EAAuB,CAAE,KAAM,kBAAmB,SAAUK,EAAO,CAAE,EAI/E,CAAE,OAFMN,EAAU,OAAOpK,IAASA,GAAM,cAAgBP,CAAM,EAAE,MAAM,EAAGgE,EAAO,SAAS,EAE/E,KAAM,SAAS,EAElC,UAAYJ,IACVG,EAAU,IAAIH,CAAQ,EAEf,IAAK,CACVG,EAAU,OAAOH,CAAQ,CAC3B,GAGN"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jsx as n,jsxs as s}from"react/jsx-runtime";import{n as o,h as r}from"./panel-5jvisQBr.js";const l={frameRevision:(e,i)=>`${e} \xB7 rev ${i}`,gapDropped:e=>` \xB7 ${e} frames dropped`,gapRestarted:" \xB7 history restarted from a snapshot",gapTitle:"gap",noCommits:"No commit has been recorded in this session yet.",timelineChanged:e=>`${e} changed record${e===1?"":"s"}`,timelineCommit:"commit",timelineLog:"Committed transactions"},d={frameRevision:(e,i)=>`${e} \xB7 \u0440\u0435\u0432\u0438\u0437\u0438\u044F ${i}`,gapDropped:e=>` \xB7 \u043F\u043E\u0442\u0435\u0440\u044F\u043D\u043E \u043A\u0430\u0434\u0440\u043E\u0432: ${e}`,gapRestarted:" \xB7 \u0438\u0441\u0442\u043E\u0440\u0438\u044F \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0449\u0435\u043D\u0430 \u0441\u043E \u0441\u043D\u0438\u043C\u043A\u0430",gapTitle:"\u0440\u0430\u0437\u0440\u044B\u0432",noCommits:"\u0412 \u044D\u0442\u043E\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 \u0435\u0449\u0451 \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u043D\u043E \u043D\u0438 \u043E\u0434\u043D\u043E\u0433\u043E \u043A\u043E\u043C\u043C\u0438\u0442\u0430.",timelineChanged:e=>`\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u043E \u0437\u0430\u043F\u0438\u0441\u0435\u0439: ${e}`,timelineCommit:"\u043A\u043E\u043C\u043C\u0438\u0442",timelineLog:"\u0417\u0430\u0444\u0438\u043A\u0441\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0438"};function m(e){return e==="ru"?d:l}function c(e,i){return e.kind==="frame"?`frame:${e.sequence}`:`gap:${i}:${e.reason}`}function p({entry:e}){var t,a;const i=m(o());return e.kind==="gap"?s("div",{className:"odt-timeline-row odt-timeline-gap",children:[n("span",{className:"odt-timeline-seq",children:i.gapTitle}),n("span",{className:"odt-timeline-time",children:"\u2014"}),s("span",{children:[e.reason,e.dropped>0?i.gapDropped(e.dropped):i.gapRestarted]})]}):s("div",{className:"odt-timeline-row",children:[n("span",{className:"odt-timeline-seq odt-mono",children:i.frameRevision(e.sequence,e.stateRevision)}),n("span",{className:"odt-timeline-time",children:r((t=e.cause)==null?void 0:t.at)}),n("span",{className:"odt-row-label",children:((a=e.cause)==null?void 0:a.kind)??i.timelineCommit}),n("span",{className:"odt-list-meta",children:i.timelineChanged(e.changed)})]})}function g({entries:e}){const i=m(o());return e.length===0?n("div",{className:"odt-empty",children:i.noCommits}):n("div",{"aria-label":i.timelineLog,className:"odt-timeline",role:"log",children:[...e].reverse().map((t,a)=>n(p,{entry:t},c(t,a)))})}export{g as TimelineView};
|
|
2
|
+
//# sourceMappingURL=timeline-view-ByPB1a7-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline-view-ByPB1a7-.js","sources":["../src/react/timeline-locale.ts","../src/react/timeline-view.tsx"],"sourcesContent":["/**\n * The timeline's own dictionary, kept out of the panel's (§4.1).\n *\n * The view renders on its own tab and nowhere else, so its words travel with its code: a session that stays on the\n * graph never carries them. The discipline is the panel's — English is the source, the Russian record is typed\n * against it — and the protocol's vocabulary is not translated in either.\n */\n\nimport type { DevtoolsLocale } from './locale';\n\nconst en = {\n frameRevision: (sequence: number, revision: number): string => `${sequence} · rev ${revision}`,\n gapDropped: (dropped: number): string => ` · ${dropped} frames dropped`,\n gapRestarted: ' · history restarted from a snapshot',\n gapTitle: 'gap',\n noCommits: 'No commit has been recorded in this session yet.',\n timelineChanged: (changed: number): string => `${changed} changed record${changed === 1 ? '' : 's'}`,\n timelineCommit: 'commit',\n timelineLog: 'Committed transactions',\n};\n\nconst ru: typeof en = {\n frameRevision: (sequence: number, revision: number): string => `${sequence} · ревизия ${revision}`,\n gapDropped: (dropped: number): string => ` · потеряно кадров: ${dropped}`,\n gapRestarted: ' · история перезапущена со снимка',\n gapTitle: 'разрыв',\n noCommits: 'В этой сессии ещё не записано ни одного коммита.',\n timelineChanged: (changed: number): string => `изменено записей: ${changed}`,\n timelineCommit: 'коммит',\n timelineLog: 'Зафиксированные транзакции',\n};\n\nfunction timelineStringsFor(locale: DevtoolsLocale): typeof en {\n return locale === 'ru' ? ru : en;\n}\n\nexport { timelineStringsFor };\n","/**\n * The timeline tab: one row per committed transaction, newest first, with dropped-gap marks inline so a hole in the\n * history is impossible to mistake for a quiet period (§6, §7).\n *\n * The time column is empty for a commit with no cause, and always empty for a gap. That is not a missing feature:\n * the protocol's only clock stamps the trigger of a commit, and a gap has none.\n */\n\nimport type { ReactElement } from 'react';\n\nimport type { TimelineEntry } from '../timeline';\n\nimport { formatOptionalTime } from './format';\nimport { useLocale } from './locale-context';\nimport { timelineStringsFor } from './timeline-locale';\n\ntype TimelineViewProps = Readonly<{\n entries: readonly TimelineEntry[];\n}>;\n\nfunction entryKey(entry: TimelineEntry, index: number): string {\n return entry.kind === 'frame' ? `frame:${entry.sequence}` : `gap:${index}:${entry.reason}`;\n}\n\nfunction TimelineRow({ entry }: { readonly entry: TimelineEntry }): ReactElement {\n const strings = timelineStringsFor(useLocale());\n\n if (entry.kind === 'gap') {\n return (\n <div className=\"odt-timeline-row odt-timeline-gap\">\n <span className=\"odt-timeline-seq\">{strings.gapTitle}</span>\n <span className=\"odt-timeline-time\">—</span>\n <span>\n {entry.reason}\n {entry.dropped > 0 ? strings.gapDropped(entry.dropped) : strings.gapRestarted}\n </span>\n </div>\n );\n }\n\n return (\n <div className=\"odt-timeline-row\">\n <span className=\"odt-timeline-seq odt-mono\">{strings.frameRevision(entry.sequence, entry.stateRevision)}</span>\n <span className=\"odt-timeline-time\">{formatOptionalTime(entry.cause?.at)}</span>\n <span className=\"odt-row-label\">{entry.cause?.kind ?? strings.timelineCommit}</span>\n <span className=\"odt-list-meta\">{strings.timelineChanged(entry.changed)}</span>\n </div>\n );\n}\n\nfunction TimelineView({ entries }: TimelineViewProps): ReactElement {\n const strings = timelineStringsFor(useLocale());\n\n if (entries.length === 0) return <div className=\"odt-empty\">{strings.noCommits}</div>;\n\n return (\n <div aria-label={strings.timelineLog} className=\"odt-timeline\" role=\"log\">\n {[...entries].reverse().map((entry, index) => (\n <TimelineRow key={entryKey(entry, index)} entry={entry} />\n ))}\n </div>\n );\n}\n\nexport { TimelineView };\n"],"names":["en","sequence","revision","dropped","changed","ru","timelineStringsFor","locale","entryKey","entry","index","TimelineRow","strings","useLocale","_jsxs","_jsx","formatOptionalTime","_a","_b","TimelineView","entries"],"mappings":"iGAUA,MAAMA,EAAK,CACT,cAAe,CAACC,EAAkBC,IAA6B,GAAGD,CAAQ,aAAUC,CAAQ,GAC5F,WAAaC,GAA4B,SAAMA,CAAO,kBACtD,aAAc,0CACd,SAAU,MACV,UAAW,mDACX,gBAAkBC,GAA4B,GAAGA,CAAO,kBAAkBA,IAAY,EAAI,GAAK,GAAG,GAClG,eAAgB,SAChB,YAAa,0BAGTC,EAAgB,CACpB,cAAe,CAACJ,EAAkBC,IAA6B,GAAGD,CAAQ,oDAAcC,CAAQ,GAChG,WAAaC,GAA4B,gGAAuBA,CAAO,GACvE,aAAc,8KACd,SAAU,uCACV,UAAW,sPACX,gBAAkBC,GAA4B,gGAAqBA,CAAO,GAC1E,eAAgB,uCAChB,YAAa,2JAGf,SAASE,EAAmBC,EAAsB,CAChD,OAAOA,IAAW,KAAOF,EAAKL,CAChC,CCdA,SAASQ,EAASC,EAAsBC,EAAa,CACnD,OAAOD,EAAM,OAAS,QAAU,SAASA,EAAM,QAAQ,GAAK,OAAOC,CAAK,IAAID,EAAM,MAAM,EAC1F,CAEA,SAASE,EAAY,CAAE,MAAAF,GAA0C,SAC/D,MAAMG,EAAUN,EAAmBO,GAAW,EAE9C,OAAIJ,EAAM,OAAS,MAEfK,EAAA,MAAA,CAAK,UAAU,8CACbC,EAAA,OAAA,CAAM,UAAU,mBAAkB,SAAEH,EAAQ,QAAQ,CAAA,EACpDG,EAAA,OAAA,CAAM,UAAU,oBAAmB,SAAA,SAAA,EACnCD,EAAA,OAAA,CAAA,SAAA,CACGL,EAAM,OACNA,EAAM,QAAU,EAAIG,EAAQ,WAAWH,EAAM,OAAO,EAAIG,EAAQ,YAAY,EAAA,CACxE,EAAA,EAMXE,EAAA,MAAA,CAAK,UAAU,mBAAkB,SAAA,CAC/BC,EAAA,OAAA,CAAM,UAAU,4BAA2B,SAAEH,EAAQ,cAAcH,EAAM,SAAUA,EAAM,aAAa,CAAC,GACvGM,EAAA,OAAA,CAAM,UAAU,oBAAmB,SAAEC,GAAmBC,EAAAR,EAAM,QAAN,YAAAQ,EAAa,EAAE,CAAC,CAAA,EACxEF,EAAA,OAAA,CAAM,UAAU,gBAAe,WAAEG,EAAAT,EAAM,QAAN,YAAAS,EAAa,OAAQN,EAAQ,eAAc,EAC5EG,EAAA,OAAA,CAAM,UAAU,gBAAe,SAAEH,EAAQ,gBAAgBH,EAAM,OAAO,CAAC,CAAA,CAAQ,CAAA,CAAA,CAGrF,CAEA,SAASU,EAAa,CAAE,QAAAC,GAA4B,CAClD,MAAMR,EAAUN,EAAmBO,GAAW,EAE9C,OAAIO,EAAQ,SAAW,EAAUL,EAAA,MAAA,CAAK,UAAU,qBAAaH,EAAQ,UAAS,EAG5EG,sBAAiBH,EAAQ,YAAa,UAAU,eAAe,KAAK,MAAK,SACtE,CAAC,GAAGQ,CAAO,EAAE,UAAU,IAAI,CAACX,EAAOC,IAClCK,EAACJ,EAAW,CAA8B,MAAOF,CAAK,EAApCD,EAASC,EAAOC,CAAK,CAAC,CACzC,CAAC,CAAA,CAGR"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded history, per `docs/devtools.md` §6: capped by both frame count and approximate
|
|
3
|
+
* payload bytes, whichever comes first. Overflow drops the oldest history and inserts a gap marker — current state
|
|
4
|
+
* is never part of what gets dropped, because it lives in the index, not here.
|
|
5
|
+
*
|
|
6
|
+
* The recorder cap on the runtime side and this UI cap are independent by design: one protects the producer, this one
|
|
7
|
+
* protects the panel's store and the developer's readable history.
|
|
8
|
+
*/
|
|
9
|
+
import type { RuntimeGraphFrame } from './graph.js';
|
|
10
|
+
import type { DiagnosticCauseRef, DiagnosticSequence, DiagnosticStateRevision } from './protocol.js';
|
|
11
|
+
/**
|
|
12
|
+
* A committed transaction. It has no clock of its own: the only timestamp in the protocol is `cause.at`, which
|
|
13
|
+
* stamps the trigger, so a commit with no cause shows an empty time column rather than the moment the panel reduced
|
|
14
|
+
* it. Ordering is carried by `sequence`, which is what ordering actually depends on.
|
|
15
|
+
*/
|
|
16
|
+
type TimelineFrameEntry = Readonly<{
|
|
17
|
+
cause?: DiagnosticCauseRef;
|
|
18
|
+
/** Changed records in the commit: the `O(delta)` size of the frame, not of the graph. */
|
|
19
|
+
changed: number;
|
|
20
|
+
kind: 'frame';
|
|
21
|
+
sequence: DiagnosticSequence;
|
|
22
|
+
stateRevision: DiagnosticStateRevision;
|
|
23
|
+
}>;
|
|
24
|
+
type TimelineGapReason = 'overflow' | 'resync' | 'session-reset';
|
|
25
|
+
type TimelineGapEntry = Readonly<{
|
|
26
|
+
/** Frames known to be missing, or 0 when the count itself was lost. */
|
|
27
|
+
dropped: number;
|
|
28
|
+
kind: 'gap';
|
|
29
|
+
reason: TimelineGapReason;
|
|
30
|
+
}>;
|
|
31
|
+
type TimelineEntry = TimelineFrameEntry | TimelineGapEntry;
|
|
32
|
+
type TimelineLimits = Readonly<{
|
|
33
|
+
maxBytes: number;
|
|
34
|
+
maxEntries: number;
|
|
35
|
+
}>;
|
|
36
|
+
declare const defaultTimelineLimits: TimelineLimits;
|
|
37
|
+
declare class DevtoolsTimeline {
|
|
38
|
+
get droppedCount(): number;
|
|
39
|
+
private bytes;
|
|
40
|
+
private dropped;
|
|
41
|
+
private readonly entries;
|
|
42
|
+
private readonly limits;
|
|
43
|
+
private nextEntry;
|
|
44
|
+
private overflow;
|
|
45
|
+
private snapshot;
|
|
46
|
+
constructor(limits?: TimelineLimits);
|
|
47
|
+
clear(): void;
|
|
48
|
+
list(): readonly TimelineEntry[];
|
|
49
|
+
recordFrame(frame: RuntimeGraphFrame): void;
|
|
50
|
+
recordGap(reason: TimelineGapReason, dropped: number): void;
|
|
51
|
+
/** The gap is part of both caps. A frame too large for the history becomes an explicit loss marker. */
|
|
52
|
+
private evict;
|
|
53
|
+
private overflows;
|
|
54
|
+
private push;
|
|
55
|
+
}
|
|
56
|
+
export { defaultTimelineLimits, DevtoolsTimeline };
|
|
57
|
+
export type { TimelineEntry, TimelineFrameEntry, TimelineGapEntry, TimelineGapReason, TimelineLimits };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three orthogonal axes of `docs/devtools.md` §2.4, derived from the kind-specific state
|
|
3
|
+
* unions. Only this module knows how a state maps onto `desired / lifecycle / health`; the panel styles nodes from
|
|
4
|
+
* the axes and never re-reads a state union, and nothing derives a state from a neighbour's colour.
|
|
5
|
+
*
|
|
6
|
+
* Every table below is a total record over its union, so adding a state to `node-state.ts` is a type error here
|
|
7
|
+
* rather than a silently grey node in the tree.
|
|
8
|
+
*/
|
|
9
|
+
import type { DiagnosticRuntimeNode } from './graph.js';
|
|
10
|
+
import type { DesiredAxis, HealthAxis, LifecycleAxis } from './protocol.js';
|
|
11
|
+
type DiagnosticAxes = Readonly<{
|
|
12
|
+
desired: DesiredAxis;
|
|
13
|
+
health: HealthAxis;
|
|
14
|
+
lifecycle: LifecycleAxis;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* The shapes of `docs/devtools.md` §4.6. State is never carried by colour alone.
|
|
18
|
+
*
|
|
19
|
+
* `declared` extends that table by owner decision: the design doc lists six states, all of which presuppose an open
|
|
20
|
+
* instance, and a feature the plan declares while nothing has opened it is none of them. It renders as a muted ring
|
|
21
|
+
* with its own tag rather than borrowing `waiting`, which would claim a blocker that does not exist.
|
|
22
|
+
*/
|
|
23
|
+
type NodeDisplayState = 'declared' | 'failed' | 'opening' | 'quarantined' | 'ready' | 'retiring' | 'waiting';
|
|
24
|
+
type Position = readonly [LifecycleAxis, HealthAxis];
|
|
25
|
+
/** Where the node sits in its own automaton, without the desired axis its owning condition group contributes. */
|
|
26
|
+
declare function nodePosition(node: DiagnosticRuntimeNode): Position;
|
|
27
|
+
/**
|
|
28
|
+
* The full style input for one node. `desired` is resolved by the caller from the owning condition group: a feature
|
|
29
|
+
* instance has no desired state of its own, and a debug override would live on the group (§5.4).
|
|
30
|
+
*/
|
|
31
|
+
declare function nodeAxes(node: DiagnosticRuntimeNode, desired: DesiredAxis): DiagnosticAxes;
|
|
32
|
+
/** Health wins over lifecycle: a quarantined node that is technically retiring must read as quarantined. */
|
|
33
|
+
declare function nodeDisplayState(axes: DiagnosticAxes): NodeDisplayState;
|
|
34
|
+
export { nodeAxes, nodeDisplayState, nodePosition };
|
|
35
|
+
export type { DiagnosticAxes, NodeDisplayState };
|
package/package.json
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opetope/devtools",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": ">=20.19.0"
|
|
6
|
+
},
|
|
7
|
+
"browserslist": [
|
|
8
|
+
"Chrome >= 82",
|
|
9
|
+
"Firefox >= 110",
|
|
10
|
+
"Safari >= 15",
|
|
11
|
+
"iOS >= 15",
|
|
12
|
+
"Android >= 82"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"README.ru.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"CHANGELOG.md"
|
|
21
|
+
],
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./react": {
|
|
30
|
+
"types": "./dist/react.d.ts",
|
|
31
|
+
"import": "./dist/react.js"
|
|
32
|
+
},
|
|
33
|
+
"./integration": {
|
|
34
|
+
"types": "./dist/integration.d.ts",
|
|
35
|
+
"import": "./dist/integration.js"
|
|
36
|
+
},
|
|
37
|
+
"./testing": {
|
|
38
|
+
"types": "./dist/testing.d.ts",
|
|
39
|
+
"import": "./dist/testing.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "rollup --config rollup.config.cjs",
|
|
44
|
+
"build:size-consumers": "rollup --config rollup.size.config.cjs",
|
|
45
|
+
"ci:eslint": "eslint src --quiet",
|
|
46
|
+
"ci:size-limit": "npm run build:size-consumers && size-limit",
|
|
47
|
+
"ci:test": "node --expose-gc --experimental-vm-modules ../../node_modules/jest/bin/jest.js",
|
|
48
|
+
"ci:type": "node ../../tooling/typecheck.mjs --noEmit"
|
|
49
|
+
},
|
|
50
|
+
"size-limit": [
|
|
51
|
+
{
|
|
52
|
+
"name": "headless session consumer",
|
|
53
|
+
"path": "../../node_modules/.cache/opetope-devtools-size/headless.js",
|
|
54
|
+
"limit": "5.5kb"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "react panel consumer",
|
|
58
|
+
"path": "../../node_modules/.cache/opetope-devtools-size/panel.js",
|
|
59
|
+
"limit": "21kb"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "react control surface",
|
|
63
|
+
"path": "../../node_modules/.cache/opetope-devtools-size/control.js",
|
|
64
|
+
"limit": "2kb"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "react legend surface",
|
|
68
|
+
"path": "../../node_modules/.cache/opetope-devtools-size/legend.js",
|
|
69
|
+
"limit": "1.5kb"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "snapshot exporter",
|
|
73
|
+
"path": "../../node_modules/.cache/opetope-devtools-size/export.js",
|
|
74
|
+
"limit": "1.5kb"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "react timeline surface",
|
|
78
|
+
"path": "../../node_modules/.cache/opetope-devtools-size/timeline.js",
|
|
79
|
+
"limit": "1.5kb"
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"devDependencies": {
|
|
83
|
+
"@jest/globals": "30.5.0",
|
|
84
|
+
"@opetope/runtime": "0.1.0",
|
|
85
|
+
"@testing-library/react": "16.3.3",
|
|
86
|
+
"@types/react": "19.2.18",
|
|
87
|
+
"react": "19.2.8",
|
|
88
|
+
"react-dom": "19.2.8"
|
|
89
|
+
},
|
|
90
|
+
"peerDependencies": {
|
|
91
|
+
"@opetope/runtime": "0.1.0",
|
|
92
|
+
"react": ">=19.0.0 <20",
|
|
93
|
+
"react-dom": ">=19.0.0 <20"
|
|
94
|
+
},
|
|
95
|
+
"sideEffects": false,
|
|
96
|
+
"description": "Inspection, diagnostics and developer tools for Opetope.",
|
|
97
|
+
"license": "MIT",
|
|
98
|
+
"author": "Aleksei Berezin",
|
|
99
|
+
"repository": {
|
|
100
|
+
"type": "git",
|
|
101
|
+
"url": "git+https://github.com/telchardev/opetope.git",
|
|
102
|
+
"directory": "packages/devtools"
|
|
103
|
+
},
|
|
104
|
+
"publishConfig": {
|
|
105
|
+
"access": "public"
|
|
106
|
+
}
|
|
107
|
+
}
|