@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":"panel-5jvisQBr.js","sources":["../src/control-subject.ts","../src/react/edge-filter.ts","../src/react/locale.ts","../src/react/locale-context.tsx","../src/react/edge-filters.tsx","../src/react/activity-rows.ts","../src/react/activity-view.tsx","../src/react/format.ts","../src/react/glyph.tsx","../src/react/icons.tsx","../src/react/inspector-view.tsx","../src/react/lazy-module.ts","../src/react/label.ts","../src/react/graph-layout.ts","../src/react/graph-viewport.ts","../src/react/graph-view.tsx","../src/react/main-column.tsx","../src/react/panel-header.tsx","../src/react/panel-status.tsx","../src/react/search-results.tsx","../src/react/selection.ts","../src/react/styles.ts","../src/react/theme.ts","../src/react/tree.tsx","../src/react/use-store.ts","../src/react/panel.tsx"],"sourcesContent":["/**\n * Whether the selected node is something the write port can address at all (`docs/devtools.md` §5.1).\n *\n * It lives here, outside the control surface, because two callers need the same answer at different moments: the\n * panel, to decide whether the surface is worth fetching, and the surface itself, to decide what to draw. One\n * definition keeps those two from drifting into a panel that loads a chunk it will not use, or one that has a chunk\n * and refuses to use it.\n */\n\nimport type { DevtoolsGraphStore } from './graph-store';\nimport type { InspectorProjection } from './inspector';\n\n/** A group is addressable through its conditions, and a group without any is not addressable at all (§5.1). */\ntype ControlSubject = 'condition-group' | 'quarantined-instance';\n\n/** A group with no condition is addressable by nothing, so it is not a control subject either. */\nfunction hasCondition(store: DevtoolsGraphStore, id: InspectorProjection['id']): boolean {\n const node = store.graph.planNode(id);\n\n return node?.kind === 'condition-group' && node.conditions.length > 0;\n}\n\nfunction quarantined(projection: InspectorProjection): boolean {\n return projection.kind === 'feature-instance' && projection.display === 'quarantined';\n}\n\nfunction controlSubjectOf(\n store: DevtoolsGraphStore,\n projection: InspectorProjection | undefined,\n): ControlSubject | undefined {\n if (projection === undefined) return undefined;\n\n if (projection.kind === 'condition-group') {\n return hasCondition(store, projection.id) ? 'condition-group' : undefined;\n }\n\n return quarantined(projection) ? 'quarantined-instance' : undefined;\n}\n\nexport { controlSubjectOf };\nexport type { ControlSubject };\n","/**\n * What the `Graph` tab draws, as the developer decides it: one chip per protocol edge kind, and presets that are\n * named sets of those chips (`docs/devtools.md` §4.2).\n *\n * The five lenses this replaces were five answers to one question — which relations am I looking at — and a\n * developer who wanted two of them at once had to choose. A chip set is the same choice made additive, so the\n * presets are shorthand rather than modes: the state is the set of enabled kinds, and a preset is just the name that\n * set happens to have.\n */\n\nimport type { DiagnosticEdgeKind } from '../protocol';\n\n/** The two tabs of §4.1. Everything that used to be a tab is a filter inside `graph`. */\ntype DevtoolsTab = 'graph' | 'timeline';\n\ntype EdgePresetId = 'conditions' | 'extension-points' | 'imports-and-ports' | 'ownership';\n\ntype EdgePreset = Readonly<{\n id: EdgePresetId;\n kinds: readonly DiagnosticEdgeKind[];\n /** Key into the string dictionary: a preset name is prose, and prose is translated. */\n label: 'presetConditions' | 'presetExtensionPoints' | 'presetImportsAndPorts' | 'presetOwnership';\n}>;\n\n/**\n * Chip order is the protocol's own grouping — imports, then ports, then the structural relations — so a developer\n * reading the row finds a kind where its neighbours are. The labels are protocol vocabulary and stay untranslated.\n */\nconst edgeKinds: readonly DiagnosticEdgeKind[] = [\n 'hard-import',\n 'optional-import',\n 'absent-import',\n 'on-demand-import',\n 'requires-port',\n 'optional-port',\n 'absent-port',\n 'provides-port',\n 'owns',\n 'contributes-to',\n 'condition-control',\n];\n\nconst edgePresets: readonly EdgePreset[] = [\n {\n id: 'imports-and-ports',\n kinds: [\n 'absent-import',\n 'absent-port',\n 'hard-import',\n 'on-demand-import',\n 'optional-import',\n 'optional-port',\n 'provides-port',\n 'requires-port',\n ],\n label: 'presetImportsAndPorts',\n },\n { id: 'conditions', kinds: ['condition-control', 'owns'], label: 'presetConditions' },\n { id: 'ownership', kinds: ['owns'], label: 'presetOwnership' },\n { id: 'extension-points', kinds: ['contributes-to', 'owns'], label: 'presetExtensionPoints' },\n];\n\nconst defaultPreset: EdgePresetId = 'imports-and-ports';\n\nfunction presetKinds(id: EdgePresetId): ReadonlySet<DiagnosticEdgeKind> {\n return new Set(edgePresets.find(preset => preset.id === id)?.kinds ?? []);\n}\n\nfunction sameKinds(left: ReadonlySet<DiagnosticEdgeKind>, right: readonly DiagnosticEdgeKind[]): boolean {\n return left.size === right.length && right.every(kind => left.has(kind));\n}\n\n/**\n * The name of the current selection, or `undefined` when it has none. Derived rather than stored: a chip toggled\n * back into a preset's exact set is that preset again, and a panel that remembered otherwise would be lying about\n * what it draws.\n */\nfunction presetOf(selected: ReadonlySet<DiagnosticEdgeKind>): EdgePresetId | undefined {\n return edgePresets.find(preset => sameKinds(selected, preset.kinds))?.id;\n}\n\nfunction toggleKind(\n selected: ReadonlySet<DiagnosticEdgeKind>,\n kind: DiagnosticEdgeKind,\n): ReadonlySet<DiagnosticEdgeKind> {\n const next = new Set(selected);\n\n if (!next.delete(kind)) next.add(kind);\n\n return next;\n}\n\nexport { defaultPreset, edgeKinds, edgePresets, presetKinds, presetOf, toggleKind };\nexport type { DevtoolsTab, EdgePreset, EdgePresetId };\n","/**\n * Two languages for the panel chrome, per the owner's request: English and Russian, defaulting to the browser and\n * switchable in the header.\n *\n * What is translated is the prose the panel writes: buttons, headings, empty states, explanations. What is never\n * translated is the vocabulary of the protocol — `Feature`, `FeatureInstance`, `Condition`, `declared`,\n * `hard-import`, `quarantined`, `drain` — because those are identifiers a developer greps for, matches against\n * `spec.md` §3 and reads back out of a snapshot. A translated `hard-import` would be a different word for the same\n * edge, which is exactly what a diagnostic tool must not invent.\n *\n * The English dictionary is the source of truth: `Strings` is derived from it, so a missing or extra Russian key is a\n * type error rather than a silent English word in a Russian panel.\n */\n\ntype DevtoolsLocale = 'en' | 'ru';\n\n/** Russian agrees the noun with the number, so a count cannot simply be pasted in front of a fixed plural. */\nconst russianRelations = (count: number): string => {\n const tail = count % 100;\n\n if (tail >= 11 && tail <= 14) return `${count} связей`;\n\n const last = count % 10;\n\n if (last === 1) return `${count} связь`;\n\n if (last >= 2 && last <= 4) return `${count} связи`;\n\n return `${count} связей`;\n};\n\nconst en = {\n activity: 'physical activity',\n activityCall: (state: string): string =>\n ({\n draining: 'Caller settled; physical body has not finished.',\n queued: 'Waiting for lane admission.',\n running: 'Call body is running.',\n })[state] ?? state,\n activityCoverage:\n 'Registered resources and feature/model Calls only. Host demand, UI models and stream loads are unknown. Counts do not prove absence of leaks.',\n activityEmpty: 'No activity reported for this selection within the producer coverage.',\n activityOwner: 'owner',\n activityTruncated: 'Activity was truncated. Missing entries are unknown.',\n axisDesired: 'desired',\n axisHealth: 'health',\n axisLifecycle: 'lifecycle',\n canvasHidden: (count: number): string =>\n count === 1\n ? '1 more relation on this node is filtered out.'\n : `${count} more relations on this node are filtered out.`,\n causeGatedBy: 'Gated by ',\n causeOpenUnder: 'Open under ',\n close: 'Close devtools',\n controlPlaneOff: 'control plane · off in this build',\n controlPlaneRequiresAuthority: 'control plane · authority required',\n copyId: 'Copy diagnostic id',\n copyIdDone: 'Diagnostic id copied to the clipboard.',\n copyIdFailed: 'The diagnostic id could not be copied.',\n dependenciesSatisfied: (total: number): string => `All ${total} dependencies are satisfied.`,\n dependenciesUnsatisfied: (unmet: number, total: number): string =>\n `${unmet} of ${total} dependencies are not satisfied.`,\n dependsOn: 'depends on',\n dependsOnCount: (unmet: number, total: number): string => `${unmet} of ${total} unsatisfied`,\n dependsOnNothing: 'this node depends on nothing',\n edgeFilters: 'Relations drawn',\n emptySelection: 'Select a feature to see what it depends on and what it owns.',\n exportSnapshot: 'Export snapshot',\n failureSentence: (subject: string, phase: string, code: string): string =>\n `${subject} failed in ${phase} with ${code}. `,\n fit: 'Fit',\n instanceCurrent: (generation: number): string => `${generation} current`,\n instanceWithPrevious: (generation: number, previous: number): string =>\n `${generation} current · ${previous} previous`,\n keyInstance: 'instance',\n keyKind: 'kind',\n keyLifetime: 'lifetime',\n keyOverride: 'override',\n keyProvenance: 'provenance',\n keyState: 'state',\n language: 'Language',\n lastCausalChain: 'last causal chain',\n legend: 'Legend',\n live: 'live',\n matchedFailureCode: 'matched failure code',\n matchedFailureSubject: 'matched failure subject',\n matchedId: 'matched id',\n matchedKind: 'matched kind',\n matchedProvenance: 'matched source path',\n neighbourhood: 'Selected node neighbourhood',\n noChain: 'no commit has touched this node in the retained history',\n noSearchHit: 'No node matches this query.',\n noSelection: 'Nothing selected.',\n noStateCause: 'No committed cause for this state yet.',\n ownedCount: (count: number, kind: string): string => `${count} ${kind}${count === 1 ? '' : 's'}`,\n owns: 'owns',\n ownsNothing: 'this node owns nothing right now',\n panelDetails: 'Details about the panel itself',\n panelTitle: 'Opetope Devtools',\n planBadge: (session: string, fingerprint: string): string => `${session} · plan ${fingerprint}`,\n presetConditions: 'Conditions',\n presetExtensionPoints: 'Extension points',\n presetImportsAndPorts: 'Imports and ports',\n presetOwnership: 'Ownership',\n presets: 'Relation presets',\n reducerPaint: (reducer: string, paint: string): string => `reducer ${reducer} · paint ${paint}`,\n searchLabel: 'Search by name, id, kind, source path or failure',\n searchResults: 'Search results',\n selectedInstanceTag: (generation: number): string => `instance ${generation}`,\n selectionPath: 'Selection path',\n showInTimeline: 'Show in timeline',\n stateDeclared: 'declared by the plan, no instance has opened it',\n stateFailed: 'failed to open, or its cleanup was reported',\n stateOpening: 'opening, not ready yet',\n stateQuarantined: 'quarantined, its cleanup did not settle',\n stateReady: 'ready, its exports are live',\n stateRetiring: 'retiring or closed',\n stateWaiting: 'waiting on a dependency it has not got',\n statusDropped: (dropped: number): string => `${dropped} dropped`,\n statusFrame: (sequence: number, revision: number): string => `frame ${sequence} · state rev ${revision}`,\n surfaceFailed: 'This part of the panel could not be loaded.',\n surfaceRetry: 'Try again',\n tabGraph: 'Graph',\n tabTimeline: 'Timeline',\n themeDefaults: 'theme · package defaults',\n themeHost: (count: number): string => `theme · host tokens via config (${count} vars)`,\n /**\n * The word stays `when`, in both languages: it is the name of the `defineFeature` option a developer greps for,\n * not prose about it. The key exists so the row has one place to read it from, not so it can be translated.\n */\n treeGroupPrefix: 'when',\n treeLabel: 'Application features by lifetime owner',\n treeSummary: (features: number, groups: number): string =>\n `application · ${features} features · ${groups} condition groups`,\n whyThisState: 'why this state',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n};\n\ntype Strings = typeof en;\n\n/**\n * Russian chrome. Protocol words are left as they are on purpose: `found`, `missing`, `hard-import` and the state\n * names come out of the snapshot and must read the same in both languages.\n */\nconst ru: Strings = {\n activity: 'физическая активность',\n activityCall: (state: string): string =>\n ({\n draining: 'Вызывающий получил исход; физическое тело ещё не завершилось.',\n queued: 'Ожидает допуска в lane.',\n running: 'Тело Call выполняется.',\n })[state] ?? state,\n activityCoverage:\n 'Только зарегистрированные ресурсы и вызовы фич/моделей. Спрос хоста, модели интерфейса и загрузки потоков неизвестны. Счётчики не доказывают отсутствие утечек.',\n activityEmpty: 'В пределах наблюдения активность для выбранного узла не зарегистрирована.',\n activityOwner: 'владелец',\n activityTruncated: 'Активность усечена. Отсутствующие записи неизвестны.',\n axisDesired: 'желаемое',\n axisHealth: 'исправность',\n axisLifecycle: 'жизненный цикл',\n canvasHidden: (count: number): string => `Ещё ${russianRelations(count)} этого узла отфильтровано.`,\n causeGatedBy: 'Заблокировано условием ',\n causeOpenUnder: 'Открыто при условии ',\n close: 'Закрыть devtools',\n controlPlaneOff: 'control plane · выключен в этой сборке',\n controlPlaneRequiresAuthority: 'control plane · нужна authority',\n copyId: 'Скопировать диагностический id',\n copyIdDone: 'Диагностический id скопирован в буфер обмена.',\n copyIdFailed: 'Скопировать диагностический id не удалось.',\n dependenciesSatisfied: (total: number): string => `Все зависимости удовлетворены: ${total}.`,\n dependenciesUnsatisfied: (unmet: number, total: number): string =>\n `Не удовлетворено ${unmet} из ${total} зависимостей.`,\n dependsOn: 'зависит от',\n dependsOnCount: (unmet: number, total: number): string => `${unmet} из ${total} не удовлетворено`,\n dependsOnNothing: 'узел ни от чего не зависит',\n edgeFilters: 'Какие связи рисовать',\n emptySelection: 'Выберите фичу, чтобы увидеть её зависимости и то, чем она владеет.',\n exportSnapshot: 'Выгрузить снимок',\n failureSentence: (subject: string, phase: string, code: string): string =>\n `${subject}: отказ в фазе ${phase}, код ${code}. `,\n fit: 'Вписать',\n instanceCurrent: (generation: number): string => `${generation} текущий`,\n instanceWithPrevious: (generation: number, previous: number): string =>\n `${generation} текущий · ${previous} предыдущий`,\n keyInstance: 'экземпляр',\n keyKind: 'вид',\n keyLifetime: 'время жизни',\n keyOverride: 'override',\n keyProvenance: 'источник',\n keyState: 'состояние',\n language: 'Язык',\n lastCausalChain: 'последняя причинная цепочка',\n legend: 'Легенда',\n live: 'живой',\n matchedFailureCode: 'совпал код отказа',\n matchedFailureSubject: 'совпал субъект отказа',\n matchedId: 'совпал id',\n matchedKind: 'совпал вид',\n matchedProvenance: 'совпал путь к исходнику',\n neighbourhood: 'Окрестность выбранного узла',\n noChain: 'в сохранённой истории нет коммита, затронувшего этот узел',\n noSearchHit: 'Ни один узел не подходит под запрос.',\n noSelection: 'Ничего не выбрано.',\n noStateCause: 'У этого состояния ещё нет зафиксированной причины.',\n ownedCount: (count: number, kind: string): string => `${kind}: ${count}`,\n owns: 'владеет',\n ownsNothing: 'сейчас узел ничем не владеет',\n panelDetails: 'Подробности о самой панели',\n panelTitle: 'Opetope Devtools',\n planBadge: (session: string, fingerprint: string): string => `${session} · план ${fingerprint}`,\n presetConditions: 'Условия',\n presetExtensionPoints: 'Точки расширения',\n presetImportsAndPorts: 'Импорты и порты',\n presetOwnership: 'Владение',\n presets: 'Наборы связей',\n reducerPaint: (reducer: string, paint: string): string => `reducer ${reducer} · отрисовка ${paint}`,\n searchLabel: 'Поиск по имени, id, виду, пути к исходнику или отказу',\n searchResults: 'Результаты поиска',\n selectedInstanceTag: (generation: number): string => `экземпляр ${generation}`,\n selectionPath: 'Путь выбора',\n showInTimeline: 'Показать в хронологии',\n stateDeclared: 'объявлено планом, экземпляр ещё не открывался',\n stateFailed: 'не открылось, либо об уборке доложено',\n stateOpening: 'открывается, ещё не готово',\n stateQuarantined: 'в карантине, уборка не завершилась',\n stateReady: 'готово, экспорты живые',\n stateRetiring: 'уходит или закрыто',\n stateWaiting: 'ждёт зависимость, которой у него нет',\n statusDropped: (dropped: number): string => `потеряно: ${dropped}`,\n statusFrame: (sequence: number, revision: number): string => `кадр ${sequence} · ревизия ${revision}`,\n surfaceFailed: 'Эту часть панели не удалось загрузить.',\n surfaceRetry: 'Попробовать снова',\n tabGraph: 'Граф',\n tabTimeline: 'Хронология',\n themeDefaults: 'тема · умолчания пакета',\n themeHost: (count: number): string => `тема · токены хоста из конфига (${count})`,\n /**\n * The word stays `when`, in both languages: it is the name of the `defineFeature` option a developer greps for,\n * not prose about it. The key exists so the row has one place to read it from, not so it can be translated.\n */\n treeGroupPrefix: 'when',\n treeLabel: 'Фичи приложения по владельцу времени жизни',\n treeSummary: (features: number, groups: number): string => `приложение · фич: ${features} · групп условий: ${groups}`,\n whyThisState: 'почему это состояние',\n zoomIn: 'Приблизить',\n zoomOut: 'Отдалить',\n};\n\nconst dictionaries: Readonly<Record<DevtoolsLocale, Strings>> = { en, ru };\n\nconst locales: readonly DevtoolsLocale[] = ['en', 'ru'];\n\nfunction isLocale(value: string): value is DevtoolsLocale {\n return (locales as readonly string[]).includes(value);\n}\n\n/** The browser's preference, narrowed to what the panel speaks. Anything else falls back to English. */\nfunction detectLocale(languages: readonly string[] = globalThis.navigator?.languages ?? []): DevtoolsLocale {\n for (const language of languages) {\n const tag = language.slice(0, 2).toLowerCase();\n\n if (isLocale(tag)) return tag;\n }\n\n return 'en';\n}\n\nfunction stringsFor(locale: DevtoolsLocale): Strings {\n return dictionaries[locale];\n}\n\nexport { detectLocale, locales, stringsFor };\nexport type { DevtoolsLocale, Strings };\n","/**\n * The current dictionary, passed down by context rather than threaded through every component.\n *\n * There is no provider-less fallback to English: a component that reads strings outside the panel is a bug, and a\n * silent default would hide it until a Russian panel showed one English button.\n */\n\nimport type { ReactElement, ReactNode } from 'react';\nimport { createContext, useContext, useMemo } from 'react';\n\nimport type { DevtoolsLocale, Strings } from './locale';\nimport { stringsFor } from './locale';\n\ntype LocaleValue = Readonly<{\n locale: DevtoolsLocale;\n strings: Strings;\n}>;\n\nconst LocaleContext = createContext<LocaleValue | undefined>(undefined);\n\ntype LocaleProviderProps = Readonly<{\n children: ReactNode;\n locale: DevtoolsLocale;\n}>;\n\nfunction LocaleProvider({ children, locale }: LocaleProviderProps): ReactElement {\n const value = useMemo<LocaleValue>(() => ({ locale, strings: stringsFor(locale) }), [locale]);\n\n return <LocaleContext value={value}>{children}</LocaleContext>;\n}\n\nfunction useLocaleValue(): LocaleValue {\n const value = useContext(LocaleContext);\n\n if (value === undefined) throw new Error('Devtools strings were read outside the panel.');\n\n return value;\n}\n\nfunction useStrings(): Strings {\n return useLocaleValue().strings;\n}\n\n/** For the lazily loaded surfaces, which carry their own dictionary rather than adding words to the panel's. */\nfunction useLocale(): DevtoolsLocale {\n return useLocaleValue().locale;\n}\n\nexport { LocaleProvider, useLocale, useStrings };\n","/**\n * The filter row of `docs/devtools.md` §4.2: four presets on the left, one chip per edge kind on the right.\n *\n * A preset is a button and not a tab, because pressing it is not a mode switch — it writes the chips and leaves.\n * The chips are the state, so the pressed preset is whichever one currently matches them, and none is pressed while\n * the developer holds a set of their own.\n */\n\nimport type { ReactElement } from 'react';\nimport { useCallback } from 'react';\n\nimport type { DiagnosticEdgeKind } from '../protocol';\n\nimport type { EdgePresetId } from './edge-filter';\nimport { edgeKinds, edgePresets, presetOf } from './edge-filter';\nimport { useStrings } from './locale-context';\n\ntype EdgeFiltersProps = Readonly<{\n onPreset: (preset: EdgePresetId) => void;\n onToggle: (kind: DiagnosticEdgeKind) => void;\n selected: ReadonlySet<DiagnosticEdgeKind>;\n}>;\n\ntype PresetButtonProps = Readonly<{\n label: string;\n onPreset: (preset: EdgePresetId) => void;\n preset: EdgePresetId;\n pressed: boolean;\n}>;\n\nfunction PresetButton({ label, onPreset, preset, pressed }: PresetButtonProps): ReactElement {\n const press = useCallback(() => onPreset(preset), [onPreset, preset]);\n\n return (\n <button aria-pressed={pressed} className=\"odt-preset\" type=\"button\" onClick={press}>\n {label}\n </button>\n );\n}\n\ntype EdgeChipProps = Readonly<{\n kind: DiagnosticEdgeKind;\n on: boolean;\n onToggle: (kind: DiagnosticEdgeKind) => void;\n}>;\n\n/** A switch, not a checkbox: the chip turns one relation on or off, and its own name is the whole label. */\nfunction EdgeChip({ kind, on, onToggle }: EdgeChipProps): ReactElement {\n const toggle = useCallback(() => onToggle(kind), [kind, onToggle]);\n\n return (\n <button aria-checked={on} className=\"odt-chip\" role=\"switch\" type=\"button\" onClick={toggle}>\n {kind}\n </button>\n );\n}\n\nfunction EdgeFilters({ onPreset, onToggle, selected }: EdgeFiltersProps): ReactElement {\n const strings = useStrings();\n const active = presetOf(selected);\n\n return (\n <div className=\"odt-filters\">\n <div aria-label={strings.presets} className=\"odt-presets\" role=\"group\">\n {edgePresets.map(preset => (\n <PresetButton\n key={preset.id}\n label={strings[preset.label]}\n preset={preset.id}\n pressed={preset.id === active}\n onPreset={onPreset}\n />\n ))}\n </div>\n <div aria-label={strings.edgeFilters} className=\"odt-chips\" role=\"group\">\n {edgeKinds.map(kind => (\n <EdgeChip key={kind} kind={kind} on={selected.has(kind)} onToggle={onToggle} />\n ))}\n </div>\n </div>\n );\n}\n\nexport { EdgeFilters };\n","import type { ActivityOwner, CallActivity, ResourceActivity, RuntimeActivitySnapshot } from '../activity';\n\ntype ActivityRow = Readonly<{\n details: readonly (readonly [string, number | string])[];\n id: string;\n kind: 'call' | 'feature' | 'resource' | 'stream';\n label: string;\n owner: ActivityOwner;\n state: string;\n}>;\n\nfunction blockersOf(call: CallActivity): string {\n const blockers = call.lane?.blockedBy;\n\n return blockers === 'unknown' ? blockers : (blockers?.join(', ') ?? '');\n}\n\nfunction loadsOf(resource: ResourceActivity): string {\n return resource.loads === 'unknown' ? 'unknown' : resource.loads.map(load => `${load.id}: ${load.state}`).join(', ');\n}\n\nfunction activityRows(snapshot: RuntimeActivitySnapshot): ActivityRow[] {\n const rows: ActivityRow[] = snapshot.features.map(feature => ({\n details: [\n ['body', feature.body],\n ['demand', feature.demandCount],\n ],\n id: feature.id,\n kind: 'feature',\n label: feature.feature,\n owner: feature,\n state: feature.phase,\n }));\n\n for (const call of snapshot.calls) {\n rows.push({\n details: [\n ['pendingWaiters', call.pendingWaiters],\n ['lane', call.lane?.id ?? 'parallel'],\n ['blockedBy', blockersOf(call)],\n ],\n id: call.id,\n kind: 'call',\n label: call.declaration,\n owner: call.owner,\n state: call.state,\n });\n }\n\n for (const resource of snapshot.resources) {\n rows.push({\n details: [\n ['generation', resource.generation],\n ['retention', resource.retention],\n ['retainers', resource.retainers],\n ['loads', loadsOf(resource)],\n ],\n id: resource.id,\n kind: resource.kind,\n label: resource.id,\n owner: resource.owner,\n state: resource.state,\n });\n }\n\n return rows;\n}\n\nexport { activityRows };\nexport type { ActivityRow };\n","import type { ReactElement } from 'react';\nimport { useCallback } from 'react';\n\nimport type { InspectorProjection } from '../inspector';\nimport type { DiagnosticNodeId } from '../protocol';\nimport { diagnosticNodeId } from '../protocol';\n\nimport type { ActivityRow } from './activity-rows';\nimport { activityRows } from './activity-rows';\nimport { useStrings } from './locale-context';\n\ntype ActivityViewProps = Readonly<{\n onSelect: (id: DiagnosticNodeId) => void;\n projection: InspectorProjection;\n}>;\n\nfunction ActivityItem({\n onSelect,\n row,\n}: Readonly<{\n onSelect: (id: DiagnosticNodeId) => void;\n row: ActivityRow;\n}>): ReactElement {\n const strings = useStrings();\n const select = useCallback(() => onSelect(diagnosticNodeId(row.owner.feature)), [onSelect, row.owner.feature]);\n\n return (\n <div id={row.id} className=\"odt-chain\">\n <div>\n <div className=\"odt-mono\">\n {row.kind} · {row.label} · {row.state}\n </div>\n <div className=\"odt-k\">{row.id}</div>\n {row.kind === 'call' ? <div>{strings.activityCall(row.state)}</div> : undefined}\n <button className=\"odt-btn odt-btn-quiet\" type=\"button\" onClick={select}>\n {strings.activityOwner} · {row.owner.instance} · #{row.owner.generation}\n </button>\n {row.details.map(([key, value]) => (\n <div key={key} className=\"odt-k\">\n {key}: {value === '' ? '—' : value}\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction rowsFor(projection: InspectorProjection): readonly ActivityRow[] {\n const snapshot = projection.applicationActivity;\n const owners = new Set([projection.id, ...projection.owned.map(row => row.node.id)]);\n const rows =\n snapshot === undefined\n ? []\n : activityRows(snapshot).filter(\n row =>\n projection.kind === 'application' ||\n owners.has(row.owner.feature as DiagnosticNodeId) ||\n owners.has(row.owner.instance as DiagnosticNodeId),\n );\n\n return rows;\n}\n\nfunction ActivityView({ onSelect, projection }: ActivityViewProps): ReactElement {\n const strings = useStrings();\n const snapshot = projection.applicationActivity;\n const rows = rowsFor(projection);\n\n return (\n <section className=\"odt-section\">\n <h3 className=\"odt-sec\">{strings.activity}</h3>\n <div className=\"odt-k\">\n {snapshot?.executionId} · {snapshot?.freshness ?? 'unknown'}\n </div>\n {snapshot?.truncated ? <div>{strings.activityTruncated}</div> : undefined}\n <div className=\"odt-k\">{strings.activityCoverage}</div>\n {rows.length === 0 ? (\n <div className=\"odt-k\">{strings.activityEmpty}</div>\n ) : (\n rows.map(row => <ActivityItem key={row.id} row={row} onSelect={onSelect} />)\n )}\n </section>\n );\n}\n\nexport { ActivityView };\n","/** Presentation-only formatting. Nothing here decides state; it renders values the projection already resolved. */\n\nimport type { DiagnosticTimestamp } from '../protocol';\n\nimport type { Strings } from './locale';\n\nconst timeFormat = new Intl.DateTimeFormat(undefined, {\n hour: '2-digit',\n hour12: false,\n minute: '2-digit',\n second: '2-digit',\n});\n\n/** `14:02:31` — wall-clock only, for facts where the millisecond adds noise rather than ordering. */\nfunction formatClock(at: DiagnosticTimestamp): string {\n return timeFormat.format(at);\n}\n\n/** `14:02:31.114` — the timestamp column of the causal chain and the timeline, where ordering is the point. */\nfunction formatTime(at: DiagnosticTimestamp): string {\n const milliseconds = String(at % 1000).padStart(3, '0');\n\n return `${formatClock(at)}.${milliseconds}`;\n}\n\n/**\n * `3 current · 2 previous` — a feature declaration outlives its instances, so the counter says which life this is.\n * The number of the previous life carries no time: the protocol's only clock is `cause.at`, and it stamps a trigger,\n * not a retirement.\n */\nfunction formatInstance(generation: number, previous: number | undefined, strings: Strings): string {\n return previous === undefined\n ? strings.instanceCurrent(generation)\n : strings.instanceWithPrevious(generation, previous);\n}\n\n/** The time column of a commit that has no cause is empty, because the protocol never stamped one. */\nfunction formatOptionalTime(at: DiagnosticTimestamp | undefined): string {\n return at === undefined ? '—' : formatTime(at);\n}\n\nfunction formatMilliseconds(value: number): string {\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ms`;\n}\n\nexport { formatClock, formatInstance, formatMilliseconds, formatOptionalTime, formatTime };\n","/**\n * State coding per `docs/devtools.md` §4.6: shape, colour and text tag together, never colour alone.\n *\n * The glyph itself is `aria-hidden`: it is always rendered next to the state's own text — a tag in the tree and the\n * inspector, the sub-line on a graph card — so a screen reader gets the state once, as words.\n */\n\nimport type { ReactElement } from 'react';\n\nimport type { NodeDisplayState } from '../visual-axes';\n\nimport type { Strings } from './locale';\nimport { useStrings } from './locale-context';\n\ntype GlyphTone = 'bad' | 'mute' | 'ok' | 'warn';\n\ntype GlyphShape = 'circle' | 'cross-square' | 'diamond' | 'ring' | 'triangle';\n\nconst shapeByState: Readonly<Record<NodeDisplayState, GlyphShape>> = {\n declared: 'ring',\n failed: 'triangle',\n opening: 'ring',\n quarantined: 'cross-square',\n ready: 'circle',\n retiring: 'diamond',\n waiting: 'ring',\n};\n\nconst toneByState: Readonly<Record<NodeDisplayState, GlyphTone>> = {\n declared: 'mute',\n failed: 'bad',\n opening: 'mute',\n quarantined: 'bad',\n ready: 'ok',\n retiring: 'mute',\n waiting: 'warn',\n};\n\nconst tagToneByState: Readonly<Record<NodeDisplayState, string>> = {\n declared: 'odt-tag-mute',\n failed: 'odt-tag-bad',\n opening: 'odt-tag-mute',\n quarantined: 'odt-tag-bad',\n ready: 'odt-tag-ok',\n retiring: 'odt-tag-mute',\n waiting: 'odt-tag-warn',\n};\n\n/**\n * Wording for screen readers and tooltips: the tag text alone is terse by design. The state name itself is a protocol\n * word and stays as it is in every language; only the sentence explaining it is translated.\n */\nconst stateDescriptionKey: Readonly<Record<NodeDisplayState, keyof Strings>> = {\n declared: 'stateDeclared',\n failed: 'stateFailed',\n opening: 'stateOpening',\n quarantined: 'stateQuarantined',\n ready: 'stateReady',\n retiring: 'stateRetiring',\n waiting: 'stateWaiting',\n};\n\nfunction stateDescription(state: NodeDisplayState, strings: Strings): string {\n return strings[stateDescriptionKey[state]] as string;\n}\n\n/** Every lifecycle state the panel can draw, in the order the legend lists them. */\nconst displayStates: readonly NodeDisplayState[] = [\n 'ready',\n 'opening',\n 'waiting',\n 'declared',\n 'retiring',\n 'failed',\n 'quarantined',\n];\n\nfunction shapeElement(shape: GlyphShape): ReactElement {\n if (shape === 'circle') return <circle cx=\"5\" cy=\"5\" fill=\"currentColor\" r=\"5\" />;\n\n if (shape === 'ring') return <circle cx=\"5\" cy=\"5\" fill=\"none\" r=\"4\" stroke=\"currentColor\" strokeWidth=\"2\" />;\n\n if (shape === 'diamond') return <path d=\"M5 0l5 5-5 5-5-5z\" fill=\"currentColor\" />;\n\n if (shape === 'triangle') return <path d=\"M5 0l5 10H0z\" fill=\"currentColor\" />;\n\n return (\n <g fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M1 1h8v8H1z\" />\n <path d=\"M1 1l8 8M9 1L1 9\" strokeWidth=\"1.2\" />\n </g>\n );\n}\n\nfunction StateGlyph({ size = 10, state }: { size?: number; state: NodeDisplayState }): ReactElement {\n return (\n <span className={`odt-glyph odt-glyph-${toneByState[state]}`} aria-hidden>\n <svg height={size} viewBox=\"0 0 10 10\" width={size}>\n {shapeElement(shapeByState[state])}\n </svg>\n </span>\n );\n}\n\nfunction StateTag({ state }: { state: NodeDisplayState }): ReactElement {\n const strings = useStrings();\n\n return (\n <span className={`odt-tag ${tagToneByState[state]}`} title={stateDescription(state, strings)}>\n {state}\n </span>\n );\n}\n\nexport { displayStates, stateDescription, StateGlyph, StateTag };\n","/** The panel's own icon set. Kept local so `@opetope/devtools` needs no icon package to render. */\n\nimport type { ReactElement } from 'react';\n\ntype IconProps = { readonly size?: number };\n\nfunction frame(path: ReactElement, size: number): ReactElement {\n return (\n <span className=\"odt-glyph\" aria-hidden>\n <svg fill=\"currentColor\" height={size} viewBox=\"0 0 24 24\" width={size}>\n {path}\n </svg>\n </span>\n );\n}\n\nfunction SearchIcon({ size = 16 }: IconProps): ReactElement {\n return frame(\n <path\n clipRule=\"evenodd\"\n d=\"M11 4a7 7 0 1 0 4.856 12.041 1 1 0 0 1 .185-.185A7 7 0 0 0 11 4m7.032 12.618a9 9 0 1 0-1.414 1.414l3.675 3.675a1 1 0 0 0 1.414-1.414z\"\n fillRule=\"evenodd\"\n />,\n size,\n );\n}\n\nfunction CloseIcon({ size = 16 }: IconProps): ReactElement {\n return frame(\n <path d=\"M6.707 5.293a1 1 0 0 0-1.414 1.414L10.586 12l-5.293 5.293a1 1 0 1 0 1.414 1.414L12 13.414l5.293 5.293a1 1 0 0 0 1.414-1.414L13.414 12l5.293-5.293a1 1 0 0 0-1.414-1.414L12 10.586z\" />,\n size,\n );\n}\n\nfunction CopyIcon({ size = 16 }: IconProps): ReactElement {\n return frame(\n <path d=\"M8 3a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zm0 2h8v10H8zM4 8a1 1 0 0 1 1 1v9h8a1 1 0 1 1 0 2H5a2 2 0 0 1-2-2V9a1 1 0 0 1 1-1\" />,\n size,\n );\n}\n\nfunction ChevronIcon({ open, size = 16 }: IconProps & { readonly open: boolean }): ReactElement {\n return frame(\n open ? (\n <path d=\"M8.293 9.293a1 1 0 0 1 1.414 0L12 11.586l2.293-2.293a1 1 0 1 1 1.414 1.414l-3 3a1 1 0 0 1-1.414 0l-3-3a1 1 0 0 1 0-1.414\" />\n ) : (\n <path d=\"M9.293 8.293a1 1 0 0 1 1.414 0l3 3a1 1 0 0 1 0 1.414l-3 3a1 1 0 0 1-1.414-1.414L11.586 12 9.293 9.707a1 1 0 0 1 0-1.414\" />\n ),\n size,\n );\n}\n\nexport { ChevronIcon, CloseIcon, CopyIcon, SearchIcon };\n","/**\n * The inspector of `docs/devtools.md` §4: axis tags, key/value grid, \"why this state\", blockers, owned\n * nodes and the last causal chain, over a scrolling body with a pinned action footer.\n *\n * Every sentence here is composed from the typed facts of `InspectorProjection`. The panel decides wording; it never\n * receives prose, parses an error, or infers a state from a colour (§2).\n */\n\nimport type { ReactElement, ReactNode } from 'react';\nimport { useCallback } from 'react';\n\nimport type { InspectorBlocker, InspectorOwned, InspectorProjection, InspectorWhy } from '../inspector';\nimport type { DiagnosticCausalStep } from '../node-state';\nimport type { DiagnosticConditionId, DiagnosticFailure, DiagnosticNodeId } from '../protocol';\n\nimport { ActivityView } from './activity-view';\nimport { formatInstance, formatOptionalTime } from './format';\nimport { StateGlyph } from './glyph';\nimport { CopyIcon } from './icons';\nimport type { Strings } from './locale';\nimport { useStrings } from './locale-context';\n\ntype InspectorViewProps = Readonly<{\n /** The last outcome of an action, shown next to the buttons so an export or a copy is visibly not a no-op. */\n actionStatus?: string;\n /** Resolves the atom a cause names to the declaration id the author wrote (D200). */\n conditionLabelOf: ConditionLabel;\n /** The control slot of §5, when a host passed a write port. Nothing at all otherwise. */\n control: ReactNode;\n /** Resolves a causal step's node ref to its label. Labels live on nodes, not repeated on every step. */\n labelOf: (id: DiagnosticNodeId) => string;\n onCopyId: (id: DiagnosticNodeId) => void;\n onExport: () => void;\n onSelect: (id: DiagnosticNodeId) => void;\n onShowInTimeline: () => void;\n projection: InspectorProjection;\n}>;\n\n/** How a view turns the atom a condition is addressed by into the name a reader recognises. */\ntype ConditionLabel = (id: DiagnosticConditionId) => string;\n\nfunction axisTone(healthy: boolean): string {\n return healthy ? 'odt-tag-ok' : 'odt-tag-bad';\n}\n\n/**\n * The two words of the runtime's own error: the subject class and its code (D69). Never a message (§2.6). The three\n * protocol words are placed into a translated sentence rather than translated themselves.\n */\nfunction failureSentence(failure: DiagnosticFailure, strings: Strings): string {\n return strings.failureSentence(failure.subject, failure.phase, failure.code);\n}\n\n/** A condition flip names the condition; anything else names its cause kind. Time comes from `cause.at` only. */\nfunction causeSentence(\n projection: InspectorProjection,\n strings: Strings,\n conditionLabelOf: ConditionLabel,\n): readonly ReactNode[] {\n const cause = projection.why.cause;\n\n if (cause === undefined) return [];\n\n const when = cause.at === undefined ? '. ' : ` · ${formatOptionalTime(cause.at)}. `;\n\n if (cause.condition === undefined) return [`${cause.kind}${when}`];\n\n return [\n projection.axes.lifecycle === 'ready' ? strings.causeOpenUnder : strings.causeGatedBy,\n // The protocol carries the escaped atom; a reader is owed the declaration id the author wrote (D200).\n <span key=\"condition\" className=\"odt-why-ref\">\n {conditionLabelOf(cause.condition)}\n </span>,\n when,\n ];\n}\n\nfunction blockerSentence(why: InspectorWhy, strings: Strings): string | undefined {\n if (why.totalBlockers === 0) return undefined;\n\n if (why.readyBlockers === why.totalBlockers) return strings.dependenciesSatisfied(why.totalBlockers);\n\n return strings.dependenciesUnsatisfied(why.totalBlockers - why.readyBlockers, why.totalBlockers);\n}\n\n/** \"Open under sampleApp.authorized at 14:02:31.072. All 4 dependencies are satisfied.\" */\nfunction whyText(projection: InspectorProjection, strings: Strings, conditionLabelOf: ConditionLabel): ReactNode {\n const { why } = projection;\n const parts: ReactNode[] =\n why.failure === undefined\n ? [...causeSentence(projection, strings, conditionLabelOf)]\n : [failureSentence(why.failure, strings)];\n\n if (why.progress !== undefined) parts.push(`${why.progress}. `);\n\n const blockers = blockerSentence(why, strings);\n\n if (blockers !== undefined) parts.push(blockers);\n\n return parts.length === 0 ? strings.noStateCause : parts;\n}\n\nfunction KeyValue({ children, label }: { readonly children: ReactNode; readonly label: string }): ReactElement {\n return (\n <>\n <span className=\"odt-k\">{label}</span>\n <span className=\"odt-v\" title={typeof children === 'string' ? children : undefined}>\n {children}\n </span>\n </>\n );\n}\n\n/** The instance counter of a feature instance; other node kinds have no life to number. */\nfunction InstanceRow({ projection }: { readonly projection: InspectorProjection }): ReactNode {\n const strings = useStrings();\n const { generation, node } = projection;\n\n if (generation === undefined) return undefined;\n\n const previous = node?.kind === 'feature-instance' ? node.previous : undefined;\n\n return (\n <KeyValue label={strings.keyInstance}>\n <span className=\"odt-mono\">{formatInstance(generation, previous, strings)}</span>\n </KeyValue>\n );\n}\n\nfunction IdentityGrid({ projection }: { readonly projection: InspectorProjection }): ReactElement {\n const strings = useStrings();\n const { groupLabel, node, override, provenance } = projection;\n\n return (\n <div className=\"odt-kv\">\n <KeyValue label={strings.keyKind}>{projection.kind}</KeyValue>\n <InstanceRow projection={projection} />\n {groupLabel === undefined ? undefined : <KeyValue label={strings.keyLifetime}>{groupLabel}</KeyValue>}\n {node === undefined ? undefined : <KeyValue label={strings.keyState}>{node.state.kind}</KeyValue>}\n {override === 'none' ? undefined : <KeyValue label={strings.keyOverride}>{override}</KeyValue>}\n {provenance === undefined ? undefined : <KeyValue label={strings.keyProvenance}>{provenance}</KeyValue>}\n </div>\n );\n}\n\ntype BlockerRowProps = Readonly<{\n blocker: InspectorBlocker;\n onSelect: (id: DiagnosticNodeId) => void;\n}>;\n\nfunction BlockerRow({ blocker, onSelect }: BlockerRowProps): ReactElement {\n const select = useCallback(() => onSelect(blocker.node), [blocker.node, onSelect]);\n\n return (\n <button className=\"odt-section-row\" type=\"button\" onClick={select}>\n <StateGlyph size={8} state={blocker.display} />\n <span className=\"odt-section-row-label\">{blocker.label}</span>\n <span className=\"odt-k\">\n {blocker.kind}\n {blocker.lookup === undefined ? '' : ` · ${blocker.lookup}`}\n </span>\n </button>\n );\n}\n\ntype OwnedRowProps = Readonly<{\n onSelect: (id: DiagnosticNodeId) => void;\n row: InspectorOwned;\n}>;\n\nfunction OwnedRow({ onSelect, row }: OwnedRowProps): ReactElement {\n const select = useCallback(() => onSelect(row.node.id), [onSelect, row.node.id]);\n\n return (\n <button\n className={row.depth > 0 ? 'odt-section-row odt-section-row-nested' : 'odt-section-row'}\n type=\"button\"\n onClick={select}\n >\n <StateGlyph size={8} state={row.display} />\n <span className=\"odt-section-row-label\">{row.node.label}</span>\n <span className=\"odt-k odt-mono\">{row.node.state.kind}</span>\n </button>\n );\n}\n\ntype ChainRowProps = Readonly<{\n conditionLabelOf: ConditionLabel;\n labelOf: (id: DiagnosticNodeId) => string;\n step: DiagnosticCausalStep;\n}>;\n\nfunction ChainRow({ conditionLabelOf, labelOf, step }: ChainRowProps): ReactElement {\n const condition = step.cause.condition === undefined ? undefined : conditionLabelOf(step.cause.condition);\n const subject = step.node === undefined ? step.cause.kind : labelOf(step.node);\n\n return (\n <div className=\"odt-chain\">\n <span className=\"odt-chain-time\">{formatOptionalTime(step.cause.at)}</span>\n <span>\n {condition === undefined ? (\n <>\n {subject} · {step.lifecycle ?? step.cause.kind}\n </>\n ) : (\n <>\n <span className=\"odt-why-ref\">{condition}</span> → {subject}\n </>\n )}\n </span>\n </div>\n );\n}\n\nfunction InspectorView({\n actionStatus,\n conditionLabelOf,\n control,\n labelOf,\n onCopyId,\n onExport,\n onSelect,\n onShowInTimeline,\n projection,\n}: InspectorViewProps): ReactElement {\n const strings = useStrings();\n const { axes, blockers, chain, owned } = projection;\n const copy = useCallback(() => onCopyId(projection.id), [onCopyId, projection.id]);\n\n return (\n <div className=\"odt-inspector\">\n <div className=\"odt-inspector-scroll\">\n <div className=\"odt-inspector-head\">\n <div className=\"odt-inspector-title\">\n <span className=\"odt-truncate\">{projection.label}</span>\n <button\n aria-label={strings.copyId}\n className=\"odt-btn odt-btn-icon odt-btn-quiet\"\n type=\"button\"\n onClick={copy}\n >\n <CopyIcon />\n </button>\n </div>\n <div className=\"odt-axes\">\n <span className=\"odt-tag odt-tag-accent\">\n {strings.axisDesired} · {axes.desired}\n </span>\n <span className={`odt-tag ${axisTone(axes.lifecycle !== 'closed')}`}>\n {strings.axisLifecycle} · {axes.lifecycle}\n </span>\n <span className={`odt-tag ${axisTone(axes.health === 'healthy')}`}>\n {strings.axisHealth} · {axes.health}\n </span>\n </div>\n </div>\n\n <IdentityGrid projection={projection} />\n\n <div className=\"odt-why\">\n <div className=\"odt-sec\">{strings.whyThisState}</div>\n <div className=\"odt-why-text\">{whyText(projection, strings, conditionLabelOf)}</div>\n </div>\n\n <section className=\"odt-section\">\n <h3 className=\"odt-sec\">\n {strings.dependsOn} ·{' '}\n {strings.dependsOnCount(\n projection.why.totalBlockers - projection.why.readyBlockers,\n projection.why.totalBlockers,\n )}\n </h3>\n <div className=\"odt-section-rows\">\n {blockers.length === 0 ? (\n <span className=\"odt-k\">{strings.dependsOnNothing}</span>\n ) : (\n blockers.map(blocker => <BlockerRow key={blocker.node} blocker={blocker} onSelect={onSelect} />)\n )}\n </div>\n </section>\n\n <section className=\"odt-section\">\n <h3 className=\"odt-sec\">{strings.owns}</h3>\n <div className=\"odt-section-rows\">\n {owned.length === 0 ? (\n <span className=\"odt-k\">{strings.ownsNothing}</span>\n ) : (\n owned.map(row => <OwnedRow key={row.edge.id} row={row} onSelect={onSelect} />)\n )}\n </div>\n </section>\n\n <ActivityView projection={projection} onSelect={onSelect} />\n\n <section className=\"odt-section\">\n <h3 className=\"odt-sec\">{strings.lastCausalChain}</h3>\n <div className=\"odt-section-rows\">\n {chain.length === 0 ? (\n <span className=\"odt-k\">{strings.noChain}</span>\n ) : (\n chain.map(step => (\n <ChainRow\n key={`${step.sequence}:${step.node ?? ''}`}\n conditionLabelOf={conditionLabelOf}\n labelOf={labelOf}\n step={step}\n />\n ))\n )}\n </div>\n </section>\n </div>\n\n {/*\n The control actions of §5, when this build has a write port at all. Their code is a chunk of its own, so a\n panel installed without one has nothing here and never fetched the bytes that would fill it; the status bar\n is where it says so.\n */}\n <div className=\"odt-footer\">\n {control}\n <button className=\"odt-btn odt-btn-small\" type=\"button\" onClick={onShowInTimeline}>\n {strings.showInTimeline}\n </button>\n <button className=\"odt-btn odt-btn-small\" type=\"button\" onClick={onExport}>\n {strings.exportSnapshot}\n </button>\n <span aria-live=\"polite\" className=\"odt-footer-status odt-footer-end\">\n {actionStatus ?? ''}\n </span>\n </div>\n </div>\n );\n}\n\nexport { InspectorView };\n","/**\n * Loads a surface only when the panel actually needs it (`docs/devtools.md` §6).\n *\n * Four surfaces earn a chunk of their own: the control plane, which a host without a write port must not carry at\n * all; the legend, collapsed until a developer asks what a shape means; the exporter, behind the click that uses it;\n * and the timeline, which arrives with its tab. They are the same shape — a module the panel wants at a moment it\n * can name — so they share one hook rather than one loader each.\n *\n * The loader is compared by identity, so it has to be a module-level constant; a loader built during render would\n * refetch on every commit. The cache is per page, because a second panel in the same document should not fetch a\n * module the first one already has.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport type * as ControlUi from './control-ui';\nimport type * as ExportRun from './export-run';\nimport type * as LegendUi from './legend';\nimport type * as TimelineUi from './timeline-view';\n\ntype Loader<Module> = () => Promise<Module>;\n\n/**\n * What the panel knows about a surface right now. A fetch can fail — a chunk can be missing, a deploy can be half\n * replaced, a network can refuse — and a failure that only rejects a promise leaves the panel showing nothing while\n * telling nobody. So the state is explicit, and a failed surface offers the one action that can help: try again.\n */\ntype LazyModule<Module> = Readonly<{\n error: unknown;\n module: Module | undefined;\n retry: () => void;\n}>;\n\n/** Modules already loaded, so a second panel in the same document reads them without a fetch or a blank frame. */\nconst loaded = new Map<Loader<never>, unknown>();\n\n/** Fetches in flight, so two surfaces asking at once share one request rather than starting two. */\nconst pending = new Map<Loader<never>, Promise<unknown>>();\n\nfunction useLazyModule<Module>(load: Loader<Module> | undefined): LazyModule<Module> {\n const [attempt, setAttempt] = useState(0);\n const [failure, setFailure] = useState<unknown>(undefined);\n const [fetched, setFetched] = useState<Module | undefined>(undefined);\n const key = load as Loader<never> | undefined;\n const retry = useCallback(() => {\n setFailure(undefined);\n setAttempt(count => count + 1);\n }, []);\n\n useEffect(() => {\n if (key === undefined || loaded.has(key)) return undefined;\n\n let active = true;\n const request = pending.get(key) ?? load!();\n\n pending.set(key, request);\n request.then(\n module => {\n loaded.set(key, module);\n pending.delete(key);\n\n if (active) setFetched(module as Module);\n },\n (error: unknown) => {\n // The failed attempt is forgotten rather than cached: a retry has to be able to ask again.\n pending.delete(key);\n\n if (active) setFailure(error);\n },\n );\n\n return () => {\n active = false;\n };\n }, [attempt, key, load]);\n\n // A surface that is no longer wanted is no longer rendered, even though its module stays in the page cache.\n const module = key === undefined ? undefined : ((loaded.get(key) as Module | undefined) ?? fetched);\n\n return { error: key === undefined ? undefined : failure, module, retry };\n}\n\n/** The write port's surface (§5): fetched when a host passes a control session, and never otherwise. */\nconst loadControlUi = (): Promise<typeof ControlUi> => import('./control-ui');\n\n/** The legend (§4.6): fetched the first time it is opened, which for most sessions is never. */\nconst loadLegend = (): Promise<typeof LegendUi> => import('./legend');\n\n/** The exporter (§2.6): fetched by the click, because a session that never exports never needs it. */\nconst loadExportRun = (): Promise<typeof ExportRun> => import('./export-run');\n\n/** The timeline (§4.1): a whole tab, and a session that watches the graph never opens it. */\nconst loadTimeline = (): Promise<typeof TimelineUi> => import('./timeline-view');\n\nexport { loadControlUi, loadExportRun, loadLegend, loadTimeline, useLazyModule };\nexport type { LazyModule };\n","/**\n * Fitting a node's name into a card of fixed width without losing the part that tells it apart (§4.3).\n *\n * A graph id is a path, and the tail is what distinguishes siblings: `sample.dev-mode` and `sample.dev-mode.settings`\n * differ only after the last dot, which is exactly what a CSS ellipsis on the right throws away first. So the panel\n * shortens on purpose instead of letting the box do it — relative to the selection where that is possible, and from\n * the middle where it is not — and hands the full id to `title`, so hovering always answers what the card is.\n *\n * The budgets are estimates, not measurements: a card is 188 px wide with 12 px of padding either side and a glyph\n * ahead of the text, which leaves roughly 148 px, and the panel's font runs about 6.3 px per character at 12 px and\n * 7.3 px at 14 px. CSS truncation stays as the backstop for the cases arithmetic gets wrong.\n */\n\nconst neighbourBudget = 23;\nconst selectedBudget = 19;\n\n/**\n * A neighbour written relative to the selected node: `sample.dev-mode.settings` beside `sample.dev-mode` becomes\n * `…settings`. Only a true prefix counts, and only at a dot, so `sample.dev-modes` is left alone.\n */\nfunction relativeTo(label: string, selected: string | undefined): string {\n if (selected === undefined || selected === label) return label;\n\n return label.startsWith(`${selected}.`) ? `…${label.slice(selected.length + 1)}` : label;\n}\n\n/**\n * Middle truncation that keeps the last segment whole: `features.sessions.confirmAction` becomes\n * `features….confirmAction` rather than `features.sessions.conf…`. When the last segment alone does not fit, the\n * cut moves into it from the left, because its end is still the most distinguishing thing left.\n */\nfunction fitLabel(text: string, budget: number): string {\n if (text.length <= budget) return text;\n\n const lastDot = text.lastIndexOf('.');\n const tail = lastDot === -1 ? text : text.slice(lastDot);\n\n if (tail.length + 1 >= budget) return `…${text.slice(text.length - budget + 1)}`;\n\n return `${text.slice(0, budget - tail.length - 1)}…${tail}`;\n}\n\n/** What a neighbour card draws: relative to the selection first, and cut from the middle only if it still overflows. */\nfunction neighbourLabel(label: string, selected: string | undefined): string {\n return fitLabel(relativeTo(label, selected), neighbourBudget);\n}\n\n/** The selected card carries its own name in a larger type, so it has fewer characters to spend and no relative form. */\nfunction selectedLabel(label: string): string {\n return fitLabel(label, selectedBudget);\n}\n\nexport { fitLabel, neighbourLabel, relativeTo, selectedLabel };\n","/**\n * Deterministic three-column layout for the selected node's neighbourhood: blockers on the left, the selection in\n * the middle, what it owns and publishes on the right — the arrangement `docs/devtools.md` §4 describes.\n *\n * Layout is pure and measured in CSS pixels, and the SVG that draws the edges uses the same pixel box as the layer\n * holding the cards. That is what keeps edges attached to cards at any drawer height (§8 acceptance), and it keeps\n * the layout testable and cacheable by topology revision (§6) without a DOM.\n */\n\nimport type { ExtensionPointsProjection, ExtensionRow } from '../extension-points';\nimport type { InspectorBlocker, InspectorOwned, InspectorProjection } from '../inspector';\nimport type { DiagnosticEdgeKind, DiagnosticLabel, DiagnosticNodeId } from '../protocol';\nimport type { NodeDisplayState } from '../visual-axes';\n\nimport { neighbourLabel, selectedLabel } from './label';\nimport type { Strings } from './locale';\n\nconst cardWidth = 188;\nconst cardHeight = 52;\nconst selectedCardHeight = 76;\nconst columnStep = 244;\nconst rowStep = 96;\nconst leftPadding = 24;\nconst topPadding = 52;\nconst bottomPadding = 44;\n\ntype LaidOutNode = Readonly<{\n /** Third line of the selected card: what its current generation owns. */\n detail?: string;\n display: NodeDisplayState;\n height: number;\n id: DiagnosticNodeId;\n /**\n * React key. It cannot be the node id: one provider can reach the same consumer through two relations — a\n * candidate admission and a selected-provider wait, say — and then appears in the column twice.\n */\n key: string;\n label: DiagnosticLabel;\n selected: boolean;\n /**\n * The `<relation> · <state>` line under the title, already split so the card does not build strings. Absent on the\n * selected card, which carries its kind and generation as tags and its state as a state tag instead.\n */\n sub?: readonly [string, string];\n /** Tag chips on the selected card: its kind and its generation. */\n tags?: readonly string[];\n /** The full name, for `title`: `label` may have been shortened to fit the card, and this never is (§4.3). */\n title: DiagnosticLabel;\n x: number;\n y: number;\n}>;\n\ntype LaidOutEdge = Readonly<{\n id: string;\n kind: DiagnosticEdgeKind;\n path: string;\n}>;\n\ntype GraphLayout = Readonly<{\n edges: readonly LaidOutEdge[];\n height: number;\n /** Relations the filter leaves out. Shown as a hint, so an empty canvas is never mistaken for an isolated node. */\n hidden: number;\n nodes: readonly LaidOutNode[];\n width: number;\n}>;\n\ntype Anchor = Readonly<{ x: number; y: number }>;\n\nfunction centerRight(node: LaidOutNode): Anchor {\n return { x: node.x + cardWidth, y: node.y + node.height / 2 };\n}\n\nfunction centerLeft(node: LaidOutNode): Anchor {\n return { x: node.x, y: node.y + node.height / 2 };\n}\n\nfunction curve(from: Anchor, to: Anchor): string {\n if (from.y === to.y) return `M ${from.x} ${from.y} L ${to.x} ${to.y}`;\n\n const bend = Math.min(40, (to.x - from.x) / 2);\n\n return `M ${from.x} ${from.y} C ${from.x + bend} ${from.y}, ${to.x - bend} ${to.y}, ${to.x} ${to.y}`;\n}\n\nfunction column(index: number): number {\n return leftPadding + index * columnStep;\n}\n\nfunction stack(index: number, count: number, tallest: number): number {\n const offset = (tallest - count) / 2;\n\n return topPadding + (index + Math.max(0, offset)) * rowStep;\n}\n\nfunction blockerNode(\n blocker: InspectorBlocker,\n index: number,\n count: number,\n tallest: number,\n selected: DiagnosticLabel,\n): LaidOutNode {\n return {\n display: blocker.display,\n height: cardHeight,\n id: blocker.node,\n key: `in:${index}:${blocker.node}`,\n label: neighbourLabel(blocker.label, selected),\n selected: false,\n sub: [blocker.kind, blocker.ready ? 'ready' : 'waiting'],\n title: blocker.label,\n x: column(0),\n y: stack(index, count, tallest),\n };\n}\n\nfunction ownedNode(\n owned: InspectorOwned,\n index: number,\n count: number,\n tallest: number,\n selected: DiagnosticLabel,\n): LaidOutNode {\n return {\n display: owned.display,\n height: cardHeight,\n id: owned.node.id,\n key: owned.edge.id,\n label: neighbourLabel(owned.node.label, selected),\n selected: false,\n sub: [owned.edge.kind, owned.node.state.kind],\n title: owned.node.label,\n x: column(2),\n y: stack(index, count, tallest),\n };\n}\n\n/** \"2 attachments · 1 contribution\" — what the selected node owns right now, on its own card. */\nfunction ownershipSummary(projection: InspectorProjection, strings: Strings): string | undefined {\n const counts = new Map<string, number>();\n\n for (const row of projection.owned) counts.set(row.node.kind, (counts.get(row.node.kind) ?? 0) + 1);\n\n const parts = [...counts.entries()].map(([kind, count]) => strings.ownedCount(count, kind));\n\n return parts.length === 0 ? undefined : parts.join(' · ');\n}\n\nfunction selectedTags(projection: InspectorProjection, strings: Strings): readonly string[] {\n if (projection.generation === undefined) return [projection.kind];\n\n return [projection.kind, strings.selectedInstanceTag(projection.generation)];\n}\n\nfunction contributionNode(\n row: ExtensionRow,\n index: number,\n count: number,\n tallest: number,\n inverted: boolean,\n selected: DiagnosticLabel,\n): LaidOutNode {\n return {\n display: row.contributionDisplay,\n height: cardHeight,\n id: row.contribution,\n key: `contribution:${index}:${row.contribution}`,\n label: neighbourLabel(row.contributionLabel, selected),\n selected: false,\n sub: [inverted ? 'contributes-to' : row.contributorLabel, row.state],\n title: row.contributionLabel,\n x: column(1),\n y: stack(index, count, tallest),\n };\n}\n\nfunction endpointNode(\n row: ExtensionRow,\n index: number,\n count: number,\n tallest: number,\n inverted: boolean,\n selected: DiagnosticLabel,\n): LaidOutNode {\n return {\n display: row.endpointDisplay,\n height: cardHeight,\n id: row.endpoint,\n key: `endpoint:${index}:${row.endpoint}`,\n label: neighbourLabel(row.endpointLabel, selected),\n selected: false,\n sub: [inverted ? 'contributor' : 'target', row.endpointDisplay],\n title: row.endpointLabel,\n x: column(2),\n y: stack(index, count, tallest),\n };\n}\n\n/**\n * Lays out the neighbourhood the filter is interested in. Nested owned rows are flattened into the right column: the\n * canvas shows one hop, the inspector shows the ownership tree.\n */\nfunction layoutNeighbourhood(\n projection: InspectorProjection,\n edgeKinds: ReadonlySet<DiagnosticEdgeKind> | undefined,\n strings: Strings,\n): GraphLayout {\n const shows = (kind: DiagnosticEdgeKind): boolean => edgeKinds === undefined || edgeKinds.has(kind);\n const blockers = projection.blockers.filter(blocker => shows(blocker.kind));\n const owned = projection.owned.filter(row => row.depth === 0 && shows(row.edge.kind));\n const tallest = Math.max(blockers.length, owned.length, 1);\n const left = blockers.map((blocker, index) =>\n blockerNode(blocker, index, blockers.length, tallest, projection.label),\n );\n const right = owned.map((row, index) => ownedNode(row, index, owned.length, tallest, projection.label));\n const summary = ownershipSummary(projection, strings);\n const selected: LaidOutNode = {\n ...(summary === undefined ? {} : { detail: summary }),\n display: projection.display,\n height: selectedCardHeight,\n id: projection.id,\n key: `selected:${projection.id}`,\n label: selectedLabel(projection.label),\n selected: true,\n tags: selectedTags(projection, strings),\n title: projection.label,\n x: column(1),\n y: topPadding + ((tallest - 1) * rowStep + cardHeight - selectedCardHeight) / 2,\n };\n const edges: LaidOutEdge[] = [];\n\n for (const [index, blocker] of blockers.entries()) {\n const node = left[index];\n\n if (node !== undefined) {\n edges.push({ id: node.key, kind: blocker.kind, path: curve(centerRight(node), centerLeft(selected)) });\n }\n }\n\n for (const [index, row] of owned.entries()) {\n const node = right[index];\n\n if (node !== undefined) {\n edges.push({ id: node.key, kind: row.edge.kind, path: curve(centerRight(selected), centerLeft(node)) });\n }\n }\n\n const shownRelations = blockers.length + owned.length;\n const allRelations = projection.blockers.length + projection.owned.filter(row => row.depth === 0).length;\n\n return {\n edges,\n height: topPadding + tallest * rowStep + bottomPadding,\n hidden: allRelations - shownRelations,\n nodes: [...left, selected, ...right],\n width: column(2) + cardWidth + leftPadding,\n };\n}\n\n/**\n * The `Extension points` picture: the selection on the left, every contribution that reaches the same targets in the\n * middle, and those targets on the right — inverted into contributors when a target is what was selected.\n *\n * Sibling contributions are drawn without an edge back to the selection, because they have none: they compete for\n * the same target, which is the whole reason they are on the canvas.\n */\nfunction layoutExtensionPoints(projection: ExtensionPointsProjection): GraphLayout {\n const { inverted, rows } = projection;\n const endpoints = [...new Map(rows.map(row => [row.endpoint, row])).values()];\n const tallest = Math.max(rows.length, endpoints.length, 1);\n const middle = rows.map((row, index) =>\n contributionNode(row, index, rows.length, tallest, inverted, projection.label),\n );\n const right = endpoints.map((row, index) =>\n endpointNode(row, index, endpoints.length, tallest, inverted, projection.label),\n );\n const endpointNodes = new Map<DiagnosticNodeId, LaidOutNode>();\n\n for (const node of right) endpointNodes.set(node.id, node);\n\n const selected: LaidOutNode = {\n display: projection.display,\n height: selectedCardHeight,\n id: projection.id,\n key: `selected:${projection.id}`,\n label: selectedLabel(projection.label),\n selected: true,\n tags: [projection.kind],\n title: projection.label,\n x: column(0),\n y: topPadding + ((tallest - 1) * rowStep + cardHeight - selectedCardHeight) / 2,\n };\n const edges: LaidOutEdge[] = [];\n\n for (const [index, row] of rows.entries()) {\n const node = middle[index];\n const endpoint = endpointNodes.get(row.endpoint);\n\n if (node === undefined || endpoint === undefined) continue;\n\n if (row.own)\n edges.push({ id: `own:${node.key}`, kind: 'owns', path: curve(centerRight(selected), centerLeft(node)) });\n\n edges.push({ id: node.key, kind: 'contributes-to', path: curve(centerRight(node), centerLeft(endpoint)) });\n }\n\n return {\n edges,\n height: topPadding + tallest * rowStep + bottomPadding,\n hidden: 0,\n nodes: [selected, ...middle, ...right],\n width: column(2) + cardWidth + leftPadding,\n };\n}\n\nexport { cardWidth, layoutExtensionPoints, layoutNeighbourhood };\nexport type { GraphLayout, LaidOutEdge, LaidOutNode };\n","/**\n * The camera over the graph canvas: a pan offset and a zoom, kept as plain numbers so the whole of it is testable\n * without a DOM.\n *\n * The canvas clips (`overflow: hidden`), so nothing the lens draws can leave the lens. That makes the camera the only\n * way to reach a node outside the current view, which is why pan, wheel zoom and fit-to-view are one unit rather than\n * three loose handlers: they all have to agree on what \"the graph is at x, y, scaled by z\" means.\n */\n\ntype Viewport = Readonly<{ height: number; width: number }>;\n\ntype CanvasTransform = Readonly<{ x: number; y: number; zoom: number }>;\n\ntype ViewportPoint = Readonly<{ x: number; y: number }>;\n\nconst minZoom = 0.25;\nconst maxZoom = 2.5;\n\n/** One press of −/+ is a deliberate, noticeable step. A wheel notch is not: it is whatever the device reported. */\nconst zoomStep = 1.2;\n\n/**\n * How much one pixel of wheel travel zooms. Small enough that a trackpad flick glides instead of jumping, and\n * exponential so the same gesture feels identical at any scale — zooming is multiplicative, not additive.\n */\nconst wheelSensitivity = 0.0015;\n\n/** A wheel event may report pixels, lines or pages; only pixels can be used directly. */\nconst wheelPixels = (delta: number, mode: number): number => {\n if (mode === 1) return delta * 16;\n\n if (mode === 2) return delta * 400;\n\n return delta;\n};\n\n/**\n * The factor one wheel event should apply. Clamped per event so a single coarse notch — a mouse that reports whole\n * pages — cannot cross the whole zoom range at once.\n */\nfunction wheelFactor(delta: number, mode = 0): number {\n const pixels = Math.max(-200, Math.min(200, wheelPixels(delta, mode)));\n\n return Math.exp(-pixels * wheelSensitivity);\n}\n\n/** Space left around the graph when it is fitted, so a card never touches the edge of the lens. */\nconst fitPadding = 24;\n\nconst identityTransform: CanvasTransform = { x: 0, y: 0, zoom: 1 };\n\nfunction clampZoom(zoom: number): number {\n if (!Number.isFinite(zoom)) return 1;\n\n return Math.min(maxZoom, Math.max(minZoom, zoom));\n}\n\nfunction isMeasured(viewport: Viewport): boolean {\n return viewport.width > 0 && viewport.height > 0;\n}\n\n/**\n * Scales the graph to fit the lens and centres it. An unmeasured viewport — a panel that has not laid out yet, or a\n * headless test — returns the identity rather than dividing by zero, so opening a node never leaves a blank canvas.\n */\nfunction fitTransform(layout: Viewport, viewport: Viewport): CanvasTransform {\n if (!isMeasured(viewport) || !isMeasured(layout)) return identityTransform;\n\n const usableWidth = Math.max(1, viewport.width - fitPadding * 2);\n const usableHeight = Math.max(1, viewport.height - fitPadding * 2);\n const zoom = clampZoom(Math.min(1, usableWidth / layout.width, usableHeight / layout.height));\n\n return {\n x: (viewport.width - layout.width * zoom) / 2,\n y: (viewport.height - layout.height * zoom) / 2,\n zoom,\n };\n}\n\nfunction panBy(transform: CanvasTransform, dx: number, dy: number): CanvasTransform {\n return { x: transform.x + dx, y: transform.y + dy, zoom: transform.zoom };\n}\n\n/**\n * Zooms around a point given in viewport coordinates, so whatever sits under the cursor stays under it. Without this\n * the graph slides away as it grows and the developer chases the node they were reading.\n */\nfunction zoomAround(transform: CanvasTransform, point: ViewportPoint, factor: number): CanvasTransform {\n const zoom = clampZoom(transform.zoom * factor);\n const applied = zoom / transform.zoom;\n\n return {\n x: point.x - (point.x - transform.x) * applied,\n y: point.y - (point.y - transform.y) * applied,\n zoom,\n };\n}\n\n/** The centre of the lens, used when zoom comes from a button rather than from a cursor. */\nfunction viewportCentre(viewport: Viewport): ViewportPoint {\n return { x: viewport.width / 2, y: viewport.height / 2 };\n}\n\nfunction transformStyle(transform: CanvasTransform): string {\n return `translate(${transform.x}px, ${transform.y}px) scale(${transform.zoom})`;\n}\n\nexport {\n clampZoom,\n fitTransform,\n identityTransform,\n maxZoom,\n minZoom,\n panBy,\n transformStyle,\n viewportCentre,\n wheelFactor,\n zoomAround,\n zoomStep,\n};\nexport type { CanvasTransform, Viewport, ViewportPoint };\n","/**\n * The graph canvas of `docs/devtools.md` §4, and the list that replaces it on narrow widths (§4.4).\n *\n * The SVG shares one pixel box with the layer holding the cards and uses `preserveAspectRatio=\"xMinYMin meet\"`, so\n * edges stay attached to cards at any zoom — that is the §8 acceptance criterion for this view. The camera moves the\n * layer, never the coordinates, so the layout stays cacheable and edges never drift.\n *\n * The canvas clips its content: a lens may not draw outside itself. Reaching a node that the fit did not cover is\n * therefore pan and zoom, which is what the surrounding column owns.\n */\n\nimport type { ReactElement, PointerEvent as ReactPointerEvent, RefObject } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { DiagnosticEdgeKind, DiagnosticNodeId } from '../protocol';\n\nimport { StateGlyph, StateTag } from './glyph';\nimport type { GraphLayout, LaidOutNode } from './graph-layout';\nimport { cardWidth } from './graph-layout';\nimport type { CanvasTransform, ViewportPoint } from './graph-viewport';\nimport { transformStyle, wheelFactor } from './graph-viewport';\nimport { useStrings } from './locale-context';\n\nconst weakOrHardEdges: ReadonlySet<DiagnosticEdgeKind> = new Set<DiagnosticEdgeKind>([\n 'absent-import',\n 'absent-port',\n 'hard-import',\n 'optional-import',\n 'optional-port',\n 'requires-port',\n]);\n\n/** `docs/devtools.md` §4.6: a dependency is a muted line, ownership is accent, a contribution is dashed. */\nfunction edgeClass(kind: DiagnosticEdgeKind): string {\n if (weakOrHardEdges.has(kind)) return 'odt-edge odt-edge-wait';\n\n if (kind === 'contributes-to') return 'odt-edge odt-edge-contribute';\n\n return 'odt-edge odt-edge-own';\n}\n\ntype NodeCardProps = Readonly<{\n node: LaidOutNode;\n onSelect: (id: DiagnosticNodeId) => void;\n}>;\n\nfunction NodeCard({ node, onSelect }: NodeCardProps): ReactElement {\n const select = useCallback(() => onSelect(node.id), [node.id, onSelect]);\n // A card is not empty space, so pressing one must not also start a pan.\n const hold = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => event.stopPropagation(), []);\n const contribution = node.sub?.[0] === 'contributes-to';\n const style = useMemo(() => ({ left: node.x, top: node.y, width: cardWidth }), [node.x, node.y]);\n\n return (\n <button\n aria-current={node.selected}\n className={contribution ? 'odt-node odt-node-contribution' : 'odt-node'}\n style={style}\n type=\"button\"\n onClick={select}\n onPointerDown={hold}\n >\n <span className=\"odt-node-head\">\n <StateGlyph state={node.display} />\n {/* The full name lives in `title`: the drawn one may have been shortened to fit the card (§4.3). */}\n <span className={node.selected ? 'odt-node-title odt-truncate' : 'odt-truncate'} title={node.title}>\n {node.label}\n </span>\n </span>\n {node.tags === undefined ? undefined : (\n <span className=\"odt-node-tags\">\n {node.tags.map(tag => (\n <span key={tag} className=\"odt-tag odt-tag-mute odt-mono\">\n {tag}\n </span>\n ))}\n <StateTag state={node.display} />\n </span>\n )}\n {node.sub === undefined ? undefined : (\n <span className=\"odt-node-sub\">\n {node.sub[0]} · {node.sub[1]}\n </span>\n )}\n {node.detail === undefined ? undefined : <span className=\"odt-node-detail\">{node.detail}</span>}\n </button>\n );\n}\n\ntype GraphViewProps = Readonly<{\n canvasRef: RefObject<HTMLDivElement | null>;\n layout: GraphLayout;\n onPan: (dx: number, dy: number) => void;\n onSelect: (id: DiagnosticNodeId) => void;\n onZoomAt: (point: ViewportPoint, factor: number) => void;\n transform: CanvasTransform;\n}>;\n\n/** Drag on empty canvas moves the camera; a drag that started on a card is a click on that card, never a pan. */\nfunction usePan(onPan: (dx: number, dy: number) => void): {\n readonly onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void;\n readonly onPointerMove: (event: ReactPointerEvent<HTMLDivElement>) => void;\n readonly onPointerUp: (event: ReactPointerEvent<HTMLDivElement>) => void;\n readonly panning: boolean;\n} {\n const origin = useRef<ViewportPoint | undefined>(undefined);\n const [panning, setPanning] = useState(false);\n\n return {\n onPointerDown: useCallback((event: ReactPointerEvent<HTMLDivElement>) => {\n // Without this the drag selects the labels it passes over, and the canvas ends a pan full of blue text.\n event.preventDefault();\n origin.current = { x: event.clientX, y: event.clientY };\n setPanning(true);\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }, []),\n onPointerMove: useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n const from = origin.current;\n\n if (from === undefined) return;\n\n origin.current = { x: event.clientX, y: event.clientY };\n onPan(event.clientX - from.x, event.clientY - from.y);\n },\n [onPan],\n ),\n onPointerUp: useCallback((event: ReactPointerEvent<HTMLDivElement>) => {\n origin.current = undefined;\n setPanning(false);\n event.currentTarget.releasePointerCapture?.(event.pointerId);\n }, []),\n panning,\n };\n}\n\n/**\n * Wheel zoom is attached by hand rather than through `onWheel`: React registers wheel listeners passively at the\n * root, so a passive handler could not stop the page from scrolling behind the panel.\n */\nfunction useWheelZoom(\n canvasRef: RefObject<HTMLDivElement | null>,\n onZoomAt: (point: ViewportPoint, factor: number) => void,\n): void {\n useEffect(() => {\n const element = canvasRef.current;\n\n if (element === null) return undefined;\n\n const onWheel = (event: WheelEvent): void => {\n event.preventDefault();\n\n const box = element.getBoundingClientRect();\n const point = { x: event.clientX - box.left, y: event.clientY - box.top };\n\n onZoomAt(point, wheelFactor(event.deltaY, event.deltaMode));\n };\n\n element.addEventListener('wheel', onWheel, { passive: false });\n\n return () => element.removeEventListener('wheel', onWheel);\n }, [canvasRef, onZoomAt]);\n}\n\nfunction GraphView({ canvasRef, layout, onPan, onSelect, onZoomAt, transform }: GraphViewProps): ReactElement {\n const strings = useStrings();\n const { panning, ...handlers } = usePan(onPan);\n const layerStyle = useMemo(\n () => ({ height: layout.height, transform: transformStyle(transform), width: layout.width }),\n [layout.height, layout.width, transform],\n );\n\n useWheelZoom(canvasRef, onZoomAt);\n\n return (\n <div\n aria-label={strings.neighbourhood}\n className={panning ? 'odt-canvas odt-canvas-panning' : 'odt-canvas'}\n ref={canvasRef}\n role=\"application\"\n {...handlers}\n onPointerCancel={handlers.onPointerUp}\n onPointerLeave={handlers.onPointerUp}\n >\n {layout.hidden === 0 ? undefined : <p className=\"odt-canvas-hint\">{strings.canvasHidden(layout.hidden)}</p>}\n <div className=\"odt-canvas-layer\" style={layerStyle}>\n <svg className=\"odt-edges\" preserveAspectRatio=\"xMinYMin meet\" viewBox={`0 0 ${layout.width} ${layout.height}`}>\n {layout.edges.map(edge => (\n <path key={edge.id} className={edgeClass(edge.kind)} d={edge.path} />\n ))}\n </svg>\n {layout.nodes.map(node => (\n <NodeCard key={node.key} node={node} onSelect={onSelect} />\n ))}\n </div>\n </div>\n );\n}\n\nfunction ListRow({ node, onSelect }: NodeCardProps): ReactElement {\n const select = useCallback(() => onSelect(node.id), [node.id, onSelect]);\n\n return (\n <button\n aria-selected={node.selected}\n className=\"odt-list-row\"\n role=\"option\"\n tabIndex={node.selected ? 0 : -1}\n type=\"button\"\n onClick={select}\n >\n <StateGlyph state={node.display} />\n <span className=\"odt-row-label\" title={node.title}>\n {node.label}\n </span>\n <span className=\"odt-list-meta\">{node.sub === undefined ? node.display : `${node.sub[0]} · ${node.sub[1]}`}</span>\n </button>\n );\n}\n\ntype NeighbourListProps = Readonly<{\n layout: GraphLayout;\n onSelect: (id: DiagnosticNodeId) => void;\n}>;\n\n/** The same neighbourhood as a list: the graph's fallback on narrow widths, and a keyboard-first way to walk it. */\nfunction NeighbourList({ layout, onSelect }: NeighbourListProps): ReactElement {\n const strings = useStrings();\n\n return (\n <div aria-label={strings.neighbourhood} className=\"odt-list\" role=\"listbox\">\n {layout.nodes.map(node => (\n <ListRow key={node.key} node={node} onSelect={onSelect} />\n ))}\n </div>\n );\n}\n\nexport { GraphView, NeighbourList };\n","/**\n * The middle column: breadcrumbs over the canvas, with zoom pinned to its corner.\n *\n * There is no `Graph`/`List` switch (§4.4). The list is what a viewport narrower than 1100 px gets instead of a\n * canvas it cannot draw legibly, not a second way to read a wide one: a manual switch would have been a second\n * layout, a second set of tests and a second set of dictionary strings for a view nobody asked for.\n */\n\nimport type { ReactElement, ReactNode, RefObject } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { ExtensionPointsProjection } from '../extension-points';\nimport type { InspectorBreadcrumb, InspectorProjection } from '../inspector';\nimport type { DiagnosticEdgeKind, DiagnosticNodeId } from '../protocol';\n\nimport type { GraphLayout } from './graph-layout';\nimport { layoutExtensionPoints, layoutNeighbourhood } from './graph-layout';\nimport { GraphView, NeighbourList } from './graph-view';\nimport type { CanvasTransform, Viewport, ViewportPoint } from './graph-viewport';\nimport { fitTransform, identityTransform, panBy, viewportCentre, zoomAround, zoomStep } from './graph-viewport';\nimport type { Strings } from './locale';\nimport { useStrings } from './locale-context';\n\n/** Below this viewport width the three-column canvas stops being readable and the list is the better default. */\nconst narrowViewport = 1100;\n\ntype MainColumnProps = Readonly<{\n /** The control slot of §5, when a host passed a write port. Empty markup otherwise, and absent from the bundle. */\n control: ReactNode;\n edgeKinds: ReadonlySet<DiagnosticEdgeKind>;\n /** Present only under the `Extension points` preset, and then it is what the canvas draws instead (§4.2). */\n extensionPoints: ExtensionPointsProjection | undefined;\n onSelect: (id: DiagnosticNodeId) => void;\n projection: InspectorProjection | undefined;\n}>;\n\nfunction isNarrow(): boolean {\n return typeof globalThis.innerWidth === 'number' && globalThis.innerWidth < narrowViewport;\n}\n\nfunction useNarrowViewport(): boolean {\n const [narrow, setNarrow] = useState(isNarrow);\n\n useEffect(() => {\n const update = (): void => setNarrow(isNarrow());\n\n update();\n globalThis.addEventListener('resize', update);\n\n return () => globalThis.removeEventListener('resize', update);\n }, []);\n\n return narrow;\n}\n\ntype NeighbourhoodProps = Readonly<{\n asList: boolean;\n canvasRef: RefObject<HTMLDivElement | null>;\n layout: GraphLayout;\n onFit: () => void;\n onPan: (dx: number, dy: number) => void;\n onSelect: (id: DiagnosticNodeId) => void;\n onZoomAt: (point: ViewportPoint, factor: number) => void;\n onZoomIn: () => void;\n onZoomOut: () => void;\n transform: CanvasTransform;\n}>;\n\nfunction Neighbourhood({\n asList,\n canvasRef,\n layout,\n onFit,\n onPan,\n onSelect,\n onZoomAt,\n onZoomIn,\n onZoomOut,\n transform,\n}: NeighbourhoodProps): ReactElement {\n const strings = useStrings();\n\n if (asList) return <NeighbourList layout={layout} onSelect={onSelect} />;\n\n return (\n <>\n <GraphView\n canvasRef={canvasRef}\n layout={layout}\n transform={transform}\n onPan={onPan}\n onSelect={onSelect}\n onZoomAt={onZoomAt}\n />\n <div className=\"odt-canvas-zoom\">\n <button\n aria-label={strings.zoomOut}\n className=\"odt-btn odt-btn-small odt-btn-icon\"\n type=\"button\"\n onClick={onZoomOut}\n >\n −\n </button>\n <button\n aria-label={strings.zoomIn}\n className=\"odt-btn odt-btn-small odt-btn-icon\"\n type=\"button\"\n onClick={onZoomIn}\n >\n +\n </button>\n <button className=\"odt-btn odt-btn-small\" type=\"button\" onClick={onFit}>\n {strings.fit}\n </button>\n </div>\n </>\n );\n}\n\ntype CrumbProps = Readonly<{\n crumb: InspectorBreadcrumb;\n current: boolean;\n onSelect: (id: DiagnosticNodeId) => void;\n}>;\n\n/** An ancestor crumb navigates back to that node; the current one is a label, and a crumb without an id is neither. */\nfunction Crumb({ crumb, current, onSelect }: CrumbProps): ReactElement {\n const { id } = crumb;\n const select = useCallback(() => {\n if (id !== undefined) onSelect(id);\n }, [id, onSelect]);\n\n if (current || id === undefined) {\n return (\n <span className={current ? 'odt-crumb-current odt-truncate' : undefined} title={crumb.label}>\n {crumb.label}\n </span>\n );\n }\n\n return (\n <button className=\"odt-crumb-link odt-truncate\" title={crumb.label} type=\"button\" onClick={select}>\n {crumb.label}\n </button>\n );\n}\n\ntype BreadcrumbsProps = Readonly<{\n onSelect: (id: DiagnosticNodeId) => void;\n projection: InspectorProjection | undefined;\n}>;\n\nfunction Breadcrumbs({ onSelect, projection }: BreadcrumbsProps): ReactElement {\n const strings = useStrings();\n const crumbs = projection?.breadcrumbs ?? [];\n\n return (\n <nav aria-label={strings.selectionPath} className=\"odt-crumbs\">\n {crumbs.map((crumb, index) => (\n <span key={`${crumb.id ?? ''}:${crumb.label}`} className=\"odt-crumb\">\n {index === 0 ? '' : '› '}\n <Crumb crumb={crumb} current={index === crumbs.length - 1} onSelect={onSelect} />\n </span>\n ))}\n </nav>\n );\n}\n\n/** The lens box as the camera sees it. Zero until the panel has laid out, which `fitTransform` treats as unmeasured. */\nfunction viewportOf(element: HTMLDivElement | null): Viewport {\n return { height: element?.clientHeight ?? 0, width: element?.clientWidth ?? 0 };\n}\n\n/** One canvas, two pictures: the one-hop neighbourhood, or the two-step walk through the extension points. */\nfunction layoutFor(\n projection: InspectorProjection | undefined,\n extensionPoints: ExtensionPointsProjection | undefined,\n edgeKinds: ReadonlySet<DiagnosticEdgeKind>,\n strings: Strings,\n): GraphLayout | undefined {\n if (extensionPoints !== undefined) return layoutExtensionPoints(extensionPoints);\n\n return projection === undefined ? undefined : layoutNeighbourhood(projection, edgeKinds, strings);\n}\n\nfunction MainColumn({ control, edgeKinds, extensionPoints, onSelect, projection }: MainColumnProps): ReactElement {\n const strings = useStrings();\n const asList = useNarrowViewport();\n const [transform, setTransform] = useState<CanvasTransform>(identityTransform);\n const canvasRef = useRef<HTMLDivElement>(null);\n const layout = useMemo(\n () => layoutFor(projection, extensionPoints, edgeKinds, strings),\n [projection, extensionPoints, edgeKinds, strings],\n );\n\n const pan = useCallback((dx: number, dy: number) => setTransform(current => panBy(current, dx, dy)), []);\n const zoomAt = useCallback(\n (point: ViewportPoint, factor: number) => setTransform(current => zoomAround(current, point, factor)),\n [],\n );\n const zoomBy = useCallback(\n (factor: number) =>\n setTransform(current => zoomAround(current, viewportCentre(viewportOf(canvasRef.current)), factor)),\n [],\n );\n const zoomOut = useCallback(() => zoomBy(1 / zoomStep), [zoomBy]);\n const zoomIn = useCallback(() => zoomBy(zoomStep), [zoomBy]);\n const fit = useCallback(() => {\n if (layout !== undefined) setTransform(fitTransform(layout, viewportOf(canvasRef.current)));\n }, [layout]);\n\n // Opening a node re-frames the graph around it: the camera the previous selection left behind is rarely useful.\n useEffect(() => {\n fit();\n }, [fit, projection?.id]);\n\n return (\n <div className=\"odt-main\">\n <div className=\"odt-main-bar\">\n <Breadcrumbs projection={projection} onSelect={onSelect} />\n {control}\n </div>\n {layout === undefined ? (\n <div className=\"odt-empty\">{strings.emptySelection}</div>\n ) : (\n <Neighbourhood\n asList={asList}\n canvasRef={canvasRef}\n layout={layout}\n transform={transform}\n onFit={fit}\n onPan={pan}\n onSelect={onSelect}\n onZoomAt={zoomAt}\n onZoomIn={zoomIn}\n onZoomOut={zoomOut}\n />\n )}\n </div>\n );\n}\n\nexport { MainColumn };\n","/** Header of `docs/devtools.md` §4.1: identity badges, the two tabs, search and window actions. */\n\nimport type { ChangeEvent, ReactElement, RefObject } from 'react';\nimport { useCallback } from 'react';\n\nimport type { DevtoolsStoreStatus } from '../graph-store';\n\nimport type { DevtoolsTab } from './edge-filter';\nimport { CloseIcon, SearchIcon } from './icons';\nimport type { DevtoolsLocale } from './locale';\nimport { locales } from './locale';\nimport { useStrings } from './locale-context';\n\ntype PanelHeaderProps = Readonly<{\n legendOpen: boolean;\n locale: DevtoolsLocale;\n onClose: (() => void) | undefined;\n onLegend: () => void;\n onLocale: (locale: DevtoolsLocale) => void;\n onQuery: (query: string) => void;\n onTab: (tab: DevtoolsTab) => void;\n query: string;\n searchRef: RefObject<HTMLInputElement | null>;\n status: DevtoolsStoreStatus;\n tab: DevtoolsTab;\n}>;\n\ntype PanelTabProps = Readonly<{\n label: string;\n onSelect: (tab: DevtoolsTab) => void;\n selected: boolean;\n tab: DevtoolsTab;\n}>;\n\nfunction PanelTab({ label, onSelect, selected, tab }: PanelTabProps): ReactElement {\n const select = useCallback(() => onSelect(tab), [onSelect, tab]);\n\n return (\n <button aria-selected={selected} className=\"odt-tab\" role=\"tab\" type=\"button\" onClick={select}>\n {label}\n </button>\n );\n}\n\ntype LocalePickerProps = Readonly<{\n locale: DevtoolsLocale;\n onLocale: (locale: DevtoolsLocale) => void;\n}>;\n\n/** A picker rather than a toggle: a third language must not need a new control. */\nfunction LocalePicker({ locale, onLocale }: LocalePickerProps): ReactElement {\n const strings = useStrings();\n const change = useCallback(\n (event: ChangeEvent<HTMLSelectElement>) => onLocale(event.target.value as DevtoolsLocale),\n [onLocale],\n );\n\n return (\n <select aria-label={strings.language} className=\"odt-locale\" value={locale} onChange={change}>\n {locales.map(option => (\n <option key={option} value={option}>\n {option.toUpperCase()}\n </option>\n ))}\n </select>\n );\n}\n\nfunction PanelHeader({\n legendOpen,\n locale,\n onClose,\n onLegend,\n onLocale,\n onQuery,\n onTab,\n query,\n searchRef,\n status,\n tab,\n}: PanelHeaderProps): ReactElement {\n const strings = useStrings();\n const onChange = useCallback((event: ChangeEvent<HTMLInputElement>) => onQuery(event.target.value), [onQuery]);\n\n return (\n <div className=\"odt-header\">\n <div className=\"odt-header-group\">\n <span>{strings.panelTitle}</span>\n <span className=\"odt-tag odt-tag-mute odt-mono\">\n {strings.planBadge(status.sessionId, status.planFingerprint)}\n </span>\n </div>\n <div className=\"odt-tabs\" role=\"tablist\">\n <PanelTab label={strings.tabGraph} selected={tab === 'graph'} tab=\"graph\" onSelect={onTab} />\n <PanelTab label={strings.tabTimeline} selected={tab === 'timeline'} tab=\"timeline\" onSelect={onTab} />\n </div>\n <div className=\"odt-header-group\">\n <label className=\"odt-search\">\n <SearchIcon />\n <input\n aria-label={strings.searchLabel}\n placeholder={strings.searchLabel}\n ref={searchRef}\n value={query}\n onChange={onChange}\n />\n </label>\n <LocalePicker locale={locale} onLocale={onLocale} />\n <button aria-expanded={legendOpen} className=\"odt-btn odt-btn-small\" type=\"button\" onClick={onLegend}>\n {strings.legend}\n </button>\n {onClose === undefined ? undefined : (\n <button\n aria-label={strings.close}\n className=\"odt-btn odt-btn-icon odt-btn-quiet\"\n type=\"button\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport { PanelHeader };\n","/**\n * Status bar of `docs/devtools.md` §4.5: the panel's own health, not the application's. It answers \"can I trust what\n * I am looking at\" — the cursor it has reached, the frames it never saw, and that it is live.\n *\n * The rest describes the panel rather than the application, so it lives behind `⋯`: its own cost against the §6\n * budgets, where the theme came from, the schema revision, and whether this build can control anything at all. A\n * developer who wants those numbers asks for them; a developer watching the graph should not have to read past them.\n */\n\nimport type { ReactElement } from 'react';\nimport { useCallback, useState } from 'react';\n\nimport type { DevtoolsStoreStatus } from '../graph-store';\n\nimport { formatMilliseconds } from './format';\nimport { StateGlyph } from './glyph';\nimport { useStrings } from './locale-context';\nimport type { DevtoolsMode } from './panel-mode';\n\ntype PanelStatusProps = Readonly<{\n mappedTokens: number;\n mode: DevtoolsMode;\n renderCost: number;\n status: DevtoolsStoreStatus;\n}>;\n\nfunction PanelStatus({ mappedTokens, mode, renderCost, status }: PanelStatusProps): ReactElement {\n const strings = useStrings();\n const [detailed, setDetailed] = useState(false);\n const toggle = useCallback(() => setDetailed(open => !open), []);\n\n return (\n <div className=\"odt-status\">\n <div className=\"odt-status-group\">\n <span className=\"odt-mono\">{strings.statusFrame(status.lastSequence, status.stateRevision)}</span>\n <span className=\"odt-mono\">{strings.statusDropped(status.droppedFrames)}</span>\n <span className=\"odt-tag odt-tag-ok\">\n <StateGlyph size={6} state=\"ready\" />\n {strings.live}\n </span>\n </div>\n <div className=\"odt-status-group\">\n {detailed ? (\n <>\n <span className=\"odt-mono\">\n {strings.reducerPaint(formatMilliseconds(status.reducerMs), formatMilliseconds(renderCost))}\n </span>\n <span>{mappedTokens === 0 ? strings.themeDefaults : strings.themeHost(mappedTokens)}</span>\n <span>{mode === 'inspect' ? strings.controlPlaneOff : strings.controlPlaneRequiresAuthority}</span>\n <span className=\"odt-mono\">{status.schemaRevision}</span>\n </>\n ) : undefined}\n <button\n aria-expanded={detailed}\n aria-label={strings.panelDetails}\n className=\"odt-status-more\"\n type=\"button\"\n onClick={toggle}\n >\n ⋯\n </button>\n </div>\n </div>\n );\n}\n\nexport { PanelStatus };\n","/**\n * Search replaces the tree while a query is active. §2 fixes what is searchable, and the second column explains a\n * surprising match rather than restating the obvious one.\n *\n * It used to print the matched field verbatim, which meant every ordinary hit read `label` — a protocol word the\n * developer never asked about, sitting where a useful fact belonged. A hit matched on the node's own name now shows\n * what kind of node it is; only a match found somewhere else says where.\n */\n\nimport type { ReactElement } from 'react';\nimport { useCallback } from 'react';\n\nimport type { DiagnosticNodeId } from '../protocol';\nimport type { SearchHit } from '../search';\n\nimport { StateGlyph } from './glyph';\nimport type { Strings } from './locale';\nimport { useStrings } from './locale-context';\n\n/** Where the query was found, in words, for the fields whose name alone would not explain the hit. */\nconst matchedIn: Readonly<Record<string, keyof Strings>> = {\n 'failure-code': 'matchedFailureCode',\n 'failure-subject': 'matchedFailureSubject',\n id: 'matchedId',\n kind: 'matchedKind',\n provenance: 'matchedProvenance',\n};\n\n/** A match on the node's own name is not worth explaining, so the row shows what kind of node it is instead. */\nfunction hitReason(hit: SearchHit, strings: Strings): string {\n const key = matchedIn[hit.field];\n\n return key === undefined ? hit.kind : (strings[key] as string);\n}\n\ntype SearchResultsProps = Readonly<{\n hits: readonly SearchHit[];\n onSelect: (id: DiagnosticNodeId) => void;\n selectedId: DiagnosticNodeId | undefined;\n}>;\n\ntype HitRowProps = Readonly<{\n hit: SearchHit;\n onSelect: (id: DiagnosticNodeId) => void;\n selected: boolean;\n}>;\n\nfunction HitRow({ hit, onSelect, selected }: HitRowProps): ReactElement {\n const strings = useStrings();\n const select = useCallback(() => onSelect(hit.id), [hit.id, onSelect]);\n\n return (\n <button aria-selected={selected} className=\"odt-row\" role=\"option\" type=\"button\" onClick={select}>\n <StateGlyph state={hit.display} />\n <span className=\"odt-row-label\">{hit.label}</span>\n <span className=\"odt-k\">{hitReason(hit, strings)}</span>\n </button>\n );\n}\n\nfunction SearchResults({ hits, onSelect, selectedId }: SearchResultsProps): ReactElement {\n const strings = useStrings();\n\n return (\n <div aria-label={strings.searchResults} className=\"odt-tree\" role=\"listbox\">\n {hits.length === 0 ? <span className=\"odt-empty\">{strings.noSearchHit}</span> : undefined}\n {hits.map(hit => (\n <HitRow key={hit.id} hit={hit} selected={hit.id === selectedId} onSelect={onSelect} />\n ))}\n </div>\n );\n}\n\nexport { SearchResults };\n","/**\n * What the panel opens on.\n *\n * A developer opens a runtime inspector because something is not ready, so the initial selection is the first feature\n * that is not, and every lifetime owner holding a troubled feature starts expanded. On a healthy application it falls\n * back to the first feature of the first owner.\n */\n\nimport type { TreeGroupRow } from '../graph-index';\nimport type { DevtoolsGraphStore } from '../graph-store';\nimport type { DiagnosticNodeId } from '../protocol';\nimport type { NodeDisplayState } from '../visual-axes';\n\ntype InitialSelection = Readonly<{\n expanded: ReadonlySet<DiagnosticNodeId>;\n selectedId: DiagnosticNodeId | undefined;\n}>;\n\ntype DisplayOf = (id: DiagnosticNodeId) => NodeDisplayState;\n\nfunction isTroubled(group: TreeGroupRow, displayOf: DisplayOf): boolean {\n return group.features.some(row => displayOf(row.id) !== 'ready');\n}\n\nfunction firstUnready(groups: readonly TreeGroupRow[], displayOf: DisplayOf): DiagnosticNodeId | undefined {\n for (const group of groups) {\n for (const row of group.features) {\n if (displayOf(row.id) !== 'ready') return row.id;\n }\n }\n\n return undefined;\n}\n\nfunction firstFeature(groups: readonly TreeGroupRow[]): DiagnosticNodeId | undefined {\n for (const group of groups) {\n const first = group.features[0];\n\n if (first !== undefined) return first.id;\n }\n\n return undefined;\n}\n\nfunction ownerOfFeature(\n groups: readonly TreeGroupRow[],\n feature: DiagnosticNodeId | undefined,\n): TreeGroupRow | undefined {\n return groups.find(group => group.features.some(row => row.id === feature));\n}\n\nfunction initialSelection(store: DevtoolsGraphStore): InitialSelection {\n const groups = store.graph.tree();\n const displayOf: DisplayOf = id => store.graph.displayOf(store.graph.currentNodeId(id));\n const selectedId = firstUnready(groups, displayOf) ?? firstFeature(groups);\n const expanded = new Set(groups.filter(group => isTroubled(group, displayOf)).map(group => group.id));\n const home = ownerOfFeature(groups, selectedId);\n\n if (home !== undefined) expanded.add(home.id);\n\n return { expanded, selectedId };\n}\n\nexport { initialSelection };\n","/**\n * The panel's stylesheet, injected once per document. Values follow the anatomy of `docs/devtools.md` §4 and the\n * type ramp it fixes; every colour is a variable so a host mapping in config is the only theming mechanism.\n *\n * Layout is flex and grid with `gap` throughout — margin-based spacing is not used — and the inspector scrolls with\n * its action footer pinned.\n */\n\nconst stylesheet = `\n.odt {\n --odt-canvas: #0e0f14;\n --odt-surface: #17191f;\n --odt-surface-2: #292c34;\n --odt-text: rgba(246, 247, 255, 1);\n --odt-text-muted: rgba(246, 247, 255, 0.5);\n --odt-line: rgba(246, 247, 255, 0.06);\n --odt-line-strong: rgba(246, 247, 255, 0.25);\n --odt-control: rgba(246, 247, 255, 0.08);\n --odt-accent: #4763f0;\n --odt-accent-text: #5364ff;\n --odt-accent-surface: rgba(71, 99, 240, 0.15);\n --odt-ok: rgba(0, 185, 122, 1);\n --odt-ok-surface: rgba(0, 159, 112, 0.15);\n --odt-warn: rgba(231, 200, 42, 1);\n --odt-warn-surface: rgba(255, 204, 74, 0.15);\n --odt-bad: rgba(254, 85, 100, 1);\n --odt-bad-surface: rgba(241, 79, 93, 0.15);\n --odt-radius: 8px;\n --odt-font: system-ui, -apple-system, sans-serif;\n\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n height: 100%;\n min-height: 0;\n background: var(--odt-surface);\n border-top: 1px solid var(--odt-line);\n color: var(--odt-text);\n font-family: var(--odt-font);\n font-size: 14px;\n font-weight: 500;\n line-height: 1.142;\n -webkit-font-smoothing: antialiased;\n}\n.odt *, .odt *::before, .odt *::after { box-sizing: border-box; }\n.odt button { appearance: none; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }\n.odt input { appearance: none; border: 0; background: none; color: inherit; font: inherit; }\n.odt :focus-visible { outline: 2px solid var(--odt-accent-text); outline-offset: 1px; }\n.odt-mono { font-variant-numeric: lining-nums tabular-nums; }\n.odt-sec { font-size: 10px; line-height: 1.6; text-transform: uppercase; color: var(--odt-text-muted); }\n.odt-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.odt-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n height: 48px;\n flex-shrink: 0;\n padding: 0 12px 0 16px;\n border-bottom: 1px solid var(--odt-line);\n}\n.odt-header-group { display: flex; align-items: center; gap: 12px; min-width: 0; }\n.odt-tabs { display: flex; align-items: stretch; gap: 4px; height: 48px; }\n.odt-tab {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 40px;\n padding: 0 12px;\n color: var(--odt-text-muted);\n white-space: nowrap;\n}\n.odt-tab[aria-selected='true'] { color: var(--odt-text); box-shadow: inset 0 -1px 0 var(--odt-text); }\n\n.odt-filters {\n display: flex;\n align-items: center;\n gap: 8px 16px;\n flex-wrap: wrap;\n flex-shrink: 0;\n padding: 6px 16px;\n border-bottom: 1px solid var(--odt-line);\n}\n.odt-presets { display: flex; align-items: center; gap: 2px; padding: 2px; border-radius: 1000px; background: var(--odt-control); }\n.odt-preset {\n padding: 3px 12px;\n border-radius: 50px;\n font-size: 12px;\n line-height: 1.333;\n color: var(--odt-text-muted);\n white-space: nowrap;\n}\n.odt-preset[aria-pressed='true'] { background: var(--odt-surface); color: var(--odt-text); }\n.odt-chips { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; min-width: 0; }\n.odt-chip {\n padding: 2px 8px;\n border: 1px solid var(--odt-line);\n border-radius: 1000px;\n font-size: 11px;\n line-height: 1.45;\n color: var(--odt-text-muted);\n white-space: nowrap;\n}\n.odt-chip[aria-checked='true'] {\n border-color: var(--odt-accent-text);\n background: var(--odt-accent-surface);\n color: var(--odt-accent-text);\n}\n\n.odt-tag {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n min-height: 16px;\n padding: 2px 4px;\n border-radius: 4px;\n font-size: 10px;\n line-height: 1.6;\n text-transform: uppercase;\n white-space: nowrap;\n}\n.odt-tag-ok { background: var(--odt-ok-surface); color: var(--odt-ok); }\n.odt-tag-warn { background: var(--odt-warn-surface); color: var(--odt-warn); }\n.odt-tag-bad { background: var(--odt-bad-surface); color: var(--odt-bad); }\n.odt-tag-mute { background: var(--odt-line); color: var(--odt-text-muted); }\n/* A tag that must give way rather than push its row label out: it clips itself and keeps the rest in the title. */\n.odt-tag-clip { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\n.odt-tag-accent { background: var(--odt-accent-surface); color: var(--odt-accent-text); }\n\n.odt-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 32px;\n padding: 0 12px;\n border-radius: var(--odt-radius);\n background: var(--odt-control);\n white-space: nowrap;\n}\n.odt-btn-small { height: 28px; font-size: 12px; }\n.odt-btn-icon { width: 32px; padding: 0; }\n.odt-btn-quiet { background: none; color: var(--odt-text-muted); }\n.odt-btn:disabled { background: rgba(246, 247, 255, 0.04); color: rgba(246, 247, 255, 0.25); cursor: default; }\n\n.odt-search {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 300px;\n max-width: 40vw;\n height: 32px;\n padding: 0 12px;\n border: 1px solid var(--odt-line);\n border-radius: var(--odt-radius);\n background: rgba(246, 247, 255, 0.04);\n color: var(--odt-text-muted);\n}\n.odt-search input { width: 100%; min-width: 0; color: var(--odt-text); }\n.odt-search input::placeholder { color: var(--odt-text-muted); }\n\n.odt-body { display: grid; grid-template-columns: 320px minmax(0, 1fr) 400px; flex-grow: 1; min-height: 0; }\n\n.odt-tree {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px;\n border-right: 1px solid var(--odt-line);\n overflow-y: auto;\n}\n.odt-row {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 32px;\n flex-shrink: 0;\n padding: 0 12px 0 44px;\n border-radius: var(--odt-radius);\n text-align: left;\n width: 100%;\n}\n.odt-row-group { padding: 0 12px 0 20px; font-size: 12px; line-height: 1.333; text-transform: uppercase; color: var(--odt-text-muted); }\n.odt-row-root { padding-left: 12px; }\n.odt-row[aria-selected='true'] { background: var(--odt-control); box-shadow: inset 2px 0 0 var(--odt-accent); }\n.odt-row-label { flex-grow: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.odt-glyph { display: inline-flex; width: 16px; height: 16px; align-items: center; justify-content: center; flex-shrink: 0; }\n.odt-glyph-ok { color: var(--odt-ok); }\n.odt-glyph-warn { color: var(--odt-warn); }\n.odt-glyph-bad { color: var(--odt-bad); }\n.odt-glyph-mute { color: var(--odt-text-muted); }\n\n.odt-main { position: relative; display: flex; flex-direction: column; border-right: 1px solid var(--odt-line); min-width: 0; }\n.odt-main-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n height: 40px;\n flex-shrink: 0;\n padding: 0 16px;\n border-bottom: 1px solid var(--odt-line);\n}\n.odt-crumbs { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 12px; line-height: 1.333; color: var(--odt-text-muted); }\n.odt-crumb { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }\n.odt-crumb-link { color: inherit; text-decoration: underline; text-decoration-color: var(--odt-line-strong); }\n.odt-crumb-link:hover, .odt-crumb-link:focus-visible { color: var(--odt-text); }\n.odt-crumb-current { color: var(--odt-text); }\n.odt-locale {\n padding: 2px 6px;\n border: 1px solid var(--odt-line);\n border-radius: var(--odt-radius);\n background: var(--odt-control);\n font: inherit;\n font-size: 12px;\n line-height: 1.333;\n color: var(--odt-text-muted);\n}\n\n.odt-canvas {\n position: relative;\n flex-grow: 1;\n min-height: 0;\n /* A lens draws inside itself: the camera is what reaches a node the fit did not cover. */\n overflow: hidden;\n touch-action: none;\n /* A drag moves the camera; it must not also select the labels it crosses. */\n user-select: none;\n cursor: grab;\n background-image: radial-gradient(var(--odt-line) 1px, transparent 1px);\n background-size: 16px 16px;\n}\n.odt-canvas-panning { cursor: grabbing; }\n.odt-canvas-layer { position: absolute; top: 0; left: 0; transform-origin: 0 0; }\n/* Edges sit under the cards, and the cards are opaque, so a line can never cross a badge. */\n.odt-edges { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }\n.odt-node {\n position: absolute;\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 188px;\n padding: 8px 12px;\n z-index: 1;\n border: 1px solid var(--odt-line);\n border-radius: var(--odt-radius);\n background: var(--odt-surface-2);\n font-size: 12px;\n line-height: 1.333;\n text-align: left;\n color: var(--odt-text);\n}\n.odt-node-contribution { border-style: dashed; }\n.odt-node[aria-current='true'] { gap: 6px; border-color: var(--odt-accent); background: var(--odt-accent-surface); }\n.odt-node-head { display: flex; align-items: center; gap: 6px; min-width: 0; }\n.odt-node-title { font-size: 14px; line-height: 1.142; }\n.odt-node-sub { font-size: 10px; line-height: 1.6; text-transform: uppercase; color: var(--odt-text-muted); }\n.odt-node-detail { font-size: 10px; line-height: 1.6; color: var(--odt-text-muted); }\n.odt-node-tags { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }\n.odt-node-tags > * { flex-shrink: 0; }\n.odt-canvas-hint {\n position: absolute;\n right: 16px;\n top: 12px;\n max-width: 60%;\n margin: 0;\n padding: 4px 8px;\n border-radius: var(--odt-radius);\n background: var(--odt-surface-2);\n font-size: 10px;\n line-height: 1.6;\n text-transform: uppercase;\n color: var(--odt-text-muted);\n}\n.odt-legend-panel {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n gap: 12px 24px;\n flex-shrink: 0;\n max-height: 40%;\n overflow: auto;\n padding: 12px 16px;\n border-bottom: 1px solid var(--odt-line);\n background: var(--odt-surface);\n}\n.odt-legend-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }\n.odt-legend-row { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 12px; line-height: 1.333; }\n.odt-legend-name { flex-shrink: 0; color: var(--odt-text); }\n.odt-legend-detail { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--odt-text-muted); }\n.odt-canvas-zoom { position: absolute; right: 16px; bottom: 12px; display: flex; gap: 4px; }\n.odt-edge { fill: none; stroke-width: 1.5; }\n.odt-edge-wait { stroke: var(--odt-line-strong); }\n.odt-edge-own { stroke: var(--odt-accent-text); }\n.odt-edge-contribute { stroke: var(--odt-line-strong); stroke-dasharray: 4 4; }\n.odt-edge-sample { display: inline-block; width: 16px; height: 0; border-top: 1.5px solid var(--odt-line-strong); }\n.odt-edge-sample-accent { border-color: var(--odt-accent-text); }\n.odt-edge-sample-dashed { border-top-style: dashed; }\n\n.odt-list { display: flex; flex-direction: column; gap: 2px; padding: 8px; overflow-y: auto; flex-grow: 1; min-height: 0; }\n.odt-list-row { display: flex; align-items: center; gap: 8px; height: 32px; flex-shrink: 0; padding: 0 12px; border-radius: var(--odt-radius); text-align: left; }\n.odt-list-row[aria-selected='true'] { background: var(--odt-control); }\n.odt-list-meta { font-size: 12px; line-height: 1.333; color: var(--odt-text-muted); white-space: nowrap; }\n\n.odt-inspector-host { display: flex; min-width: 0; min-height: 0; }\n.odt-inspector { display: flex; flex-direction: column; flex-grow: 1; min-width: 0; min-height: 0; }\n.odt-inspector-scroll { display: flex; flex-direction: column; gap: 10px; padding: 12px 16px; overflow-y: auto; flex-grow: 1; min-height: 0; }\n.odt-inspector-head { display: flex; flex-direction: column; gap: 6px; }\n.odt-inspector-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 16px; line-height: 1.25; }\n.odt-axes { display: flex; flex-wrap: wrap; gap: 4px; }\n.odt-kv { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 4px 12px; font-size: 12px; line-height: 1.333; }\n.odt-k { color: var(--odt-text-muted); }\n.odt-v { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.odt-why { display: flex; flex-direction: column; gap: 6px; padding: 8px 12px; border-radius: var(--odt-radius); background: rgba(246, 247, 255, 0.05); }\n.odt-why-text { font-size: 12px; line-height: 1.333; }\n.odt-why-ref { color: var(--odt-accent-text); }\n.odt-section { display: flex; flex-direction: column; gap: 6px; }\n.odt-section-rows { display: flex; flex-direction: column; gap: 4px; font-size: 12px; line-height: 1.333; }\n.odt-section-row { display: flex; align-items: center; gap: 8px; text-align: left; width: 100%; }\n.odt-section-row-nested { padding-left: 16px; }\n.odt-section-row-label { flex-grow: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.odt-chain { display: flex; gap: 10px; align-items: flex-start; font-size: 12px; line-height: 1.333; }\n.odt-chain-time { width: 78px; flex-shrink: 0; color: var(--odt-text-muted); font-variant-numeric: tabular-nums; }\n.odt-footer { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--odt-line); flex-shrink: 0; }\n.odt-footer-end { margin-left: auto; }\n.odt-footer-status { min-width: 0; font-size: 10px; line-height: 1.6; text-align: right; color: var(--odt-text-muted); }\n.odt-empty { padding: 12px 16px; font-size: 12px; line-height: 1.333; color: var(--odt-text-muted); }\n\n.odt-timeline { display: flex; flex-direction: column; gap: 2px; padding: 8px 16px; overflow-y: auto; flex-grow: 1; min-height: 0; }\n.odt-timeline-row { display: flex; align-items: center; gap: 12px; height: 28px; flex-shrink: 0; font-size: 12px; line-height: 1.333; text-align: left; }\n.odt-timeline-gap { color: var(--odt-warn); }\n.odt-timeline-seq { width: 96px; flex-shrink: 0; color: var(--odt-text-muted); font-variant-numeric: tabular-nums; }\n.odt-timeline-time { width: 96px; flex-shrink: 0; color: var(--odt-text-muted); font-variant-numeric: tabular-nums; }\n\n.odt-status {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n flex-wrap: wrap;\n min-height: 28px;\n flex-shrink: 0;\n padding: 4px 16px;\n border-top: 1px solid var(--odt-line);\n font-size: 10px;\n line-height: 1.6;\n text-transform: uppercase;\n color: var(--odt-text-muted);\n}\n.odt-status-group { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 16px; min-width: 0; }\n.odt-status-more { padding: 0 4px; font-size: 12px; line-height: 1; color: var(--odt-text-muted); }\n.odt-status-more[aria-expanded='true'] { color: var(--odt-text); }\n\n/**\n * Below 1100 px the three columns stop being readable, so the neighbourhood — drawn as a list at this width — and\n * the inspector share the second column instead of one of them disappearing. Losing the neighbourhood would leave\n * the panel unable to answer what a node is waiting for, which is the question it exists for.\n */\n@media (max-width: 1100px) {\n .odt-body { grid-template-columns: 320px minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); }\n .odt-tree { grid-row: 1 / span 2; }\n .odt-main { border-right: 0; border-bottom: 1px solid var(--odt-line); }\n}\n@media (max-width: 720px) {\n .odt-body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; }\n .odt-tree { grid-row: auto; border-right: 0; }\n .odt-step-hidden { display: none; }\n .odt-search { width: auto; max-width: none; flex-grow: 1; }\n}\n@media (prefers-reduced-motion: no-preference) {\n .odt-canvas-layer { transition: transform 120ms ease-out; }\n}\n`;\n\nconst marker = 'data-opetope-devtools';\n\n/** Injects one stylesheet once per document. Safe to call on every mount and outside a browser. */\nfunction injectStylesheet(name: string, css: string, target: Document | undefined = globalThis.document): void {\n if (target?.querySelector(`style[${name}]`) !== null) return;\n\n const element = target.createElement('style');\n\n element.setAttribute(name, '');\n element.textContent = css;\n target.head.append(element);\n}\n\nfunction ensureStylesheet(target?: Document): void {\n injectStylesheet(marker, stylesheet, target);\n}\n\nexport { stylesheet as devtoolsStylesheet };\nexport { ensureStylesheet, injectStylesheet };\n","/**\n * Theming per `docs/devtools.md` §4.6: the panel ships its own CSS variables with neutral dark defaults\n * and never imports a host design system. A host maps its own tokens once, in config.\n *\n * Overrides are applied as inline custom properties on the panel root, so nothing leaks into the host's cascade and\n * the panel still renders correctly in an application that has no design system at all.\n */\n\nimport type { CSSProperties } from 'react';\n\ntype DevtoolsTheme = Readonly<{\n accent?: string;\n accentSurface?: string;\n accentText?: string;\n bad?: string;\n badSurface?: string;\n canvas?: string;\n control?: string;\n font?: string;\n line?: string;\n lineStrong?: string;\n ok?: string;\n okSurface?: string;\n radius?: string;\n surface?: string;\n surfaceRaised?: string;\n text?: string;\n textMuted?: string;\n warn?: string;\n warnSurface?: string;\n}>;\n\nconst variableByToken: Readonly<Record<keyof DevtoolsTheme, string>> = {\n accent: '--odt-accent',\n accentSurface: '--odt-accent-surface',\n accentText: '--odt-accent-text',\n bad: '--odt-bad',\n badSurface: '--odt-bad-surface',\n canvas: '--odt-canvas',\n control: '--odt-control',\n font: '--odt-font',\n line: '--odt-line',\n lineStrong: '--odt-line-strong',\n ok: '--odt-ok',\n okSurface: '--odt-ok-surface',\n radius: '--odt-radius',\n surface: '--odt-surface',\n surfaceRaised: '--odt-surface-2',\n text: '--odt-text',\n textMuted: '--odt-text-muted',\n warn: '--odt-warn',\n warnSurface: '--odt-warn-surface',\n};\n\ntype ThemeMapping = Readonly<{\n /** How many variables the host actually mapped. The status bar reports it behind its disclosure (§4.5). */\n mapped: number;\n style: CSSProperties;\n}>;\n\nfunction themeMapping(theme: DevtoolsTheme | undefined): ThemeMapping {\n if (theme === undefined) return { mapped: 0, style: {} };\n\n const style: Record<string, string> = {};\n\n for (const [token, variable] of Object.entries(variableByToken)) {\n const value = theme[token as keyof DevtoolsTheme];\n\n if (value !== undefined) style[variable] = value;\n }\n\n return { mapped: Object.keys(style).length, style };\n}\n\n/** A neutral explicit theme; applications may provide any subset through DevtoolsTheme. */\nconst defaultTheme: DevtoolsTheme = {\n accent: '#60a5fa',\n accentText: '#dbeafe',\n bad: '#f87171',\n badSurface: '#321f23',\n canvas: '#111827',\n control: '#273449',\n font: 'system-ui, sans-serif',\n line: '#334155',\n lineStrong: '#64748b',\n ok: '#4ade80',\n okSurface: '#18332a',\n radius: '6px',\n surface: '#1e293b',\n surfaceRaised: '#334155',\n text: '#f1f5f9',\n textMuted: '#94a3b8',\n warn: '#fbbf24',\n warnSurface: '#352d1c',\n};\n\nexport { defaultTheme, themeMapping };\nexport type { DevtoolsTheme, ThemeMapping };\n","/**\n * The feature tree of `docs/devtools.md` §4, retold in the runtime's words: lifetime owners as uppercase\n * groups — the application itself and one row per condition group — with features as 32 px rows carrying glyph plus\n * text tag, and the glyph legend pinned at the bottom.\n *\n * Rows are flattened to a single list before rendering, both for keyboard navigation and so that swapping in a\n * virtualizer later is a change of one `map` (§6).\n */\n\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useMemo } from 'react';\n\nimport type { TreeGroupRow } from '../graph-index';\nimport type { DiagnosticLabel, DiagnosticNodeId } from '../protocol';\nimport type { NodeDisplayState } from '../visual-axes';\n\nimport { StateGlyph, StateTag } from './glyph';\nimport { ChevronIcon } from './icons';\nimport { useStrings } from './locale-context';\n\ntype TreeRow = Readonly<{\n /**\n * The conditions that gate this owner, kept as a list rather than a sentence: the row shows what fits and hands\n * the whole of it to `title`, and the plan's own label would otherwise print the same ids a second time (§4.3).\n */\n conditions?: readonly DiagnosticLabel[];\n display?: NodeDisplayState;\n expandable: boolean;\n expanded: boolean;\n id: DiagnosticNodeId;\n label: DiagnosticLabel;\n level: number;\n variant: 'feature' | 'group';\n}>;\n\ntype TreeProps = Readonly<{\n /** Resolved per rendered row, so a collapsed owner costs nothing when a commit changes its members (§6). */\n displayOf: (id: DiagnosticNodeId) => NodeDisplayState;\n expanded: ReadonlySet<DiagnosticNodeId>;\n groups: readonly TreeGroupRow[];\n onConfirm: () => void;\n onSelect: (id: DiagnosticNodeId) => void;\n onToggle: (id: DiagnosticNodeId) => void;\n selectedId: DiagnosticNodeId | undefined;\n summary: DiagnosticLabel;\n version: number;\n}>;\n\nfunction buildRows(\n groups: readonly TreeGroupRow[],\n expanded: ReadonlySet<DiagnosticNodeId>,\n displayOf: (id: DiagnosticNodeId) => NodeDisplayState,\n): readonly TreeRow[] {\n const rows: TreeRow[] = [];\n\n for (const group of groups) {\n const open = expanded.has(group.id);\n const conditions = group.conditions.map(condition => condition.label);\n\n rows.push({\n ...(conditions.length === 0 ? {} : { conditions }),\n display: displayOf(group.id),\n expandable: group.features.length > 0,\n expanded: open,\n id: group.id,\n label: group.label,\n level: 1,\n variant: 'group',\n });\n\n if (!open) continue;\n\n for (const row of group.features) {\n rows.push({\n display: displayOf(row.id),\n expandable: false,\n expanded: false,\n id: row.id,\n label: row.label,\n level: 2,\n variant: 'feature',\n });\n }\n }\n\n return rows;\n}\n\nfunction nextSelection(rows: readonly TreeRow[], index: number, key: string): DiagnosticNodeId | undefined {\n if (key === 'ArrowDown') return rows[Math.min(index + 1, rows.length - 1)]?.id;\n\n if (key === 'ArrowUp') return rows[Math.max(index - 1, 0)]?.id;\n\n return undefined;\n}\n\n/** Right opens a collapsed group, left closes an open one — the rest of the arrow keys move the selection. */\nfunction togglesGroup(row: TreeRow | undefined, key: string): row is TreeRow {\n if (row?.expandable !== true) return false;\n\n if (key === 'ArrowRight') return !row.expanded;\n\n return key === 'ArrowLeft' && row.expanded;\n}\n\ntype TreeAction = Readonly<{ id: DiagnosticNodeId; kind: 'select' | 'toggle' }> | Readonly<{ kind: 'confirm' }>;\n\n/** Decides what a key means before anything is applied, so the handler stays a short dispatch. */\nfunction keyAction(\n rows: readonly TreeRow[],\n selectedId: DiagnosticNodeId | undefined,\n key: string,\n): TreeAction | undefined {\n if (key === 'Enter' || key === ' ') return { kind: 'confirm' };\n\n const index = rows.findIndex(row => row.id === selectedId);\n const current = rows[index];\n\n if (togglesGroup(current, key)) return { id: current.id, kind: 'toggle' };\n\n const next = nextSelection(rows, index, key);\n\n return next === undefined ? undefined : { id: next, kind: 'select' };\n}\n\ntype TreeRowViewProps = Readonly<{\n onSelect: (id: DiagnosticNodeId) => void;\n onToggle: (id: DiagnosticNodeId) => void;\n row: TreeRow;\n selected: boolean;\n}>;\n\n/**\n * A lifetime owner is both a container and an inspectable node — a condition group has conditions, a desired axis and\n * a retirement of its own — so one click opens it and selects it. The keyboard keeps the two apart: arrows expand and\n * collapse, Enter moves into the inspector.\n */\n/**\n * The conditions, as much of them as the column has room for. One condition is shown whole; several show the first\n * and a count, because a list truncated in the middle says less than a list that admits how long it is. The whole\n * list is always in `title`, so the answer is one hover away.\n */\nfunction ConditionsTag({ conditions }: { readonly conditions: readonly DiagnosticLabel[] | undefined }): ReactElement {\n if (conditions === undefined || conditions.length === 0) return <span />;\n\n const [first = '', ...rest] = conditions;\n const full = conditions.join(' · ');\n\n return (\n <span className=\"odt-tag odt-tag-mute odt-tag-clip\" title={full}>\n {rest.length === 0 ? first : `${first} +${rest.length}`}\n </span>\n );\n}\n\nfunction GroupRow({ onSelect, onToggle, row, selected }: TreeRowViewProps): ReactElement {\n const strings = useStrings();\n const open = useCallback(() => {\n onToggle(row.id);\n onSelect(row.id);\n }, [onSelect, onToggle, row.id]);\n\n return (\n <button\n aria-expanded={row.expandable ? row.expanded : undefined}\n aria-level={row.level}\n aria-selected={selected}\n className=\"odt-row odt-row-group\"\n role=\"treeitem\"\n tabIndex={selected ? 0 : -1}\n type=\"button\"\n onClick={open}\n >\n <ChevronIcon open={row.expanded} />\n {/*\n A gated group is introduced by the word its declaration uses and shows its conditions once, in the tag; the\n plan's own label spells the same ids and would print them twice. The application owner has no conditions to\n introduce, so it keeps its name.\n */}\n <span className=\"odt-row-label\" title={row.label}>\n {row.conditions === undefined ? row.label : strings.treeGroupPrefix}\n </span>\n <ConditionsTag conditions={row.conditions} />\n </button>\n );\n}\n\nfunction FeatureRow({ onSelect, row, selected }: Omit<TreeRowViewProps, 'onToggle'>): ReactElement {\n const select = useCallback(() => onSelect(row.id), [onSelect, row.id]);\n const display = row.display ?? 'declared';\n\n return (\n <button\n aria-level={row.level}\n aria-selected={selected}\n className=\"odt-row\"\n role=\"treeitem\"\n tabIndex={selected ? 0 : -1}\n type=\"button\"\n onClick={select}\n >\n <StateGlyph state={display} />\n <span className=\"odt-row-label\">{row.label}</span>\n <StateTag state={display} />\n </button>\n );\n}\n\nfunction TreeRowView({ onSelect, onToggle, row, selected }: TreeRowViewProps): ReactElement {\n if (row.variant === 'group') {\n return <GroupRow row={row} selected={selected} onSelect={onSelect} onToggle={onToggle} />;\n }\n\n return <FeatureRow row={row} selected={selected} onSelect={onSelect} />;\n}\n\nfunction Tree({\n displayOf,\n expanded,\n groups,\n onConfirm,\n onSelect,\n onToggle,\n selectedId,\n summary,\n version,\n}: TreeProps): ReactElement {\n const strings = useStrings();\n const rows = useMemo(() => {\n // The graph mutates without replacing its topology or display reader. Resolve state only for visible rows.\n void version;\n\n return buildRows(groups, expanded, displayOf);\n }, [groups, expanded, displayOf, version]);\n\n const onKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n const action = keyAction(rows, selectedId, event.key);\n\n if (action === undefined) return;\n\n event.preventDefault();\n\n if (action.kind === 'confirm') onConfirm();\n else if (action.kind === 'toggle') onToggle(action.id);\n else onSelect(action.id);\n },\n [onConfirm, onSelect, onToggle, rows, selectedId],\n );\n\n return (\n <div aria-label={strings.treeLabel} className=\"odt-tree\" role=\"tree\" onKeyDown={onKeyDown}>\n <div className=\"odt-row odt-row-group odt-row-root odt-mono odt-truncate\" title={summary}>\n {summary}\n </div>\n {rows.map(row => (\n <TreeRowView key={row.id} row={row} selected={row.id === selectedId} onSelect={onSelect} onToggle={onToggle} />\n ))}\n </div>\n );\n}\n\nexport { Tree };\n","import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';\n\nimport type { DevtoolsGraphStore } from '../graph-store';\n\n/** Subscribes a component to the store's version counter, which changes exactly once per applied frame or reset. */\nfunction useStoreVersion(store: DevtoolsGraphStore): number {\n return useSyncExternalStore(\n useCallback((listener: () => void) => store.subscribe(listener), [store]),\n useCallback(() => store.getVersion(), [store]),\n () => 0,\n );\n}\n\nfunction now(): number {\n return typeof performance === 'object' ? performance.now() : 0;\n}\n\n/**\n * Rolling cost of the panel's own render-to-commit work, for the status bar budget of §6.\n *\n * It writes to refs during render and reads the previous measurement, so measuring never schedules a render of its\n * own — a diagnostics readout that re-rendered the panel to display its own cost would be measuring itself.\n */\nfunction useRenderCost(version: number): number {\n const cost = useRef(0);\n const startedAt = useRef(0);\n\n startedAt.current = now();\n\n useEffect(() => {\n cost.current = cost.current * 0.8 + (now() - startedAt.current) * 0.2;\n }, [version]);\n\n return cost.current;\n}\n\nexport { useRenderCost, useStoreVersion };\n","/**\n * The bottom-drawer shell of `docs/devtools.md` §4.1: header with the two tabs and search, the edge filter row, a\n * tree / graph / inspector body, and a status bar carrying the panel's own health.\n *\n * The selection and the filter are independent state on purpose (§4.3): switching a preset never moves the\n * selection, and selecting never resets the preset. That is what makes the filter a question about one node rather\n * than a mode the developer has to leave.\n *\n * The panel reads, and writes only where a host handed it a write port and the selection holds something that port\n * can address (§5). Without both it never fetches the surface that would write, so it is read-only by construction\n * rather than by a disabled button; the status bar says which of the two it is.\n */\n\nimport type { KeyboardEvent, ReactElement, ReactNode } from 'react';\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport type { ControlAuditEntry, RuntimeControlSession } from '../control';\nimport { controlSubjectOf } from '../control-subject';\nimport type { ControlSubject } from '../control-subject';\nimport type { DevtoolsExport } from '../export-snapshot';\nimport type { ExtensionPointsProjection } from '../extension-points';\nimport { projectExtensionPoints } from '../extension-points';\nimport type { DevtoolsGraphStore } from '../graph-store';\nimport type { InspectorProjection } from '../inspector';\nimport { projectInspector } from '../inspector';\nimport type { DiagnosticConditionId, DiagnosticEdgeKind, DiagnosticNodeId } from '../protocol';\nimport { searchGraph } from '../search';\nimport type { TimelineEntry } from '../timeline';\n\nimport type * as ControlUi from './control-ui';\nimport type { DevtoolsTab, EdgePresetId } from './edge-filter';\nimport { defaultPreset, presetKinds, presetOf, toggleKind } from './edge-filter';\nimport { EdgeFilters } from './edge-filters';\nimport type { ExportHost } from './export-delivery';\nimport { InspectorView } from './inspector-view';\nimport type { LazyModule } from './lazy-module';\nimport { loadControlUi, loadExportRun, loadLegend, loadTimeline, useLazyModule } from './lazy-module';\nimport type * as LegendUi from './legend';\nimport type { DevtoolsLocale, Strings } from './locale';\nimport { detectLocale } from './locale';\nimport { LocaleProvider, useStrings } from './locale-context';\nimport { MainColumn } from './main-column';\nimport { PanelHeader } from './panel-header';\nimport type { DevtoolsMode } from './panel-mode';\nimport { PanelStatus } from './panel-status';\nimport { SearchResults } from './search-results';\nimport { initialSelection } from './selection';\nimport { ensureStylesheet } from './styles';\nimport type { DevtoolsTheme } from './theme';\nimport { themeMapping } from './theme';\nimport type * as TimelineUi from './timeline-view';\nimport { Tree } from './tree';\nimport { useRenderCost, useStoreVersion } from './use-store';\n\ntype DevtoolsPanelProps = Readonly<{\n /**\n * The write port, when the host has one to give. Without it the panel is read-only and never even fetches the\n * chunk that would write: the control surface is loaded by its presence, not by a flag (§5).\n */\n control?: RuntimeControlSession;\n /** Overrides feature detection for the export destinations. Tests and non-browser hosts pass their own. */\n exportHost?: ExportHost;\n /** Initial language. Defaults to the browser's preference; the header switch overrides it either way. */\n locale?: DevtoolsLocale;\n mode?: DevtoolsMode;\n onClose?: () => void;\n onExport?: (payload: DevtoolsExport) => void;\n store: DevtoolsGraphStore;\n theme?: DevtoolsTheme;\n}>;\n\n/** Keyboard contract: `/` focuses search, Escape clears a query and otherwise closes the panel. */\nfunction keyIntent(key: string, inSearch: boolean): 'dismiss' | 'focus-search' | undefined {\n if (key === '/' && !inSearch) return 'focus-search';\n\n return key === 'Escape' ? 'dismiss' : undefined;\n}\n\nfunction summaryOf(store: DevtoolsGraphStore, strings: Strings): string {\n const { application } = store.graph.plan;\n\n return strings.treeSummary(application.features, application.groups);\n}\n\nfunction currentSelection(store: DevtoolsGraphStore, id: DiagnosticNodeId | undefined): DiagnosticNodeId | undefined {\n return id === undefined ? undefined : store.graph.currentNodeId(id);\n}\n\n/**\n * The two-step walk, and only under its own preset. `Extension points` is the one filter that is not just a set of\n * edges: a contribution sits between a feature and its target, so the question it is opened for is two hops away.\n */\nfunction extensionPointsFor(\n store: DevtoolsGraphStore,\n selectedId: DiagnosticNodeId | undefined,\n edgeKinds: ReadonlySet<DiagnosticEdgeKind>,\n): ExtensionPointsProjection | undefined {\n if (selectedId === undefined || presetOf(edgeKinds) !== 'extension-points') return undefined;\n\n return projectExtensionPoints(store, store.graph.currentNodeId(selectedId));\n}\n\ntype ControlModule = typeof ControlUi;\n\n/**\n * What a surface shows when its chunk never arrived. It is the panel's own failure, not the application's, so it\n * says so in one line and offers the only thing that can help — asking again (§6, §7).\n */\nfunction LazyFailure({ onRetry }: { readonly onRetry: () => void }): ReactElement {\n const strings = useStrings();\n\n return (\n <div className=\"odt-empty\">\n {strings.surfaceFailed}{' '}\n <button className=\"odt-btn odt-btn-small\" type=\"button\" onClick={onRetry}>\n {strings.surfaceRetry}\n </button>\n </div>\n );\n}\n\n/**\n * Both loaders are module constants, because `useLazyModule` compares them by identity to decide what to fetch.\n *\n * The control surface needs a write port _and_ something for it to address. An application whose plan holds no\n * condition group — and the strangler application is one — would otherwise fetch a chunk on every attach that it\n * could never draw, which the §6 profile caught.\n */\nfunction controlLoader(\n control: RuntimeControlSession | undefined,\n subject: ControlSubject | undefined,\n): typeof loadControlUi | undefined {\n return control === undefined || subject === undefined ? undefined : loadControlUi;\n}\n\nfunction legendLoader(open: boolean): typeof loadLegend | undefined {\n return open ? loadLegend : undefined;\n}\n\nfunction timelineLoader(tab: DevtoolsTab): typeof loadTimeline | undefined {\n return tab === 'timeline' ? loadTimeline : undefined;\n}\n\ntype InspectorHostProps = Readonly<{\n actionStatus: string | undefined;\n conditionLabelOf: (id: DiagnosticConditionId) => string;\n control: ReactNode;\n labelOf: (id: DiagnosticNodeId) => string;\n onCopyId: (id: DiagnosticNodeId) => void;\n onExport: () => void;\n onSelect: (id: DiagnosticNodeId) => void;\n onShowInTimeline: () => void;\n projection: InspectorProjection | undefined;\n}>;\n\n/** The legend, or the reason it is not here. */\nfunction LegendSurface({ state }: { readonly state: LazyModule<typeof LegendUi> }): ReactElement | undefined {\n if (state.module !== undefined) return <state.module.Legend />;\n\n return state.error === undefined ? undefined : <LazyFailure onRetry={state.retry} />;\n}\n\ntype ControlSlotHostProps = Readonly<{\n audit: readonly ControlAuditEntry[];\n control: RuntimeControlSession | undefined;\n controlUi: LazyModule<ControlModule>;\n onAudit: (entry: ControlAuditEntry) => void;\n place: 'bar' | 'inspector';\n projection: InspectorProjection | undefined;\n store: DevtoolsGraphStore;\n}>;\n\n/**\n * Renders the control surface where the panel keeps a place for it, and nothing at all until both halves are there:\n * a host that gave no write port, and a chunk that has not landed yet, look the same from here.\n */\nfunction ControlSlotHost({\n audit,\n control,\n controlUi,\n onAudit,\n place,\n projection,\n store,\n}: ControlSlotHostProps): ReactElement | undefined {\n if (control === undefined) return undefined;\n\n if (controlUi.module === undefined) {\n return controlUi.error === undefined ? undefined : <LazyFailure onRetry={controlUi.retry} />;\n }\n\n return (\n <controlUi.module.ControlSlot\n audit={audit}\n place={place}\n projection={projection}\n session={control}\n store={store}\n onAudit={onAudit}\n />\n );\n}\n\ntype TimelineTabProps = Readonly<{\n audit: readonly ControlAuditEntry[];\n controlUi: ControlModule | undefined;\n entries: readonly TimelineEntry[];\n timeline: LazyModule<typeof TimelineUi>;\n}>;\n\n/** The history tab: the panel's own audit above the runtime's commits, each arriving with the code that draws it. */\nfunction TimelineTab({ audit, controlUi, entries, timeline }: TimelineTabProps): ReactElement {\n if (timeline.module === undefined && timeline.error !== undefined) return <LazyFailure onRetry={timeline.retry} />;\n\n return (\n <>\n {controlUi === undefined ? undefined : <controlUi.ControlAudit entries={audit} />}\n {timeline.module === undefined ? undefined : <timeline.module.TimelineView entries={entries} />}\n </>\n );\n}\n\n/** The right column, with the empty state it shows before anything is selected. */\nfunction InspectorHost({ actionStatus, control, projection, ...actions }: InspectorHostProps): ReactElement {\n const strings = useStrings();\n\n if (projection === undefined) return <div className=\"odt-empty\">{strings.noSelection}</div>;\n\n return (\n <InspectorView\n {...(actionStatus === undefined ? {} : { actionStatus })}\n {...actions}\n control={control}\n projection={projection}\n />\n );\n}\n\n/**\n * The panel proper. It is split from `DevtoolsPanel` so every part of it can read strings from context: the provider\n * has to sit above the component that consumes it.\n */\nfunction PanelBody({\n control,\n exportHost,\n locale,\n mode = 'inspect',\n onClose,\n onExport,\n onLocale,\n store,\n theme,\n}: DevtoolsPanelProps & {\n readonly locale: DevtoolsLocale;\n readonly onLocale: (locale: DevtoolsLocale) => void;\n}): ReactElement {\n const strings = useStrings();\n ensureStylesheet();\n\n const version = useStoreVersion(store);\n const renderCost = useRenderCost(version);\n const initial = useMemo(() => initialSelection(store), [store]);\n const [tab, setTab] = useState<DevtoolsTab>('graph');\n /** The panel's own audit trail: a rejected command commits no frame, so nothing else records that it happened. */\n const [audit, setAudit] = useState<readonly ControlAuditEntry[]>([]);\n /** The chips are the state and the preset is their name, so the panel stores one set and derives the rest. */\n const [edgeKinds, setEdgeKinds] = useState<ReadonlySet<DiagnosticEdgeKind>>(() => presetKinds(defaultPreset));\n /** The last outcome of an action the panel took on its own: an export delivered, an id copied, either refused. */\n const [actionStatus, setActionStatus] = useState<string | undefined>(undefined);\n /** Collapsed by default: the legend is an answer to a question, not a permanent tenant of the panel. */\n const [legendOpen, setLegendOpen] = useState(false);\n /** Collapsed means unloaded: most sessions never ask what a shape means, and those bytes are theirs to keep. */\n const legend = useLazyModule(legendLoader(legendOpen));\n /** A whole tab, and one most sessions never open: the history arrives with the tab that shows it. */\n const timeline = useLazyModule(timelineLoader(tab));\n const [query, setQuery] = useState('');\n const [expanded, setExpanded] = useState(initial.expanded);\n const [selectedId, setSelectedId] = useState(initial.selectedId);\n const searchRef = useRef<HTMLInputElement>(null);\n const inspectorRef = useRef<HTMLDivElement>(null);\n\n const { mapped, style } = useMemo(() => themeMapping(theme), [theme]);\n const { status } = store;\n const inspectedId = currentSelection(store, selectedId);\n /**\n * The index mutates in place, so identity cannot be the dependency — `version` can, because the store bumps it\n * exactly once per applied frame or reset. Without it the inspector projection and a full-graph search would both\n * run on every keystroke and every unrelated re-render (§6).\n */\n const projection = useMemo(() => {\n // Read so the dependency is not mistaken for a stray one: it is the only thing that signals a mutated index.\n void version;\n\n return selectedId === undefined ? undefined : projectInspector(store, store.graph.currentNodeId(selectedId));\n }, [store, selectedId, version]);\n const controlSubject = controlSubjectOf(store, projection);\n const controlUi = useLazyModule(controlLoader(control, controlSubject));\n const extensionPoints = useMemo(() => {\n void version;\n\n return extensionPointsFor(store, selectedId, edgeKinds);\n }, [store, selectedId, edgeKinds, version]);\n const hits = useMemo(() => {\n void version;\n\n return query === '' ? [] : searchGraph(store.graph, query);\n }, [store, query, version]);\n\n const toggleGroup = useCallback((id: DiagnosticNodeId) => {\n setExpanded(current => {\n const next = new Set(current);\n\n if (!next.delete(id)) next.add(id);\n\n return next;\n });\n }, []);\n\n const labelOf = useCallback((id: DiagnosticNodeId) => store.graph.node(id)?.label ?? id, [store]);\n /** A condition is addressed by an escaped atom and read by its label; the panel never shows the atom (D200). */\n const conditionLabelOf = useCallback((id: DiagnosticConditionId) => store.graph.condition(id)?.label ?? id, [store]);\n const displayOf = useCallback(\n (id: DiagnosticNodeId) => store.graph.displayOf(store.graph.currentNodeId(id)),\n [store],\n );\n const selectNode = useCallback(\n (id: DiagnosticNodeId) => {\n const node = store.graph.runtimeNode(id);\n setSelectedId(node?.kind === 'feature-instance' ? (node.declaration ?? id) : id);\n },\n [store],\n );\n const recordAudit = useCallback((entry: ControlAuditEntry) => setAudit(current => [...current, entry]), []);\n const focusInspector = useCallback(() => inspectorRef.current?.focus(), []);\n const toggleLegend = useCallback(() => setLegendOpen(open => !open), []);\n const showTimeline = useCallback(() => setTab('timeline'), []);\n const applyPreset = useCallback((preset: EdgePresetId) => setEdgeKinds(presetKinds(preset)), []);\n const toggleEdgeKind = useCallback(\n (kind: DiagnosticEdgeKind) => setEdgeKinds(current => toggleKind(current, kind)),\n [],\n );\n /** An export that cannot even load its own chunk is an outcome too, not a rejection for the host to discover. */\n const runExport = useCallback(() => {\n void loadExportRun()\n .then(module => module.runExport({ host: exportHost, locale, onExport, store }))\n .then(setActionStatus, () => setActionStatus(strings.surfaceFailed));\n }, [exportHost, locale, onExport, store, strings]);\n /**\n * A clipboard can refuse — a denied permission is the ordinary case — and a refusal the panel drops is a rejected\n * promise nobody handles. It is an outcome like the export's: it goes to the same line the footer already shows.\n */\n const copyId = useCallback(\n (id: DiagnosticNodeId) => {\n const clipboard = globalThis.navigator?.clipboard;\n\n if (clipboard === undefined) {\n setActionStatus(strings.copyIdFailed);\n\n return;\n }\n\n void clipboard.writeText(id).then(\n () => setActionStatus(strings.copyIdDone),\n () => setActionStatus(strings.copyIdFailed),\n );\n },\n [strings],\n );\n\n const onKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n const handled = keyIntent(event.key, event.target === searchRef.current);\n\n if (handled === undefined) return;\n\n event.preventDefault();\n\n if (handled === 'focus-search') searchRef.current?.focus();\n else if (query !== '') setQuery('');\n else onClose?.();\n },\n [onClose, query],\n );\n\n return (\n <div aria-label=\"Opetope Devtools\" className=\"odt\" role=\"region\" style={style} onKeyDown={onKeyDown}>\n <PanelHeader\n legendOpen={legendOpen}\n locale={locale}\n query={query}\n searchRef={searchRef}\n status={status}\n tab={tab}\n onClose={onClose}\n onLegend={toggleLegend}\n onLocale={onLocale}\n onQuery={setQuery}\n onTab={setTab}\n />\n\n {tab === 'graph' ? (\n <EdgeFilters selected={edgeKinds} onPreset={applyPreset} onToggle={toggleEdgeKind} />\n ) : undefined}\n\n <LegendSurface state={legend} />\n\n {tab === 'timeline' ? (\n <TimelineTab audit={audit} controlUi={controlUi.module} entries={store.timeline.list()} timeline={timeline} />\n ) : (\n <div className=\"odt-body\">\n {query === '' ? (\n <Tree\n displayOf={displayOf}\n expanded={expanded}\n groups={store.graph.tree()}\n selectedId={selectedId}\n summary={summaryOf(store, strings)}\n version={version}\n onConfirm={focusInspector}\n onSelect={selectNode}\n onToggle={toggleGroup}\n />\n ) : (\n <SearchResults hits={hits} selectedId={inspectedId} onSelect={selectNode} />\n )}\n\n <MainColumn\n control={\n <ControlSlotHost\n audit={audit}\n control={control}\n controlUi={controlUi}\n place=\"bar\"\n projection={projection}\n store={store}\n onAudit={recordAudit}\n />\n }\n edgeKinds={edgeKinds}\n extensionPoints={extensionPoints}\n projection={projection}\n onSelect={selectNode}\n />\n\n <div className=\"odt-inspector-host\" ref={inspectorRef} tabIndex={-1}>\n <InspectorHost\n actionStatus={actionStatus}\n conditionLabelOf={conditionLabelOf}\n control={\n <ControlSlotHost\n audit={audit}\n control={control}\n controlUi={controlUi}\n place=\"inspector\"\n projection={projection}\n store={store}\n onAudit={recordAudit}\n />\n }\n labelOf={labelOf}\n projection={projection}\n onCopyId={copyId}\n onExport={runExport}\n onSelect={selectNode}\n onShowInTimeline={showTimeline}\n />\n </div>\n </div>\n )}\n\n <PanelStatus mappedTokens={mapped} mode={mode} renderCost={renderCost} status={status} />\n </div>\n );\n}\n\n/** Owns the language so the provider can sit above everything that reads a string. */\nfunction DevtoolsPanel(props: DevtoolsPanelProps): ReactElement {\n const [locale, setLocale] = useState<DevtoolsLocale>(() => props.locale ?? detectLocale());\n\n return (\n <LocaleProvider locale={locale}>\n <PanelBody {...props} locale={locale} onLocale={setLocale} />\n </LocaleProvider>\n );\n}\n\nexport { DevtoolsPanel };\nexport type { DevtoolsMode } from './panel-mode';\nexport type { DevtoolsPanelProps };\n"],"names":["hasCondition","store","id","node","quarantined","projection","controlSubjectOf","edgeKinds","edgePresets","defaultPreset","presetKinds","_a","preset","sameKinds","left","right","kind","presetOf","selected","toggleKind","next","russianRelations","count","tail","last","en","state","total","unmet","subject","phase","code","generation","previous","session","fingerprint","reducer","paint","dropped","sequence","revision","features","groups","ru","dictionaries","locales","isLocale","value","detectLocale","languages","language","tag","stringsFor","locale","LocaleContext","createContext","LocaleProvider","children","useMemo","_jsx","useLocaleValue","useContext","useStrings","useLocale","PresetButton","label","onPreset","pressed","press","useCallback","EdgeChip","on","onToggle","toggle","EdgeFilters","strings","active","_jsxs","blockersOf","call","blockers","loadsOf","resource","load","activityRows","snapshot","rows","feature","ActivityItem","onSelect","row","select","diagnosticNodeId","key","rowsFor","owners","ActivityView","timeFormat","formatClock","at","formatTime","milliseconds","formatInstance","formatOptionalTime","formatMilliseconds","shapeByState","toneByState","tagToneByState","stateDescriptionKey","stateDescription","displayStates","shapeElement","shape","StateGlyph","size","StateTag","frame","path","SearchIcon","CloseIcon","CopyIcon","ChevronIcon","open","axisTone","healthy","failureSentence","failure","causeSentence","conditionLabelOf","cause","when","blockerSentence","why","whyText","parts","KeyValue","_Fragment","InstanceRow","IdentityGrid","groupLabel","override","provenance","BlockerRow","blocker","OwnedRow","ChainRow","labelOf","step","condition","InspectorView","actionStatus","control","onCopyId","onExport","onShowInTimeline","axes","chain","owned","copy","loaded","pending","useLazyModule","attempt","setAttempt","useState","setFailure","fetched","setFetched","retry","useEffect","request","module","error","loadControlUi","loadLegend","loadExportRun","loadTimeline","neighbourBudget","selectedBudget","relativeTo","fitLabel","text","budget","lastDot","neighbourLabel","selectedLabel","cardWidth","cardHeight","selectedCardHeight","columnStep","rowStep","leftPadding","topPadding","bottomPadding","centerRight","centerLeft","curve","from","to","bend","column","index","stack","tallest","offset","blockerNode","ownedNode","ownershipSummary","counts","selectedTags","contributionNode","inverted","endpointNode","layoutNeighbourhood","shows","summary","edges","shownRelations","allRelations","layoutExtensionPoints","endpoints","middle","endpointNodes","endpoint","minZoom","maxZoom","zoomStep","wheelSensitivity","wheelPixels","delta","mode","wheelFactor","pixels","fitPadding","identityTransform","clampZoom","zoom","isMeasured","viewport","fitTransform","layout","usableWidth","usableHeight","panBy","transform","dx","dy","zoomAround","point","factor","applied","viewportCentre","transformStyle","weakOrHardEdges","edgeClass","NodeCard","hold","event","contribution","style","usePan","onPan","origin","useRef","panning","setPanning","_b","useWheelZoom","canvasRef","onZoomAt","element","onWheel","box","GraphView","handlers","layerStyle","edge","ListRow","NeighbourList","narrowViewport","isNarrow","useNarrowViewport","narrow","setNarrow","update","Neighbourhood","asList","onFit","onZoomIn","onZoomOut","Crumb","crumb","current","Breadcrumbs","crumbs","viewportOf","layoutFor","extensionPoints","MainColumn","setTransform","pan","zoomAt","zoomBy","zoomOut","zoomIn","fit","PanelTab","tab","LocalePicker","onLocale","change","option","PanelHeader","legendOpen","onClose","onLegend","onQuery","onTab","query","searchRef","status","onChange","PanelStatus","mappedTokens","renderCost","detailed","setDetailed","matchedIn","hitReason","hit","HitRow","SearchResults","hits","selectedId","isTroubled","group","displayOf","firstUnready","firstFeature","first","ownerOfFeature","initialSelection","expanded","home","stylesheet","marker","injectStylesheet","name","css","target","ensureStylesheet","variableByToken","themeMapping","theme","token","variable","defaultTheme","buildRows","conditions","nextSelection","togglesGroup","keyAction","ConditionsTag","rest","full","GroupRow","FeatureRow","display","TreeRowView","Tree","onConfirm","version","onKeyDown","action","useStoreVersion","useSyncExternalStore","listener","now","useRenderCost","cost","startedAt","keyIntent","inSearch","summaryOf","application","currentSelection","extensionPointsFor","projectExtensionPoints","LazyFailure","onRetry","controlLoader","legendLoader","timelineLoader","LegendSurface","ControlSlotHost","audit","controlUi","onAudit","place","TimelineTab","entries","timeline","InspectorHost","actions","PanelBody","exportHost","initial","setTab","setAudit","setEdgeKinds","setActionStatus","setLegendOpen","legend","setQuery","setExpanded","setSelectedId","inspectorRef","mapped","inspectedId","projectInspector","controlSubject","searchGraph","toggleGroup","selectNode","recordAudit","entry","focusInspector","toggleLegend","showTimeline","applyPreset","toggleEdgeKind","runExport","copyId","clipboard","handled","DevtoolsPanel","props","setLocale"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The producer's own id composition, modelled once so the fixture composes ids the way a real application does
|
|
3
|
+
* (D200, `docs/devtools.md` §2.6).
|
|
4
|
+
*
|
|
5
|
+
* The runtime escapes every part of an id before it joins the parts, because a declaration id may hold `/` and `:`
|
|
6
|
+
* and a condition group key joins its conditions with `|` — none of which the consumer's grammar admits, and the
|
|
7
|
+
* last of which it would read as a separator. The escape is reversible, so `probe.inspect/a` and `probe.inspect-a`
|
|
8
|
+
* stay two nodes rather than folding into one.
|
|
9
|
+
*
|
|
10
|
+
* This package cannot import the runtime, so these are the same rules written out again. That is a copy with a
|
|
11
|
+
* purpose: `__tests__/producer-ids.spec.ts` states the producer's output for every rule as a literal, so a change on
|
|
12
|
+
* either side breaks a test here rather than quietly giving the fixture a composition of its own.
|
|
13
|
+
*/
|
|
14
|
+
declare function encodeIdPart(value: string): string;
|
|
15
|
+
export { encodeIdPart };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
class r extends Error{code;constructor(i,t){super(t),this.code=i,this.name="DevtoolsProtocolError"}}const p=/^[A-Za-z][\w.:-]*$/,s=160,c=Math.floor((s-1)/2),a=s+c,e=13+a,u=19+2*(e+1+c);function o(n,i,t){if(n.length>t||!p.test(n))throw new r("invalid-id",`Invalid diagnostic ${i}: ${JSON.stringify(n)}.`);return n}function d(n,i,t){if(!Number.isSafeInteger(n)||n<0)throw new r(i,`Diagnostic ${t} must be a non-negative safe integer, got ${n}.`);return n}function l(n){return o(n,"session id",e)}function m(n,i=e){return o(n,"node id",i)}function h(n,i=u){return o(n,"edge id",i)}function E(n){return o(n,"condition id",a)}function I(n){return o(n,"plan fingerprint",s)}function v(n){return d(n,"invalid-sequence","sequence")}function w(n){return d(n,"invalid-revision","state revision")}function x(n){return d(n,"invalid-revision","topology revision")}const S=new Set(["hard-import","requires-port"]),b=new Set(["absent-import","absent-port","optional-import","optional-port"]);function g(n){return S.has(n.kind)}function f(n){return b.has(n.kind)}function q(n){return g(n)||f(n)}export{r as D,w as a,v as b,m as c,x as d,l as e,I as f,E as g,h,u as i,e as j,q as k,g as l,a as m,f as n};
|
|
2
|
+
//# sourceMappingURL=protocol-joKTjlMj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-joKTjlMj.js","sources":["../src/protocol.ts"],"sourcesContent":["/**\n * Executable form of the diagnostic protocol. `docs/devtools.md` §2 sketched it before the\n * decisions D68–D112 of [`decisions.md`](../../docs/decisions.md); where the two disagree the runtime wins, and it is\n * recorded in the decision log of document 14 rather than by editing its prose.\n *\n * The protocol is data-only by construction: no callbacks, no `FeatureInstance`, no models, resources or repository\n * objects, no raw `Error`, `AbortSignal` or thenable, no DOM or React instance (§2.6). Failures carry the subject and\n * the code of the runtime's own error classes and nothing else — never a message, a stack or a cause (§2.6).\n *\n * The id brands are *optional* markers, and that is the whole of decision T29. `RuntimeInspectionSession` is a\n * consumed interface: the runtime produces these ids and declares them `string` and `number`, so a required brand\n * would have made the producer unable to satisfy the very interface written for it, and every host attaching the\n * panel would have carried a cast. An optional marker keeps the names — a signature still reads `DiagnosticNodeId`,\n * not `string` — while a plain string the runtime built is accepted as it is. What it does not do is keep the kinds\n * apart at compile time; the guarantee that an id is well formed lives where it can be enforced, in the validators\n * below and in the hostile decoder (§7).\n */\n\ndeclare const conditionIdBrand: unique symbol;\ndeclare const edgeIdBrand: unique symbol;\ndeclare const nodeIdBrand: unique symbol;\ndeclare const planFingerprintBrand: unique symbol;\ndeclare const sequenceBrand: unique symbol;\ndeclare const sessionIdBrand: unique symbol;\ndeclare const stateRevisionBrand: unique symbol;\ndeclare const topologyRevisionBrand: unique symbol;\n\ntype DiagnosticSessionId = string & { readonly [sessionIdBrand]?: true };\ntype DiagnosticNodeId = string & { readonly [nodeIdBrand]?: true };\ntype DiagnosticEdgeId = string & { readonly [edgeIdBrand]?: true };\ntype DiagnosticConditionId = string & { readonly [conditionIdBrand]?: true };\ntype DiagnosticPlanFingerprint = string & { readonly [planFingerprintBrand]?: true };\ntype DiagnosticSequence = number & { readonly [sequenceBrand]?: true };\ntype DiagnosticStateRevision = number & { readonly [stateRevisionBrand]?: true };\ntype DiagnosticTopologyRevision = number & { readonly [topologyRevisionBrand]?: true };\n\n/**\n * Non-negative integer epoch milliseconds within Date's range, up to 8_640_000_000_000_000 inclusive.\n * The protocol has exactly one clock and it belongs to `DiagnosticCauseRef`: it stamps the\n * trigger of a commit, not the commit itself, and no duration is derived from it. State records therefore carry no\n * timestamps of their own — a second clock would let the panel invent spans the runtime never measured.\n */\ntype DiagnosticTimestamp = number;\n\n/**\n * Human-readable text the compiler derived from declarations. Presentation only: search may index it, control must\n * never accept it as a target (§2.6).\n */\ntype DiagnosticLabel = string;\n\n/** Project-relative provenance of a declaration. Never an execution identity (§2.6). */\ntype DiagnosticProvenance = string;\n\nclass DevtoolsProtocolError extends Error {\n public constructor(\n public readonly code: 'invalid-id' | 'invalid-revision' | 'invalid-sequence',\n message: string,\n ) {\n super(message);\n this.name = 'DevtoolsProtocolError';\n }\n}\n\nconst idPattern = /^[A-Za-z][\\w.:-]*$/;\n\n/**\n * How long an id may be, derived from the producer's own laws rather than chosen (D200, §2.6).\n *\n * An atom is a declaration id: at most 160 characters over `[A-Za-z0-9./:-]`, where a separator always sits between\n * two alphanumerics, so at most 79 of them. Escaping turns `/` and `:` into two characters each, and that is the\n * only growth an atom can suffer.\n *\n * A node id is a prefix and one escaped atom — `contribution:` is the longest prefix the producer writes. A group is\n * the exception: its key joins the ids of its conditions, so a set large enough to outgrow one escaped atom is\n * refused as an oversized id. That is a budget rather than a law, and it is the same kind of refusal `maxNodes` is.\n *\n * An edge id is a kind and its two endpoints escaped again, which doubles every escape the endpoints already carry.\n */\nconst maxAtomId = 160;\nconst maxAtomEscapes = Math.floor((maxAtomId - 1) / 2);\nconst maxEncodedAtom = maxAtomId + maxAtomEscapes;\nconst maxNodeId = 'contribution:'.length + maxEncodedAtom;\nconst maxEdgeId = 'condition-control'.length + 2 + 2 * (maxNodeId + 1 + maxAtomEscapes);\n\nfunction requireId(value: string, what: string, limit: number): string {\n if (value.length > limit || !idPattern.test(value)) {\n throw new DevtoolsProtocolError('invalid-id', `Invalid diagnostic ${what}: ${JSON.stringify(value)}.`);\n }\n\n return value;\n}\n\nfunction requireCounter(value: number, code: 'invalid-revision' | 'invalid-sequence', what: string): number {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new DevtoolsProtocolError(code, `Diagnostic ${what} must be a non-negative safe integer, got ${value}.`);\n }\n\n return value;\n}\n\nfunction diagnosticSessionId(value: string): DiagnosticSessionId {\n return requireId(value, 'session id', maxNodeId);\n}\n\nfunction diagnosticNodeId(value: string, limit = maxNodeId): DiagnosticNodeId {\n return requireId(value, 'node id', limit);\n}\n\nfunction diagnosticEdgeId(value: string, limit = maxEdgeId): DiagnosticEdgeId {\n return requireId(value, 'edge id', limit);\n}\n\n/**\n * A condition id is one escaped atom: the producer writes `encodeIdPart(declarationId)` and addresses control by it,\n * while the readable original stays in the node's label (D200). Escaping is the only growth it can suffer, so it is\n * bounded by the encoded atom rather than by the declaration id it came from.\n */\nfunction diagnosticConditionId(value: string): DiagnosticConditionId {\n return requireId(value, 'condition id', maxEncodedAtom);\n}\n\nfunction diagnosticPlanFingerprint(value: string): DiagnosticPlanFingerprint {\n return requireId(value, 'plan fingerprint', maxAtomId);\n}\n\nfunction diagnosticSequence(value: number): DiagnosticSequence {\n return requireCounter(value, 'invalid-sequence', 'sequence');\n}\n\nfunction diagnosticStateRevision(value: number): DiagnosticStateRevision {\n return requireCounter(value, 'invalid-revision', 'state revision');\n}\n\nfunction diagnosticTopologyRevision(value: number): DiagnosticTopologyRevision {\n return requireCounter(value, 'invalid-revision', 'topology revision');\n}\n\n/**\n * The node kinds of the compiled plan and of the live world, named with the public words of `spec.md` §3: a\n * feature, one instance of it, the condition group that owns its activation, the port it requires or provides, the\n * host contract the application binds, the target it contributes to and the contribution itself.\n *\n * Projection hides kinds; it never renames them into generic \"nodes\".\n */\ntype DiagnosticNodeKind =\n | 'absent-provider'\n | 'application'\n | 'attachment'\n | 'condition'\n | 'condition-group'\n | 'contribution'\n | 'contribution-target'\n | 'feature'\n | 'feature-instance'\n | 'host-contract'\n | 'port';\n\n/**\n * A hard edge: the provider opens before the consumer, the consumer closes before the provider, and the compiler\n * refuses the edge unless the provider's condition set is a subset of the consumer's (`spec.md` §4). These are the\n * only edges an activation can wait on.\n */\ntype HardEdgeKind = 'hard-import' | 'requires-port';\n\n/**\n * A weak edge: one word, `optional`, for features and for ports (D105). The consumer may outlive the provider, reads\n * a `Lookup` projection instead of a value, and never waits for it. `absent-import` and `absent-port` are the same\n * edge with no provider in the plan at all — the runtime value is identical, which is exactly D105's point, and only\n * the plan remembers the difference.\n */\ntype WeakEdgeKind = 'absent-import' | 'absent-port' | 'optional-import' | 'optional-port';\n\n/**\n * Edges that carry no state of their own. `provides-port` names the single provider the compiler selected,\n * `condition-control` names a condition that gates a group, `owns` names the lifetime owner of a feature, and\n * `on-demand-import` is a host contract whose connection is deferred to the attachment that opens it, so it is\n * neither a wait nor a `Lookup`.\n */\ntype StructuralEdgeKind = 'condition-control' | 'contributes-to' | 'on-demand-import' | 'owns' | 'provides-port';\n\ntype DiagnosticEdgeKind = HardEdgeKind | StructuralEdgeKind | WeakEdgeKind;\n\n/** What a weak edge reports to its consumer right now: literally the `Lookup` the projection yields (D105). */\ntype WeakEdgeState = 'found' | 'missing';\n\ntype DiagnosticEdgeBase = Readonly<{\n from: DiagnosticNodeId;\n id: DiagnosticEdgeId;\n to: DiagnosticNodeId;\n}>;\n\n/**\n * Orientation is fixed: provider, blocker or owner → consumer, waiter or owned node. The panel may print\n * \"B depends on A\"; it must not flip the data.\n *\n * State lives on the edge kinds that have one, so a weak edge cannot claim to be pending and a hard edge cannot\n * claim a `Lookup`.\n */\ntype DiagnosticEdge =\n | (DiagnosticEdgeBase & Readonly<{ kind: HardEdgeKind; pending: boolean }>)\n | (DiagnosticEdgeBase & Readonly<{ kind: StructuralEdgeKind }>)\n | (DiagnosticEdgeBase & Readonly<{ kind: WeakEdgeKind; lookup: WeakEdgeState }>);\n\nconst hardEdgeKinds: ReadonlySet<string> = new Set<HardEdgeKind>(['hard-import', 'requires-port']);\nconst weakEdgeKinds: ReadonlySet<string> = new Set<WeakEdgeKind>([\n 'absent-import',\n 'absent-port',\n 'optional-import',\n 'optional-port',\n]);\n\n/** A hard edge is the only thing an activation waits on, so only these can hold up a feature instance. */\nfunction isHardEdge(edge: DiagnosticEdge): edge is DiagnosticEdgeBase & { kind: HardEdgeKind; pending: boolean } {\n return hardEdgeKinds.has(edge.kind);\n}\n\nfunction isWeakEdge(edge: DiagnosticEdge): edge is DiagnosticEdgeBase & { kind: WeakEdgeKind; lookup: WeakEdgeState } {\n return weakEdgeKinds.has(edge.kind);\n}\n\n/** Both kinds of dependency edge, which is what the inspector lists as \"blocked by\" (weak rows read `missing`). */\nfunction isDependencyEdge(edge: DiagnosticEdge): boolean {\n return isHardEdge(edge) || isWeakEdge(edge);\n}\n\n/** Axis one: what the machine wants, before and after a debug override that no build can set yet (§5.4). */\ntype DesiredAxis = 'active' | 'inactive';\ntype DiagnosticOverride = 'force-inactive' | 'none';\n\n/**\n * Axis two: where the node sits in its own automaton. `declared` is the seventh value: a feature the plan declares\n * while no instance of it is open is in none of the other six, and calling it `waiting` would claim a blocker that\n * does not exist.\n */\ntype LifecycleAxis = 'closed' | 'declared' | 'fencing' | 'opening' | 'ready' | 'retiring' | 'waiting';\n\n/** Axis three: whether that position is a problem. */\ntype HealthAxis = 'blocked' | 'cancelled' | 'failed' | 'healthy' | 'quarantined' | 'stale';\n\n/**\n * When a host contract is connected: with the instance that owns it, or lazily on first use. The literal is the\n * runtime's own `ImportDemand` from `runtime/src/feature-contract.ts` and is declared once here, so following the\n * runtime is one edit rather than three.\n */\ntype HostContractDemand = 'instance' | 'onDemand';\n\n/** The phase vocabulary of D14, unchanged: one word set for every lifecycle transaction in the runtime. */\ntype DiagnosticPhase = 'close' | 'drain' | 'fence' | 'open' | 'retry' | 'rollback';\n\n/**\n * The whole vocabulary of failure the protocol exports, and it is the runtime's own: one class per subject of the\n * author vocabulary with the state in `code` (`spec.md` §4, D69). Subject and code are one discriminated union, so a\n * `ContributionError` code can never be reported under `FeatureError`. Arbitrary error text stays out (§2.6).\n */\ntype DiagnosticFailureCode =\n | Readonly<{ code: 'binding-invalid' | 'duplicate' | 'inactive' | 'missing'; subject: 'contribution' }>\n | Readonly<{ code: 'cancelled' | 'closed' | 'publication-rejected' | 'unavailable'; subject: 'call' }>\n | Readonly<{ code: 'cleanup-failed' | 'not-ready' | 'quarantined' | 'retired'; subject: 'feature' }>\n | Readonly<{ code: 'closed'; subject: 'application' }>\n | Readonly<{ code: 'closed'; subject: 'readable' }>\n | Readonly<{ code: 'invalid-id'; subject: 'declaration' }>;\n\ntype DiagnosticFailure = DiagnosticFailureCode & Readonly<{ cause?: DiagnosticCauseRef; phase: DiagnosticPhase }>;\n\n/**\n * Why a feature instance has not opened yet. Typed, so the panel never infers a reason from a neighbour's colour.\n * `awaiting-turn` is the honest name for the canonical order: members of a group open one at a time in\n * `plan.groups[].order`, so a member can be blocked by nothing but its own position.\n */\ntype DiagnosticWaitReason = 'awaiting-condition' | 'awaiting-hard-import' | 'awaiting-port' | 'awaiting-turn';\n\ntype DiagnosticClosedReason =\n | 'application-closed'\n | 'condition-inactive'\n | 'debug-override'\n | 'plan-replacement'\n | 'retired';\n\ntype DiagnosticCauseKind =\n | 'activity-change'\n | 'condition-change'\n | 'contribution-change'\n | 'control-command'\n | 'failure'\n | 'group-transition'\n | 'instance-transition'\n | 'plan-replacement'\n | 'session-reset';\n\n/**\n * A ref, not an explanation: the panel resolves it against the snapshot instead of parsing prose. `at` stamps the\n * trigger and is the protocol's only clock; a commit with no cause has no time, and the timeline shows that column\n * empty rather than inventing one.\n */\ntype DiagnosticCauseRef = Readonly<{\n at?: DiagnosticTimestamp;\n condition?: DiagnosticConditionId;\n kind: DiagnosticCauseKind;\n node?: DiagnosticNodeId;\n sequence?: DiagnosticSequence;\n}>;\n\n/**\n * What a condition group wants. `source` is the conjunction of its conditions, `override` is the debug override no\n * build can set yet, and `effective` is what the activation machine acts on.\n */\ntype DiagnosticDesiredState = Readonly<{\n effective: DesiredAxis;\n override: DiagnosticOverride;\n source: DesiredAxis;\n}>;\n\nexport {\n DevtoolsProtocolError,\n diagnosticConditionId,\n diagnosticEdgeId,\n diagnosticNodeId,\n diagnosticPlanFingerprint,\n diagnosticSequence,\n diagnosticSessionId,\n diagnosticStateRevision,\n diagnosticTopologyRevision,\n isDependencyEdge,\n isHardEdge,\n isWeakEdge,\n maxAtomId,\n maxEdgeId,\n maxEncodedAtom,\n maxNodeId,\n};\nexport type {\n DesiredAxis,\n DiagnosticCauseKind,\n DiagnosticCauseRef,\n DiagnosticClosedReason,\n DiagnosticConditionId,\n DiagnosticDesiredState,\n DiagnosticEdge,\n DiagnosticEdgeId,\n DiagnosticEdgeKind,\n DiagnosticFailure,\n DiagnosticFailureCode,\n DiagnosticLabel,\n DiagnosticNodeId,\n DiagnosticNodeKind,\n DiagnosticOverride,\n DiagnosticPhase,\n DiagnosticPlanFingerprint,\n DiagnosticProvenance,\n DiagnosticSequence,\n DiagnosticSessionId,\n DiagnosticStateRevision,\n DiagnosticTimestamp,\n DiagnosticTopologyRevision,\n DiagnosticWaitReason,\n HardEdgeKind,\n HealthAxis,\n HostContractDemand,\n LifecycleAxis,\n StructuralEdgeKind,\n WeakEdgeKind,\n WeakEdgeState,\n};\n"],"names":["DevtoolsProtocolError","code","message","idPattern","maxAtomId","maxAtomEscapes","maxEncodedAtom","maxNodeId","maxEdgeId","requireId","value","what","limit","requireCounter","diagnosticSessionId","diagnosticNodeId","diagnosticEdgeId","diagnosticConditionId","diagnosticPlanFingerprint","diagnosticSequence","diagnosticStateRevision","diagnosticTopologyRevision","hardEdgeKinds","weakEdgeKinds","isHardEdge","edge","isWeakEdge","isDependencyEdge"],"mappings":"AAqDA,MAAMA,UAA8B,KAAK,CAErB,KADlB,YACkBC,EAChBC,EAAe,CAEf,MAAMA,CAAO,EAHG,KAAA,KAAAD,EAIhB,KAAK,KAAO,uBACd,CACD,CAED,MAAME,EAAY,qBAeZC,EAAY,IACZC,EAAiB,KAAK,OAAOD,EAAY,GAAK,CAAC,EAC/CE,EAAiBF,EAAYC,EAC7BE,EAAY,GAAyBD,EACrCE,EAAY,GAAiC,GAAKD,EAAY,EAAIF,GAExE,SAASI,EAAUC,EAAeC,EAAcC,EAAa,CAC3D,GAAIF,EAAM,OAASE,GAAS,CAACT,EAAU,KAAKO,CAAK,EAC/C,MAAM,IAAIV,EAAsB,aAAc,sBAAsBW,CAAI,KAAK,KAAK,UAAUD,CAAK,CAAC,GAAG,EAGvG,OAAOA,CACT,CAEA,SAASG,EAAeH,EAAeT,EAA+CU,EAAY,CAChG,GAAI,CAAC,OAAO,cAAcD,CAAK,GAAKA,EAAQ,EAC1C,MAAM,IAAIV,EAAsBC,EAAM,cAAcU,CAAI,6CAA6CD,CAAK,GAAG,EAG/G,OAAOA,CACT,CAEA,SAASI,EAAoBJ,EAAa,CACxC,OAAOD,EAAUC,EAAO,aAAcH,CAAS,CACjD,CAEA,SAASQ,EAAiBL,EAAeE,EAAQL,EAAS,CACxD,OAAOE,EAAUC,EAAO,UAAWE,CAAK,CAC1C,CAEA,SAASI,EAAiBN,EAAeE,EAAQJ,EAAS,CACxD,OAAOC,EAAUC,EAAO,UAAWE,CAAK,CAC1C,CAOA,SAASK,EAAsBP,EAAa,CAC1C,OAAOD,EAAUC,EAAO,eAAgBJ,CAAc,CACxD,CAEA,SAASY,EAA0BR,EAAa,CAC9C,OAAOD,EAAUC,EAAO,mBAAoBN,CAAS,CACvD,CAEA,SAASe,EAAmBT,EAAa,CACvC,OAAOG,EAAeH,EAAO,mBAAoB,UAAU,CAC7D,CAEA,SAASU,EAAwBV,EAAa,CAC5C,OAAOG,EAAeH,EAAO,mBAAoB,gBAAgB,CACnE,CAEA,SAASW,EAA2BX,EAAa,CAC/C,OAAOG,EAAeH,EAAO,mBAAoB,mBAAmB,CACtE,CAoEA,MAAMY,EAAqC,IAAI,IAAkB,CAAC,cAAe,eAAe,CAAC,EAC3FC,EAAqC,IAAI,IAAkB,CAC/D,gBACA,cACA,kBACA,eACD,CAAA,EAGD,SAASC,EAAWC,EAAoB,CACtC,OAAOH,EAAc,IAAIG,EAAK,IAAI,CACpC,CAEA,SAASC,EAAWD,EAAoB,CACtC,OAAOF,EAAc,IAAIE,EAAK,IAAI,CACpC,CAGA,SAASE,EAAiBF,EAAoB,CAC5C,OAAOD,EAAWC,CAAI,GAAKC,EAAWD,CAAI,CAC5C"}
|